From 6ce28fab50591d21a3a78ed05a5fdde8e50ddfd7 Mon Sep 17 00:00:00 2001 From: Thomas Adam Date: Mon, 26 Aug 2019 23:33:33 +0100 Subject: [PATCH] Initial import --- .message | 1 + .message~ | 1 + ChangeLog | 1568 ++++++++++++++++ Cleanme | 46 + Imakefile | 45 + MakeMakefiles | 20 + README.Install | 55 + configure.h | 205 +++ documentation/WhereToGetIt | 44 + documentation/error_codes | 209 +++ documentation/m4_hacks | 127 ++ documentation/mailing_list | 24 + documentation/modules.tex | 391 ++++ fvwm.README | 11 + fvwm/Imakefile | 43 + fvwm/add_window.c | 933 ++++++++++ fvwm/alpha_header.h | 18 + fvwm/borders.c | 1287 +++++++++++++ fvwm/colormaps.c | 243 +++ fvwm/configure.c | 2140 +++++++++++++++++++++ fvwm/decorations.c | 444 +++++ fvwm/events.c | 1460 +++++++++++++++ fvwm/functions.c | 1711 +++++++++++++++++ fvwm/fvwm.c | 1179 ++++++++++++ fvwm/fvwm.h | 288 +++ fvwm/fvwm.man | 1701 +++++++++++++++++ fvwm/icons.c | 917 +++++++++ fvwm/menus.c | 783 ++++++++ fvwm/menus.h | 144 ++ fvwm/misc.c | 445 +++++ fvwm/misc.h | 331 ++++ fvwm/module.c | 685 +++++++ fvwm/module.h | 48 + fvwm/move.c | 503 +++++ fvwm/pager.c | 815 ++++++++ fvwm/parse.h | 65 + fvwm/placement.c | 349 ++++ fvwm/resize.c | 662 +++++++ fvwm/screen.h | 247 +++ fvwm/style.c | 399 ++++ fvwm/sun_headers.h | 55 + fvwm/windows.c | 159 ++ fvwm_icons/arrdown2.xpm | 41 + fvwm_icons/arrows2.xpm | 51 + fvwm_icons/arrup2.xpm | 41 + fvwm_icons/bomb.xpm | 47 + fvwm_icons/ccode.icon | 17 + fvwm_icons/clamp.xpm | 43 + fvwm_icons/datebook.xpm | 60 + fvwm_icons/default.xbm | 27 + fvwm_icons/desk.xpm | 46 + fvwm_icons/dialog_box.xpm | 47 + fvwm_icons/editres.xpm | 47 + fvwm_icons/eps.xpm | 53 + fvwm_icons/flow_chart.xpm | 46 + fvwm_icons/folder2.xpm | 44 + fvwm_icons/folders.xpm | 58 + fvwm_icons/fvwm.bitmap | 21 + fvwm_icons/fvwm.xpm | 44 + fvwm_icons/fvwm2.xpm | 78 + fvwm_icons/graphs.xpm | 52 + fvwm_icons/hcode.icon | 17 + fvwm_icons/mag_glass.xpm | 47 + fvwm_icons/mail1.xpm | 50 + fvwm_icons/mail2.xpm | 46 + fvwm_icons/map.xpm | 48 + fvwm_icons/math4.xpm | 44 + fvwm_icons/ocode.icon | 17 + fvwm_icons/page.xpm | 46 + fvwm_icons/page2.xpm | 43 + fvwm_icons/prog.icon | 17 + fvwm_icons/ps.xpm | 51 + fvwm_icons/question.xpm | 42 + fvwm_icons/rbomb.xpm | 43 + fvwm_icons/rcalc.xpm | 49 + fvwm_icons/rterm.xpm | 50 + fvwm_icons/term.xpm | 48 + fvwm_icons/tiff2.xpm | 61 + fvwm_icons/toolbox.xpm | 48 + fvwm_icons/unknown1.xpm | 59 + fvwm_icons/wierd_page3.xpm | 52 + fvwm_icons/word_processor.xpm | 45 + fvwm_icons/xcalc.xpm | 56 + fvwm_icons/xman.xpm | 55 + fvwm_icons/xterm-axp.xpm | 51 + fvwm_icons/xterm-blank.xpm | 56 + fvwm_icons/xterm-dec.xpm | 57 + fvwm_icons/xterm-sgi.xpm | 49 + fvwm_icons/xterm-sol.xpm | 49 + fvwm_icons/xterm-sun.xpm | 56 + fvwm_icons/xterm.xpm | 56 + libs/CatString3.c | 22 + libs/CopyString.c | 38 + libs/GetFdWidth.c | 15 + libs/Imakefile | 18 + libs/ReadPacket.c | 57 + libs/SendInfo.c | 26 + libs/SendText.c | 24 + libs/findIconFile.c | 81 + libs/fvwmlib.h | 12 + libs/hostname.c | 29 + libs/mygetostype.c | 26 + libs/mystrcasecmp.c | 29 + libs/safemalloc.c | 27 + libs/sleep.c | 24 + libs/strncmp.c | 19 + libs/wild.c | 75 + modules/FvwmAudio/FvwmAudio.c | 503 +++++ modules/FvwmAudio/FvwmAudio.man | 125 ++ modules/FvwmAudio/Imakefile | 45 + modules/FvwmAudio/README | 37 + modules/FvwmAuto/FvwmAuto.c | 170 ++ modules/FvwmAuto/FvwmAuto.man | 35 + modules/FvwmAuto/Imakefile | 30 + modules/FvwmBacker/FvwmBacker.README | 36 + modules/FvwmBacker/FvwmBacker.c | 384 ++++ modules/FvwmBacker/FvwmBacker.h | 31 + modules/FvwmBacker/FvwmBacker.man | 70 + modules/FvwmBacker/Imakefile | 31 + modules/FvwmBacker/Mallocs.c | 62 + modules/FvwmBacker/Mallocs.h | 25 + modules/FvwmBacker/root_bits.c | 73 + modules/FvwmBanner/FvwmBanner.c | 319 ++++ modules/FvwmBanner/FvwmBanner.man | 34 + modules/FvwmBanner/Imakefile | 39 + modules/FvwmBanner/fvwm3.xpm | 265 +++ modules/FvwmClean/FvwmClean.c | 430 +++++ modules/FvwmClean/FvwmClean.h | 37 + modules/FvwmClean/FvwmClean.man | 60 + modules/FvwmClean/Imakefile | 30 + modules/FvwmDebug/FvwmDebug.c | 505 +++++ modules/FvwmDebug/FvwmDebug.h | 38 + modules/FvwmDebug/FvwmDebug.man | 44 + modules/FvwmDebug/Imakefile | 27 + modules/FvwmIconBox/COPYRIGHT | 62 + modules/FvwmIconBox/FvwmIconBox.c | 2451 +++++++++++++++++++++++++ modules/FvwmIconBox/FvwmIconBox.h | 181 ++ modules/FvwmIconBox/FvwmIconBox.man | 254 +++ modules/FvwmIconBox/Imakefile | 33 + modules/FvwmIconBox/icons.c | 387 ++++ modules/FvwmIconBox/stipple | 6 + modules/FvwmIdent/FvwmIdent.c | 727 ++++++++ modules/FvwmIdent/FvwmIdent.h | 73 + modules/FvwmIdent/FvwmIdent.man | 68 + modules/FvwmIdent/Imakefile | 30 + modules/FvwmPager/FvwmPager.c | 956 ++++++++++ modules/FvwmPager/FvwmPager.h | 141 ++ modules/FvwmPager/FvwmPager.man | 171 ++ modules/FvwmPager/Imakefile | 31 + modules/FvwmPager/x_pager.c | 1626 ++++++++++++++++ modules/FvwmSave/FvwmSave.c | 392 ++++ modules/FvwmSave/FvwmSave.h | 44 + modules/FvwmSave/FvwmSave.man | 64 + modules/FvwmSave/Imakefile | 29 + modules/FvwmSaveDesk/FvwmSaveDesk.c | 459 +++++ modules/FvwmSaveDesk/FvwmSaveDesk.h | 45 + modules/FvwmSaveDesk/FvwmSaveDesk.man | 70 + modules/FvwmSaveDesk/Imakefile | 29 + modules/FvwmSaveDesk/example/fvwmrc | 284 +++ modules/FvwmSaveDesk/example/xinitrc | 30 + modules/FvwmScroll/FvwmScroll.c | 282 +++ modules/FvwmScroll/FvwmScroll.h | 35 + modules/FvwmScroll/FvwmScroll.man | 76 + modules/FvwmScroll/GrabWindow.c | 987 ++++++++++ modules/FvwmScroll/Imakefile | 29 + modules/FvwmWinList/ButtonArray.c | 253 +++ modules/FvwmWinList/ButtonArray.h | 41 + modules/FvwmWinList/CHANGELOG | 64 + modules/FvwmWinList/Colors.c | 105 ++ modules/FvwmWinList/Colors.h | 19 + modules/FvwmWinList/FvwmWinList.c | 804 ++++++++ modules/FvwmWinList/FvwmWinList.h | 107 ++ modules/FvwmWinList/FvwmWinList.man | 109 ++ modules/FvwmWinList/Imakefile | 31 + modules/FvwmWinList/List.c | 236 +++ modules/FvwmWinList/List.h | 43 + modules/FvwmWinList/Mallocs.c | 63 + modules/FvwmWinList/Mallocs.h | 28 + modules/FvwmWinList/README | 114 ++ modules/FvwmWinList/config.sample | 17 + modules/GoodStuff/GoodStuff.c | 1527 +++++++++++++++ modules/GoodStuff/GoodStuff.h | 76 + modules/GoodStuff/GoodStuff.man | 161 ++ modules/GoodStuff/Imakefile | 33 + modules/GoodStuff/icons.c | 233 +++ sample.fvwmrc/4Dwm.fvwmrc | 507 +++++ sample.fvwmrc/README | 10 + sample.fvwmrc/minimal.fvwmrc | 472 +++++ sample.fvwmrc/mwm.fvwmrc | 470 +++++ sample.fvwmrc/system.fvwmrc | 572 ++++++ tar_script | 5 + version.h | 2 + xpmroot/Imakefile | 33 + xpmroot/xpmroot.c | 128 ++ xpmroot/xpmroot.man | 16 + 195 files changed, 43410 insertions(+) create mode 100644 .message create mode 100644 .message~ create mode 100644 ChangeLog create mode 100755 Cleanme create mode 100644 Imakefile create mode 100755 MakeMakefiles create mode 100644 README.Install create mode 100644 configure.h create mode 100644 documentation/WhereToGetIt create mode 100644 documentation/error_codes create mode 100644 documentation/m4_hacks create mode 100644 documentation/mailing_list create mode 100644 documentation/modules.tex create mode 100644 fvwm.README create mode 100644 fvwm/Imakefile create mode 100644 fvwm/add_window.c create mode 100644 fvwm/alpha_header.h create mode 100644 fvwm/borders.c create mode 100644 fvwm/colormaps.c create mode 100644 fvwm/configure.c create mode 100644 fvwm/decorations.c create mode 100644 fvwm/events.c create mode 100644 fvwm/functions.c create mode 100644 fvwm/fvwm.c create mode 100644 fvwm/fvwm.h create mode 100644 fvwm/fvwm.man create mode 100644 fvwm/icons.c create mode 100644 fvwm/menus.c create mode 100644 fvwm/menus.h create mode 100644 fvwm/misc.c create mode 100644 fvwm/misc.h create mode 100644 fvwm/module.c create mode 100644 fvwm/module.h create mode 100644 fvwm/move.c create mode 100644 fvwm/pager.c create mode 100644 fvwm/parse.h create mode 100644 fvwm/placement.c create mode 100644 fvwm/resize.c create mode 100644 fvwm/screen.h create mode 100644 fvwm/style.c create mode 100644 fvwm/sun_headers.h create mode 100644 fvwm/windows.c create mode 100644 fvwm_icons/arrdown2.xpm create mode 100644 fvwm_icons/arrows2.xpm create mode 100644 fvwm_icons/arrup2.xpm create mode 100644 fvwm_icons/bomb.xpm create mode 100644 fvwm_icons/ccode.icon create mode 100644 fvwm_icons/clamp.xpm create mode 100644 fvwm_icons/datebook.xpm create mode 100644 fvwm_icons/default.xbm create mode 100644 fvwm_icons/desk.xpm create mode 100644 fvwm_icons/dialog_box.xpm create mode 100644 fvwm_icons/editres.xpm create mode 100644 fvwm_icons/eps.xpm create mode 100644 fvwm_icons/flow_chart.xpm create mode 100644 fvwm_icons/folder2.xpm create mode 100644 fvwm_icons/folders.xpm create mode 100644 fvwm_icons/fvwm.bitmap create mode 100644 fvwm_icons/fvwm.xpm create mode 100644 fvwm_icons/fvwm2.xpm create mode 100644 fvwm_icons/graphs.xpm create mode 100644 fvwm_icons/hcode.icon create mode 100644 fvwm_icons/mag_glass.xpm create mode 100644 fvwm_icons/mail1.xpm create mode 100644 fvwm_icons/mail2.xpm create mode 100644 fvwm_icons/map.xpm create mode 100644 fvwm_icons/math4.xpm create mode 100644 fvwm_icons/ocode.icon create mode 100644 fvwm_icons/page.xpm create mode 100644 fvwm_icons/page2.xpm create mode 100644 fvwm_icons/prog.icon create mode 100644 fvwm_icons/ps.xpm create mode 100644 fvwm_icons/question.xpm create mode 100644 fvwm_icons/rbomb.xpm create mode 100644 fvwm_icons/rcalc.xpm create mode 100644 fvwm_icons/rterm.xpm create mode 100644 fvwm_icons/term.xpm create mode 100644 fvwm_icons/tiff2.xpm create mode 100644 fvwm_icons/toolbox.xpm create mode 100644 fvwm_icons/unknown1.xpm create mode 100644 fvwm_icons/wierd_page3.xpm create mode 100644 fvwm_icons/word_processor.xpm create mode 100644 fvwm_icons/xcalc.xpm create mode 100644 fvwm_icons/xman.xpm create mode 100644 fvwm_icons/xterm-axp.xpm create mode 100644 fvwm_icons/xterm-blank.xpm create mode 100644 fvwm_icons/xterm-dec.xpm create mode 100644 fvwm_icons/xterm-sgi.xpm create mode 100644 fvwm_icons/xterm-sol.xpm create mode 100644 fvwm_icons/xterm-sun.xpm create mode 100644 fvwm_icons/xterm.xpm create mode 100644 libs/CatString3.c create mode 100644 libs/CopyString.c create mode 100644 libs/GetFdWidth.c create mode 100644 libs/Imakefile create mode 100644 libs/ReadPacket.c create mode 100644 libs/SendInfo.c create mode 100644 libs/SendText.c create mode 100644 libs/findIconFile.c create mode 100644 libs/fvwmlib.h create mode 100644 libs/hostname.c create mode 100644 libs/mygetostype.c create mode 100644 libs/mystrcasecmp.c create mode 100644 libs/safemalloc.c create mode 100644 libs/sleep.c create mode 100644 libs/strncmp.c create mode 100644 libs/wild.c create mode 100644 modules/FvwmAudio/FvwmAudio.c create mode 100644 modules/FvwmAudio/FvwmAudio.man create mode 100644 modules/FvwmAudio/Imakefile create mode 100644 modules/FvwmAudio/README create mode 100644 modules/FvwmAuto/FvwmAuto.c create mode 100644 modules/FvwmAuto/FvwmAuto.man create mode 100644 modules/FvwmAuto/Imakefile create mode 100644 modules/FvwmBacker/FvwmBacker.README create mode 100644 modules/FvwmBacker/FvwmBacker.c create mode 100644 modules/FvwmBacker/FvwmBacker.h create mode 100644 modules/FvwmBacker/FvwmBacker.man create mode 100644 modules/FvwmBacker/Imakefile create mode 100644 modules/FvwmBacker/Mallocs.c create mode 100644 modules/FvwmBacker/Mallocs.h create mode 100644 modules/FvwmBacker/root_bits.c create mode 100644 modules/FvwmBanner/FvwmBanner.c create mode 100644 modules/FvwmBanner/FvwmBanner.man create mode 100644 modules/FvwmBanner/Imakefile create mode 100644 modules/FvwmBanner/fvwm3.xpm create mode 100644 modules/FvwmClean/FvwmClean.c create mode 100644 modules/FvwmClean/FvwmClean.h create mode 100644 modules/FvwmClean/FvwmClean.man create mode 100644 modules/FvwmClean/Imakefile create mode 100644 modules/FvwmDebug/FvwmDebug.c create mode 100644 modules/FvwmDebug/FvwmDebug.h create mode 100644 modules/FvwmDebug/FvwmDebug.man create mode 100644 modules/FvwmDebug/Imakefile create mode 100644 modules/FvwmIconBox/COPYRIGHT create mode 100644 modules/FvwmIconBox/FvwmIconBox.c create mode 100644 modules/FvwmIconBox/FvwmIconBox.h create mode 100644 modules/FvwmIconBox/FvwmIconBox.man create mode 100644 modules/FvwmIconBox/Imakefile create mode 100644 modules/FvwmIconBox/icons.c create mode 100644 modules/FvwmIconBox/stipple create mode 100644 modules/FvwmIdent/FvwmIdent.c create mode 100644 modules/FvwmIdent/FvwmIdent.h create mode 100644 modules/FvwmIdent/FvwmIdent.man create mode 100644 modules/FvwmIdent/Imakefile create mode 100644 modules/FvwmPager/FvwmPager.c create mode 100644 modules/FvwmPager/FvwmPager.h create mode 100644 modules/FvwmPager/FvwmPager.man create mode 100644 modules/FvwmPager/Imakefile create mode 100644 modules/FvwmPager/x_pager.c create mode 100644 modules/FvwmSave/FvwmSave.c create mode 100644 modules/FvwmSave/FvwmSave.h create mode 100644 modules/FvwmSave/FvwmSave.man create mode 100644 modules/FvwmSave/Imakefile create mode 100644 modules/FvwmSaveDesk/FvwmSaveDesk.c create mode 100644 modules/FvwmSaveDesk/FvwmSaveDesk.h create mode 100644 modules/FvwmSaveDesk/FvwmSaveDesk.man create mode 100644 modules/FvwmSaveDesk/Imakefile create mode 100644 modules/FvwmSaveDesk/example/fvwmrc create mode 100755 modules/FvwmSaveDesk/example/xinitrc create mode 100644 modules/FvwmScroll/FvwmScroll.c create mode 100644 modules/FvwmScroll/FvwmScroll.h create mode 100644 modules/FvwmScroll/FvwmScroll.man create mode 100644 modules/FvwmScroll/GrabWindow.c create mode 100644 modules/FvwmScroll/Imakefile create mode 100644 modules/FvwmWinList/ButtonArray.c create mode 100644 modules/FvwmWinList/ButtonArray.h create mode 100644 modules/FvwmWinList/CHANGELOG create mode 100644 modules/FvwmWinList/Colors.c create mode 100644 modules/FvwmWinList/Colors.h create mode 100644 modules/FvwmWinList/FvwmWinList.c create mode 100644 modules/FvwmWinList/FvwmWinList.h create mode 100644 modules/FvwmWinList/FvwmWinList.man create mode 100644 modules/FvwmWinList/Imakefile create mode 100644 modules/FvwmWinList/List.c create mode 100644 modules/FvwmWinList/List.h create mode 100644 modules/FvwmWinList/Mallocs.c create mode 100644 modules/FvwmWinList/Mallocs.h create mode 100644 modules/FvwmWinList/README create mode 100644 modules/FvwmWinList/config.sample create mode 100644 modules/GoodStuff/GoodStuff.c create mode 100644 modules/GoodStuff/GoodStuff.h create mode 100644 modules/GoodStuff/GoodStuff.man create mode 100644 modules/GoodStuff/Imakefile create mode 100644 modules/GoodStuff/icons.c create mode 100644 sample.fvwmrc/4Dwm.fvwmrc create mode 100644 sample.fvwmrc/README create mode 100644 sample.fvwmrc/minimal.fvwmrc create mode 100644 sample.fvwmrc/mwm.fvwmrc create mode 100644 sample.fvwmrc/system.fvwmrc create mode 100755 tar_script create mode 100644 version.h create mode 100644 xpmroot/Imakefile create mode 100644 xpmroot/xpmroot.c create mode 100644 xpmroot/xpmroot.man diff --git a/.message b/.message new file mode 100644 index 0000000..2309ee1 --- /dev/null +++ b/.message @@ -0,0 +1 @@ +Latest Version is 1.24r! diff --git a/.message~ b/.message~ new file mode 100644 index 0000000..4c125d8 --- /dev/null +++ b/.message~ @@ -0,0 +1 @@ +Latest Version is 1.24q! diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..500363a --- /dev/null +++ b/ChangeLog @@ -0,0 +1,1568 @@ +q to r + 1. Fixed blatant GoodStuff boo-boo, with the 'Swallow' command. + +p to q + 1. Fixed bug in Move/Resize with coordinates specified, when + accessed through modules. + 2. Prohibited zero width/height windows, which are nasty. + 3. Fixed error caused by HandleWidth = 0. The error was: + fvwm: internal error + Request 1, Error 2 + EventType: 20 + This should look familiar to some people. + 4. Added FvwmAuto, and auto-raise module which will replace + built in auto-raise in future versions. Built in + auto-raise is still there, but the module works better! + 5. Thought about adding m4_read module, but this can't be + done under the fvwm-1.xxx system, because of the distinction + between configuration commands and built-in commands. + +o to p + 1. Minor patch to Circulate functions + 2. Removed button-stays-depressed feature from the sample .fvwmrc + files. No changes to the source code, I just removed the qouted + part of the Exec expressions. It seems that people can't read or + understand the man page: + + If command is an fvwm Exec command, then the button + will remain pushed in until a window whose name or + class matches the qouted portion of the command is + encountered. This is intended to provide visual feed- + back to the user that the action he has requested will + be performed. If the qouted portion contains no charac- + ters, then the button will pop out immediately. Note + that users can continue pressing the button, and re- + executing the command, even when it looks "pressed in." + + 3. Removed my e-mail address from everything. + +n to o + 1. Fixed: + a. raising of no-title icons + b. CirculateDown enters an infinite loop + c. command line argument -w was interpreted + as -workspace for application programs. + +m to n + 1. minor colormap fixup + 2. minor restart fixup. + +l to m + 1. Fixed a problem where de-iconified windows don't always + end up on top. + +k to l + 1. Removed a debugging printf + 2. Restored pager.c which got abused during a disk-space crunch. + +j to k + 1. Fixes (?) for Move +i to j + 1. Fixed bug in FvwmPager + 2. Made Click-to-focus work with CapsLock on. + +h to i + 1. Miscellaneous little things + Top level imakefile fixed up + fixed a few small errors. + +g to h + 1. Mailing List changed + To subscribe: + + mail to majordomo@wonderland.org with the body of the message: + + subscribe fvwm + + That's all there is to it. To send to the list, mail to + fvwm@wonderland.org. + 2. Fixed the icon-label-disappears-after-move problem + 3. Added optional arguments to resize, just like move. + 4. Updated man page to reflect changes for versions g & h. +f to g + 1. Fixed core-dump from FvwmBacker. + 2. Added (but didn't test much) a feature where you can + specify arguments to Scroll, movecursor, and maximize + in either percent-of-screen-size (as before) or in pixels. + Example + Scroll 10 10 + Scroll 50p 50p + + The first goes 10 percent of the screen in each direction, the + second goes 50 pixels. You can mix, ie + Scroll 10 50p + which does "Scroll 10 percent left, 50 pixels down. + + 3. Gave Move optional arguments, to specify where to move to + arguments can be in pixels or percent of screen-size, like + the other commands above. + +e to f + 1. Switched from XFetchName to XGetWMName, + in deference to motif 1.2 (? bug report) + 2. Kept the FvwmPager from allowing you to move windows + into never-never land (in the title region). + 3. When selecting a window in the WIndowList, fvwm + makes sure that the window is visible at the end. + +d to e + 1. fixed some bugs associated with (c) + 2. Added quick-restart, which ain't so quick, but may + lead to something +c to d + 1. Futzed with #ifdefs a lot. + +1.24b to c + 1. Kept moving common subroutines in the library. +1.24 to 1.24b + 1. Renamed strncasecmp, strcasecmp, gethostname to avoid + potential conflicts with OS provided functions. + +1.23f to 1.24 + 1. Create libs subdirectory. + Inserted (in libs directory) code for + strncasecmp, strcasecmp, gethostname, CatString3, + SendInfo, SendText. + Removed ifdef's aroung strncasecmp, strcasecmp, gethostname. + Everyone uses the fvwm version now, I hope! + + 2. Skipped 1.23f to 1.23z so that everyone will think that big + progress has been made, and will upgrade. + + 3. Time to get rid of #ifdef PRUNE ? Soon I think! + +1.23e to f + 1. Applied a few patches + A. fvwm man patch m4 stuff + B. FvwmIconBox +1.23d to 1.23e + 1. Made mouse and button operations insensitive to the + position of the caps-lock key. It use to be sensitive if + modifier was not AnyModifier. We all know that true unix + users typically break off the useless caps-lock key before + turning on the computer, but this seems to be an improvement + in useability anyway. + +1.23c to 1.23d + 1. Remove the configure.h options + NEEDS_SIGCHLD + and + UNION_WAIT + fvwm now NEVER traps SIGCHLD, but ALWAYS + waits() for dead children. Maybe it'll even work. + + Tried it on SunOS 4.1.3 and Solaris 2.3 and OSF/1 + 2. Incorportated M4 patches. + +1.23b to 1.23c + 1. Applied various patches: + 1. FvwmIconBox patch #6. Something to do with windows + that change their icons. + 2. Using the built-in windowlist on a window which is + on another desk and iconified now causes + a switch to that windows desk, instead of bringing + the window to the current desk. + 3. Patch to eliminate some errors from GoodStuff while + it terminates. + 2. Made fvwm grab the X-server during desktop changes. This + keeps windows from redrawing themselves as they are (briefly) + exposed, and makes the desktop change feel much faster. + Even better would be to move windows in a stacking-order + sensitive manner. + + 3. Made CirculateUp, CirculateDown, and Warp accept wildcards in + the name-to-match field. Also allowed these functions to warp/ + circulate to globally-active-focus model windows which were + incorrectly prohibited before. + +1.23 to 1.23b + 1. Applied patches for the m4 / GNU m4 problem + 2. Applied patch for MWMButtons with new NoButton stuff. + 3. remove xpm.h from the distribution, since there are at least + two incompatible versions of xpm out there. References are now + , so you can put your copy in /usr/include/X11/xpm.h + 4. Fixed malloc(0) problem in FvwmFileMgr. + +z.1 to 1.23 + 1. Applied m4 patches. + 2. Applied some FvwmIconBox patchs + 3. Applied GNU m4 patches + 4. Applied the NoButton and ButtonStyle extension patches. + 5. Fixed the problem "Warp skips over icons if NoIcons is set". +1.22z to z.1 + 1. Fixed up the Imakefile to reasonably allow + installation into a non-standard directory. Tried it too. + +y to z + 1. Fiddled with the errno return values when writing to pipes. + +x to y + 1. Fixed click-to-focus mode. + 2. Added FvwmSaveDesk module + +w to x + 1. Allow negative auto-raise delays to suppress the + raise-on-focus behavior of click-to-focus mode. + 2. Fixed (?) GoodStuff for ALphas + 3. Modified module-interface code to speed it up (maybe). +v to w + 1. Added some dead-child reaping changes. + 2. Completely fixed fvwm-to-module communications. +u to v. + 1. Added Set_Mask command for modules to set their message mask + which will reduce unneeded traffic into the pipes. + Updated GoodStuff and FvwmPager to use the new feature. + +t to u. + 1. Added some FvwmIconBox changes. + 2. Fiddled with Fvwm-to-module communications a bit. + +s to t + 1. Incorporated the NoIconTitle patches. You can add a style + Style "xmag" NoIconTitle, Icon magnifying_glass2.xpm + 2. Added the very nice FvwmIconBox module. I've switched to it + myself. (Actually, I swallowed it into an 8x2 + GoodStuff, which is pretty cool). + 3. Made FvwmScroll scrollbars look and function like the + FvwmIconBox scroll-bars. +r to s + 1. Add the built-in Close, a hybrid of Delete and Destroy, which + probably mimics OpenWindows and MWM's close function. + +q to r + 1. Made FvwmFileManager handle icons that it can't find. + +p to q + 1. Small fix with regards to starting a window on a specific + desk and then quickly changing desks. + 2. Loss-of-focus-after-iconifying bug fixed (?) + 3. Added ForeColor and BackColor styles to supplement Color, since the + choice of "/" as a fore/back color seperator turns out + to be poor. + +1.22o to p + 1. Bug (?) fixed which affected multi-screen support. + Probably explains reports of gradual loss of functionality + when used on multi-screen displays. + 2. Altered icon-move code: + a. Unmaps the icon-label window during an opaque + icon move, if there is a pixmap. + b. Unmaps the entire icon during a non-opaque move. + These are really for the FvwmFileManager, and can be + changed back if deemed inappropriate. + 3. Added an XAllowEvents to WaitForButtonsUp(), + in case that was causing lock-ups. + +1.22n to o + 1. Bug fixes for FvwmFileMgr. + +1.22m to n + 1. Lots of FvwmFileMgr changes. Its now pretty useable, although + sluggish at times. + Read the README in the source directory. +1.22l to m + 1. Still More fixes for big buttons in GoodStuff + 2. More upgrades to FvwmFileMgr. + +1.22k to 1.22l + 1. More fixes for big buttons in GoodStuff + 2. Upgrades to FvwmFileMgr. Now it periodically + refreshes its directory contents, also alphabetizes the files. + +1.22j to 1.22k + 1. Fixed an over-lap problem with SmartPlacement + 2. Fixed up big button shuffling in GoodStuff (a little) + 3. Added the preliminary FvwmFileManager. Don't send bug reports, + its only a veryveryvery preliminary version. + +1.22i to 1.22j + 1. Attempt to fix problem with zombies from swallowed windows + by forcing fvwm to do ReapChildren() on start-up and + exit. + 2. Fixed a very obscure bug relating to handling of windows + that map and unmap themselves a lot. + 3. Fixed a bug in random-placement, where "off-screen" windows + weren't detected quite right. + 4. Incorporated the latest FvwmWinList patches. +1.22h to 1.22i + 1.Fi xed auto-raise for small time-out values. + 2. Converted val1 and val2 in the menu-structure to + longs for the Alphas out there. + 3. Changed FvwmWinList to give black shadows on monochrome systems. + 4. Improved GoodStuff's handling of multi-width/height buttons +1.22g to 1.22h + 1. Added stuff to GoodStuff. + a. Multi-width/height butttons + b. Swallowed modules + c. Selective omission of button titles + (not yet smart enough to change window size + accordingly). + Look in system.fvwmrc for an example. + +1.22f to 1.22g + 1. Added support for starting applications on a specific + desk by specifying the command line flag: + -xrm "*Desk:1" or whatever. Works for some apps like + xterm, xfontsel, but not for others, like rxvt, xclock. This + code was a patch which I believe was lifted from ctwm. + +1.22e to 1.22f + 1. Fixed F_RAISE_IT by merging with F_FOCUS +1.22d to e + 1. Made GoodStuff do a constrained resize when it swallows windows. + 2. Updated mwm.fvwmrc and 4Dwm.fvwmrc samples. + 3. Fixed the 1-pixel width/height error that pervaded fvwm. + It was just that the base-width/height was assumed to be 1, not + zero, if the application didn't supply it. +1.22c to d + 1. Fixed a minor focus bug, a few other little odds and ends. + +1.22b to 1.22c + 1. Fixed some configure.c errors were options were incorrectly + left out + 2. Fixed the "swallow" bug in goodstuff that only shows up + if you specify a valid pixmap and expect it to be + covered by your swallowed window. Why would anyone do + that anyway???!! + 3. Fixed(?) the loss-of-focus problem (click-to-focus mode) when a new + window is mapped that doesn't want focus. This was not really + a bug in the first place. + 4. Fixed FvwmPager error when an icon which has the focus is + de-iconified + 5. Fixed sample.fvwmrc to parse colors correctly. You need to + make sure that styles are defined before any functions or + menus, and before the internal pager is started. + +1.22 to 1.22b + 1. Fixed various minor stuff, mostly with pager, and a few + cross-platform compatibility things. + 2. Added StartIconic/StartNormal to the style command. + 3. Added per-window border colors via the Style command: + Style "*" BorderWidth 5, HandleWidth 5, Color Black/#60a0c0 + Style "rxvt" Icon term.xpm, Color black/grey + Could use this to replace the StdForeColor/StdBackColor options. + +1.21zo to 1.22 + 1. Fixed minor focus problem: when an attempt was made + to give focus to a window that won't take it, the focus was + left on (I think) window None, ie keyboard input was lost, and + keyboard shortcuts failed. + 2. Fixed some bugs in the FvwmPager and other modules. + 3. Fixed case where moving an icon across desks in the pager didn't + work quite right. +1.21zn to zo + 1. Added special functions + InitFunction + RestartFunction + which are executed on start-up or restarts. + 2. Addressed click-to-focus focus queue manipulation when + warp and circulate up/down commands are used. + 3. Added some potential improvements for colormap handling. + 4. Added the Wait builtin to make InitFunction more useful. +1.21zm to zn + 1. Added BorderWidth and HandleWidth to style command. + ---> replaces BoundaryWidth and NoBoundaryWidth + commands & adds flexibility. + 2. Ifdef'd out old style-setting code + ---> #ifndef PRUNE + 3. FIxed error in wild-card matching for trailing "*", + in case where the trailing * needs to match a null-string. +1.21zl to 1.21zm + 1. Added opposite behaviors to Style: + Title, Handles, StaysPut, Slippery, CirculateHit, + WindowListHit, StartsAnywhere. You can now change default + fvwm behavior with Style "*" .... + and then re-enable properties on specific windows as desired. + 2. Made Style "*" Icon unknown1.xpm + set the default icon, used only after a windows + built-in icons are checked. + 3. Added NoIcon option for style. Also, Icon attribute without + an argument undows the NoIcon attribute without specifying a window, + so + Style "*" NoIcon + Style "Fvwm Pager" Icon + allows only the FvwmPager module's built-in icon to appear. + 4. Fixed a few minor bugs in Style. + +1.21zk to zl + 1. Fixed man page for Focus built-in. Focus does not + de-iconify. + 2. Built-in pager is no longer automatically sticky. + 3. Added the Style command. Not finished, but fully + functional. The default Icon handling with Style is + bad, so we still need the old default icon command. No + new capabilities have been added at this time. + +1.21zj to zk + 1. Fixed some bugs in FvwmScroll + 2. Removed all use of CurrentTime in focus control. + (Use propertyNotify events for click-to-focus when first + mapping a new window). + 3. Remove symlinks from source tree +1.21zi to 1.21zj + 1. Added wild-card parsing to NoTitle, Sticky, + NoBorder, Icon, WindowListSkip, and StartsOnDesk. Neat. + Cuts down on .fvwmrc entries. Added it to FvwmWinList too. + +1.21zh to 1.21zi + 1. Fixed Keyboard shortcuts in DeferExecution. + 2. Added FvwmScroll module. +1.21zg to 1.21zh + 1. Fixed border drawing code to look OK for any width + of border from 0 up. BoundaryWidth 0 really gives no + boundary at all. BoundaryWidth 1 or 2 gives a solid + shadow-color boundary. + 2. Incorporated patches to add a seperate menu fore and back + color, and a menu-stipple color for the shaded out entries in + window menus. All this is conditional on #ifdef MENUCOLOR. + Need to add: + MenuForeColor Black + MenuBackColor grey + MenuStippleColor SlateGrey + to .fvwmrc. + +1.21zf to 1.21zg + 1. Fixed pager for monochrome mode (ignores user colors). + 2. Adjusted fonts, border widths, etc of the default + system.fvwmrc + +ze to zf + 1. Fixed minor error in pager geometries. + +1.21zd to ze + 1. Fixed the problem of vestigial decorations for swallowed + windows. + 2. Made NoBoundaryWidth 0 actually give a boundary-width of zero. +1.21zc to 1.21zd + 1. Added "swallow" to GoodStuff + +1.21zb to 1.21zc + 1. Colormap handling changes. + +1.21za to 1.21zb + 1. A couple of residual focus-on-root patches. + 2. Minor tweak to FvwmWinList, replacing c==' ' + with isspace(c) + 3. XSendEvent at the end of HandleButtonPress needed + a little extra filtering. + +1.21z to 1.21za + 1. Appied still more patches about unions status wait.... + 2. Updated 4Dwm.fvwmrc + 3. Switched to FvwmWinList version 0.4. Made some minor tweaks to + FvwmWinList in the process. + +1.21y to 1.21z + 1. Added HOSTDISPLAY enviroment variable; should be a network + ready version of DISPLAY + 2. Added SloppyFocus, which works like the default focus-follows- + mouse, except that focus stays witht the window until you enter + a new window. + +1.21w to 1.21 y + 1. Fixed up LookInList, so that + Sticky xbiff + Notitle XBiff + will have the expected result. Note: this is not making + the string comparison case-insensitive, but is performing an + exhaustive search for matches, instead of stopping at the first + match. + 2. Gave GoodStuff buttons that can remain pushed in until + an application actually materializes. In Exec commands, + the qouted portion of the command will be compared to + names and classes of new windows, until a match is found, + then the button will be release. Qouting an empty string + will restore the original behavior. + + This needs to be extended: it should be possible for a + button to remain pushed in until the application dies, + or to grab the application icons, or to grab the application + window itself (for xclock, xbiff). + + +1.21v to 1.21w + 1. Fixed focus-on-warping problem. + 2. Fixed StickyIcons in new FvwmPager + 3. Fixed circulate up/down handling of windows that don't + accept focus +1.21u to 1.21v + 1. Added built-in Focus for use by FvwmWinList + 2. Made fvwm ungrab the pointer just prior to + invoking a module. Allows modules to do natural + pop-up menus if desired. + +1.21t to 1.21u + 1. Added FvwmPager code to detect + *FvwmPagerFont none + which causes the desktop-labels to be omitted. + 2. Added FvwmPagerRows and FvwmPagerColumns +1.21s to 1.21t + 1. Remove most of HandleLeaveNotify, since it caused occasional + focus loss. + 2. Cleaned up colormap focusing + 3. Added StartIconic and IconGeometry + to FvwmPager. Needs a little work + still. + 4. Updated FvwmWinList to ver 0.3 + 5. Fixed up focusing for click-to-focus and colormap + handling. + +1.21r to 1.21s + 1. Applied patch to FvwmWinList + 2. Changed comment delimiter from ## to + /* */ in Imakefiles. + +1.21q to 1.21r + 1. Beat up on the makefile and configure.h + 2. Added AppsBackingStore, SaveUnders, and + BackingStore as run-time options. They + used to be compile time. + 3. Remove NO_MORE_COLORS compile time + option. + 4. Made LENIENCE a run time option. + 5. Fixed the focus-on-root problem + + +1.21p to 1.21q + 1. Added FvwmWinList +1.21o to 1.21p + 1. Big clean up for focus control. Completely + eliminated CheckAndSetFocus(). + 2. Big time, really stupid and quite serious bug in My_XNextEvent + was fixed. This caused some events to be skipped, and others + to be processed twice. + 3. FvwmPager now has a "current desk only" pager for an icon. + If you have a line like + Icon "Fvwm Pager" map.xpm + get rid of it! This icon does not yet allow you to move windows + or viewports. + 4. Iconic view of the pager now also allows the user to + move windows and viewports within the icon. + 5. Can now drag windows out of the pager onto the + desktop for final placement. + +1.21m to 1.21o + 1. Fixed some segmentation faults + 2. Fixed Raise operation with no on-top windows. + 3. Cleaned up sample config files. + +1.21l to 1.21m + 1. Fixed focusing problems caused by sometimes processing + events out of order. + 2. Split M_ICONIFY module message into M_ICONIFY and + M_ICON_LOCATION. + 3. Fixed up pager for monochrome user + 4. Added window-labels to the new pager. + +1.21k to 1.21l + 1. Improved handling of ONTOP windows, so they + no longer fight each other for top-billing. Also, + a window-manager induced raise will not briefly raise + the target window above the ONTOP's. + 2. Gave the FvwmPager the ability to move keyboard + focus to a window which you select by clicking with + button 2. Focus can only be given to + windows on the current desk. + +1.21h to 1.21k + 1. Made FvwmPager understand initial stacking order + 2. made windows stay on desk when de-iconifying. +1.21g to 1.21h + 1. Added the built-in WindowsDesk to move a window to + another desk, without having to go through + the stick-changedesks-unstick process. Made the + pager module use this option. + 2. Added a man pager for FvwmPager and an FvwmPagerLabel + command. +1.21e to 1.21g + 1. Fixed a focusing bug. Seems to affect motif windows. + 2. Got the new FvwmPager module mostly written. People + can try it out, but there's no man page yet. + It lets you drag windows between desktops, and you can + see all desktops at once. The B&W mode isn't done, and + window-labels don't show up in the pager. Also, + the move-windows-between desktops is clumsy. +1.21e to 1.21f + 1. Make AddToList case sensitive, since re-extracting + info is case sensitive. May have a small effect on + config files. + 2. Modified the re-start procedure so that it was more + reliable for some people. + 3. Started writing a pager module. Its not done, so + don't bother with it yet. + +1.21d to 1.21e + 1. Changed smart-placement grid from 10 pixels to 3 + 2. Changed mapping/unmapping scheme for multi-desktop + operation. I had noticed a problem, triggered as + follows. + 1. Set StartOnDesk Maker 2 + 2. Start Frame-maker 4.0 + 3. Wait for startup screen. + 4. immediately change desks. + 5. Wait for the top-level buttons for framemaker to + show up. + 6. While fvwm switches back to the frame-maker desk, trying + to map the frame-maker buttons, the initialization + screen tries to unmap itself. + 7. fvwm got confused, and left an undecorated init + screen displayed, which frame-maker thought was unmapped. + Solution: when changing desks, only unmap the parent, not + the window itself. This means that windows don't know + they were removed from the screen. + 3. Changed time stamp for XSetInputFocus from CurrentTime to + lastEventTime, to be more ICCCM compliant. + + +1.21c to 1.21d + 1. Added MWMHintOverride. + I suppose this should open a dialog box to confirm the + override before actually proceding. Maybe some day.... + +1.21b to 1.21c + 1. Fixed the problem of sending 2 de-iconify messages to + modules. + 2. Added FvwmSound in the optional directory. + 3. Got smart about m4 pre-processing and modules. The m4-processed + .fvwmrc file is saved in /tmp for use by modules. + Modules are passed the name of the pre-processed file + (/tmp/fvwmrcXXXXX) to read. File is delete on exit from fvwm. + 4. Fixed a border-width error in smart-placement. + +1.21 to 1.21b + 1. Fixed bitmap handling in revised GoodStuff module. + (Used to fail with BadMatch). + 2. Changed a few instances of FvwmInitBanner to FvwmBanner. + + +1.20z to 1.21 + 1. Finished conversion to 14 or less character file names. + Unfortunately, module names are changed: + FvmInitBanner ->FvwmBanner + FvwmNoClutter ->FvwmClutter + FvwmModuleDebugger ->FvwmDebug + FvwmIdentify -> FvwmIdent + FvwmSaveDesktop -> FvwmSave + For existing sites with >14 character file names, + these changes could be addressed with a handful of + links in the /usr/lib/X11/fvwm directory, if desired. + + 2. Tidied up a little code in fvwm itself, created + colormaps.c to handle colormap switching code, moved + Iconify and DeIconify into icons.c, and move all window-placement + code into placement.c + +1.20y to 1.20z + 1. Fixed icon-desktop selection. Particularly affected + restarts with icons on desks other than the + current desk. + 2. Started shortening files names that are more than 14 + characters. I only did the easy stuff so far. + 3. Ammended Module calling sequence to pass one user-specified + command line argument. + + This argument is the entire + body of the Module command line in the .fvwmrc file, + after the actual name of the module. It may contain + spaces, qoutes, whatever. For example, in: + Module "FvwmIdentify" FvwmIdentify Hello rob! -fg purple + the argument would be "Hello rob! -fg purple" all passed in + argv[6]. Of course, no modules use this option yet. + +1.20w to 1.20y + 1. Fixed qouting problem in FvwmSaveDesktop. + 2. Fixed one really stupid bug, and made improvements in + GoodStuff to reduce re-draw frequency. Should be much + better now. + 3. Added the PagingDefault patches. + +1.20v to 1.20w + 1. Fixed seg fault on second-level pop-ups, as reported in the + mail channel + 2. Fixed colormap handling, at least enough to run + toolchest on SGI's + +1.20u to 1.20v + 1. Improved complex functions a bit: + a. Can now have + Function "Move-or-Raise" + Raise "Motion" + Move "Motion" + Raise "Click" + RaiseLower "DoubleClick" + EndFunction + which used to fail unless the move was done first. + b. Now detect motion by a pointer movement of + 5 pixels or greater, or by expiration of + click-time, whichever occurs first. Delays waiting + to decide on whether an event is a click or motion should + be minimized. + c. Can now bind complex functions to the root window, + AS LONG AS NO BUILT-IN IN THE FUNCTION REQUIRES A + TARGET WINDOW. This will typically be used to create + menus that stay up after a click: + Function "StickyMenu" + PopUp "Motion" MyMenu + PopUp "Click" MyMenu + EndFunction + or to overload a mouse button: + Function "Overload" + PopUp "Motion" Menu1 + PopUp "Click" Menu2 + WindowLost "DoubleClick" + EndFunction + this should provide a superior user interface for people + with only one or two mouse buttons (mostly macintosh and + PC people, I guess). + 2. Made the pager update during moves and resizes only after the window + in the pager moves 2 or more pixels. This should improve interactive + response. GoodStuff needs some big-time clean up for opaque + move users, though. + + +1.20s to 1.20u + 1. Added some extra support for keeping transients on the same + desk as their parents, and for keeping window groups together. + 2. Added a minor correction. If a transient was unmapped because + its parent was iconified, the pager was not getting updated + correctly +1.20p to 1.20s + 1. Added support for interpreting the mwm-hints functions field + not all done yet. + 2. Added MWMFunctionHints + 3. Added resize-on-window-placement, remove now uneeded FvwmResizeModule + Resize is triggered twm style (pressing button 2) if MWMMenus + is not selected. Triggering is mwm style (shift-button 1) if + MWMMenus is selected. + 4. Added StartsOnDesk, and patches to remember desktop + number of windows through re-starts. (Thanks to + Mr. Miyamae miya@pen214.prod.cpg.sony.co.jp) + 5. Improved reliability of FetchWMProtocols, which is used + to scan for WM_DELETE_WINDOW and WM_TAKES_FOCUS + 6. Made Add_window switch to desktop of new window before + popping up the outline. + 7. Fixed operation for Sun's Wabi, running on a solaris 2 + machine, display on a xterm, fvwm running on SunOS4.1.3. + + Problems included focusing and colormap obnoxiousness by fvwm. + + Looks good now, only tried wabi itself, since I don't have + any windows apps to try out. + +1.20f to 1.20p + 1. Added some window placement corrections + 2. A few tweaks for move and resize operations. I think they're a + little smoother now. + 3. Made Icon placement for sticky icons always on the current + page. Otherwise, you can't ever see them. + 4. Made Focus policy ICCCM compliant, I think. No longer + assigns focus to windows that don't accept focus, like + xload (NoInput model). + Openwindows cm (calander manager), which uses the Globally + Active model, still works OK. + 5. Added configuration option XORvalue for users of 24 bit color + machines. + 6. Added MWMDecorHints to the configuration options. Use + NoBoundaryWidth 4 for best results. Shading of narrow-but-still + there frames needs some work! + 7. Fixed up border drawing in a few spots to allow for the new + mwm hints stuff. Still needs a little work for MWMBorders. + 8. Replaced system(action) with an execl() as suggested by + (lubkin@cs.rochester.edu). + 9. Fixed error from #4 above, where an application (Frame-maker + dialog boxes) didn't ever get the input focus because they + did set wmhints but did not set the input field. + 10. Really radical colormap handling changes. Maybe this will bring fvwm + into conformance with the icccm. + +1.20 to 1.20f + 1. Fixed a bug in the modules, where fvwm would hang trying to + write to a module whose write buffer was full. Also, a + few very minor other patches were made. + 2. Fixed a bug in strcasecmp. + 3. Added a missing KeepOnTop() to the FocusOn routine, which + is used by circulate up/down and warp. + 4. Cleaned up a top-level makefile, added script MakeMyMakefiles + since my version of Imake seems to be broken. Removed MakeMe + and InstallMe. Removed all -Wall flags for subdirectory + Imakefiles. Now specify compiler and flags in the top + level Imakefile. + 5. Made safemalloc in all units handle specified lengths of + 0. It gets called this way when reading an EndWindowList + packet from fvwm. + 6. Improved detection of mouse-on-edge-of-screen, by + Hermann Dunkel, HEDU, dunkel@cul-ipn.uni-kiel.de + 7. Made DeferExecution sensitive to pressing and releasing + the mouse buttons in different windows. + 8. Cleaned up window-move and resize code. Maybe more + responsive now. + 9. Finally fixed menu-exposure problem with pager and GoodStuff. + 10.Fixed(?) placement for windows with border width != 1. + May help fvwm pass tcl/tk window manager tests. + 11.Fixed error in which InstallWindowColormaps was accessing freed + memory sometimes. + 12.Fixed border color problem stimulated as follows + 1. Iconify + 2. Stick + 3. De-Iconify. + 13.Restored ability to change viewports while waiting to select + a window. + 14.Added SAVE_UNDER_EVERYTHING, a compile time option to trade + extra memory for increased re-draw speed when moving/raising/ + lowering windows. Also added USE_BACKING_STORE and + USE_BACKING_STORE_FOR_APPS_TOO. + 15. Oops. number 11 above caused a core dump. Fixed it. +1.18d to 1.20 + 1. Added -DSTUBBORN_ICONS + 2. Remove -DCENTER_SIZEWIN, made it toggle with MWMMenus + 3. Eliminated use of Makefile, always use Imake now, + edit configuration.h in this directory, instead of + separate Imakefiles. Create top level script MakeMe + to do the build. See README.Install + 4. Fixed a menu bug where a window popping up near the + bottom of the screen immediately pops up a sub-menu, and + the base menu fails to draw itself. + 5. fixed an error in icon auto-placement relating to wide + icons at the screen edge. + 6. Incorporated SAVE_DESKTOP patches. No man page yet. + 7. Twiddled focus control for multi-screen displays a + bit more. + 8. Eliminated the Lost X connection stuff. It was causing + trouble for some people. + 9. Added lots of capacity for modules and fvwm to talk to each + other. + 10. Made Iconify take an optional argument to limit actions to + either iconification or de-iconification. + 11. Fixed a long standing bug regarding positioning of icons + that change their name of bitmap, and are not being + auto-placed. Corrections work for Frame-maker. Haven't + got LEmacs to try. + 12. Fixed lock-up problem with icons that are big and hang + over the edge of the screen. + 13. Fixed problem with killing modules. + 14. Added lots of capability to the module interface. Documented + in subdirectory documentation. Some minor changes need for + existing modules (done). + 15. Modified Send_WindowList function to send all info necessary + for the module to estimate the current fvwm status, + including desktop number, paging status, focus. + 16. Added several command line arguments for modules, so that they + can tell if they are invoked from a window context, etc. + 17. Added a module packet type, so that a module can request + a window list, and then tell when the complete list has been + sent. + 18. Made NoClutter have user-configurable time-outs and actions. + 19. Fixed flaw in GoodStuff. If you linked it to "TermStuff" then + you could pretend that you had a TermStuff module, but + "OtherStuff" wouldn't work because it has a different number + of characters. + 20. Move the XAllowEvents in HandleButtonPress to AFTER + the window was raised. Helps prevent application + pop-up menus from showing up below the application window. + 21. When De-Iconifying, with Center-On-Circulate, in click + to focus mode, we were centering on the de-iconified window, + which was incorrect. All fixed now. + 22. Sub-menus popped up near the bottom of the screen had an + undesireable pointer warp in MWMMenu mode. Fixed. + 23. Mailing List set-up + To subscribe: + + mail to majordomo@shrug.org with the body of the message: + + subscribe fvwm + + That's all there is to it. To send to the list, mail to + fvwm@shrug.org, or to get me direclty mail to + fvwm-request@shrug.org + 24. Added FvwmIdentify module. Removed from unsupported patches. + 25. Ooops - bug in broadcastConfig for fvwm-1.19p, fixed. Seemed + to cause lockups every now and then. + 26. Split MakeMe into MakeMe and InstallMe + 27. Separated the module-tester from NoClutter. Added missing + free's for module packet readers. General module clean-up; + 28. Changed CirculateSkipIcons to a run-time configuration in + .fvwmrc, instead of compile time. Also, StubbornIcons, + StubbornIconPlacement, StubbornPlacement, and OpaqueResize + 29. Fixed another obscure cause of crashes, stimulated as follows + A> Pop up an xcalc + B> Resize it really big. + C> While its redrawing itself (its slow) type q, in the window + D> Move mouse to the title-bar. + E> As soon as the title-bar redraws itself (should happen + before xcalc finishes redrawing), hit middle mouse button, + to bring up menu. + F> xcalc window responds to the "q", by exiting. + G> Window decorations, and popped-up menu are still there + H> Choose "Destroy" from the menu. + I> fvwm crashes. + 30. Slightly faster resizes and moves, due to improved drawing + of size window + 31. Created FvwmSaveDesktop module, removed builtin "Save". + 32. Created FvwmInitBanner module. Silly. + 33. Renamed all modules to Fvwmwhatever, so that I don't + tread on program name-space. Left GoodStuff alone, since + its been available for some time. + 34. Module clean-up. fixed Installatipn directory of modules. +1.16c to 1.18d + 1. Added support for multiple desktops via the DESK built-in. + + BUG: All windows wind up on desk 0 after a re-start. + + Intentional: No support for providing a pager-like view of + other desks. This will be supported in a module later. + + 2. Enhanced the windowList to allow display of + all windows + only windows on the current desktop + only windows on a specified desktop + also, can use the window name or the window's icon name in + the list. + + 3. Fixed the business about raising windows and transients + together. (Accidentally broke it some time ago). + + 4. Decided that some windows are not setting the WM_DELETE_WINDOW + protocol fast enough, so fvwm doesn't know its set. Made + fvwm re-read the window property, to make sure. + Fixed problems with Mailtool not deleting properly. Probably + not the real problem, though. + + 5. Incorportated the m4 patches into the core distribution, using + option -DM4. -DCENTER_SIZEWIN came with it. + 6. Switched to xpm-3.3. No real changes needed, except re-copying + xpm.h and commenting out one prototype that gcc -Wall + -Wstrict-prototypes had problems with. Still compiles for + xpm-3.2, even with the new header file. + 7. Switched m4 method of obtaining the USER name to + the same method that rxvt uses. Was GETENV("USER"); which + is unreliable. Also changed XmuGetHostname to gethostname, + since it eliminates the use of a whole slew of libraries. + 8. A few mwm_like.fvwmrc improvements from bobw@PROCASE.COM + 9. An update SGI_4DWM-like.fvwmrc from tabaer@magnus.acs.ohio-state.edu + 10. Added code to detect cursors moving from one screen to another + on a multiple screen display, so that focus control can be handled + better. Left some debugging printfs in place so I could + get feedback from people about what's going on. + 11. Arranged for fvwm to pass the name of the config + file that it used on to each module, in the command line. + This helps modules select the correct config file (GoodStuff + didn't in earlier releases), and eliminates the definition + FVWMRC, the directory for the system.fvwmrc file, in all + places except the fvwm Makefile + 12. Made GoodStuff accept the Delete Window Protocol. +Version 1.17 skipped altogether. + +1.16b to 1.16c + 1. Fixed Segmentation fault from failing to modify + Scr.Hilite when destroying hilighted window. +1.16 to 1.16b + 1. Fixed a conflict with auto-raise and the GoodStuff module. + +1.15 to 1.16 + 1. Incorporated portability improvements from + Rogers Huw + 2. Icorporated speed improvement for ComplexFunctions fro + Makoto Matsushita + 3. Fixed bitmap color problem for GoodStuff on monochrome screens. + 4. Trimmed down the total number of colors in the icons that + I supply. Should alleviate colormap clogging a bit. + 5. Added NoPPosition for emacs-18 users and others who + tired of windows placing themselves sometimes. + 6. Added NEEDS_SIGCHLD so that people can omit the + SIG_CHLD stuff if needed. + 7. Merge -DMENU_HOTKEYS and -DWINDOWLIST_HOTKEYS into + -DHOTKEYS + 8. Added SmartPlacement, which is even better than the button-bar. + +1.14 to 1.15b + 1. Mostly updated the man pages, etc. + 2. Marked module pipes close-on-exec just after the module + forks, so that other programs don't inherit the pipes. + If other programs inherited the pipes, fvwm couldn't + re-start correctly. + 3. Cleaned up warnings under various compilation flags +1.13 to 1.14 + 1. Yay! Multi-screen mode works CORRECTLY! + changed references to XSync(dpy,Scr.screen) to + XSync(dpy,0). The second argument means throw away + events if its non-zero. No wonder it didn't work. + + Important note: + 1. Re-starts affect each screen sepately. + 2. Quitting requires a quit from each screen. + 3. Multi-screen mode is not normally compiled + in. + 2. Removed references to Scr.d_visual. + 3. Cleaned up some icon creation code. + 4. Finished a good version of GoodStuff. Everyone + should try it. Sorry, no man pages yet. + 5. Included all referenced pixmaps and any bitmaps + which are not part of the X11 distribution, in + the fvwm_icons directory. + +1.12 to 1.13 + 1. Added my ongoing "module" support, and created a + subdirectory "GoodStuff" which contains the beginning + of the first module. To try it out, compile with + fvwm -DMODULES, add *GoodStuff business to + .fvwmrc (look in GoodStuff/sample.fvwmrc). + 2. Added patch to detect loss of server connection. + 3. Added IconPath and PixmapPath upgrades (now works + like regular unix path. + 4. Added TogglePage Command to enable/disable + page toggling + 5. Pruned a few lines of code in Iconify(), unneeded + because of re-parenting + 6. Fixed up Makefile.noImake. + +1.11 to 1.12 + 1. Fixed some bizarre window-positioning problems that occur + during re-starts when either window gravity was not set or + it was set with XSetNormalHints instead of XSetWMNormalHints. + 2. Modified Icon auto-placement to place on the same screen + as the center of the window, not necessarily on the + current screen. + 3. Fixed up some oscillation problems with focus control, + regarding the property DOES_WM_TAKE_FOCUS. Seems to affect + openwin clients mostly + 4. Touch ups for shadow colors on ALPHA machines. + 5. Fixed a source of core dumps during iconification + in click-to-focus mode + 6. Fixed a flaw in the WindowList's paging when trying to + find a window. + 7. Assorted fixes to focus handling and flickering borders. + 8. Incorporated patches for mxterm solid/hollow cursor probs. + 9. Made MWM-style menus pop up with the upper left of the menu on + the mouse. + 10. Fixed 1-pixel over the edge problem with maximize and edge + resistance. + 11. Made multi-screen support a compile time option. Made fvwm + pass the -s command line option when restarting in multi + screen mode. +1.10 to 1.11 + 1. Fixed the stupid 1 pixel offset that I always have for shaped + no title windows. + +1.09 to 1.10 + 1. Fixed up some focus handling a bit. Probably, some clients shifted + the input focus to their children, confusing fvwm. + 2. If MWMButtons is enabled, fvwm omits the right side buttons + for transient windows, like mwm. + 3. Updated the system.fvwmrc and mwm_like.fvwmrc files. + 4. Added an Immediate option to complex functions. + 5. Added function Warp, like Circulate, but de-iconifies as + it goes. + 6. Improved focus handling for iconification and de-iconification. + 7. Added StickyForeColor and StickyBackColor for sticky windows, + if compiled with -DMORE_COLORS + 8. Added IconPath and PixmapPath to make config files simpler + +1.07 to 1.09 + 1. Changed Scr.Focus to Scr.Hilite + ungrabbed to Scr.Focus + previous_focus to Scr.Previous focus. + All fallout from the Lucid emacs focusing nonsense. + 2. Added prototypes to allow compilation on SunOS using + -Wall -Wstrict-prototypes with GCC. For Linux, + -Wall -Wstrict-prototypes has never been a problem. + 3. Fixed it so that icons could get the focus once again + (broke during the Lucid emacs work). + 4. Fixed circulateup/down again. (Still more fall out + from lucid emacs). + 5. Fiddled with focus and colormap control when paging, + esp for keyboard-induced paging. Removed all use + of colormapNotify, since it seemed to be unneeded. + 6. Incorporated assorted motif-like patches + 7. Added visual button press info for all windows, + unless -DMOTIF is used, in which case, only title-bar + windows are done. + 8. Implemented somewhat more conventional sub-menus, + left justified all menus, except for titles. Added + NoBoundaryWidth for decoration width on undecorated + windows. + 9. Changed all #ifdef MOTIF's to if(Scr.flags & MWM....) + There are 3 options for the .fvwmrc: + MWMborders + MWMbuttons + MWMMenus. + 10. Fixed error in handling of RaiseLower when window is + partially obscured by a StaysOnTop Window. +1.06 to 1.07 + 1. Changed several instances of strncasecmp to strcasecmp to + improve handling of menu binding for people who like + to have several menus with similar names. + 2. Fixed (?) problems with windows moving during re-starts. + (caused by mods to restorewidthdrawnlocation which were + supposed to help with disappearing dialog boxes) + 3. did a few mods regarding placement of windows on de-iconification + (try to de-iconify onto the current screen). + 4. Fixed ComplexFunctions so that they work correctly when + called from a root window menu. + 5. Added a patch from mark@ofps.ucar.edu (Mark Bradford) + to correctly handle bindings to keysyms that have multiple + physical keys. + 6. Fixed CenterOnCirculate. This ought to cause serious + grief for the unsupported_patches, since it changes the + definitions for Scr.flags. + 7. Fixed up operation for actively following the real input + focus (Lucid Emacs). Now, the highlighted window should be + the one that really has the input focus, not the + window that fvwm thinks should have the focus. This is achieved by + having EnterNotify and LeaveNotify (or ButtonPress for click to + focus) call setFocus only. When a FocusIn or FocusOut is received, + fvwm updates the border color. The variable ungrabbed tells which + window fvwm last sent the input focus to. The variable + Scr.Focus tells which window is currently high-lighted. + +From 1.05 to 1.06 + 1. Fixed up detection of iconified windows on re-starts. Should + lead to ability to re-start without loosing iconic state. Allows + re-starts from mwm without loosing iconified windows. + 2. Fixed up so fvwm respects iconic state accross re-starts. + Restarts to and from mwm and olwm respect this too. Twm fails to + respect the new stuff, but windows don't get lost, so it should be + OK. + (All this because I kept loosing my clock when re-starting into + fvwm from mwm). + 3. Fixed a minor error in button3 handling around the pager + decorations. + 4. In click to focus mode, corrected window-focus stack on window + iconfication. + 5. Added correction for unmapping dialog boxes. May help with + problems of disappearing dialog boxes. + 6. Corrected flaw in Sticking and Unsticking windows failing + to make the window show up/disappear in the pager. + 7. Corrected a problem where deleting (not destroying) a + window caused the next key-binding action to be executed twice + IF the pointer wound up in the root window after the + destroy. (Wow, weird). + 8. Made Icon placement respect application supplied icon placement + hints + 9. Once the icon is moved, fvwm will no longer auto-place it. + +From 1.04 to 1.05 + 1. Fixed a minor flag in SetMapStateProp +From 1.03 to 1.04 + 1. Eliminated the appearance of a (NL) character preceding + the 2nd column menu entries. + 2. Made title-bar and title-bar-button popups line up neatly under + their buttons. A nice little touch. + 3. Whacked up the mwm-like.fvwmrc to use the new -DHOT_KEYS + 4. Fixed problem with de-iconifying pager causing warping. + 5. Added code to raise all of a windows transients with + the window itself. + 6. Fixed (?) a problem with border color errors on windows + that unmap themselves and re-map quickly + 7. Made default for menu popups to request save_unders. + Quicker re-draws after a popup. Added a compile + time option to get rid of it. + 8. Compiled with -Wall and -Wstrict-prototypes again, and fixed a + few minor errors. Removed all references to Xos.h, since it + seems to be unneeded. +From 1.02 to 1.03 + 1. #ifdef'd out this: + If a window is moved using pager and meets opaque + move criteria, move the window itself in real-time too. + since it caused problems for some people. + 2. Fixed the move-window indicator to display 12 characters, which + was needed to indicate +1024 +1024. + 3. Integrated patches for menu hotkeys and motif-like appearance + right into the main source, since these are neatly #ifdef'd + Left the default configuration as it was. Flags can be set + in the makefile +From 1.01 to 1.02 + 1. Fixed up pager code a bit. + Leave grid lines on during a button3 drag in pager. + If a window is moved using pager and meets opaque + move criteria, move the window itself in real-time too. + +From 1.0 to 1.01 + 1. Fixed some border-drawingf details for tiny windows. + 2. Fixed a possible crash condition during startup in + MoveResizeViewportIndicator + 3. Fixed a minor boo-boo in click to focus handling + when mouse activities are bound to window events. + +To Do List (Sorted by # of requests): + Nothing + + +From 0.99 to 1.0 + 1. Fixed the problem with grid lines not showing unless + a pager font was used. + 2. Removed flags |= VISIBLE from RaiseWindow in pager.c + It prevented correct auto-raise operation. + 3. Fixed the pager window title color problems. + 4. Added a move-window location indicator similar + to the one for resizing from Henrique Martins + + 5. fixed the window-resize wrap around problem. + 6. Added code to move pager representation of windows as + the real window moves/resizes. + 7. Changed XCopyPlane for drawing icon pixmaps + to xcopy area, so that apps can pass color pixmaps + to fvwm. Beat up on icon pixmap drawing to let it + handle application supplied color icon pixmaps + and shaped icon pixmaps. + 8. For cases when NumberOfScreens > 1, added a query + to check for current screen prior to setting keyboard + focus. Should fix problems of mysteriously loosing + focus. Problems of not re-drawing decorations on expose + events for screens other than 0 remain. + 9. In order to get both matlab and xv to stop walking their + windows around when the re-configure themselves, I had + to re-parent application windows inside a parent that + is exactly the same size as the app window. While I was in + there, made fvwm re-parent undecorated windows, since this + simplifies some things. Also, can now have seperate cursors + for the four corners, which is ofter requested. (Why do + matlab and xv have to be too smart for their own good?) + 10.Tidied up above code, now let AddWindow() drop the decorations + any old place, then let SetupFrame clean up the mess. + 11.Middle-clicking on a window in the pager no longer moves + the pager image of the window. + 12.Changed to DrawImageString for pager labels, so that they are + readable in monochrome. + 13.Tried to improve icon autoplacement for icons that + are too wide or tall for the icon box. + +From 0.985 to 0.99 + + 1. Took a whack at multi-screen support. + Had to explicitly draw menus when they pop-up. They + didn't seem to get expose events properly. + 2. Repaired the default-icon support. + 3. Got xpaint dialog boxes to work. I was doing an + XMapSubWindows() which caused xpaint's watch- + window bizareness to break if the window was + not re-parented! (All subwindows of the + main application window got mapped). + 4. Re-worked the pager for efficiency & improved + appearance. Added PagerForeColor + 5. Made LookInList case sensitive again. + 6. Incorporated OpaqueMove and EdgeScroll Improvements + from Henrique Martins + 7. Added OpaqueMove to the default setup, with a + percentage above which rubber-bands are used again. + +To Do List (Sorted by # of requests): + +(Don't construe this as an indication that these will eventually + be done. This is just a list to help me remember what requests have + been made) + + Done Job + + optional no icon labels + unlikely Seperate Icon & Menu Colors + impossible? Be able to fake mouse button presses for applications + partly Function correctly on multi-screen displays + x Improve Icon Auto-placement + x Impove pager drawing speed + + +From 0.98 to 0.985 + 1. Fixed some typos in fvwm.1 + 2. Fixed a clicktofocus test (typo) in + functions.c, FocusOn(); + 3. Fixed Foreground color usage in decorations. + 4. Fixed placement of application supplied windows. + 5. Patched up mwm_like.fvwmrc, so that it would delete + windows if you double click on button 1. + 6. Added code to grab buttons and keys in icon windows, + just in case. + 7. Removed some WM_STATE setting for parent and icon windows. + caused editres to break. + 8. changed + struct _gravity_offset + { + int x, y; + }; + in add_window.c back to an int structure for RS/6000 users + who had problems when it was char x,y; + 9. Added a little functionality to CirculateUp/Down + 10.Added user-selectable config file. + 11.In GrabEm, Changed PointerGrab mode from false to true. + 12.Fiddled AutoPlace so that if an Icon is going to wind up + partly off the screen, it moves it back on. Now, if you + specify an iconbox thats ot tall enough, along the bottom + of the screen, Icons end up lined up neatly. + 13.Fixed an unsigned/regular int problem in pager code which + caused windows to "wrap around" if you moved them partly + of the pager window. + 14.Improved EdgeResistance scrolling code so that it + makes sure that the mouse stayed in the scroll region of + the screen for the entire delay period. (It used to just + check the start and stop points. + 15.Removed lots of XGetGeometry and XSync calls to try + to speed things up. Suppressed error messages relating to + input focus and Colormap installation along the way. + 16.Merged all name_lists into a single list with a flag + to tell what attributes are set. Saves memory in the list + and allows for expansion. + 17.Fixed a few missing pixels in mono mode for menus and title-bar. + 18.Major overhaul of borders.c, add_window.c, including touches to + other modules, under the guise of speed enhancement. + 19.Added option for WindowListSkip. + 20.Added compile time option to skip iconified windows when + circulating. + +To Do List (Sorted by # of requests): + +(Don't construe this as an indication that these will eventually + be done. This is just a list to help me remember what requests have + been made) + + Done Job + + x opaque move (compile time) + + optional no icon labels + + unlikely Seperate Icon & Menu Colors + + impossible? Be able to fake mouse button presses for applications + + mostly Clean up border drawing code to improve speed + + x editres is broken now. + + x if you move a window over the top of the + pager, it jumps to the bottom of the desktop. + + x No good way of lining up icons (neatly along the + bottom of the screen. + + x User selectable startup file + Add Weird and obscure options + + x Add option to leave entries out of the window list + + x Option to circulate skip over icons (compile time) + +From 0.975 to 0.98 + 1. Improved handling of Icons that change their + pixmaps. They no longer switch positions, and if + they go from no pixmap to having a pixmap, that + is detected and handled. + 2. Fixed Circulate Up/Down to handle SuppressIcons + and shaped windows. + 3. Improved AutoRaise handling when used in conjunction + with application pop-up windows. + 4. Fixed bug where all 10 title-bar buttons show up if you bind + something to "A" (all contexts) + 5. Fixed problem of clicking button 2 in the pager causing windows to + shuffle around a bit. + 6. Fixed problem where moving an icon in the pager window caused only + the label to move. + 7. Added code to unmap icons supplied by application windows during + re-starts. + 8. Added code to check for window existence prior to setting the + input focus to that window. Eliminates some internal errors. + 9. When using application-supplied icon windows, added code to + reparent the icon window to the root window, because olwais + (and maybe others) make the icon windows children of the application + window. + 10.Stopped clearing the icon pixmap window since its not needed and + causes flickering. + 11.Compiled with -Wall -Wstrict-prototypes and cleaned up a lot + of the warnings. Suns don't seem to have prototypes for a lot + of standard functions like fprintf, so I can't leave these in. + Some items of siginificance were found and correct, must was of + no real concern. + 12.Ran Purify on fvwm, found a few items of no real significance. + 13.Remove the check for pointer motion from HandleMotionNotify, + since that kept us from scrolling in deferExecution. Consolidate + all EdgeScrolling by pointer motion code into one routine in + the pager, HandlePaging + 14.Added StickyIcons. + 15.Changed all Bool type flags in the Scr structure to flags in an + unsigned int. Should allow easier expansion in the future. + 16.Added IconBoxes (up to 4). Removed keyword AutoPlaceIcons, since + an IconBox line implies this. + 17.Fixed up code for title-bar buttons, so that they never draw over + the frame corners. Also fixed the way left side buttons are + drawn for shaped windows, and the way the title-bar, top and + bottom side bars are drawn for really teeny windows. + 18.Added code to optionally label the windows in the pager + with a really teeny font. + 19.Added a call to WaitForButtonsUp() at the end of addWindow(), since + it seemed to be possible to loose the input focus by moving the + cursor really fast after adding a window. + 20.Added IconFont (optional) for icon labels. To do this, + changed the PagerGC to FontGC, whose sole purpose in life + is to host miscellaneous fonts. Defined a macro in misc.h + to switch the font for FontGC. + 21.Switch from using XShapeCombineShape to XShapeCombineRectangles + to make shaped window title-bars. Does it all in one call, + much faster. Also move Shape setting code to its own subroutine + for ShapeNotify events. Moved SetupFrame to borders.c + 22.Fixed problem where windows partly off the top or left of the + desktop didn't show up in the pager. + 23.Made the window list use the middle of the window as a test + of on/off screen/desktop, instead of all sorts of bizarre + quantities. + 24.Consolidated a few config.c subroutines while adding EdgeResistance. + 25.General clean up in events.c, borders.c, functions.c +To Do List (Sorted by # of requests: + Done Job + x IconBoxes (for autoplacement) + x PagerLabelFont + Seperate Icon & Menu Colors + x EdgeResistance + x IconFont + x Sticky Icons + Be able to fake mouse button presses for applications + partial Clean up border drawing code to improve speed + x Clean up shaped window handling in SetupFrame, to + improve speed. + +From 0.97 to 0.975 + 1. Changed getdtablesize() to sysconf() in events.c + (getdtablesize doesn't exist in HP/UX. + 2. Added a ConstrainSize call to the Maximize routine + in functions.c (thanks to Pete Bevin ). + 3. Fixed misc bugs in AutoRaise and WindowList + 4. Allowed ^N, ^P, ^f, ^b shortcuts in addition to arrow keys + + +From 0.96 to 0.97 + 1. Fixed the problem of not being able to correctly bind + a function key to a decoration point such as the title-bar. + This involved moving the XGrabKey() grabs from the + decorations/windows to the frame, and then fixing up + GetContext to recognize the subwindow field of the xkey + events. + 2. Fixed the Fvwm Internal Errors found when de-iconifying windows + These were caused by doing a deferExecution on an icon window + and trying to unset the keyboard focus before grabbing the + keyboard, andthen restoring it later. The error was in trying to + restore the focus to the application window instead of the icon + Create functions GrabEm and UngrabEm to handle moving the + keyboard focus, grabbing the pointer and keyboard, and then + ungrabbing/re-focusing later. + 3. In HandleEnterNotify, decided to detect entering the root window, + because we sometimes can leave a window without it being + detected by HandleEnterNotify. This was related to pop-up + menus in window title-bars. + 4. Fixed a small error in add_window() which caused completely + undecorated windows to be made one pixel taller than they should be. + 5. Moved click to focus code in HandleButtonPress() to + the very start of the routine, since it would lock up + the WM when pressing button 2 in a window otherwise. + 6. Swapped order of UngrabEm and XUnmapWIndow in PopDownMenu() + so that focus is not lost when using keyboard shortcut menus + , for example, in a window. + 7. Added a DefaultIcon enable by adding a line + Icon "" my-favorite-bitmap-or-pixmap. + 8. Bottom and Right sides of shaped titled windows were + colored with the border shadow color. Fixed it. + 9. Added user selectable title bar button decoration shapes. + 10. Added an AnyModifier modifier type, and an AnyButton button type. + 11. With RandomPlacement, we didn't GrabServer before adding a new + window so it was possible to get an decoration with no + window. Fixed this. Also made GrabEm() fail after 1 second, + and provided appropriate handling for all routines that + call it. Thus if we need to grab the pointer, and fail after + 1 second, then we give up. + 12. Added a WaitForButtonsUp() routine which hangs around until all + mouse buttons are up, then double checks on window focus + (for point-to-focus mode). This is called on termination of + any menu for function execution. + 13. Added a WindowList function like TwmWindows. Required some + menu-drawing upgrades. + 14. Added a SuppressIcons to use in conjunction with the WindowList + for people who like icon-managers. + 15. Gave Maximize some optional arguments to control which directions + are maximized. + 16. Utilize the WindowList mods to menus to provide 2-column + menu entries (For shortcut labelling). This also provides for + left adjusted menus. + 17. Made the restart do a conventional restart if the restart + into another program failed. + 18. Added a CursorMove function to aid in mouseless use. + 19. Changed icon windows to two part windows with the label window + seperate from the bitmap window. This improves appearance of + icons when the label size does not match the bitmap size. Also + label window width is now equal to bitmap window width unless the + icon has the input focus. This should improve auto-placement. + 20. Added some input focus queue code for click to focus mode. + 21. Move button grabs in click-to-focus mode to the frame because + otherwise frame-maker crashes sometimes. + 22. Fixed a problem of a failed attempt to bind Alt+button2 + to resize in a window. + 23. Modified use of tolower() in configure.c to be compatible + with some BSD versions. + 24. Cleaned up the shaped window handling a little, because + xlogo -shape came out wrong. + 25. Added the Function built-in. Removed the raise-on-click + behaviour for move and resize builtins too. + 26. Changed zombie handling code to a simple + signal(SIGCHLD,SIG_IGN). Seems to work. Old method + caused problems for HP-UX. + 27. Added AutoRaise with user selectable delay. + +Bugs: +Should re-parent undecorated windows because of the button/key grabbing +problems + +**************************************************************************** + +From 0.95 to 0.96 + 1. Changed #ifdef SYSV to #ifdef POSIX for ReapChildren + 2. Divided the NoTitle option into separate + NoTitle and NoBorder options. This eliminated + a lot of the #ifdef SHAPE sections and cleaned up + code a little. + 3. Took another whack at getting windows to stay put + through the re-start command. This time, I tried doing + it by measuring window placement before re-parenting + and after, to get the delta + 4. Took a patch from davem@extro.ucc.su.OZ.AU to + make color XPM icons into shaped icons if + both SHAPE and COLOR are specified in the makefile. + Diffs were pretty much limited to icons.c. + 5. Allowed icon windows to take input focus so that + keyboard key binds would work in icon windows. Involved + minor changes in events.c and borders.c + 6. Attempted to switch from using if(tmp_win->title_w) + and if(tmp_win->title_height) to using just + if(tmp_win->flags & TITLE). Required for splitting + the NoTitle option into NoTitle and NoBorder. + 7. Fixed a small bug with icon AutoPlacement, reported long + ago but just identified. AutoPlacement wanted five pixels + space on all sides of the icon EVEN IF IT WAS ON THE NEXT + PAGE. Oops. Should be fixed. + 8. Replaced usleep() call with a subroutine that should be + OK for more systems, using select(). Thanks to krumnow@sap-ag.de + 9. Fixed a problem with fvwm reporting stray mouse-button releases + to applications. This was caused by de-iconifying on a + button press in the icon window. If the window appears under + the icon, it receives the release event. Caused xmeter to croak. + 10. Fixed a problem where you could move a window over a page + boundary, release the mouse button, move the mouse really + fast, and the window would show up in the wrong place. + Change was limited to move.c. Added an extra XQueryPointer() + call. + 11. Move the ExececuteFunction() call from menus.c to functions.c + where it really belonged. Along the way, caused the pointer to + warp back to its pre-menu popup location when a resize operation + is invoker. The move operation has always worked this way. + 12. Fixed an error in parsing Key bindings for Restart and + Exec functions. + 13. Re-wrote the pager so that you could move windows using it, + and could select the focus in click-to-focus mode. + 14. Added a Maximize function. + 15. Added a user-selectable number of title-bar buttons. + 16. When trying to grab the pointer for whatever reason, + added a 1 msec delay between events, and give up after + 1 second. If some other window has a grab on the pointer, + we don't want to lock up the whole system just + because we want the pointer. + +0.96 Known Unresolved bugs: +1. Keyboard keys can't be bound to actions in the window decorations. + +2. Fvwm crashes occasionally? One report, involving Ftptool 4.5, + could not be re-created by me. + diff --git a/Cleanme b/Cleanme new file mode 100755 index 0000000..c864095 --- /dev/null +++ b/Cleanme @@ -0,0 +1,46 @@ +#!/bin/sh +rm modules/FvwmAudio/FvwmAudio +rm modules/FvwmBacker/FvwmBacker +rm modules/FvwmBanner/FvwmBanner +rm modules/FvwmClean/FvwmClean +rm modules/FvwmDebug/FvwmDebug +rm modules/FvwmIconBox/FvwmIconBox +rm modules/FvwmIdent/FvwmIdent +rm modules/FvwmPager/FvwmPager +rm modules/FvwmSave/FvwmSave +rm modules/FvwmSaveDesk/FvwmSaveDesk +rm modules/FvwmScroll/FvwmScroll +rm modules/FvwmWinList/FvwmWinList +rm modules/FvwmAuto/FvwmAuto +rm modules/GoodStuff/GoodStuff +rm fvwm/fvwm +rm xpmroot/xpmroot +rm libs/*.a +rm -f *.o +rm -f *~ +rm -f *.bak +rm -f *.orig +rm -f *.rej +rm -f Makefile +rm -f core +rm -f #*# +rm -f */*.o +rm -f */*~ +rm -f */*.bak +rm -f */*.orig +rm -f */*.rej +rm -f */Makefile +rm -f */core +rm -f */#*# +rm -f */*/*.o +rm -f */*/*~ +rm -f */*/*.bak +rm -f */*/*.orig +rm -f */*/*.rej +rm -f */*/Makefile +rm -f */*/core +rm -f */*/#*# + + + + diff --git a/Imakefile b/Imakefile new file mode 100644 index 0000000..3882dfe --- /dev/null +++ b/Imakefile @@ -0,0 +1,45 @@ +/* Imakefile for fvwm-1.20 and later. 1/31/94. */ +/* Procedure is xmkmf; make Makefiles; make all */ +/* make install; make install.man */ + +/* I need to get the #define XPM from configuration.h if its in there, */ +/* so that I can tell if I should include -lXpm */ +#include + +#define IHaveSubdirs + +/* Can define CDEBUGFLAGS to anything you need */ +/*CDEBUGFLAGS = -LMyLibrarydir*/ + +ALLSUBDIRS = libs \ + fvwm \ + modules/GoodStuff \ + modules/FvwmIdent \ + modules/FvwmDebug \ + modules/FvwmBacker \ + modules/FvwmClean \ + modules/FvwmPager \ + modules/FvwmAudio \ + modules/FvwmScroll \ + modules/FvwmIconBox \ + modules/FvwmSave \ + modules/FvwmSaveDesk \ + modules/FvwmAuto \ + modules/FvwmWinList + +#ifdef XPM +XPMSUBDIRS = xpmroot modules/FvwmBanner +#endif + +SUBDIRS = $(ALLSUBDIRS) $(XPMSUBDIRS) $(SHAPESUBDIRS) +/* I have absolutely no idea what this does, but it seems to be needed */ +#define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)' + +MakeSubdirs($(SUBDIRS)) + +/* Doesn't work for me! */ +/* #DependSubdirs($(SUBDIRS))*/ + + + + diff --git a/MakeMakefiles b/MakeMakefiles new file mode 100755 index 0000000..6de709c --- /dev/null +++ b/MakeMakefiles @@ -0,0 +1,20 @@ +#!/bin/sh +# +# Replaces the commands xmkmf; make Makefiles for my broken setup. +# + +echo Making top-level Makefile +xmkmf +echo done + +TOPDIR=`pwd` +echo TOPDIR is $TOPDIR + +for i in libs fvwm xpmroot modules/* +do +echo Making Makefile in $i +cd $i ; xmkmf ; cd $TOPDIR +echo done +done + + diff --git a/README.Install b/README.Install new file mode 100644 index 0000000..a8ccc1a --- /dev/null +++ b/README.Install @@ -0,0 +1,55 @@ + +This is release 1.something of fvwm. + +fvwm is a relatively small window manager which provides a 3-D look for window +decorations and a virtual desktop. It is reconfigurable in a manner +similar to twm. Most of the Twm functionality has been maintained, with +some new features added. + +I would like to know about any bugs that you find. + +In this release, there are many optional configuration items. +Edit configure.h in this directory. Look in the file OS_specifics for settings +that may be required to satisfy your operating system. + +Edit the Imakefile in this directory if needed. + +You should not need to modify the individual Imakefiles much. +X11R4 users will want to edit fvwm/Imakefile and change + InstallNonExecFile to InstallNonExec + +Untar the fvwm-modules.tar file in this directory. If someone would like to +clean up the build procedure, please do. + +Untar the fvwm-icons.tar file in this directory. If someone would like to +clean up the build procedure, please do. + +execute the following commands + + xmkmf + make Makefiles + (If this command fails or ends in an endless loop, + use the shell script MakeMakefiles). + make all +Monitor the output of the above commands for error messages. + +(It is likely that you will need root privilege to write to the +installation directories. If so, become root now) + make install + make install.man +Copy fvwm_icons/*.xpm to /usr/include/X11/pixmaps if you want to. +Copy fvwm_icons/*.xbm to /usr/include/X11/bitmaps if you want to. +Copy fvwm_icons/*.bitmap to /usr/include/X11/bitmaps if you want to. +Copy fvwm_icons/*.icon to /usr/include/X11/bitmaps if you want to. + + +When that's done, you can look at the optional modules in the +optional directory. These will need to be built one by one. These +modules are the ones which I believe may depend on the existence of +software packages or hardware components which may not exist for many +systems. + + +Rob Nation + + diff --git a/configure.h b/configure.h new file mode 100644 index 0000000..4825331 --- /dev/null +++ b/configure.h @@ -0,0 +1,205 @@ +#define FVWMDIR "/usr/lib/X11/fvwm" +/* #define FVWMDIR "/local/homes/dsp/nation/modules"*/ +#define FVWM_ICONDIR "/usr/include/X11/bitmaps:/usr/include/X11/pixmaps" +#define FVWMRC "/usr/lib/X11/fvwm/system.fvwmrc" + +/* Imake command needed to put modules in desired target location */ +/* Use the second version if it causes grief */ +#define TARGET_DIR BINDIR=FVWMDIR +/* #define TARGET_DIR*/ + + +/* If you want Imake to leave your binary in the standard place where + * Imake wants to leave binaries, then choose the second line here. + * If you want to install it in a different directory, uncomment and + * edit the first line */ +/* #define FVWM_BIN_DIR BINDIR=/local/homes/dsp/nation/bin/4.1.3*/ +#define FVWM_BIN_DIR BINDIR=/usr/bin/X11 +/*#define FVWM_BIN_DIR*/ + +/* Compiler over-ride for Imakefiles */ +/* Leave it as shown to get your default compiler */ +#define COMPILER CC=gcc +/* #define COMPILER */ + + +/*************************************************************************** + *#define SHAPE + * If you want the Shaped window extensions, specify #define SHAPE + * Shaped window extensions seem to increase the window managers RSS + * by about 60 Kbytes. They provide for leaving a title-bar on the window + * without a border. + * If you dont use shaped window extension, you can either make your shaped + * windows undecorated, or live with a border and backdrop around all + * your shaped windows (oclock, xeyes) + * + * If you normally use a shaped window (xeyes or oclock), you might as + * well compile this extension in, since the memory cost is minimal in + * this case (The shaped window shared libs will be loaded anyway. If you + * don't normally use a shaped window, you have to decide for yourself + ***************************************************************************/ +#define SHAPE + +/*************************************************************************** + *#define XPM + * if you want color icons, specify #define XPM, and get libXpm + * from sunsite.unc.edu. The following files are recommended in addition + * to the fvwm package (from ftp.x.org) + * /pub/R6untarred/contrib/lib/xpm-3.4c + * /pub/X11/contrib/xpm3icons.tar.Z, sample icons + * /pub/X11/contrib/ctwm-3.0.tar.Z, pull out the icons. ctwm has really nice + * color icons. + * and this from ftp.x.org: + * /contrib/icons.tar.gz, lots of sample icons, + * + * For monochrome, Xpm icons still work, but they're only better than regular + * bitmaps because they're shaped (if you specify #define SHAPE). + ***************************************************************************/ +#define XPM +/* linker flags needed to locate and link in the Xpm library, if you use it */ +#define XPMLIBRARY -L/usr/lib/X11 -lXpm + +/*************************************************************************** + *#define M4 + * Causes m4 pre-processor patches to be included. Try man m4 for more info. + * Warning: m4 defines macros for some simple things like "include" + * which might mess up a config like + * IconPath /usr/include/X11/bitmaps, for example, so you + * would need to include + * undefine(`include') to fix that one. Some version of m4 + * seem to give good error messages, others don't? + ***************************************************************************/ +/* #define M4 */ + +/*************************************************************************** + *#define NO_PAGER + * Omits the code for the built-in pager. The pager module FvwmPager + * can be used instead. + ***************************************************************************/ +/* #define NO_PAGER */ + +/*************************************************************************** + *#define NON_VIRTUAL + * Omits the virtual desktop - requires NO_PAGER + ***************************************************************************/ +/* #define NON_VIRTUAL */ + +/*************************************************************************** + *#define NO_SAVEUNDERS + * tells thw WM not to request save unders for pop-up + * menus. A quick test using monochrome X11 shows that save + * unders cost about 4Kbytes RAM, but saves a lot of + * window redraws if you have windows that take a while + * to refresh. For xcolor, I assume the cost is more like + * 4Kbytesx8 = 32kbytes (256 color). + ***************************************************************************/ +/* #define NO_SAVEUNDERS */ + +/*************************************************************************** + *#define NO_WINDOWLIST + * Caused fvwm built-in window-list to be omitted. The window-list + * module FvwmWinList can be used instead + ***************************************************************************/ +/* #define NO_WINDOWLIST */ + +/*************************************************************************** + *#define PRUNE + * Removes old configuration commands: + * BoundaryWidth, NoBoundaryWidth, Sticky, NoTitle, NoBorder, + * StaysOnTop, StartsOnDesk, CirculateSkip, WindowListSkip, Icon, + * SuppressIcons, and Module (when used for initial startup + * These commands were replaced with Style, except for the Module + * command, which is replaced with InitFunction + * + * + ***************************************************************************/ +/* #define PRUNE */ + +/************************************************************************* + * + * Really, no one but me should need this + * + ************************************************************************/ +#if defined __sun__ && !defined SYSV +#define BROKEN_SUN_HEADERS +#endif +/*************************************************************************** + * + * In theory, this stuff can be replaced with GNU Autoconf + * + **************************************************************************/ + +#if defined _POSIX_SOURCE || defined SYSV || defined __sun__ + +#define HAVE_WAITPID 1 +#define HAVE_GETITIMER 1 +#define HAVE_SETITIMER 1 +#define HAVE_SYSCONF 1 +#define HAVE_UNAME 1 +#undef HAVE_GETHOSTNAME + +#else + +/************************************************************************** + * + * Do it yourself here if you don't like the above! + * + **************************************************************************/ +/*************************************************************************** + * Define if you have waitpid. + **************************************************************************/ +#define HAVE_WAITPID 1 +/*************************************************************************** + * Define if you have getitimer/setitimer. + * undefining this will break auto-raise + **************************************************************************/ +#define HAVE_GETITIMER 1 +#define HAVE_SETITIMER 1 + +/*************************************************************************** + * Define if you have sysconf + **************************************************************************/ +#define HAVE_SYSCONF 1 + +/*************************************************************************** + * Define if you have uname. Otherwise, define gethostname + ***************************************************************************/ +#define HAVE_UNAME 1 +/* #define HAVE_GETHOSTNAME 1 */ + +#endif /* End of do-it-yourself OS support section */ + + +/* Please translate the strings into the language which you use for your + * pop-up menus */ +/* Some decisions about where a function is prohibited (based on + * mwm-function-hints) is based on a string comparison between the + * menu item and the strings below */ +#define MOVE_STRING "move" +#define RESIZE_STRING1 "size" +#define RESIZE_STRING2 "resize" +#define MINIMIZE_STRING "minimize" +#define MINIMIZE_STRING2 "iconify" +#define MAXIMIZE_STRING "maximize" +#define CLOSE_STRING1 "close" +#define CLOSE_STRING2 "delete" +#define CLOSE_STRING3 "destroy" +#define CLOSE_STRING4 "quit" + +#ifdef __alpha +#define NEEDS_ALPHA_HEADER +#undef BROKEN_SUN_HEADERS +#endif /* (__alpha) */ + + +/* Allows gcc users to use inline, doesn't cause problems + * for others. */ +#ifndef __GNUC__ +#define FVWM_INLINE /*nothing*/ +#else +#if defined(__GNUC__) && !defined(inline) +#define FVWM_INLINE __inline__ +#else +#define FVWM_INLINE inline +#endif +#endif diff --git a/documentation/WhereToGetIt b/documentation/WhereToGetIt new file mode 100644 index 0000000..67e5306 --- /dev/null +++ b/documentation/WhereToGetIt @@ -0,0 +1,44 @@ +Return-Path: morton!joe@sd.com +Return-Path: +Received: from sd.com (guardian.tessi.com) by rocket (SPCOT.6) + id AA06675; Wed, 30 Mar 94 18:08:00 EST +Received: from guardian.tessi.com by sd.com (4.1/SMI-4.1) + id AA02292; Wed, 30 Mar 94 15:07:52 PST +Received: by morton.rain.com (/\==/\ Smail3.1.25.1 #25.3) + id ; Wed, 30 Mar 94 15:03 PST +Message-Id: +From: joe@morton.rain.com (Joe Moss) +Subject: Re: fvwm versions: I'm confused +Date: Wed, 30 Mar 94 15:03:19 PST +In-Reply-To: <9403292134.AA26150@rocket>; from "Robert Nation" at Mar 29, 94 4:34 pm +X-Mailer: ELM [version 2.3 PL11] + + + +Robert, + + A couple of suggestions: + + 1) Place a file in the fvwm distribution called 'WhereToGet' + which tells people that the latested released version + is on sunsite and that the latest beta version can be + obtained from spcot.sanders.com - I think it would + cut down on a lot of questions + + 2) A good source of icons is the directory 'AIcons' in + the contrib directory of any X archive site, e.g.: + + ftp.x.org: /contrib/AIcons + + this is collection of the best icons taken from many + sources (including the ones you're currently pointing + people to). It also has the advantage of having had + the colors reduced to a standard colormap of 30 or + so colors, so the icons don't use up the entire color + map on a PsuedoColor display + +-- +Joe V. Moss | joe@morton.rain.com +Morton & Associates | joem@m2xenix.psg.com +7478 S.W. Coho Ct. | - or - +Tualatin, OR 97062-9277 | uunet!m2xenix!morton!joe diff --git a/documentation/error_codes b/documentation/error_codes new file mode 100644 index 0000000..2e9b3fb --- /dev/null +++ b/documentation/error_codes @@ -0,0 +1,209 @@ +/********************************************************************** + * + * This file contains the codes needed to descipher an Fvwm Internal + * Error. This list is compiled from pieces of the X include files, + * but is not actually used by the fvwm code. It is included for + * debugging purposes. + *********************************************************************/ + +/************************************************************************* + * Request codes + * From Xproto.h + *************************************************************************/ + +#define X_CreateWindow 1 +#define X_ChangeWindowAttributes 2 +#define X_GetWindowAttributes 3 +#define X_DestroyWindow 4 +#define X_DestroySubwindows 5 +#define X_ChangeSaveSet 6 +#define X_ReparentWindow 7 +#define X_MapWindow 8 +#define X_MapSubwindows 9 +#define X_UnmapWindow 10 +#define X_UnmapSubwindows 11 +#define X_ConfigureWindow 12 +#define X_CirculateWindow 13 +#define X_GetGeometry 14 +#define X_QueryTree 15 +#define X_InternAtom 16 +#define X_GetAtomName 17 +#define X_ChangeProperty 18 +#define X_DeleteProperty 19 +#define X_GetProperty 20 +#define X_ListProperties 21 +#define X_SetSelectionOwner 22 +#define X_GetSelectionOwner 23 +#define X_ConvertSelection 24 +#define X_SendEvent 25 +#define X_GrabPointer 26 +#define X_UngrabPointer 27 +#define X_GrabButton 28 +#define X_UngrabButton 29 +#define X_ChangeActivePointerGrab 30 +#define X_GrabKeyboard 31 +#define X_UngrabKeyboard 32 +#define X_GrabKey 33 +#define X_UngrabKey 34 +#define X_AllowEvents 35 +#define X_GrabServer 36 +#define X_UngrabServer 37 +#define X_QueryPointer 38 +#define X_GetMotionEvents 39 +#define X_TranslateCoords 40 +#define X_WarpPointer 41 +#define X_SetInputFocus 42 +#define X_GetInputFocus 43 +#define X_QueryKeymap 44 +#define X_OpenFont 45 +#define X_CloseFont 46 +#define X_QueryFont 47 +#define X_QueryTextExtents 48 +#define X_ListFonts 49 +#define X_ListFontsWithInfo 50 +#define X_SetFontPath 51 +#define X_GetFontPath 52 +#define X_CreatePixmap 53 +#define X_FreePixmap 54 +#define X_CreateGC 55 +#define X_ChangeGC 56 +#define X_CopyGC 57 +#define X_SetDashes 58 +#define X_SetClipRectangles 59 +#define X_FreeGC 60 +#define X_ClearArea 61 +#define X_CopyArea 62 +#define X_CopyPlane 63 +#define X_PolyPoint 64 +#define X_PolyLine 65 +#define X_PolySegment 66 +#define X_PolyRectangle 67 +#define X_PolyArc 68 +#define X_FillPoly 69 +#define X_PolyFillRectangle 70 +#define X_PolyFillArc 71 +#define X_PutImage 72 +#define X_GetImage 73 +#define X_PolyText8 74 +#define X_PolyText16 75 +#define X_ImageText8 76 +#define X_ImageText16 77 +#define X_CreateColormap 78 +#define X_FreeColormap 79 +#define X_CopyColormapAndFree 80 +#define X_InstallColormap 81 +#define X_UninstallColormap 82 +#define X_ListInstalledColormaps 83 +#define X_AllocColor 84 +#define X_AllocNamedColor 85 +#define X_AllocColorCells 86 +#define X_AllocColorPlanes 87 +#define X_FreeColors 88 +#define X_StoreColors 89 +#define X_StoreNamedColor 90 +#define X_QueryColors 91 +#define X_LookupColor 92 +#define X_CreateCursor 93 +#define X_CreateGlyphCursor 94 +#define X_FreeCursor 95 +#define X_RecolorCursor 96 +#define X_QueryBestSize 97 +#define X_QueryExtension 98 +#define X_ListExtensions 99 +#define X_ChangeKeyboardMapping 100 +#define X_GetKeyboardMapping 101 +#define X_ChangeKeyboardControl 102 +#define X_GetKeyboardControl 103 +#define X_Bell 104 +#define X_ChangePointerControl 105 +#define X_GetPointerControl 106 +#define X_SetScreenSaver 107 +#define X_GetScreenSaver 108 +#define X_ChangeHosts 109 +#define X_ListHosts 110 +#define X_SetAccessControl 111 +#define X_SetCloseDownMode 112 +#define X_KillClient 113 +#define X_RotateProperties 114 +#define X_ForceScreenSaver 115 +#define X_SetPointerMapping 116 +#define X_GetPointerMapping 117 +#define X_SetModifierMapping 118 +#define X_GetModifierMapping 119 +#define X_NoOperation 127 + +/***************************************************************** + * ERROR CODES + * from X.h + *****************************************************************/ + +#define Success 0 /* everything's okay */ +#define BadRequest 1 /* bad request code */ +#define BadValue 2 /* int parameter out of range */ +#define BadWindow 3 /* parameter not a Window */ +#define BadPixmap 4 /* parameter not a Pixmap */ +#define BadAtom 5 /* parameter not an Atom */ +#define BadCursor 6 /* parameter not a Cursor */ +#define BadFont 7 /* parameter not a Font */ +#define BadMatch 8 /* parameter mismatch */ +#define BadDrawable 9 /* parameter not a Pixmap or Window */ +#define BadAccess 10 /* depending on context: + - key/button already grabbed + - attempt to free an illegal + cmap entry + - attempt to store into a read-only + color map entry. + - attempt to modify the access control + list from other than the local host. + */ +#define BadAlloc 11 /* insufficient resources */ +#define BadColor 12 /* no such colormap */ +#define BadGC 13 /* parameter not a GC */ +#define BadIDChoice 14 /* choice not in range or already used */ +#define BadName 15 /* font or color name doesn't exist */ +#define BadLength 16 /* Request length incorrect */ +#define BadImplementation 17 /* server is defective */ + +#define FirstExtensionError 128 +#define LastExtensionError 255 + + +/************************************************************************* + * Event Types + * From X.h + *************************************************************************/ +#define KeyPress 2 +#define KeyRelease 3 +#define ButtonPress 4 +#define ButtonRelease 5 +#define MotionNotify 6 +#define EnterNotify 7 +#define LeaveNotify 8 +#define FocusIn 9 +#define FocusOut 10 +#define KeymapNotify 11 +#define Expose 12 +#define GraphicsExpose 13 +#define NoExpose 14 +#define VisibilityNotify 15 +#define CreateNotify 16 +#define DestroyNotify 17 +#define UnmapNotify 18 +#define MapNotify 19 +#define MapRequest 20 +#define ReparentNotify 21 +#define ConfigureNotify 22 +#define ConfigureRequest 23 +#define GravityNotify 24 +#define ResizeRequest 25 +#define CirculateNotify 26 +#define CirculateRequest 27 +#define PropertyNotify 28 +#define SelectionClear 29 +#define SelectionRequest 30 +#define SelectionNotify 31 +#define ColormapNotify 32 +#define ClientMessage 33 +#define MappingNotify 34 +#define LASTEvent 35 /* must be bigger than any event # */ + diff --git a/documentation/m4_hacks b/documentation/m4_hacks new file mode 100644 index 0000000..27080a0 --- /dev/null +++ b/documentation/m4_hacks @@ -0,0 +1,127 @@ +Return-Path: dale@felix.dircon.co.uk +Return-Path: +Received: from eagle.is.lmsc.lockheed.com by rocket (SPCOT.6) + id AA07582; Wed, 30 Mar 94 21:26:48 EST +Received: from felix.dircon.co.uk by eagle.is.lmsc.lockheed.com (5.65/Ultrix4.3-C) + id AA27884; Wed, 30 Mar 1994 18:24:30 -0800 +Received: from ISOlde.dale.co.uk by tristan.dale.co.uk with smtp + (Linux Smail3.1.28.1 #25) id m0pm2IB-0002kOC; Wed, 30 Mar 94 16:34 BST +Received: by ISOlde.dale.co.uk (Linux Smail3.1.28.1 #25) + id m0pm2IP-000JHaC; Wed, 30 Mar 94 16:35 BST +Message-Id: +Date: Wed, 30 Mar 94 16:35 BST +From: Pete.Chown@dale.dircon.co.uk +Subject: fvwm, copyright infringement, m4, etc... + +I came up with a hack in m4 to get round the problem where you get +substitution for ordinary words, like 'include'. I wanted to +substitute a # onto the beginning of every command, so you say +#include as in cpp. I couldn't do that because only the underscore +and the alphabetics are recognised by m4 as being legitimate in +identifiers. However, I put an underscore onto the beginning, and +that seems to work quite well. + +Given that you refer to the same problem in the documentation for +fvwm, I thought I would send the hack to you: + +------ snip ------ snip ------ snip ------ snip ------ snip ------ snip +divert(-1) +changequote(+,-) +changequote(@`,@') +define(_,@`_dnl @') + +# We now add an underscore onto the front of all the builtins, to prevent +# unexpected conflicts with words in the text. The following gross hack does +# this. Understand it if you can... ;-) + +define(def,defn(@`define@')) +define(definition,defn(@`defn@')) +define(remove,defn(@`undefine@')) +define(alias,@`def(@`$2@',definition(@`$1@'))@') +define(hack,@`alias(@`$1@',@`_$1@') remove(@`$1@')@') + +hack(@`builtin@') +hack(@`changecom@') +hack(@`changequote@') +hack(@`debugfile@') +hack(@`debugmode@') +hack(@`decr@') +hack(@`define@') +hack(@`defn@') +hack(@`divert@') +hack(@`divnum@') +hack(@`dnl@') +hack(@`dumpdef@') +hack(@`errprint@') +hack(@`esyscmd@') +hack(@`eval@') +hack(@`file@') +hack(@`format@') +hack(@`gnu@') +hack(@`ifdef@') +hack(@`ifelse@') +hack(@`include@') +hack(@`incr@') +hack(@`index@') +hack(@`indir@') +hack(@`len@') +hack(@`line@') +hack(@`m4exit@') +hack(@`m4wrap@') +hack(@`maketemp@') +hack(@`patsubst@') +hack(@`popdef@') +hack(@`pushdef@') +hack(@`regexp@') +hack(@`shift@') +hack(@`sinclude@') +hack(@`substr@') +hack(@`syscmd@') +hack(@`sysval@') +hack(@`traceoff@') +hack(@`traceon@') +hack(@`translit@') +hack(@`undefine@') +hack(@`undivert@') +hack(@`unix@') + +_undefine(@`def@') +_undefine(@`definition@') +_undefine(@`alias@') +_undefine(@`hack@') + +_divert(0) +------ snip ------ snip ------ snip ------ snip ------ snip ------ snip + +(I redefine the quotes as well, because I find that the ordinary +single quote characters are much too common in text that you want to +preprocess.) + +One problem with this script is that if someone extends m4 by adding a +new builtin command foo, say, then it will not get an underscore +prepended; this is because you can't get m4 to give you a complete +list of builtins. For the same reason, the script will probably give +trouble with System V m4, because it won't have definitions for the +GNU extensions. + +Anyway, do what you want with the script - if you think it might be +useful to fvwm users you are more than welcome to include it in the +distribution. Or file it away in /dev/null if you are unimpressed. + +I was rather concerned by the little bit of Motif that is getting +distributed along with fvwm. It may be only a couple of pages out of +10M (is Motif really that big? Argh!) but that will not stop you +getting sued. If the Motif people start to get the idea that they are +not selling so many copies because people use fvwm instead of twm, +they will sue you for copyright infringement - not because there is +any particular justice to them protecting two pages of code, but just +because it is the easiest way of making you go away. + +It is correct that there is no copyright in structures, only in the +source code that defines them. So you would be quite within your +rights to rewrite the offending two pages, and then I can't see that +there is anything that the Motif people could do. + +------------------------------------------------------------------------------- +Pete.Chown@dale.dircon.co.uk "The Pen is mightier than the Quill" + -- anonymous diff --git a/documentation/mailing_list b/documentation/mailing_list new file mode 100644 index 0000000..c899a9f --- /dev/null +++ b/documentation/mailing_list @@ -0,0 +1,24 @@ +A kind soul has set up a mailing list for fvwm. Here's the info: + + +Okay, I set it up... + +1. To subscribe: + + mail to Majordomo@wonderland.org with the body of the message: + + subscribe fvwm + + That's all there is to it. To send to the list, mail to fvwm@wonderland.org. + +2. To unsubscribe + If you are bored with this list, the way to get off of the list is to mail + Majordomo@wonderland.org a one line message (subject is ignored) saying + unsubscribe fvwm -- that's it. If you get an error message, mail me, + and I'll do it by hand. + +3. There's also fvwm-announce. Just change 'fvwm' in the above instructions to + 'fvwm-announce'. + + + diff --git a/documentation/modules.tex b/documentation/modules.tex new file mode 100644 index 0000000..f00c60b --- /dev/null +++ b/documentation/modules.tex @@ -0,0 +1,391 @@ +\documentstyle[11pt]{article} % Specifies the document style. +\setlength{\textwidth}{6in} +\setlength{\oddsidemargin}{.25in} +\setlength{\topmargin}{0in} +\setlength{\textheight}{8in} +\setcounter{secnumdepth}{2} + +\begin{document} % End of preamble and beginning of text. + +\title {The Fvwm Module Interface} +\date{\today} +\author {Robert J. Nation} +\maketitle + +\section{Concept} +The module interface had several design goals: +\begin{itemize} +\item{Modules (user programs) should be able to provide the window +manager with a limited amount of instruction regarding instructions to +execute.} +\item{Modules should not be able to corrupt the internal data bases +maintained by Fvwm, nor should unauthorized modules be able to +interface to Fvwm.} +\item{Modules should be able to extract all or nearly all information +held by the window manager, in a simple manner, to provide users with +feedback not available from built in services.} +\item{Modules should gracefully terminate when the window manager +dies, quits, or is re-started.} +\item{It should be possible for programmer-users to add modules +without understanding the internals of Fvwm. Ideally, modules could be +written in some scripting language such as Tcl/Tk.} +\end{itemize} +These goals have not entirely been met at this point, as the module +interface is a work in progress. + +\section{Implementation Overview} +Although the module interface is not complete, some details of its +implementation are available. +\subsection{Security} +Limited effort has been placed on security issues. In short, modules +can not communicate with Fvwm unless they are launched by Fvwm, which +means that they must be listed in the user's .fvwmrc file. +Modules can only issue commands to Fvwm that could be issued from a +menu or key binding. These measures do not keep a poorly written +module from destroying windows or terminating an X session, but they +do keep users from maliciously connecting to another users window +manager, and it should keep modules from corrupting the Fvwm internal +databases. +\subsection{Interface and Initialization Mechanism} +Modules MUST be launched by Fvwm. Fvwm will first open a pair of pipes +for communication with the module. One pipe is for messages to Fvwm +from the module, and the other is for messages to the module from +Fvwm. Each module has its own pair of pipes. After the pipes are open, +Fvwm will fork and spawn the module. Modules must be located in the +ModulePath, as specified in the user's .fvwmrc file. Modules can be +initiated as fvwm starts up, or can be launched part way through an X +session. + +The pipes already will be open when the module starts execution. The +integer file descriptor are passed to the module as the first and +second command line arguments. The third command line argument is the +full path name of the .fvwmrc file that fvwm used during +initialization. The next command line argument is the application +window in whose context the module was launched. This will be 0 if the +module is launched without an application window context. The next +argument is the context of the window decoration in which the module +was launched. Contexts are listed below: +\begin{verbatim} +#define C_NO_CONTEXT 0 - launched during initialization +#define C_WINDOW 1 - launched from an application window +#define C_TITLE 2 - launched from a title bar +#define C_ICON 4 - launched from an icon window +#define C_ROOT 8 - launched from the root window +#define C_FRAME 16 - launched from a corner piece +#define C_SIDEBAR 32 - launched from a side-bar +#define C_L1 64 - launched from left button #1 +#define C_L2 128 - launched from left button #2 +#define C_L3 256 - launched from left button #3 +#define C_L4 512 - launched from left button #4 +#define C_L5 1024 - launched from left button #5 +#define C_R1 2048 - launched from right button #1 +#define C_R2 4096 - launched from right button #2 +#define C_R3 8192 - launched from right button #3 +#define C_R4 16384 - launched from right button #4 +#define C_R5 32768 - launched from right button #5 +\end{verbatim} +An additional, user specified, command line argument may be present +(it optional). This argument is the entire +body of the Module command line in the .fvwmrc file, +after the actual name of the module. It may contain +spaces, qoutes, whatever. For example, in: +\begin{verbatim} + Module "FvwmIdentify" FvwmIdentify Hello rob! -fg purple +\end{verbatim} +the argument would be "Hello rob! -fg purple" all passed in +argv[6]. + +In the future, command line arguments may +be paresed in a more standard format. + +The following mechanism is recommended to acquire the pipe +descriptors: +\begin{verbatim} +int fd[2]; +void main(int argc, char **argv) +{ + if((argc != 6)&&(argc != 7)) + { + fprintf(stderr,"Modules should only be executed by fvwm!\n"); + exit(1); + } + fd[0] = atoi(argv[1]); + fd[1] = atoi(argv[2]); + +\end{verbatim} +The descriptor fd[0] is available for the module to send messages to +fvwm, while the descriptor fd[1] is available to read messages from +fvwm. + +Special attention is paid to the status of the pipe. If Fvwm gets a +read error on a module-to-fvwm pipe, then it assumes that the module +is terminating, +and all communication with the module is terminated. Similarly, if a +module gets a read error on an fvwm-to-module pipe, then it should +assume that fvwm is terminating, and it should gracefully shut down. +All modules should also allow themselves to be shut down via the +Delete Window protocol for X-11. + +\section{Module-to-Fvwm Communication} +Modules communicate with fvwm via a simple protocol. In essence, a +textual command line, similar to a command line which could be bound +to a mouse, or key-stroke in the .fvwmrc, is transmitted to fvwm. + +First, the module should send the ID of the window which should be +manipulated. A window ID of ``None'' may be used, in which case Fvwm +will prompt the user to select a window if needed. Next, length of +the the command line is send as an integer. After that, the command +line itself is sent. Finally, an integer 1 is sent if the module plans +to continue operating, or 0 if the module is finished. The following +subroutine is provided as an example of a suitable method of sending +messages to fvwm: +\begin{verbatim} +void SendInfo(int *fd,Window win, char *message) +{ + int w; + + if((message != NULL)&&(strlen(message) >0)) + { + /* if win == None, then Fvwm will prompt the user for a window + * on which to operate, if needed. Some commands, like Exec, + * don't operate on a window, so None is appropriate. */ + write(fd[0],&win,sizeof(Window)); + + /* calculate the length of the message */ + w=strlen(message); + /* send the message length */ + write(fd[0],&w,sizeof(int)); + /* send the message itself + write(fd[0],message,w); + + /* send a 1, indicating that this module will keep going */ + /* a 0 would mean that this module is done */ + w=1; + write(fd[0],&w,sizeof(int)); + } +} +\end{verbatim} + +There is a special built-in function, Send\_WindowList, which causes +fvwm to transmit everything that it is currently thinking about to +the module which requests the information. This information contains +the paging status (enabled/disabled), current desktop number, position +on the desktop, current focus and, for each window, the window +configuration, window, icon, and class names, and, if the window is +iconified, the icon location and size. + +An additional special function has been added to fvwm, which is used +to control exactly what information fvwm passes to each module. The +command Set\_Mask, followed by a number which is the bitwise OR of the +packet-type values which the module wishes to receive. If the module +never sends the Set\_Mask command, then all message types will be +sent. + +\section{Fvwm-to-Module Communication} +Fvwm +can send messages to the modules in either a broadcast mode, or a +module specific mode. Certain messages regarding important window or +desktop manipulations will be broadcast to all modules, whether they +want it or not. Modules are able to request information about current windows +from fvwm, via the Send\_WindowList built-in. When invoked this way, +only requesting module will receive the data. + +Packets from fvwm to modules conform to a standard format, so modules +which are not interested in broadcast messages can easily ignore them. +A header consisting of 3 unsigned long integers, followed by a body of +a variable length make up a packet. The header always begins with +0xffffffff. This is provided to help modules re-synchronize to the +data stream if necessary. The next entry describes the packet type. +Existing packet types are listing in the file module.h: +\begin{verbatim} +#define START_FLAG 0xffffffff + +#define M_TOGGLE_PAGING 1 +#define M_NEW_PAGE 2 +#define M_NEW_DESK 4 +#define M_ADD_WINDOW 8 +#define M_RAISE_WINDOW 16 +#define M_LOWER_WINDOW 32 +#define M_CONFIGURE_WINDOW 64 +#define M_FOCUS_CHANGE 128 +#define M_DESTROY_WINDOW 256 +#define M_ICONIFY 512 +#define M_DEICONIFY 1024 +#define M_WINDOW_NAME 2048 +#define M_ICON_NAME 4096 +#define M_RES_CLASS 8192 +#define M_RES_NAME 16384 +#define M_END_WINDOWLIST 32768 +#define M_ICON_LOCATION 65536 +#define M_MAP 131072 +\end{verbatim} + +Additional packet types will be defined in the future. The third entry +in the header tells the total length of the packet, in unsigned longs, +including the header. + +The body information is packet specific, as described below. +\subsection{M\_TOGGLE\_PAGING} +The body contains a single unsigned long, which is 0 is paging has +been temporarily disable through use of the TogglePage built-in, or 1 +is paging is enabled. This packet is broadcast whenever the TogglePage +built-in is invoked. + +\subsection{M\_NEW\_DESK} +The body of this packet consists of a single long integer, whose value +is the number of the currently active desktop. This packet is +transmitted whenever the desktop number is changed. + +\subsection{M\_ADD\_WINDOW, and M\_CONFIGURE\_WINDOW} +These packets contain 22 values. The first 3 identify the window, and +the next twelve identify the location and size, as described in the +table below. Configure packets will be generated when the +viewport on the current desktop changes, or when the size or location +of the window is changed. The flags field is an bitwise OR of the +flags defined in fvwm.h. + + +\begin{table} +\begin{center} +\begin{tabular}[h]{|l|l|} \hline +\multicolumn{2}{|c|}{Format for Add and Configure Window Packets} \\ \hline +Byte &Significance \\\hline +0 & 0xffffffff - Start of packet \\ +1 & packet type \\ +2 & length of packet, including header, expressed in long integers +\\ \hline +3 & ID of the application's top level window \\ +4 & ID of the Fvwm frame window \\ +5 & Pointer to the Fvwm database entry \\ +6 & X location of the window's frame \\ +7 & Y location of the window's frame\\ +8 & Width of the window's frame (pixels) \\ +9 & Height of the window's frame (pixels) \\ +10 & Desktop number\\ +11 & Windows flags field\\ +12 & Window Title Height (pixels) \\ +13 & Window Border Width (pixels) \\ +14 & Window Base Width (pixels) \\ +15 & Window Base Height (pixels) \\ +16 & Window Resize Width Increment(pixels) \\ +17 & Window Resize Height Increment (pixels) \\ +18 & Window Minimum Width (pixels) \\ +19 & Window Minimum Height (pixels) \\ +20 & Window Maximum Width Increment(pixels) \\ +21 & Window Maximum Height Increment (pixels) \\ +22 & Icon Label Window ID, or 0\\ +23 & Icon Pixmap Window ID, or 0\\ +24 & Window Gravity\\ \hline +\end{tabular} +\end{center} +\end{table} + + +\subsection{M\_NEW\_PAGE} +These packets contain 3 integers. The first two are the x and y +coordinates of the upper left corner of the current viewport on the +virtual desktop. The third value is the number of the current desktop. + +\subsection{M\_LOWER\_WINDOW, M\_RAISE\_WINDOW, and M\_DESTROY} +These packets contain 3 values, all of the same size as an unsigned +long. The first value is the ID of the affected application's top level +window, the next is the ID of the Fvwm frame window, and the final +value is the pointer to Fvwm's internal database entry for that +window. Although the pointer itself is of no use to a module, it can +be used as a reference number when referring to the window. + +\begin{table} +\begin{center} +\begin{tabular}[h]{|l|l|} \hline +\multicolumn{2}{|c|}{Format for Lower, Raise, and Focus Change Packets} \\ \hline +Byte &Significance \\\hline +0 & 0xffffffff - Start of packet \\ +1 & packet type \\ +2 & length of packet, including header, expressed in long integers +\\ \hline +3 & ID of the application's top level window \\ +4 & ID of the Fvwm frame window \\ +5 & Pointer to the Fvwm database entry \\ \hline +\end{tabular} +\end{center} +\end{table} + + +\subsection{M\_FOCUS\_CHANGE} +These packets contain 3 values, all of the same size as an unsigned +long. The first value is the ID of the affected application's (the +application which now has the input focus) top level +window, the next is the ID of the Fvwm frame window, and the final +value is the pointer to Fvwm's internal database entry for that +window. Although the pointer itself is of no use to a module, it can +be used as a reference number when referring to the window. In the +event that the window which now has the focus is not a window which +fvwm recognizes, only the ID of the affected application's top level +window is passed. Zeros are passed for the other values. + +\subsection{M\_ICONIFY and M\_ICON\_LOCATION} +These packets contain 7 values. The first 3 are the usual identifiers, +and the next four describe the location and size of the icon window, +as described in the table. Note that M\_ICONIFY packets will be sent +whenever a window is first iconified, or when the icon window is changed +via the XA\_WM\_HINTS in a property notify event. An M\_ICON\_LOCATION +packet will be sent when the icon is moved. +In addition, if a window which has transients is +iconified, then an M\_ICONIFY packet is sent for each transient +window, with the x, y, width, and height fields set to 0. This packet +will be sent even if the transients were already iconified. Note that +no icons are actually generated for the transients in this case. + + +\begin{table} +\begin{center} +\begin{tabular}[h]{|l|l|} \hline +\multicolumn{2}{|c|}{Format for Iconify and Icon Location Packets} \\ \hline +Byte &Significance \\\hline +0 & 0xffffffff - Start of packet \\ +1 & packet type \\ +2 & length of packet, including header, expressed in long integers +\\ \hline +3 & ID of the application's top level window \\ +4 & ID of the Fvwm frame window \\ +5 & Pointer to the Fvwm database entry \\ +6 & X location of the icon's frame \\ +7 & Y location of the icon's frame\\ +8 & Width of the icon's frame \\ +9 & Height of the icon's frame \\ \hline +\end{tabular} +\end{center} +\end{table} + +\subsection{M\_DEICONIFY} +These packets contain 3 values, which are the usual window +identifiers. The packet is sent when a window is de-iconified. + +\subsection{M\_MAP} +These packets contain 3 values, which are the usual window +identifiers. The packets are sent when a window is mapped, if it is +not being deiconified. This is useful to determine when a window is +finally mapped, after being added. + +\subsection{M\_WINDOW\_NAME, M\_ICON\_NAME, M\_RES\_CLASS, M\_RES\_NAME} +These packets contain 3 values, which are the usual window +identifiers, followed by a variable length character string. The +packet size field in the header is expressed in units of unsigned +longs, and the packet is zero-padded until it is the size of an +unsigned long. The RES\_CLASS and RES\_NAME fields are fields in the +XClass structure for the window. Icon and Window name packets will +will be sent upon window creation or whenever the name is changed. The +RES\_CLASS and RES\_NAME packets are sent on window creation. All +packets are sent in response to a Send\_WindowList request from a module. + +\subsection{M\_END\_WINDOWLIST} +These packets contain no values. This packet is sent to mark the end +of transmission in response to a Send\_WindowList request. A module +which request Send\_WindowList, and processes all packets received +between the request and the M\_END\_WINDOWLIST will have a snapshot of +the status of the desktop. + +\end{document} + + + diff --git a/fvwm.README b/fvwm.README new file mode 100644 index 0000000..0472d74 --- /dev/null +++ b/fvwm.README @@ -0,0 +1,11 @@ +Fvwm is a just another window manager for X11, which provides a simple virtual +desktop, a 3-D look for windows decorations, and shaped, color icons. +It can be configured to use far less memory than twm, or to give a very +good emulation of mwm. A nice button-bar can be used to provide convenient +access to frequently used functions or programs. + +Fvwm has three pieces +fvwm-1.23-core.tar.gz - the actual window manager +fvwm-1.23-icons.tar.gz - some icons that go nicely with fvwm +fvwm-1.23-modules.tar.gz - add on desktop accessories + diff --git a/fvwm/Imakefile b/fvwm/Imakefile new file mode 100644 index 0000000..ce6f3d1 --- /dev/null +++ b/fvwm/Imakefile @@ -0,0 +1,43 @@ +/* Imakefile for fvwm 1.18c */ +/* Thu Aug 5 11:21:36 MET DST 1993, mj@dfv.rwth-aachen.de */ + +/* setup is done entirely in configuration.h now! */ +/* You should need to do much in here, excpt maybe add libraries */ + +/* I need to get the #define XPM from configuration.h if its in there, */ +/* so that I can tell if I should include -lXpm */ +#include <../configure.h> + +COMPILER + +#ifdef XPM +XPMLIB = XPMLIBRARY +#endif + +DEPLIBS = $(DEPXLIB) ../libs/libfvwmlib.a + +#ifdef AlphaArchitecture +LOCAL_LIBRARIES = $(XPMLIB) $(XLIB) -ldnet_stub -L../libs -lfvwmlib +#else +#ifdef HPArchitecture +LOCAL_LIBRARIES = $(XPMLIB) $(XLIB) -lV3 -L../libs -lfvwmlib +#else +LOCAL_LIBRARIES = $(XPMLIB) $(XLIB) -lfvwmlib -L../libs +#endif /* HPArchitecture */ +#endif /* AlphaArchitecture */ + +FVWM_BIN_DIR + +LINTLIBS = $(LINTXLIB) + +SRCS = fvwm.c configure.c events.c borders.c menus.c functions.c resize.c\ + add_window.c pager.c move.c icons.c windows.c module.c placement.c\ + decorations.c colormaps.c misc.c style.c + +OBJS = fvwm.o configure.o events.o borders.o menus.o functions.o resize.o\ + add_window.o pager.o move.o icons.o windows.o module.o placement.o \ + decorations.o colormaps.o misc.o style.o + +ComplexProgramTarget(fvwm) +InstallNamedNonExec(../sample.fvwmrc/system.fvwmrc,system.fvwmrc,FVWMDIR) + diff --git a/fvwm/add_window.c b/fvwm/add_window.c new file mode 100644 index 0000000..a683576 --- /dev/null +++ b/fvwm/add_window.c @@ -0,0 +1,933 @@ +/**************************************************************************** + * THIS module is based on Twm, but has been siginificantly modified + * by Rob Nation + ****************************************************************************/ +/*****************************************************************************/ +/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ +/** Salt Lake City, Utah **/ +/** Portions Copyright 1989 by the Massachusetts Institute of Technology **/ +/** Cambridge, Massachusetts **/ +/** **/ +/** All Rights Reserved **/ +/** **/ +/** Permission to use, copy, modify, and distribute this software and **/ +/** its documentation for any purpose and without fee is hereby **/ +/** granted, provided that the above copyright notice appear in all **/ +/** copies and that both that copyright notice and this permis- **/ +/** sion notice appear in supporting documentation, and that the **/ +/** names of Evans & Sutherland and M.I.T. not be used in advertising **/ +/** in publicity pertaining to distribution of the software without **/ +/** specific, written prior permission. **/ +/** **/ +/** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/ +/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/ +/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/ +/** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/ +/** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ +/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ +/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ +/** OR PERFORMANCE OF THIS SOFTWARE. **/ +/*****************************************************************************/ + + +/********************************************************************** + * + * Add a new window, put the titlbar and other stuff around + * the window + * + **********************************************************************/ +#include "../configure.h" + +#include +#include +#include +#include "fvwm.h" +#include +#include "misc.h" +#include "screen.h" +#ifdef SHAPE +#include +#include +#endif /* SHAPE */ +#include "module.h" + +char NoName[] = "Untitled"; /* name if no name is specified */ + +/* Used to parse command line of clients for specific desk requests. */ +/* Todo: check for multiple desks. */ +static XrmDatabase db; +static XrmOptionDescRec table [] = { + /* Want to accept "-workspace N" or -xrm "fvwm*desk:N" as options + * to specify the desktop. I have to include dummy options that + * are meaningless since Xrm seems to allow -w to match -workspace + * if there would be no ambiguity. */ + {"-workspacf", "*junk", XrmoptionSepArg, (caddr_t) NULL}, + {"-workspace", "*desk", XrmoptionSepArg, (caddr_t) NULL}, + {"-xrn", NULL, XrmoptionResArg, (caddr_t) NULL}, + {"-xrm", NULL, XrmoptionResArg, (caddr_t) NULL}, +}; + +/*********************************************************************** + * + * Procedure: + * AddWindow - add a new window to the fvwm list + * + * Returned Value: + * (FvwmWindow *) - pointer to the FvwmWindow structure + * + * Inputs: + * w - the window id of the window to add + * iconm - flag to tell if this is an icon manager window + * + ***********************************************************************/ +FvwmWindow *AddWindow(Window w) +{ + FvwmWindow *tmp_win; /* new fvwm window structure */ + unsigned long valuemask; /* mask for create windows */ + XSetWindowAttributes attributes; /* attributes for create windows */ + Atom actual_type; + int actual_format,i,width,height; + unsigned long nitems, bytesafter; + int a,b; + char *value; + unsigned long tflag; + int Desk, border_width, resize_width; + extern Bool NeedToResizeToo; + extern FvwmWindow *colormap_win; + char *forecolor = NULL, *backcolor = NULL; + int client_argc; + char **client_argv = NULL, *str_type; + Bool status; + XrmValue rm_value; + unsigned long buttons; + XTextProperty text_prop; + + NeedToResizeToo = False; + /* allocate space for the fvwm window */ + tmp_win = (FvwmWindow *)calloc(1, sizeof(FvwmWindow)); + if (tmp_win == (FvwmWindow *)0) + { + return NULL; + } + tmp_win->flags = 0; + tmp_win->w = w; + + tmp_win->cmap_windows = (Window *)NULL; + + if (XGetGeometry(dpy, tmp_win->w, &JunkRoot, &JunkX, &JunkY, + &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth) == 0) + { + free((char *)tmp_win); + return(NULL); + } + if ( XGetWMName(dpy, tmp_win->w, &text_prop) != 0 ) + tmp_win->name = (char *)text_prop.value ; + else + tmp_win->name = NoName; + + tmp_win->class = NoClass; + tmp_win->focus_sequence = 0; + XGetClassHint(dpy, tmp_win->w, &tmp_win->class); + if (tmp_win->class.res_name == NULL) + tmp_win->class.res_name = NoName; + if (tmp_win->class.res_class == NULL) + tmp_win->class.res_class = NoName; + + FetchWmProtocols (tmp_win); + FetchWmColormapWindows (tmp_win); + if(!(XGetWindowAttributes(dpy,tmp_win->w,&(tmp_win->attr)))) + tmp_win->attr.colormap = Scr.FvwmRoot.attr.colormap; + + tmp_win->wmhints = XGetWMHints(dpy, tmp_win->w); + + if(XGetTransientForHint(dpy, tmp_win->w, &tmp_win->transientfor)) + tmp_win->flags |= TRANSIENT; + else + tmp_win->flags &= ~TRANSIENT; + + tmp_win->old_bw = tmp_win->attr.border_width; + +#ifdef SHAPE + { + int xws, yws, xbs, ybs; + unsigned wws, hws, wbs, hbs; + int boundingShaped, clipShaped; + + XShapeSelectInput (dpy, tmp_win->w, ShapeNotifyMask); + XShapeQueryExtents (dpy, tmp_win->w, + &boundingShaped, &xws, &yws, &wws, &hws, + &clipShaped, &xbs, &ybs, &wbs, &hbs); + tmp_win->wShaped = boundingShaped; + } +#endif /* SHAPE */ + + + /* if the window is in the NoTitle list, or is a transient, + * dont decorate it. + * If its a transient, and DecorateTransients was specified, + * decorate anyway + */ + /* Assume that we'll decorate */ + tmp_win->flags |= BORDER; + tmp_win->flags |= TITLE; + tmp_win->title_height = Scr.TitleHeight + tmp_win->bw; + + tflag = LookInList(Scr.TheList,tmp_win->name,&tmp_win->class, &value, &Desk, + &border_width, &resize_width, + &forecolor,&backcolor,&tmp_win->buttons); + + GetMwmHints(tmp_win); + + SelectDecor(tmp_win,tflag,border_width,resize_width); + + if(tflag & START_ICONIC_FLAG) + tmp_win->flags |= STARTICONIC; + if (tflag & STAYSONTOP_FLAG) + tmp_win->flags |= ONTOP; + if (tflag&STICKY_FLAG) + tmp_win->flags |= STICKY; + if(tflag & LISTSKIP_FLAG) + tmp_win->flags |= WINDOWLISTSKIP; + if(tflag & CIRCULATESKIP_FLAG) + tmp_win->flags |= CIRCULATESKIP; + + if(tflag & SUPPRESSICON_FLAG) + tmp_win->flags |= SUPPRESSICON; + if(tflag & NOICON_TITLE_FLAG) + tmp_win->flags |= NOICON_TITLE; + if(Scr.flags & SuppressIcons) + tmp_win->flags |= SUPPRESSICON; + + /* find a suitable icon pixmap */ + if(tflag & ICON_FLAG) + { + /* an icon was specified */ + tmp_win->icon_bitmap_file = value; + } + else if((tmp_win->wmhints) + &&(tmp_win->wmhints->flags & (IconWindowHint|IconPixmapHint))) + { + /* window has its own icon */ + tmp_win->icon_bitmap_file = NULL; + } + else + { + /* use default icon */ + tmp_win->icon_bitmap_file = Scr.DefaultIcon; + } + + GetWindowSizeHints (tmp_win); + + + /* Tentative size estimate */ + tmp_win->frame_width = tmp_win->attr.width+2*tmp_win->boundary_width; + tmp_win->frame_height = tmp_win->attr.height + tmp_win->title_height+ + 2*tmp_win->boundary_width; + + ConstrainSize(tmp_win, &tmp_win->frame_width, &tmp_win->frame_height); + + /* Find out if the client requested a specific desk on the command line. */ + if (XGetCommand (dpy, tmp_win->w, &client_argv, &client_argc)) { + XrmParseCommand (&db, table, 4, "fvwm", &client_argc, client_argv); + status = XrmGetResource (db, "fvwm.desk", "Fvwm.Desk", &str_type, &rm_value); + if ((status == True) && (rm_value.size != 0)) { + Desk = atoi(rm_value.addr); + tmp_win->flags |= STAYSONDESK_FLAG; + tflag |= STAYSONDESK_FLAG; + } + XrmDestroyDatabase (db); + db = NULL; + } + + if(!PlaceWindow(tmp_win, tflag, Desk)) + return NULL; + + /* + * Make sure the client window still exists. We don't want to leave an + * orphan frame window if it doesn't. Since we now have the server + * grabbed, the window can't disappear later without having been + * reparented, so we'll get a DestroyNotify for it. We won't have + * gotten one for anything up to here, however. + */ + XGrabServer(dpy); + if(XGetGeometry(dpy, w, &JunkRoot, &JunkX, &JunkY, + &JunkWidth, &JunkHeight, + &JunkBW, &JunkDepth) == 0) + { + free((char *)tmp_win); + XUngrabServer(dpy); + return(NULL); + } + + XSetWindowBorderWidth (dpy, tmp_win->w,0); + XGetWindowProperty (dpy, tmp_win->w, XA_WM_ICON_NAME, 0L, 200L, False, + XA_STRING, &actual_type, &actual_format, &nitems, + &bytesafter,(unsigned char **)&tmp_win->icon_name); + if(tmp_win->icon_name==(char *)NULL) + tmp_win->icon_name = tmp_win->name; + + tmp_win->flags &= ~ICONIFIED; + tmp_win->flags &= ~ICON_UNMAPPED; + tmp_win->flags &= ~MAXIMIZED; + + + tmp_win->TextPixel = Scr.StdColors.fore; + tmp_win->ReliefPixel = Scr.StdRelief.fore; + tmp_win->ShadowPixel = Scr.StdRelief.back; + tmp_win->BackPixel = Scr.StdColors.back; + + if(tmp_win->flags & STICKY) + { + tmp_win->BackPixel = Scr.StickyColors.back; + tmp_win->ShadowPixel = Scr.StickyRelief.back; + tmp_win->ReliefPixel = Scr.StickyRelief.fore; + tmp_win->TextPixel = Scr.StickyColors.fore; + } + if(forecolor != NULL) + { + XColor color; + + if((XParseColor (dpy, Scr.FvwmRoot.attr.colormap, forecolor, &color)) + &&(XAllocColor (dpy, Scr.FvwmRoot.attr.colormap, &color))) + { + tmp_win->TextPixel = color.pixel; + } + } + if(backcolor != NULL) + { + XColor color; + + if((XParseColor (dpy, Scr.FvwmRoot.attr.colormap,backcolor, &color)) + &&(XAllocColor (dpy, Scr.FvwmRoot.attr.colormap, &color))) + + { + tmp_win->BackPixel = color.pixel; + } + tmp_win->ShadowPixel = GetShadow(tmp_win->BackPixel); + tmp_win->ReliefPixel = GetHilite(tmp_win->BackPixel); + } + + + /* add the window into the fvwm list */ + tmp_win->next = Scr.FvwmRoot.next; + if (Scr.FvwmRoot.next != NULL) + Scr.FvwmRoot.next->prev = tmp_win; + tmp_win->prev = &Scr.FvwmRoot; + Scr.FvwmRoot.next = tmp_win; + + /* create windows */ + tmp_win->frame_x = tmp_win->attr.x + tmp_win->old_bw - tmp_win->bw; + tmp_win->frame_y = tmp_win->attr.y + tmp_win->old_bw - tmp_win->bw; + + tmp_win->frame_width = tmp_win->attr.width+2*tmp_win->boundary_width; + tmp_win->frame_height = tmp_win->attr.height + tmp_win->title_height+ + 2*tmp_win->boundary_width; + + + valuemask = CWBorderPixel | CWCursor | CWEventMask; + if(Scr.d_depth < 2) + { + attributes.background_pixmap = Scr.light_gray_pixmap ; + if(tmp_win->flags & STICKY) + attributes.background_pixmap = Scr.sticky_gray_pixmap; + valuemask |= CWBackPixmap; + } + else + { + attributes.background_pixel = tmp_win->BackPixel; + valuemask |= CWBackPixel; + } + + attributes.border_pixel = tmp_win->ShadowPixel; + + attributes.cursor = Scr.FvwmCursors[DEFAULT]; + attributes.event_mask = (SubstructureRedirectMask | ButtonPressMask | + ButtonReleaseMask |EnterWindowMask | + LeaveWindowMask |ExposureMask); + if(Scr.flags & SaveUnders) + { + valuemask |= CWSaveUnder; + attributes.save_under = TRUE; + } + /* What the heck, we'll always reparent everything from now on! */ + tmp_win->frame = + XCreateWindow (dpy, Scr.Root, tmp_win->frame_x,tmp_win->frame_y, + tmp_win->frame_width, tmp_win->frame_height, + tmp_win->bw,CopyFromParent, InputOutput, + CopyFromParent, valuemask, &attributes); + + attributes.save_under = FALSE; + + /* Thats not all, we'll double-reparent the window ! */ + attributes.cursor = Scr.FvwmCursors[DEFAULT]; + tmp_win->Parent = + XCreateWindow (dpy, tmp_win->frame, + tmp_win->boundary_width, + tmp_win->boundary_width+tmp_win->title_height, + (tmp_win->frame_width - 2*tmp_win->boundary_width), + (tmp_win->frame_height - 2*tmp_win->boundary_width - + tmp_win->title_height),tmp_win->bw, CopyFromParent, + InputOutput,CopyFromParent, valuemask,&attributes); + + if(Scr.flags & BackingStore) + { + valuemask |= CWBackingStore; + attributes.backing_store = WhenMapped; + } + +#ifndef NO_PAGER + if(Scr.Pager_w) + { + /* Create the pager_view window even if we're sticky, in case the + * user unsticks the window */ + attributes.event_mask = ExposureMask; + tmp_win->pager_view= XCreateWindow (dpy, Scr.Pager_w, -10, -10, 2, 2, 1, + CopyFromParent, InputOutput, + CopyFromParent, valuemask, + &attributes); + XMapRaised(dpy,tmp_win->pager_view); + } +#endif + + attributes.event_mask = (ButtonPressMask|ButtonReleaseMask|ExposureMask| + EnterWindowMask|LeaveWindowMask); + tmp_win->title_x = tmp_win->title_y = 0; + tmp_win->title_w = 0; + tmp_win->title_width = tmp_win->frame_width - 2*tmp_win->corner_width + - 3 + tmp_win->bw; + if(tmp_win->title_width < 1) + tmp_win->title_width = 1; + if(tmp_win->flags & BORDER) + { + /* Just dump the windows any old place and left SetupFrame take + * care of the mess */ + for(i=0;i<4;i++) + { + attributes.cursor = Scr.FvwmCursors[TOP_LEFT+i]; + tmp_win->corners[i] = + XCreateWindow (dpy, tmp_win->frame, 0,0, + tmp_win->corner_width, tmp_win->corner_width, + 0, CopyFromParent,InputOutput, + CopyFromParent, valuemask,&attributes); + } + } + + if (tmp_win->flags & TITLE) + { + tmp_win->title_x = tmp_win->boundary_width +tmp_win->title_height+1; + tmp_win->title_y = tmp_win->boundary_width; + attributes.cursor = Scr.FvwmCursors[TITLE_CURSOR]; + tmp_win->title_w = + XCreateWindow (dpy, tmp_win->frame, tmp_win->title_x, tmp_win->title_y, + tmp_win->title_width, tmp_win->title_height,0, + CopyFromParent, InputOutput, CopyFromParent, + valuemask,&attributes); + attributes.cursor = Scr.FvwmCursors[SYS]; + for(i=4;i>=0;i--) + { + if((ileft_w[i] > 0)) + { + tmp_win->left_w[i] = + XCreateWindow (dpy, tmp_win->frame, tmp_win->title_height*i, 0, + tmp_win->title_height, tmp_win->title_height, 0, + CopyFromParent, InputOutput, + CopyFromParent, valuemask, &attributes); + } + else + tmp_win->left_w[i] = None; + + if((iright_w[i] >0)) + { + tmp_win->right_w[i] = + XCreateWindow (dpy, tmp_win->frame, + tmp_win->title_width- + tmp_win->title_height*(i+1), + 0, tmp_win->title_height, + tmp_win->title_height, + 0, CopyFromParent, InputOutput, + CopyFromParent, valuemask, &attributes); + } + else + tmp_win->right_w[i] = None; + } + } + + if(tmp_win->flags & BORDER) + { + for(i=0;i<4;i++) + { + attributes.cursor = Scr.FvwmCursors[TOP+i]; + tmp_win->sides[i] = + XCreateWindow (dpy, tmp_win->frame, 0, 0, tmp_win->boundary_width, + tmp_win->boundary_width, 0, CopyFromParent, + InputOutput, CopyFromParent,valuemask, + &attributes); + } + } + + XMapSubwindows (dpy, tmp_win->frame); + XRaiseWindow(dpy,tmp_win->Parent); + XReparentWindow(dpy, tmp_win->w, tmp_win->Parent,0,0); + + valuemask = (CWEventMask | CWDontPropagate); + attributes.event_mask = (StructureNotifyMask | PropertyChangeMask | + VisibilityChangeMask | EnterWindowMask | + LeaveWindowMask | + ColormapChangeMask | FocusChangeMask); + +#ifndef NO_PAGER + if(tmp_win->w == Scr.Pager_w) + { + Scr.FvwmPager = tmp_win; + attributes.event_mask |=ButtonPressMask|ButtonReleaseMask|ExposureMask + |ButtonMotionMask; + attributes.do_not_propagate_mask = ButtonPressMask; + } + else +#endif + attributes.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask; + if(Scr.flags & AppsBackingStore) + { + valuemask |= CWBackingStore; + attributes.backing_store = WhenMapped; + } + XChangeWindowAttributes (dpy, tmp_win->w, valuemask, &attributes); + if ( XGetWMName(dpy, tmp_win->w, &text_prop) != 0 ) + tmp_win->name = (char *)text_prop.value ; + else + tmp_win->name = NoName; + +#ifndef NO_PAGER + if(tmp_win->w != Scr.Pager_w) +#endif + XAddToSaveSet(dpy, tmp_win->w); + + /* + * Reparenting generates an UnmapNotify event, followed by a MapNotify. + * Set the map state to FALSE to prevent a transition back to + * WithdrawnState in HandleUnmapNotify. Map state gets set correctly + * again in HandleMapNotify. + */ + tmp_win->flags &= ~MAPPED; + width = tmp_win->frame_width; + tmp_win->frame_width = 0; + height = tmp_win->frame_height; + tmp_win->frame_height = 0; + SetupFrame (tmp_win, tmp_win->frame_x, tmp_win->frame_y,width,height, True); + + /* wait until the window is iconified and the icon window is mapped + * before creating the icon window + */ + tmp_win->icon_w = None; + GrabButtons(tmp_win); + GrabKeys(tmp_win); + + XSaveContext(dpy, tmp_win->w, FvwmContext, (caddr_t) tmp_win); + XSaveContext(dpy, tmp_win->frame, FvwmContext, (caddr_t) tmp_win); + XSaveContext(dpy, tmp_win->Parent, FvwmContext, (caddr_t) tmp_win); + if (tmp_win->flags & TITLE) + { + XSaveContext(dpy, tmp_win->title_w, FvwmContext, (caddr_t) tmp_win); + for(i=0;ileft_w[i], FvwmContext, (caddr_t) tmp_win); + for(i=0;iright_w[i] != None) + XSaveContext(dpy, tmp_win->right_w[i], FvwmContext, + (caddr_t) tmp_win); + } + if (tmp_win->flags & BORDER) + { + for(i=0;i<4;i++) + { + XSaveContext(dpy, tmp_win->sides[i], FvwmContext, (caddr_t) tmp_win); + XSaveContext(dpy,tmp_win->corners[i],FvwmContext, (caddr_t) tmp_win); + } + } + RaiseWindow(tmp_win); + KeepOnTop(); + XUngrabServer(dpy); + + XGetGeometry(dpy, tmp_win->w, &JunkRoot, &JunkX, &JunkY, + &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth); + XTranslateCoordinates(dpy,tmp_win->frame,Scr.Root,JunkX,JunkY, + &a,&b,&JunkChild); + tmp_win->xdiff -= a; + tmp_win->ydiff -= b; + if(Scr.flags & ClickToFocus) + { + /* need to grab all buttons for window that we are about to + * unhighlight */ + for(i=0;i<3;i++) + if(Scr.buttons2grab & (1<frame,True, + ButtonPressMask, GrabModeSync,GrabModeAsync,None, + Scr.FvwmCursors[SYS]); + XGrabButton(dpy,(i+1),LockMask,tmp_win->frame,True, + ButtonPressMask, GrabModeSync,GrabModeAsync,None, + Scr.FvwmCursors[SYS]); + } + } + BroadcastConfig(M_ADD_WINDOW,tmp_win); + + BroadcastName(M_WINDOW_NAME,tmp_win->w,tmp_win->frame, + (unsigned long)tmp_win,tmp_win->name); + BroadcastName(M_ICON_NAME,tmp_win->w,tmp_win->frame, + (unsigned long)tmp_win,tmp_win->icon_name); + BroadcastName(M_RES_CLASS,tmp_win->w,tmp_win->frame, + (unsigned long)tmp_win,tmp_win->class.res_class); + BroadcastName(M_RES_NAME,tmp_win->w,tmp_win->frame, + (unsigned long)tmp_win,tmp_win->class.res_name); + + FetchWmProtocols (tmp_win); + FetchWmColormapWindows (tmp_win); + if(!(XGetWindowAttributes(dpy,tmp_win->w,&(tmp_win->attr)))) + tmp_win->attr.colormap = Scr.FvwmRoot.attr.colormap; + if(NeedToResizeToo) + { + XWarpPointer(dpy, Scr.Root, Scr.Root, 0, 0, Scr.MyDisplayWidth, + Scr.MyDisplayHeight, + tmp_win->frame_x + (tmp_win->frame_width>>1), + tmp_win->frame_y + (tmp_win->frame_height>>1)); + resize_window(tmp_win->w,tmp_win,0,0,0,0); + } + InstallWindowColormaps(colormap_win); + return (tmp_win); +} + +/*********************************************************************** + * + * Procedure: + * GrabButtons - grab needed buttons for the window + * + * Inputs: + * tmp_win - the fvwm window structure to use + * + ***********************************************************************/ +void GrabButtons(FvwmWindow *tmp_win) +{ + MouseButton *MouseEntry; + + MouseEntry = Scr.MouseButtonRoot; + while(MouseEntry != (MouseButton *)0) + { + if((MouseEntry->func != (int)0)&&(MouseEntry->Context & C_WINDOW)) + { + if(MouseEntry->Button >0) + { + XGrabButton(dpy, MouseEntry->Button, MouseEntry->Modifier, + tmp_win->w, + True, ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, None, + Scr.FvwmCursors[DEFAULT]); + if(MouseEntry->Modifier != AnyModifier) + { + XGrabButton(dpy, MouseEntry->Button, + (MouseEntry->Modifier | LockMask), + tmp_win->w, + True, ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, None, + Scr.FvwmCursors[DEFAULT]); + } + } + else + { + XGrabButton(dpy, 1, MouseEntry->Modifier, + tmp_win->w, + True, ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, None, + Scr.FvwmCursors[DEFAULT]); + XGrabButton(dpy, 2, MouseEntry->Modifier, + tmp_win->w, + True, ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, None, + Scr.FvwmCursors[DEFAULT]); + XGrabButton(dpy, 3, MouseEntry->Modifier, + tmp_win->w, + True, ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, None, + Scr.FvwmCursors[DEFAULT]); + if(MouseEntry->Modifier != AnyModifier) + { + XGrabButton(dpy, 1, + (MouseEntry->Modifier | LockMask), + tmp_win->w, + True, ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, None, + Scr.FvwmCursors[DEFAULT]); + XGrabButton(dpy, 2, + (MouseEntry->Modifier | LockMask), + tmp_win->w, + True, ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, None, + Scr.FvwmCursors[DEFAULT]); + XGrabButton(dpy, 3, + (MouseEntry->Modifier | LockMask), + tmp_win->w, + True, ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, None, + Scr.FvwmCursors[DEFAULT]); + } + } + } + MouseEntry = MouseEntry->NextButton; + } + return; +} + +/*********************************************************************** + * + * Procedure: + * GrabKeys - grab needed keys for the window + * + * Inputs: + * tmp_win - the fvwm window structure to use + * + ***********************************************************************/ +void GrabKeys(FvwmWindow *tmp_win) +{ + FuncKey *tmp; + for (tmp = Scr.FuncKeyRoot.next; tmp != NULL; tmp = tmp->next) + { + if(tmp->cont & (C_WINDOW|C_TITLE|C_RALL|C_LALL|C_SIDEBAR)) + { + XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->frame, True, + GrabModeAsync, GrabModeAsync); + if(tmp->mods != AnyModifier) + { + XGrabKey(dpy, tmp->keycode, tmp->mods|LockMask, + tmp_win->frame, True, + GrabModeAsync, GrabModeAsync); + } + } + } + return; +} + +/*********************************************************************** + * + * Procedure: + * FetchWMProtocols - finds out which protocols the window supports + * + * Inputs: + * tmp - the fvwm window structure to use + * + ***********************************************************************/ +void FetchWmProtocols (FvwmWindow *tmp) +{ + unsigned long flags = 0L; + Atom *protocols = NULL, *ap; + int i, n; + Atom atype; + int aformat; + unsigned long bytes_remain,nitems; + + if(tmp == NULL) return; + /* First, try the Xlib function to read the protocols. + * This is what Twm uses. */ + if (XGetWMProtocols (dpy, tmp->w, &protocols, &n)) + { + for (i = 0, ap = protocols; i < n; i++, ap++) + { + if (*ap == (Atom)_XA_WM_TAKE_FOCUS) flags |= DoesWmTakeFocus; + if (*ap == (Atom)_XA_WM_DELETE_WINDOW) flags |= DoesWmDeleteWindow; + } + if (protocols) XFree ((char *) protocols); + } + else + { + /* Next, read it the hard way. mosaic from Coreldraw needs to + * be read in this way. */ + if ((XGetWindowProperty(dpy, tmp->w, _XA_WM_PROTOCOLS, 0L, 10L, False, + _XA_WM_PROTOCOLS, &atype, &aformat, &nitems, + &bytes_remain, + (unsigned char **)&protocols))==Success) + { + for (i = 0, ap = protocols; i < nitems; i++, ap++) + { + if (*ap == (Atom)_XA_WM_TAKE_FOCUS) flags |= DoesWmTakeFocus; + if (*ap == (Atom)_XA_WM_DELETE_WINDOW) flags |= DoesWmDeleteWindow; + } + if (protocols) XFree ((char *) protocols); + } + } + tmp->flags |= flags; + return; +} + +/*********************************************************************** + * + * Procedure: + * GetWindowSizeHints - gets application supplied size info + * + * Inputs: + * tmp - the fvwm window structure to use + * + ***********************************************************************/ +void GetWindowSizeHints(FvwmWindow *tmp) +{ + long supplied = 0; + + if (!XGetWMNormalHints (dpy, tmp->w, &tmp->hints, &supplied)) + tmp->hints.flags = 0; + + /* Beat up our copy of the hints, so that all important field are + * filled in! */ + if (tmp->hints.flags & PResizeInc) + { + if (tmp->hints.width_inc == 0) tmp->hints.width_inc = 1; + if (tmp->hints.height_inc == 0) tmp->hints.height_inc = 1; + } + else + { + tmp->hints.width_inc = 1; + tmp->hints.height_inc = 1; + } + + /* + * ICCCM says that PMinSize is the default if no PBaseSize is given, + * and vice-versa. + */ + + if(!(tmp->hints.flags & PBaseSize)) + { + if(tmp->hints.flags & PMinSize) + { + tmp->hints.base_width = tmp->hints.min_width; + tmp->hints.base_height = tmp->hints.min_height; + } + else + { + tmp->hints.base_width = 0; + tmp->hints.base_height = 0; + } + } + if(!(tmp->hints.flags & PMinSize)) + { + tmp->hints.min_width = tmp->hints.base_width; + tmp->hints.min_height = tmp->hints.base_height; + } + if(!(tmp->hints.flags & PMaxSize)) + { + tmp->hints.max_width = MAX_WINDOW_WIDTH; + tmp->hints.max_height = MAX_WINDOW_HEIGHT; + } + if(tmp->hints.max_width < tmp->hints.min_width) + tmp->hints.max_width = MAX_WINDOW_WIDTH; + if(tmp->hints.max_height < tmp->hints.min_height) + tmp->hints.max_height = MAX_WINDOW_HEIGHT; + + /* Zero width/height windows are bad news! */ + if(tmp->hints.min_height <= 0) + tmp->hints.min_height = 1; + if(tmp->hints.min_width <= 0) + tmp->hints.min_width = 1; + + if(!(tmp->hints.flags & PWinGravity)) + { + tmp->hints.win_gravity = NorthWestGravity; + tmp->hints.flags |= PWinGravity; + } +} + + +/*********************************************************************** + * + * Procedure: + * LookInList - look through a list for a window name, or class + * + * Returned Value: + * the ptr field of the list structure or NULL if the name + * or class was not found in the list + * + * Inputs: + * list - a pointer to the head of a list + * name - a pointer to the name to look for + * class - a pointer to the class to look for + * + ***********************************************************************/ +unsigned long LookInList(name_list *list, char *name, XClassHint *class, + char **value, int *Desk, int *border_width, + int *resize_width, char **forecolor, char **backcolor, + unsigned long * buttons) +{ + name_list *nptr; + unsigned long retval = 0; + + *value = NULL; + *forecolor = NULL; + *backcolor = NULL; + *Desk = 0; + *buttons = 0; + /* look for the name first */ + for (nptr = list; nptr != NULL; nptr = nptr->next) + { + if (class) + { + /* first look for the res_class (lowest priority) */ + if (matchWildcards(nptr->name,class->res_class) == TRUE) + { + if(nptr->value != NULL)*value = nptr->value; + if(nptr->off_flags & STAYSONDESK_FLAG) + *Desk = nptr->Desk; + if(nptr->off_flags & BW_FLAG) + *border_width = nptr->border_width; + if(nptr->off_flags & FORE_COLOR_FLAG) + *forecolor = nptr->ForeColor; + if(nptr->off_flags & BACK_COLOR_FLAG) + *backcolor = nptr->BackColor; + if(nptr->off_flags & NOBW_FLAG) + *resize_width = nptr->resize_width; + retval |= nptr->off_flags; + retval &= ~(nptr->on_flags); + *buttons |= nptr->off_buttons; + *buttons &= ~(nptr->on_buttons); + } + + /* look for the res_name next */ + if (matchWildcards(nptr->name,class->res_name) == TRUE) + { + if(nptr->value != NULL)*value = nptr->value; + if(nptr->off_flags & STAYSONDESK_FLAG) + *Desk = nptr->Desk; + if(nptr->off_flags & FORE_COLOR_FLAG) + *forecolor = nptr->ForeColor; + if(nptr->off_flags & BACK_COLOR_FLAG) + *backcolor = nptr->BackColor; + if(nptr->off_flags & BW_FLAG) + *border_width = nptr->border_width; + if(nptr->off_flags & NOBW_FLAG) + *resize_width = nptr->resize_width; + retval |= nptr->off_flags; + retval &= ~(nptr->on_flags); + *buttons |= nptr->off_buttons; + *buttons &= ~(nptr->on_buttons); + } + } + /* finally, look for name matches */ + if (matchWildcards(nptr->name,name) == TRUE) + { + if(nptr->value != NULL)*value = nptr->value; + if(nptr->off_flags & STAYSONDESK_FLAG) + *Desk = nptr->Desk; + if(nptr->off_flags & FORE_COLOR_FLAG) + *forecolor = nptr->ForeColor; + if(nptr->off_flags & BACK_COLOR_FLAG) + *backcolor = nptr->BackColor; + if(nptr->off_flags & BW_FLAG) + *border_width = nptr->border_width; + if(nptr->off_flags & NOBW_FLAG) + *resize_width = nptr->resize_width; + retval |= nptr->off_flags; + retval &= ~(nptr->on_flags); + *buttons |= nptr->off_buttons; + *buttons &= ~(nptr->on_buttons); + } + } + return retval; +} + + + + + diff --git a/fvwm/alpha_header.h b/fvwm/alpha_header.h new file mode 100644 index 0000000..f40fb39 --- /dev/null +++ b/fvwm/alpha_header.h @@ -0,0 +1,18 @@ +/**************************************************************************/ +/* If I do ALL this, I can compile OK with -Wall -Wstrict-prototypes on the + * alpha's */ +#include +#include + + +extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *); + +/* string manipulation */ +#ifdef __GNUC__ +extern size_t strlen(char *); +#endif + +extern int bzero(char *, int); +extern int gethostname (char *, int); +/**************************************************************************/ + diff --git a/fvwm/borders.c b/fvwm/borders.c new file mode 100644 index 0000000..c0428a2 --- /dev/null +++ b/fvwm/borders.c @@ -0,0 +1,1287 @@ +/**************************************************************************** + * This module is based on Twm, but has been siginificantly modified + * by Rob Nation + ****************************************************************************/ +/*****************************************************************************/ +/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ +/** Salt Lake City, Utah **/ +/** Portions Copyright 1989 by the Massachusetts Institute of Technology **/ +/** Cambridge, Massachusetts **/ +/** **/ +/** All Rights Reserved **/ +/** **/ +/** Permission to use, copy, modify, and distribute this software and **/ +/** its documentation for any purpose and without fee is hereby **/ +/** granted, provided that the above copyright notice appear in all **/ +/** copies and that both that copyright notice and this permis- **/ +/** sion notice appear in supporting documentation, and that the **/ +/** names of Evans & Sutherland and M.I.T. not be used in advertising **/ +/** in publicity pertaining to distribution of the software without **/ +/** specific, written prior permission. **/ +/** **/ +/** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/ +/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/ +/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/ +/** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/ +/** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ +/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ +/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ +/** OR PERFORMANCE OF THIS SOFTWARE. **/ +/*****************************************************************************/ + + +/*********************************************************************** + * + * fvwm window border drawing code + * + ***********************************************************************/ + +#include "../configure.h" + +#include +#include +#include + +#include "fvwm.h" +#include "menus.h" +#include "misc.h" +#include "parse.h" +#include "screen.h" +#include "module.h" + +#ifdef SHAPE +#include +#endif + +void DrawLinePattern(Window win, + GC ReliefGC, + GC ShadowGC, + int num_coords, + int *x_coord, + int *y_coord, + int *line_style, + int th); + +/* macro to change window background color/pixmap */ +#define ChangeWindowColor(window) {\ + if(NewColor)\ + {\ + XChangeWindowAttributes(dpy,window,valuemask, &attributes);\ + XClearWindow(dpy,window);\ + }\ + } + +extern Window PressedW; + +/**************************************************************************** + * + * Redraws the windows borders + * + ****************************************************************************/ +void SetBorder (FvwmWindow *t, Bool onoroff,Bool force,Bool Mapped, + Window expose_win) +{ + Window w=None; + int y, i, x; + GC ReliefGC,ShadowGC; + Pixel BorderColor,BackColor; + Pixmap BackPixmap,TextColor; + Bool NewColor = False; + XSetWindowAttributes attributes; + unsigned long valuemask; + static unsigned int corners[4]; + + corners[0] = TOP_HILITE | LEFT_HILITE; + corners[1] = TOP_HILITE | RIGHT_HILITE; + corners[2] = BOTTOM_HILITE | LEFT_HILITE; + corners[3] = BOTTOM_HILITE | RIGHT_HILITE; + + if(!t) + return; + + if (onoroff) + { + /* don't re-draw just for kicks */ + if((!force)&&(Scr.Hilite == t)) + return; + + + if(Scr.Hilite != t) + NewColor = True; + + /* make sure that the previously highlighted window got unhighlighted */ + if((Scr.Hilite != t)&&(Scr.Hilite != NULL)) + SetBorder(Scr.Hilite,False,False,True,None); + + /* set the keyboard focus */ + if((Mapped)&&(t->flags&MAPPED)&&(Scr.Hilite != t)) + w = t->w; + else if((t->flags&ICONIFIED)&& + (Scr.Hilite !=t)&&(!(t->flags &SUPPRESSICON))) + w = t->icon_w; + Scr.Hilite = t; + + TextColor = Scr.HiColors.fore; + BackPixmap= Scr.gray_pixmap; + BackColor = Scr.HiColors.back; + ReliefGC = Scr.HiReliefGC; + ShadowGC = Scr.HiShadowGC; + BorderColor = Scr.HiRelief.back; + } + else + { + /* don't re-draw just for kicks */ + if((!force)&&(Scr.Hilite != t)) + return; + + if(Scr.Hilite == t) + { + Scr.Hilite = NULL; + NewColor = True; + } + + TextColor =t->TextPixel; + BackPixmap = Scr.light_gray_pixmap; + if(t->flags & STICKY) + BackPixmap = Scr.sticky_gray_pixmap; + BackColor = t->BackPixel; + if(t->BackPixel != Scr.StdColors.back) + { + Globalgcv.foreground = t->ReliefPixel; + Globalgcm = GCForeground; + XChangeGC(dpy,Scr.ScratchGC1,Globalgcm,&Globalgcv); + ReliefGC = Scr.ScratchGC1; + + Globalgcv.foreground = t->ShadowPixel; + XChangeGC(dpy,Scr.ScratchGC2,Globalgcm,&Globalgcv); + ShadowGC = Scr.ScratchGC2; + } + else + { + ReliefGC = Scr.StdReliefGC; + ShadowGC = Scr.StdShadowGC; + } + BorderColor = t->ShadowPixel; + } + +#ifndef NO_PAGER + if((Scr.Pager_w) && !(t->flags & STICKY)) + { + if(NewColor) + { + if(Scr.d_depth < 2) + XSetWindowBackgroundPixmap(dpy,t->pager_view,BackPixmap); + else + XSetWindowBackground(dpy,t->pager_view,BackColor); + XClearWindow(dpy,t->pager_view); + } + if((t->icon_name != NULL)&&(Scr.PagerFont.height > 0)) + { + NewFontAndColor(Scr.PagerFont.font->fid,TextColor,BackColor); + XDrawImageString(dpy, t->pager_view, Scr.FontGC, 2,Scr.PagerFont.y+2, + t->icon_name, strlen(t->icon_name)); + } + } +#endif + + if(t->flags & ICONIFIED) + { + DrawIconWindow(t); + return; + } + + valuemask = CWBorderPixel; + attributes.border_pixel = BorderColor; + if(Scr.d_depth < 2) + { + attributes.background_pixmap = BackPixmap; + valuemask |= CWBackPixmap; + } + else + { + attributes.background_pixel = BackColor; + valuemask |= CWBackPixel; + } + + if(t->flags & (TITLE|BORDER)) + { + XSetWindowBorder(dpy,t->Parent,BorderColor); + XSetWindowBorder(dpy,t->frame,BorderColor); + } + if(t->flags & TITLE) + { + ChangeWindowColor(t->title_w); + for(i=0;ileft_w[i] != None) + { + ChangeWindowColor(t->left_w[i]); + if(flush_expose(t->left_w[i])||(expose_win == t->left_w[i])|| + (expose_win == None)) + { + RelieveWindow(t,t->left_w[i],0,0,t->title_height, + t->title_height, + (PressedW==t->left_w[i]?ShadowGC:ReliefGC), + (PressedW==t->left_w[i]?ReliefGC:ShadowGC), + BOTTOM_HILITE); + if (Scr.use_new_style[i*2+1]) + { + DrawLinePattern(t->left_w[i],ReliefGC,ShadowGC, + Scr.left_num_coords[i], + Scr.left_x_coords[i], Scr.left_y_coords[i], + Scr.left_line_style[i], + t->title_height); + } + else + { + DrawPattern(t->left_w[i],ReliefGC,ShadowGC, + Scr.left_button_styles[1][i], + Scr.left_button_styles[0][i],t->title_height); + } + } + } + + } + for(i=0;iright_w[i] != None) + { + ChangeWindowColor(t->right_w[i]); + if(flush_expose(t->right_w[i])||(expose_win==t->right_w[i])|| + (expose_win == None)) + { + GC sgc,rgc; + + sgc=ShadowGC; + rgc=ReliefGC; + if((Scr.flags & MWMButtons)&&(!i)&&(t->flags&MAXIMIZED)) + { + sgc = ReliefGC; + rgc = ShadowGC; + } + RelieveWindow(t,t->right_w[i],0,0,t->title_height, + t->title_height, + (PressedW==t->right_w[i] + ?ShadowGC:ReliefGC), + (PressedW==t->right_w[i] + ?ReliefGC:ShadowGC), + BOTTOM_HILITE); + if (Scr.use_new_style[(i*2+2)%10]) + { + DrawLinePattern(t->right_w[i],ReliefGC,ShadowGC, + Scr.right_num_coords[i], + Scr.right_x_coords[i], Scr.right_y_coords[i], + Scr.right_line_style[i], + t->title_height); + } + else + { + DrawPattern(t->right_w[i],rgc,sgc, + Scr.right_button_styles[1][i], + Scr.right_button_styles[0][i],t->title_height); + } + } + } + } + SetTitleBar(t,onoroff, False); + + } + + if(t->flags & BORDER) + { + /* draw relief lines */ + y= t->frame_height - 2*t->corner_width; + x = t->frame_width- 2*t->corner_width +t->bw; + + for(i=0;i<4;i++) + { + ChangeWindowColor(t->sides[i]); + if((flush_expose (t->sides[i]))||(expose_win == t->sides[i])|| + (expose_win == None)) + { + GC sgc,rgc; + + sgc=ShadowGC; + rgc=ReliefGC; + if(!(Scr.flags & MWMButtons)&&(PressedW == t->sides[i])) + { + sgc = ReliefGC; + rgc = ShadowGC; + } + /* index side + * 0 TOP + * 1 RIGHT + * 2 BOTTOM + * 3 LEFT + */ + + RelieveWindow(t,t->sides[i],0,0, + ((i%2)?t->boundary_width:x), + ((i%2)?y:t->boundary_width), + rgc, sgc, (0x0001<corners[i]); + if((flush_expose(t->corners[i]))||(expose_win==t->corners[i])|| + (expose_win == None)) + { + GC rgc,sgc; + + rgc = ReliefGC; + sgc = ShadowGC; + if(!(Scr.flags & MWMButtons)&&(PressedW == t->corners[i])) + { + sgc = ReliefGC; + rgc = ShadowGC; + } + RelieveWindow(t,t->corners[i],0,0,t->corner_width, + ((i/2)?t->corner_width+t->bw:t->corner_width), + rgc,sgc, corners[i]); + if(t->boundary_width > 1) + RelieveParts(t,i,((i/2)?rgc:sgc),((i%2)?rgc:sgc)); + else + RelieveParts(t,i,((i/2)?sgc:sgc),((i%2)?sgc:sgc)); + } + } + } + else /* no decorative border */ + { + /* for mono - put a black border on + * for color, make it the color of the decoration background */ + if(t->boundary_width < 2) + { + flush_expose (t->frame); + if(Scr.d_depth <2) + { + XSetWindowBorder(dpy,t->frame,TextColor); + XSetWindowBorder(dpy,t->Parent,TextColor); + XSetWindowBackgroundPixmap(dpy,t->frame,BackPixmap); + XClearWindow(dpy,t->frame); + XSetWindowBackgroundPixmap(dpy,t->Parent,BackPixmap); + XClearWindow(dpy,t->Parent); + } + else + { + XSetWindowBackground(dpy,t->frame,BorderColor); + XSetWindowBorder(dpy,t->frame,BorderColor); + XClearWindow(dpy,t->frame); + XSetWindowBackground(dpy,t->Parent,BorderColor); + XSetWindowBorder(dpy,t->Parent,BorderColor); + XClearWindow(dpy,t->Parent); + XSetWindowBorder(dpy,t->w,BorderColor); + } + } + else + { + GC rgc,sgc; + + XSetWindowBorder(dpy,t->Parent,BorderColor); + XSetWindowBorder(dpy,t->frame,BorderColor); + + rgc=ReliefGC; + sgc=ShadowGC; + if(!(Scr.flags & MWMButtons)&&(PressedW == t->frame)) + { + sgc=ReliefGC; + rgc=ShadowGC; + } + ChangeWindowColor(t->frame); + if((flush_expose(t->frame))||(expose_win == t->frame)|| + (expose_win == None)) + { + if(t->boundary_width > 2) + { + RelieveWindow(t,t->frame,t->boundary_width-1 - t->bw, + t->boundary_width-1-t->bw, + t->frame_width- + (t->boundary_width<<1)+2+3*t->bw, + t->frame_height- + (t->boundary_width<<1)+2+3*t->bw, + sgc,rgc, + TOP_HILITE|LEFT_HILITE|RIGHT_HILITE| + BOTTOM_HILITE); + RelieveWindow(t,t->frame,0,0,t->frame_width+t->bw, + t->frame_height+t->bw,rgc,sgc, + TOP_HILITE|LEFT_HILITE|RIGHT_HILITE| + BOTTOM_HILITE); + } + else + { + RelieveWindow(t,t->frame,0,0,t->frame_width+t->bw, + t->frame_height+t->bw,rgc,rgc, + TOP_HILITE|LEFT_HILITE|RIGHT_HILITE| + BOTTOM_HILITE); + } + } + else + { + XSetWindowBackground(dpy,t->Parent,BorderColor); + } + } + } +} + + +/**************************************************************************** + * + * Redraws just the title bar + * + ****************************************************************************/ +void SetTitleBar (FvwmWindow *t,Bool onoroff, Bool NewTitle) +{ + int hor_off, w; + GC ReliefGC,ShadowGC,tGC; + Pixel Forecolor, BackColor; + + if(!t) + return; + if(!(t->flags & TITLE)) + return; + + if (onoroff) + { + Forecolor = Scr.HiColors.fore; + BackColor = Scr.HiColors.back; + ReliefGC = (PressedW==t->title_w?Scr.HiShadowGC:Scr.HiReliefGC); + ShadowGC = (PressedW==t->title_w?Scr.HiReliefGC:Scr.HiShadowGC); + } + else + { + Forecolor =t->TextPixel; + BackColor = t->BackPixel; + if(t->BackPixel != Scr.StdColors.back) + { + Globalgcv.foreground = t->ReliefPixel; + Globalgcm = GCForeground; + XChangeGC(dpy,Scr.ScratchGC1,Globalgcm,&Globalgcv); + ReliefGC = Scr.ScratchGC1; + + Globalgcv.foreground = t->ShadowPixel; + XChangeGC(dpy,Scr.ScratchGC2,Globalgcm,&Globalgcv); + ShadowGC = Scr.ScratchGC2; + } + else + { + ReliefGC = Scr.StdReliefGC; + ShadowGC = Scr.StdShadowGC; + } + if(PressedW==t->title_w) + { + tGC = ShadowGC; + ShadowGC = ReliefGC; + ReliefGC = tGC; + } + } + flush_expose(t->title_w); + + if(t->name != (char *)NULL) + { + w=XTextWidth(Scr.WindowFont.font,t->name,strlen(t->name)); + if(w > t->title_width-12) + w = t->title_width-4; + if(w < 0) + w = 0; + } + else + w = 0; + + + hor_off = (t->title_width - w)/2; + + NewFontAndColor(Scr.WindowFont.font->fid,Forecolor, BackColor); + + if(NewTitle) + XClearWindow(dpy,t->title_w); + + /* for mono, we clear an area in the title bar where the window + * title goes, so that its more legible. For color, no need */ + if(Scr.d_depth<2) + { + RelieveWindow(t,t->title_w,0,0,hor_off-2,t->title_height, + ReliefGC, ShadowGC, BOTTOM_HILITE); + RelieveWindow(t,t->title_w,hor_off+w+2,0, + t->title_width - w - hor_off-2,t->title_height, + ReliefGC, ShadowGC, BOTTOM_HILITE); + XFillRectangle(dpy,t->title_w, + (PressedW==t->title_w?ShadowGC:ReliefGC), + hor_off - 2, 0, w+4,t->title_height); + + XDrawLine(dpy,t->title_w,ShadowGC,hor_off+w+1,0,hor_off+w+1, + t->title_height); + if(t->name != (char *)NULL) + XDrawString (dpy, t->title_w,Scr.FontGC,hor_off, Scr.WindowFont.y+1, + t->name, strlen(t->name)); + } + else + { + if(t->name != (char *)NULL) + XDrawString (dpy, t->title_w,Scr.FontGC,hor_off, Scr.WindowFont.y+1, + t->name, strlen(t->name)); + RelieveWindow(t,t->title_w,0,0,t->title_width,t->title_height, + ReliefGC, ShadowGC, BOTTOM_HILITE); + } + + XFlush(dpy); +} + + + + +/**************************************************************************** + * + * Draws the relief pattern around a window + * + ****************************************************************************/ +FVWM_INLINE void RelieveWindow(FvwmWindow *t,Window win, + int x,int y,int w,int h, + GC ReliefGC,GC ShadowGC, int hilite) +{ + XSegment seg[4]; + int i; + int edge; + + edge = 0; + if((win == t->sides[0])||(win == t->sides[1])|| + (win == t->sides[2])||(win == t->sides[3])) + edge = -1; + if(win == t->corners[0]) + edge = 1; + if(win == t->corners[1]) + edge = 2; + if(win == t->corners[2]) + edge = 3; + if(win == t->corners[3]) + edge = 4; + + i=0; + seg[i].x1 = x; seg[i].y1 = y; + seg[i].x2 = w+x-1; seg[i++].y2 = y; + + seg[i].x1 = x; seg[i].y1 = y; + seg[i].x2 = x; seg[i++].y2 = h+y-1; + + if(((t->boundary_width > 2)||(edge == 0))&& + ((t->boundary_width > 3)||(edge < 1))&& + (!(Scr.flags & MWMBorders)|| + (((edge==0)||(t->boundary_width > 3))&&(hilite & TOP_HILITE)))) + { + seg[i].x1 = x+1; seg[i].y1 = y+1; + seg[i].x2 = x+w-2; seg[i++].y2 = y+1; + } + if(((t->boundary_width > 2)||(edge == 0))&& + ((t->boundary_width > 3)||(edge < 1))&& + (!(Scr.flags & MWMBorders)|| + (((edge==0)||(t->boundary_width > 3))&&(hilite & LEFT_HILITE)))) + { + seg[i].x1 = x+1; seg[i].y1 = y+1; + seg[i].x2 = x+1; seg[i++].y2 = y+h-2; + } + XDrawSegments(dpy, win, ReliefGC, seg, i); + + i=0; + seg[i].x1 = x; seg[i].y1 = y+h-1; + seg[i].x2 = w+x-1; seg[i++].y2 = y+h-1; + + if(((t->boundary_width > 2)||(edge == 0))&& + (!(Scr.flags & MWMBorders)|| + (((edge==0)||(t->boundary_width > 3))&&(hilite & BOTTOM_HILITE)))) + { + seg[i].x1 = x+1; seg[i].y1 = y+h-2; + seg[i].x2 = x+w-2; seg[i++].y2 = y+h-2; + } + + seg[i].x1 = x+w-1; seg[i].y1 = y; + seg[i].x2 = x+w-1; seg[i++].y2 = y+h-1; + + if(((t->boundary_width > 2)||(edge == 0))&& + (!(Scr.flags & MWMBorders)|| + (((edge==0)||(t->boundary_width > 3))&&(hilite & RIGHT_HILITE)))) + { + seg[i].x1 = x+w-2; seg[i].y1 = y+1; + seg[i].x2 = x+w-2; seg[i++].y2 = y+h-2; + } + XDrawSegments(dpy, win, ShadowGC, seg, i); +} + +void RelieveParts(FvwmWindow *t,int i,GC hor, GC vert) +{ + XSegment seg[2]; + int n = 0; + + if((Scr.flags & MWMBorders)||(t->boundary_width < 3)) + { + switch(i) + { + case 0: + seg[0].x1 = t->boundary_width-1; + seg[0].x2 = t->corner_width; + seg[0].y1 = t->boundary_width-1; + seg[0].y2 = t->boundary_width-1; + n=1; + break; + case 1: + seg[0].x1 = 0; + seg[0].x2 = t->corner_width - t->boundary_width /* -1*/ ; + seg[0].y1 = t->boundary_width-1; + seg[0].y2 = t->boundary_width-1; + n=1; + break; + case 2: + seg[0].x1 = t->boundary_width-1; + seg[0].x2 = t->corner_width-2; + seg[0].y1 = t->corner_width - t->boundary_width+t->bw; + seg[0].y2 = t->corner_width - t->boundary_width+t->bw; + n=1; + break; + case 3: + seg[0].x1 = 0; + seg[0].x2 = t->corner_width - t->boundary_width; + seg[0].y1 = t->corner_width - t->boundary_width+t->bw; + seg[0].y2 = t->corner_width - t->boundary_width+t->bw; + n=1; + break; + } + XDrawSegments(dpy, t->corners[i], hor, seg, n); + switch(i) + { + case 0: + seg[0].y1 = t->boundary_width-1; + seg[0].y2 = t->corner_width; + seg[0].x1 = t->boundary_width-1; + seg[0].x2 = t->boundary_width-1; + n=1; + break; + case 1: + seg[0].y1 = t->boundary_width -1; + seg[0].y2 = t->corner_width-2; + seg[0].x1 = t->corner_width - t->boundary_width; + seg[0].x2 = t->corner_width - t->boundary_width; + n=1; + break; + case 2: + seg[0].y1 = 0; + seg[0].y2 = t->corner_width - t->boundary_width; + seg[0].x1 = t->boundary_width-1; + seg[0].x2 = t->boundary_width-1; + n=1; + break; + case 3: + seg[0].y1 = 0; + seg[0].y2 = t->corner_width - t->boundary_width + t->bw; + seg[0].x1 = t->corner_width - t->boundary_width; + seg[0].x2 = t->corner_width - t->boundary_width; + n=1; + break; + } + XDrawSegments(dpy, t->corners[i], vert, seg, 1); + } + else + { + switch(i) + { + case 0: + seg[0].x1 = t->boundary_width-2; + seg[0].x2 = t->corner_width; + seg[0].y1 = t->boundary_width-2; + seg[0].y2 = t->boundary_width-2; + + seg[1].x1 = t->boundary_width-2; + seg[1].x2 = t->corner_width; + seg[1].y1 = t->boundary_width-1; + seg[1].y2 = t->boundary_width-1; + n=2; + break; + case 1: + seg[0].x1 = 1; + seg[0].x2 = t->corner_width - t->boundary_width; + seg[0].y1 = t->boundary_width-2; + seg[0].y2 = t->boundary_width-2; + + seg[1].x1 = 0; + seg[1].x2 = t->corner_width - t->boundary_width-1; + seg[1].y1 = t->boundary_width-1; + seg[1].y2 = t->boundary_width-1; + n=2; + break; + case 2: + seg[0].x1 = t->boundary_width-1; + seg[0].x2 = t->corner_width-2; + seg[0].y1 = t->corner_width - t->boundary_width+1; + seg[0].y2 = t->corner_width - t->boundary_width+1; + n=1; + if(t->boundary_width > 3) + { + seg[1].x1 = t->boundary_width-2; + seg[1].x2 = t->corner_width-3; + seg[1].y1 = t->corner_width - t->boundary_width + 2; + seg[1].y2 = t->corner_width - t->boundary_width + 2; + n=2; + } + break; + case 3: + seg[0].x1 = 0; + seg[0].x2 = t->corner_width - t->boundary_width; + seg[0].y1 = t->corner_width - t->boundary_width+1; + seg[0].y2 = t->corner_width - t->boundary_width+1; + n=1; + if(t->boundary_width > 3) + { + seg[0].x2 = t->corner_width - t->boundary_width + 1; + + seg[1].x1 = 0; + seg[1].x2 = t->corner_width - t->boundary_width + 1; + seg[1].y1 = t->corner_width - t->boundary_width + 2; + seg[1].y2 = t->corner_width - t->boundary_width + 2; + n=2; + } + break; + } + XDrawSegments(dpy, t->corners[i], hor, seg, n); + switch(i) + { + case 0: + seg[0].y1 = t->boundary_width-2; + seg[0].y2 = t->corner_width; + seg[0].x1 = t->boundary_width-2; + seg[0].x2 = t->boundary_width-2; + + seg[1].y1 = t->boundary_width-2; + seg[1].y2 = t->corner_width; + seg[1].x1 = t->boundary_width-1; + seg[1].x2 = t->boundary_width-1; + n=2; + break; + case 1: + seg[0].y1 = t->boundary_width-1; + seg[0].y2 = t->corner_width-2; + seg[0].x1 = t->corner_width - t->boundary_width; + seg[0].x2 = t->corner_width - t->boundary_width; + n=1; + if(t->boundary_width > 3) + { + seg[1].y1 = t->boundary_width-2; + seg[1].y2 = t->corner_width-3; + seg[1].x1 = t->corner_width - t->boundary_width+1; + seg[1].x2 = t->corner_width - t->boundary_width+1; + n=2; + } + break; + case 2: + seg[0].y1 = 1; + seg[0].y2 = t->corner_width - t->boundary_width+1; + seg[0].x1 = t->boundary_width-2; + seg[0].x2 = t->boundary_width-2; + n=1; + + if(t->boundary_width > 3) + { + seg[1].y1 = 0; + seg[1].y2 = t->corner_width - t->boundary_width; + seg[1].x1 = t->boundary_width-1; + seg[1].x2 = t->boundary_width-1; + } + break; + case 3: + seg[0].y1 = 0; + seg[0].y2 = t->corner_width - t->boundary_width + 1; + seg[0].x1 = t->corner_width - t->boundary_width; + seg[0].x2 = t->corner_width - t->boundary_width; + n=1; + + if(t->boundary_width > 3) + { + seg[0].y2 = t->corner_width - t->boundary_width + 2; + seg[1].y1 = 0; + seg[1].y2 = t->corner_width - t->boundary_width + 2; + seg[1].x1 = t->corner_width - t->boundary_width + 1; + seg[1].x2 = t->corner_width - t->boundary_width + 1; + n=2; + } + break; + } + XDrawSegments(dpy, t->corners[i], vert, seg, n); + } +} +/**************************************************************************** + * + * Draws a little pattern within a window + * + ****************************************************************************/ +FVWM_INLINE void DrawPattern(Window win, GC ShadowGC, GC ReliefGC, int h1, int w1, int t1) +{ + XSegment seg[2]; + int i,h,b,u,w,r,l; + + h = t1*h1/200; + b = (t1>>1) + h; + u = t1 - b-1; + w = t1*w1/200; + r = (t1>>1) + w; + l = t1 - r-1; + + i=0; + seg[i].x1 = l; seg[i].y1 = u; + seg[i].x2 = r; seg[i++].y2 = u; + + seg[i].x1 = l; seg[i].y1 = u; + seg[i].x2 = l; seg[i++].y2 = b; + XDrawSegments(dpy, win, ShadowGC, seg, i); + + i=0; + seg[i].x1 = l; seg[i].y1 = b; + seg[i].x2 = r; seg[i++].y2 = b; + + seg[i].x1 = r; seg[i].y1 = u; + seg[i].x2 = r; seg[i++].y2 = b; + XDrawSegments(dpy, win, ReliefGC, seg, i); +} + +/**************************************************************************** + * + * Draws a little pattern within a window (more complex) + * + ****************************************************************************/ +void DrawLinePattern(Window win, + GC ReliefGC, + GC ShadowGC, + int num_coords, + int *x_coord, + int *y_coord, + int *line_style, + int th) +{ + int i; + + for (i=1;iframe_XXX variables should NOT be updated with the + * values of x,y,w,h prior to calling this routine, since the new + * values are compared against the old to see whether a synthetic + * ConfigureNotify event should be sent. (It should be sent if the + * window was moved but not resized.) + * + ************************************************************************/ + +void SetupFrame(FvwmWindow *tmp_win,int x,int y,int w,int h,Bool sendEvent) +{ + XEvent client_event; + XWindowChanges frame_wc, xwc; + unsigned long frame_mask, xwcm; + int cx,cy,i; + Bool Resized = False; +#ifndef NO_PAGER + FvwmWindow *t; +#endif + int xwidth,ywidth,left,right; + + /* if windows is not being maximized, save size in case of maximization */ + if (!(tmp_win->flags & MAXIMIZED)) + { + tmp_win->orig_x = x; + tmp_win->orig_y = y; + tmp_win->orig_wd = w; + tmp_win->orig_ht = h; + } + if(Scr.flags & DontMoveOff) + { + if (x + Scr.Vx + w < 16) + x = 16 - Scr.Vx - w; + if (y + Scr.Vy + h < 16) + y = 16 - Scr.Vy - h; + } + if (x >= Scr.MyDisplayWidth + Scr.VxMax - Scr.Vx-16) + x = Scr.MyDisplayWidth + Scr.VxMax -Scr.Vx - 16; + if (y >= Scr.MyDisplayHeight+Scr.VyMax - Scr.Vy -16) + y = Scr.MyDisplayHeight + Scr.VyMax - Scr.Vy - 16; + + /* + * According to the July 27, 1988 ICCCM draft, we should send a + * "synthetic" ConfigureNotify event to the client if the window + * was moved but not resized. + */ + if ((x != tmp_win->frame_x || y != tmp_win->frame_y) && + (w == tmp_win->frame_width && h == tmp_win->frame_height)) + sendEvent = TRUE; + + if((w != tmp_win->frame_width) || (h != tmp_win->frame_height)) + Resized = True; + + if(Resized) + { + left = tmp_win->nr_left_buttons; + right = tmp_win->nr_right_buttons; + + tmp_win->title_width= w- + (left+right)*tmp_win->title_height + -2*tmp_win->boundary_width+tmp_win->bw; + + + if(tmp_win->title_width < 1) + tmp_win->title_width = 1; + + if (tmp_win->flags & TITLE) + { + xwcm = CWWidth | CWX | CWY; + tmp_win->title_x = tmp_win->boundary_width+ + (left)*tmp_win->title_height; + if(tmp_win->title_x >= w - tmp_win->boundary_width) + tmp_win->title_x = -10; + tmp_win->title_y = tmp_win->boundary_width; + + xwc.width = tmp_win->title_width; + xwc.x = tmp_win->title_x; + xwc.y = tmp_win->title_y; + XConfigureWindow(dpy, tmp_win->title_w, xwcm, &xwc); + + + xwcm = CWX | CWY; + xwc.y = tmp_win->boundary_width; + + xwc.x = tmp_win->boundary_width; + for(i=0;ileft_w[i] != None) + { + if(xwc.x + tmp_win->title_height < w - tmp_win->boundary_width) + XConfigureWindow(dpy, tmp_win->left_w[i], xwcm, &xwc); + else + { + xwc.x = -tmp_win->title_height; + XConfigureWindow(dpy, tmp_win->left_w[i], xwcm, &xwc); + } + xwc.x += tmp_win->title_height; + } + } + + xwc.x=w-tmp_win->boundary_width+tmp_win->bw; + for(i=0;iright_w[i] != None) + { + xwc.x -=tmp_win->title_height; + if(xwc.x > tmp_win->boundary_width) + XConfigureWindow(dpy, tmp_win->right_w[i], xwcm, &xwc); + else + { + xwc.x = -tmp_win->title_height; + XConfigureWindow(dpy, tmp_win->right_w[i], xwcm, &xwc); + } + } + } + } + + if(tmp_win->flags & BORDER) + { + xwidth = w - 2*tmp_win->corner_width+tmp_win->bw; + ywidth = h - 2*tmp_win->corner_width; + xwcm = CWWidth | CWHeight | CWX | CWY; + if(xwidth<2) + xwidth = 2; + if(ywidth<2) + ywidth = 2; + + for(i=0;i<4;i++) + { + if(i==0) + { + xwc.x = tmp_win->corner_width; + xwc.y = 0; + xwc.height = tmp_win->boundary_width; + xwc.width = xwidth; + } + else if (i==1) + { + xwc.x = w - tmp_win->boundary_width+tmp_win->bw; + xwc.y = tmp_win->corner_width; + xwc.width = tmp_win->boundary_width; + xwc.height = ywidth; + + } + else if(i==2) + { + xwc.x = tmp_win->corner_width; + xwc.y = h - tmp_win->boundary_width+tmp_win->bw; + xwc.height = tmp_win->boundary_width+tmp_win->bw; + xwc.width = xwidth; + } + else + { + xwc.x = 0; + xwc.y = tmp_win->corner_width; + xwc.width = tmp_win->boundary_width; + xwc.height = ywidth; + } + XConfigureWindow(dpy, tmp_win->sides[i], xwcm, &xwc); + } + + xwcm = CWX|CWY; + for(i=0;i<4;i++) + { + if(i%2) + xwc.x = w - tmp_win->corner_width+tmp_win->bw; + else + xwc.x = 0; + + if(i/2) + xwc.y = h - tmp_win->corner_width; + else + xwc.y = 0; + + XConfigureWindow(dpy, tmp_win->corners[i], xwcm, &xwc); + } + + } + } + tmp_win->attr.width = w - 2*tmp_win->boundary_width; + tmp_win->attr.height = h - tmp_win->title_height + - 2*tmp_win->boundary_width; + /* may need to omit the -1 for shaped windows, next two lines*/ + cx = tmp_win->boundary_width-tmp_win->bw; + cy = tmp_win->title_height + tmp_win->boundary_width-tmp_win->bw; + + XResizeWindow(dpy, tmp_win->w, tmp_win->attr.width, + tmp_win->attr.height); + XMoveResizeWindow(dpy, tmp_win->Parent, cx,cy, + tmp_win->attr.width, tmp_win->attr.height); + + /* + * fix up frame and assign size/location values in tmp_win + */ + frame_wc.x = tmp_win->frame_x = x; + frame_wc.y = tmp_win->frame_y = y; + frame_wc.width = tmp_win->frame_width = w; + frame_wc.height = tmp_win->frame_height = h; + frame_mask = (CWX | CWY | CWWidth | CWHeight); + XConfigureWindow (dpy, tmp_win->frame, frame_mask, &frame_wc); + + +#ifdef SHAPE + if ((Resized)&&(tmp_win->wShaped)) + { + SetShape(tmp_win,w); + } +#endif /* SHAPE */ + XSync(dpy,0); + if (sendEvent) + { + client_event.type = ConfigureNotify; + client_event.xconfigure.display = dpy; + client_event.xconfigure.event = tmp_win->w; + client_event.xconfigure.window = tmp_win->w; + + client_event.xconfigure.x = x + tmp_win->boundary_width; + client_event.xconfigure.y = y + tmp_win->title_height+ + tmp_win->boundary_width; + client_event.xconfigure.width = w-2*tmp_win->boundary_width; + client_event.xconfigure.height =h-2*tmp_win->boundary_width - + tmp_win->title_height; + + client_event.xconfigure.border_width =tmp_win->bw; + /* Real ConfigureNotify events say we're above title window, so ... */ + /* what if we don't have a title ????? */ + client_event.xconfigure.above = tmp_win->frame; + client_event.xconfigure.override_redirect = False; + XSendEvent(dpy, tmp_win->w, False, StructureNotifyMask, &client_event); + } +#ifndef NO_PAGER + if(tmp_win == Scr.FvwmPager) + { + MoveResizeViewPortIndicator(); + for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) + { + MoveResizePagerView(t); + } + } + else + MoveResizePagerView(tmp_win); +#endif + BroadcastConfig(M_CONFIGURE_WINDOW,tmp_win); +} + + +/**************************************************************************** + * + * Sets up the shaped window borders + * + ****************************************************************************/ +void SetShape(FvwmWindow *tmp_win, int w) +{ +#ifdef SHAPE + XRectangle rect; + + XShapeCombineShape (dpy, tmp_win->frame, ShapeBounding, + tmp_win->boundary_width, + tmp_win->title_height+tmp_win->boundary_width, + tmp_win->w, + ShapeBounding, ShapeSet); + if (tmp_win->title_w) + { + /* windows w/ titles */ + rect.x = tmp_win->boundary_width; + rect.y = tmp_win->title_y; + rect.width = w - 2*tmp_win->boundary_width+tmp_win->bw; + rect.height = tmp_win->title_height; + + + XShapeCombineRectangles(dpy,tmp_win->frame,ShapeBounding, + 0,0,&rect,1,ShapeUnion,Unsorted); + } +#endif +} + +/******************************************************************** + * + * Sets the input focus to the indicated window. + * + **********************************************************************/ + +void SetFocus(Window w, FvwmWindow *Fw) +{ + int i; + extern Time lastTimestamp; + + /* ClickToFocus focus queue manipulation */ + if (Fw && Fw != Scr.Focus && Fw != &Scr.FvwmRoot) + { + FvwmWindow *tmp_win1, *tmp_win2; + + tmp_win1 = Fw->prev; + tmp_win2 = Fw->next; + + if (tmp_win1) tmp_win1->next = tmp_win2; + if (tmp_win2) tmp_win2->prev = tmp_win1; + + Fw->next = Scr.FvwmRoot.next; + if(Scr.FvwmRoot.next)Scr.FvwmRoot.next->prev = Fw; + Scr.FvwmRoot.next = Fw; + Fw->prev = &Scr.FvwmRoot; + } + + if(Scr.NumberOfScreens > 1) + { + XQueryPointer(dpy, Scr.Root, &JunkRoot, &JunkChild, + &JunkX, &JunkY, &JunkX, &JunkY, &JunkMask); + if(JunkRoot != Scr.Root) + { + if((Scr.flags & ClickToFocus) && (Scr.Ungrabbed != NULL)) + { + /* Need to grab buttons for focus window */ + XSync(dpy,0); + for(i=0;i<3;i++) + if(Scr.buttons2grab & (1<frame,True, + ButtonPressMask, GrabModeSync,GrabModeAsync, + None,Scr.FvwmCursors[SYS]); + XGrabButton(dpy,(i+1),LockMask,Scr.Ungrabbed->frame,True, + ButtonPressMask, GrabModeSync,GrabModeAsync, + None,Scr.FvwmCursors[SYS]); + } + Scr.Focus = NULL; + Scr.Ungrabbed = NULL; + XSetInputFocus(dpy, Scr.NoFocusWin,RevertToParent,lastTimestamp); + } + return; + } + } + + if((Fw != NULL)&&(Fw->Desk != Scr.CurrentDesk)) + { + Fw = NULL; + w = Scr.NoFocusWin; + } + + if((Scr.flags & ClickToFocus) && (Scr.Ungrabbed != Fw)) + { + /* need to grab all buttons for window that we are about to + * unfocus */ + if(Scr.Ungrabbed != NULL) + { + XSync(dpy,0); + for(i=0;i<3;i++) + if(Scr.buttons2grab & (1<frame,True, + ButtonPressMask, GrabModeSync,GrabModeAsync,None, + Scr.FvwmCursors[SYS]); + XGrabButton(dpy,(i+1),LockMask,Scr.Ungrabbed->frame,True, + ButtonPressMask, GrabModeSync,GrabModeAsync,None, + Scr.FvwmCursors[SYS]); + } + Scr.Ungrabbed = NULL; + } + /* if we do click to focus, remove the grab on mouse events that + * was made to detect the focus change */ + if((Scr.flags & ClickToFocus)&&(Fw != NULL)) + { + for(i=0;i<3;i++) + if(Scr.buttons2grab & (1<frame); + XUngrabButton(dpy,(i+1),LockMask,Fw->frame); + } + Scr.Ungrabbed = Fw; + } + } + if((Fw)&&(Fw->flags & ICONIFIED)&&(Fw->icon_w)) + w= Fw->icon_w; + + if(Scr.flags & Lenience) + { + XSetInputFocus (dpy, w, RevertToParent, lastTimestamp); + Scr.Focus = Fw; + } + else if(!((Fw)&&(Fw->wmhints)&&(Fw->wmhints->flags & InputHint)&& + (Fw->wmhints->input == False))) + { + /* Window will accept input focus */ + XSetInputFocus (dpy, w, RevertToParent, lastTimestamp); + Scr.Focus = Fw; + } + else if ((Scr.Focus)&&(Scr.Focus->Desk == Scr.CurrentDesk)) + { + /* Window doesn't want focus. Leave focus alone */ + /* XSetInputFocus (dpy,Scr.Hilite->w , RevertToParent, lastTimestamp);*/ + } + else + { + XSetInputFocus (dpy, Scr.NoFocusWin, RevertToParent, lastTimestamp); + Scr.Focus = NULL; + } + + + if ((Fw)&&(Fw->flags & DoesWmTakeFocus)) + send_clientmessage (w,_XA_WM_TAKE_FOCUS, lastTimestamp); + + XSync(dpy,0); + +} + + + diff --git a/fvwm/colormaps.c b/fvwm/colormaps.c new file mode 100644 index 0000000..d652e55 --- /dev/null +++ b/fvwm/colormaps.c @@ -0,0 +1,243 @@ +/**************************************************************************** + * This module is all new + * by Rob Nation + * + * This code handles colormaps for fvwm. + * + * Copyright 1994 Robert Nation. No restrictions are placed on this code, + * as long as the copyright notice is preserved . No guarantees or + * warrantees of any sort whatsoever are given or implied or anything. + ****************************************************************************/ + +#include "../configure.h" + +#include +#include +#include "fvwm.h" +#include +#include "menus.h" +#include "misc.h" +#include "parse.h" +#include "screen.h" +#include "module.h" + +FvwmWindow *colormap_win; +Colormap last_cmap = None; +extern FvwmWindow *Tmp_win; + +/*********************************************************************** + * + * Procedure: + * HandleColormapNotify - colormap notify event handler + * + * This procedure handles both a client changing its own colormap, and + * a client explicitly installing its colormap itself (only the window + * manager should do that, so we must set it correctly). + * + ***********************************************************************/ +void HandleColormapNotify(void) +{ + XColormapEvent *cevent = (XColormapEvent *)&Event; + Bool ReInstall = False; + + + if(!Tmp_win) + { + return; + } + if(cevent->new) + { + XGetWindowAttributes(dpy,Tmp_win->w,&(Tmp_win->attr)); + if((Tmp_win == colormap_win)&&(Tmp_win->number_cmap_windows == 0)) + last_cmap = Tmp_win->attr.colormap; + ReInstall = True; + } + else if((cevent->state == ColormapUninstalled)&& + (last_cmap == cevent->colormap)) + { + /* Some window installed its colormap, change it back */ + ReInstall = True; + } + + while(XCheckTypedEvent(dpy,ColormapNotify,&Event)) + { + if (XFindContext (dpy, cevent->window, + FvwmContext, (caddr_t *) &Tmp_win) == XCNOENT) + Tmp_win = NULL; + if((Tmp_win)&&(cevent->new)) + { + XGetWindowAttributes(dpy,Tmp_win->w,&(Tmp_win->attr)); + if((Tmp_win == colormap_win)&&(Tmp_win->number_cmap_windows == 0)) + last_cmap = Tmp_win->attr.colormap; + ReInstall = True; + } + else if((Tmp_win)&& + (cevent->state == ColormapUninstalled)&& + (last_cmap == cevent->colormap)) + { + /* Some window installed its colormap, change it back */ + ReInstall = True; + } + else if((Tmp_win)&& + (cevent->state == ColormapInstalled)&& + (last_cmap == cevent->colormap)) + { + /* The last color map installed was the correct one. Don't + * change anything */ + ReInstall = False; + } + } + + if(ReInstall) + { + XInstallColormap(dpy,last_cmap); + } +} + +/************************************************************************ + * + * Re-Install the active colormap + * + *************************************************************************/ +void ReInstallActiveColormap(void) +{ + InstallWindowColormaps(colormap_win); +} + +/*********************************************************************** + * + * Procedure: + * InstallWindowColormaps - install the colormaps for one fvwm window + * + * Inputs: + * type - type of event that caused the installation + * tmp - for a subset of event types, the address of the + * window structure, whose colormaps are to be installed. + * + ************************************************************************/ + +void InstallWindowColormaps (FvwmWindow *tmp) +{ + int i; + XWindowAttributes attributes; + Window w; + Bool ThisWinInstalled = False; + + + /* If no window, then install root colormap */ + if(!tmp) + tmp = &Scr.FvwmRoot; + + colormap_win = tmp; + /* Save the colormap to be loaded for when force loading of + * root colormap(s) ends. + */ + Scr.pushed_window = tmp; + /* Don't load any new colormap if root colormap(s) has been + * force loaded. + */ + if (Scr.root_pushes) + { + return; + } + + if(tmp->number_cmap_windows > 0) + { + for(i=tmp->number_cmap_windows -1; i>=0;i--) + { + w = tmp->cmap_windows[i]; + if(w == tmp->w) + ThisWinInstalled = True; + XGetWindowAttributes(dpy,w,&attributes); + + if(last_cmap != attributes.colormap) + { + last_cmap = attributes.colormap; + XInstallColormap(dpy,attributes.colormap); + } + } + } + + if(!ThisWinInstalled) + { + if(last_cmap != tmp->attr.colormap) + { + last_cmap = tmp->attr.colormap; + XInstallColormap(dpy,tmp->attr.colormap); + } + } +} + + +/*********************************************************************** + * + * Procedures: + * nstallRootColormap - Force (un)loads root colormap(s) + * + * These matching routines provide a mechanism to insure that + * the root colormap(s) is installed during operations like + * rubber banding or menu display that require colors from + * that colormap. Calls may be nested arbitrarily deeply, + * as long as there is one UninstallRootColormap call per + * InstallRootColormap call. + * + * The final UninstallRootColormap will cause the colormap list + * which would otherwise have be loaded to be loaded, unless + * Enter or Leave Notify events are queued, indicating some + * other colormap list would potentially be loaded anyway. + ***********************************************************************/ +void InstallRootColormap() +{ + FvwmWindow *tmp; + if (Scr.root_pushes == 0) + { + tmp = Scr.pushed_window; + InstallWindowColormaps(&Scr.FvwmRoot); + Scr.pushed_window = tmp; + } + Scr.root_pushes++; + return; +} + +/*************************************************************************** + * + * Unstacks one layer of root colormap pushing + * If we peel off the last layer, re-install th e application colormap + * + ***************************************************************************/ +void UninstallRootColormap() +{ + if (Scr.root_pushes) + Scr.root_pushes--; + + if (!Scr.root_pushes) + { + InstallWindowColormaps(Scr.pushed_window); + } + + return; +} + + + +/***************************************************************************** + * + * Gets the WM_COLORMAP_WINDOWS property from the window + * This property typically doesn't exist, but a few applications + * use it. These seem to occur mostly on SGI machines. + * + ****************************************************************************/ +void FetchWmColormapWindows (FvwmWindow *tmp) +{ + if(tmp->cmap_windows != (Window *)NULL) + XFree((void *)tmp->cmap_windows); + + if(!XGetWMColormapWindows (dpy, tmp->w, &(tmp->cmap_windows), + &(tmp->number_cmap_windows))) + { + tmp->number_cmap_windows = 0; + tmp->cmap_windows = NULL; + } +} + + diff --git a/fvwm/configure.c b/fvwm/configure.c new file mode 100644 index 0000000..c6c6cae --- /dev/null +++ b/fvwm/configure.c @@ -0,0 +1,2140 @@ +/**************************************************************************** + * 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 + ****************************************************************************/ + + +/*************************************************************************** + * + * Configure.c: reads the .fvwmrc or system.fvwmrc file, interprets it, + * and sets up menus, bindings, colors, and fonts as specified + * + ***************************************************************************/ + +#include "../configure.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#ifdef M4 +#include +#endif + + +#include "fvwm.h" +#include "menus.h" +#include "misc.h" +#include "parse.h" +#include "screen.h" +#include "../version.h" + +char *IconPath = FVWM_ICONDIR; +#ifdef XPM +char *PixmapPath=FVWM_ICONDIR; +#endif +char *ModulePath = FVWMDIR; + +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 + +unsigned PopupCount = 0; +MenuRoot *PopupTable[MAXPOPUPS]; +int dummy; +char *config_file = ".fvwmrc"; + +extern XContext MenuContext; /* context for fvwm 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}, +#ifndef PRUNE + {"Icon", SetOneStyle, (char **)&Scr.TheList,(int *)ICON_FLAG}, + {"NoIconTitle", SetOneStyle, (char **)&Scr.TheList, (int *)NOICON_TITLE_FLAG}, +#endif + {"MWMBorders", SetFlag, (char **)MWMBorders, (int *)0}, + {"MWMMenus", SetFlag, (char **)MWMMenus, (int *)0}, + {"MWMButtons", SetFlag, (char **)MWMButtons, (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 + {"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}, + {"ButtonStyle", ButtonStyle, (char **)0, (int *)0}, + {"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 *)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 + {"", 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}, + {"Resize", set_func,(char **)F_RESIZE}, + {"RaiseLower", set_func,(char **)F_RAISELOWER}, + {"Raise", set_func,(char **)F_RAISE}, + {"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 fvwm_file that configuration was based on + * for consistency */ +char *fvwm_file; + +#ifdef M4 +static char *m4_defs(Display*, const char*, char*, char*); +#endif + +/***************************************************************************** + * + * This routine is responsible for reading and parsing the config file + * + ****************************************************************************/ +void MakeMenus(const char *display_name, char *m4_options) +{ + char *system_file = FVWMRC; + char *home_file; + char line[256],*tline; + char *Home; /* the HOME environment variable */ + int HomeLen; /* length of Home */ +#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 + { + home_file = safemalloc(HomeLen+strlen(config_file)+3); + strcpy(home_file,Home); + strcat(home_file,"/"); + strcat(home_file,config_file); + } + fvwm_file = home_file; + config_fd = fopen(home_file,"r"); + if(config_fd == (FILE *)NULL) + { + fvwm_file = system_file; + config_fd = fopen(system_file,"r"); + } + if(config_fd == (FILE *)NULL) + { + fvwm_err("can't open %s or %s",system_file,home_file,NULL); + exit(1); + } + if(fvwm_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. + */ + + fvwm_file = m4_defs(dpy, display_name, m4_options, fvwm_file); + fclose(config_fd); + + config_fd = fopen(fvwm_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(*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; + + /* 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(); + +#ifndef NO_PAGER + if(pager_x < 10000)initialize_pager(pager_x,pager_y); +#endif + + 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); +} + +/***************************************************************************** + * + * Changes a button decoration style + * + ****************************************************************************/ +void ButtonStyle(char *text, FILE *fd, char **arg,int *junk) +{ + int button,w,h,n,num; + char * letter=text; + int offset,i; + int num_coords; + int *x_coords; + int *y_coords; + int *line_style; + + while(isspace(*letter))letter++; + if (*letter == ':') /* signal for new data format */ + { + /* get button number */ + num = sscanf(++letter,"%d%n",&button,&offset); + if((num != 1)||(button>10)||(button<0)) + { + fvwm_err("Bad button style (1) in line %s",orig_tline,NULL,NULL); + return; + } + if(button==10)button=0; + /* get number of points */ + text=offset+letter; + num = sscanf(text,"%d%n",&num_coords,&offset); + if((num != 1)||(num_coords>20)||(num_coords<2)) + { + fvwm_err("Bad button style (2) in line %s",orig_tline,NULL,NULL); + return; + } + /* which arrays to use? */ + n=button/2; + if((n*2) == button) + { + /* right */ + n = n - 1; + if(n<0)n=4; + Scr.right_num_coords[n] = num_coords; + x_coords = Scr.right_x_coords[n]; + y_coords = Scr.right_y_coords[n]; + line_style = Scr.right_line_style[n]; + } + else + { + /* left */ + Scr.left_num_coords[n] = num_coords; + x_coords = Scr.left_x_coords[n]; + y_coords = Scr.left_y_coords[n]; + line_style = Scr.left_line_style[n]; + } + + /* get the points */ + for(i=0;i10)||(button<0))) + { + if(button==10)button=0; + Scr.use_new_style[button] = False; + } + + + num = sscanf(text," %d %dx%d",&button, &w, &h); + if((num != 3)||(button>10)||(button<0)) + { + fvwm_err("Bad button style in line %s",orig_tline,NULL,NULL); + return; + } + /* allow button 10 as well as button 0 as definition for 10 */ + if(button==10)button=0; + n=button/2; + if((n*2) == button) + { + n = n - 1; + if(n<0)n=4; + Scr.right_button_styles[0][n] = w; + Scr.right_button_styles[1][n] = h; + } + else + { + Scr.left_button_styles[0][n] = w; + Scr.left_button_styles[1][n] = h; + } +} + +/***************************************************************************** + * + * 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)) + { + fvwm_err("Bad cursor in line %s",orig_tline,NULL,NULL); + return; + } + Scr.FvwmCursors[cursor_num] = XCreateFontCursor(dpy,cursor_style); +} + +/***************************************************************************** + * + * Sets a boolean flag to true + * + ****************************************************************************/ +void SetFlag(char *text, FILE *fd, char **arg,int *junk) +{ + Scr.flags |= (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 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; + + 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 + + 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) +{ + 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 */ + 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; + + /* load the window-title font */ + 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; + + /* load the pager-label font */ +#ifndef NO_PAGER + if(Scr.PagerFont.name != NULL) + { + 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; + } + else + nofont(Scr.PagerFont.name); + } +#endif + + IconFont = &Scr.StdFont; + if(Scr.IconFont.name != NULL) + { + 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); + } + + /* create graphics contexts */ + CreateGCs(); + XSync(dpy,0); + return; +} + +/**************************************************************************** + * + * Prints an error message for font loading + * + ****************************************************************************/ +void nofont(char *name) +{ + fvwm_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(*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); + } + 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(*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 0) + { + i++; + j=j>>1; + } + if(Scr.nr_right_buttons 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(i0)) + { + 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) + { + fvwm_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 += 10; + if(mr->width2 > 0) + mr->width += 5; + + /* allow two pixels for top border */ + for (y=2, cur = mr->first; cur != NULL; cur = cur->next) + { + cur->y_offset = y; + cur->x = 5; + if(cur->func==F_TITLE) + { + /* Title */ + if(cur->strlen2 == 0) + cur->x = (mr->width - XTextWidth(Scr.StdFont.font, cur->item, + cur->strlen))>>1; + + if(Scr.flags & MWMMenus) + cur->y_height = Scr.EntryHeight + HEIGHT_EXTRA_TITLE; + else + { + if((cur == mr->first)||(cur->next == NULL)) + cur->y_height=Scr.EntryHeight-HEIGHT_EXTRA+1+ + (HEIGHT_EXTRA_TITLE>>1); + else + cur->y_height = Scr.EntryHeight -HEIGHT_EXTRA +1+ + HEIGHT_EXTRA_TITLE; + } + } + 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+2; + +#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.FvwmCursors[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 = (1 + (txt - start)) * which; + for (; *txt != '\0'; txt++) txt[0] = txt[1]; /* 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; + + width = XTextWidth(Scr.StdFont.font, item, tmp->strlen); + if(tmp->func == F_POPUP) + 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; + 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) +{ + fvwm_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(*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) +{ + fvwm_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 = 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; + 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); + + gcv.foreground = Scr.MenuColors.fore; + gcv.background = Scr.MenuColors.back; + Scr.MenuGC = 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); + Scr.ScratchGC1 = 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); +} + +/*********************************************************************** + * + * 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 + +#include +#include +#include +#include + +/* 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, "/fvwmrcXXXXX"); + 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 fvwm, for completeness */ + + fputs(MkDef("TWM_TYPE", "fvwm"), 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("FVWM_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 NO_WINDOWLIST + strcat(options, "NO_WINDOWLIST "); +#endif +#ifdef PRUNE + strcat(options, "PRUNE "); +#endif + fputs(MkDef("OPTIONS", options), tmpf); + + fputs(MkDef("FVWMDIR", FVWMDIR), tmpf); + + /* + * At this point, we've sent the definitions to m4. Just include + * the fvwmrc 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 */ diff --git a/fvwm/decorations.c b/fvwm/decorations.c new file mode 100644 index 0000000..4c87f75 --- /dev/null +++ b/fvwm/decorations.c @@ -0,0 +1,444 @@ +/**************************************************************************** + * + * This is all original code by Robert Nation + * which reads motif mwm window manager + * hints from a window, and makes necessary adjustments for fvwm. + * + * Definitions of the hint structure and the constants are courtesy of + * mitnits@bgumail.bgu.ac.il (Roman Mitnitski ), who sent this note, + * after conferring with a friend at the OSF: + * Hi, Rob. + * + *I'm happy to announce, that you can use motif public + *headers in any way you can... I just got the letter from + *my friend, it says literally: + * + *> Hi. + *> + *> Yes, you can use motif public header files, in particular + *> because there is NO limitation on inclusion of this files + *> in your programms....Also, no one can put copyright to the NUMBERS + *> (I mean binary flags for decorations) or DATA STRUCTURES + *> (I mean little structure used by motif to pass description + *> of the decorations to the mwm). Call it another name, if you are + *> THAT MUCH concerned. + *> + *> You can even use the little piece of code I've passed to you - + *> we are talking about 10M distribution against two pages of code. + *> Don't be silly. + *> + *> Best wishes. + *> Eli. + * + * + ****************************************************************************/ + +#include "../configure.h" + +#include +#include +#include +#include "fvwm.h" +#include +#include +#include "misc.h" +#include "screen.h" +#include "parse.h" +#include "menus.h" + +extern Atom _XA_MwmAtom; + +/* Motif window hints */ +typedef struct +{ + CARD32 flags; + CARD32 functions; + CARD32 decorations; + INT32 inputMode; +} PropMotifWmHints; + +typedef PropMotifWmHints PropMwmHints; + +PropMwmHints prop; + +/* Motif window hints */ +#define MWM_HINTS_FUNCTIONS (1L << 0) +#define MWM_HINTS_DECORATIONS (1L << 1) + +/* bit definitions for MwmHints.functions */ +#define MWM_FUNC_ALL (1L << 0) +#define MWM_FUNC_RESIZE (1L << 1) +#define MWM_FUNC_MOVE (1L << 2) +#define MWM_FUNC_MINIMIZE (1L << 3) +#define MWM_FUNC_MAXIMIZE (1L << 4) +#define MWM_FUNC_CLOSE (1L << 5) + +/* bit definitions for MwmHints.decorations */ +#define MWM_DECOR_ALL (1L << 0) +#define MWM_DECOR_BORDER (1L << 1) +#define MWM_DECOR_RESIZEH (1L << 2) +#define MWM_DECOR_TITLE (1L << 3) +#define MWM_DECOR_MENU (1L << 4) +#define MWM_DECOR_MINIMIZE (1L << 5) +#define MWM_DECOR_MAXIMIZE (1L << 6) + +#define PROP_MOTIF_WM_HINTS_ELEMENTS 4 +#define PROP_MWM_HINTS_ELEMENTS PROP_MOTIF_WM_HINTS_ELEMENTS + +extern FvwmWindow *Tmp_win; + +/**************************************************************************** + * + * Reads the property MOTIF_WM_HINTS + * + *****************************************************************************/ +void GetMwmHints(FvwmWindow *t) +{ + int actual_format; + Atom actual_type; + unsigned long nitems, bytesafter; + + if((Scr.flags & (MWMDecorHints|MWMFunctionHints))&& + (XGetWindowProperty (dpy, t->w, _XA_MwmAtom, 0L, 20L, False, + _XA_MwmAtom, &actual_type, &actual_format, &nitems, + &bytesafter,(unsigned char **)&t->mwm_hints)==Success)) + { + if(nitems >= PROP_MOTIF_WM_HINTS_ELEMENTS) + { + return; + } + } + + t->mwm_hints = NULL; +} + + + +/**************************************************************************** + * + * Interprets the property MOTIF_WM_HINTS, sets decoration and functions + * accordingly + * + *****************************************************************************/ +void SelectDecor(FvwmWindow *t, unsigned long tflags, int border_width, + int resize_width) +{ + int decor,i; + PropMwmHints *prop; + + if(!(tflags & BW_FLAG)) + border_width = Scr.NoBoundaryWidth; + + if(!(tflags & NOBW_FLAG)) + resize_width = Scr.BoundaryWidth; + + for(i=0;i<5;i++) + { + t->left_w[i] = 1; + t->right_w[i] = 1; + } + + decor = MWM_DECOR_ALL; + t->functions = MWM_FUNC_ALL; + if(t->mwm_hints) + { + prop = (PropMwmHints *)t->mwm_hints; + if(Scr.flags & MWMDecorHints) + if(prop->flags & MWM_HINTS_DECORATIONS) + decor = prop->decorations; + if(Scr.flags & MWMFunctionHints) + if(prop->flags & MWM_HINTS_FUNCTIONS) + t->functions = prop->functions; + } + + /* functions affect the decorations! if the user says + * no iconify function, then the iconify button doesn't show + * up. */ + if(t->functions & MWM_FUNC_ALL) + { + /* If we get ALL + some other things, that means to use + * ALL except the other things... */ + t->functions &= ~MWM_FUNC_ALL; + t->functions = (MWM_FUNC_RESIZE | MWM_FUNC_MOVE | MWM_FUNC_MINIMIZE | + MWM_FUNC_MAXIMIZE | MWM_FUNC_CLOSE) & (~(t->functions)); + } + if((Scr.flags & MWMFunctionHints) && (t->flags & TRANSIENT)) + { + t->functions &= ~(MWM_FUNC_MAXIMIZE|MWM_FUNC_MINIMIZE); + } + + if(decor & MWM_DECOR_ALL) + { + /* If we get ALL + some other things, that means to use + * ALL except the other things... */ + decor &= ~MWM_DECOR_ALL; + decor = (MWM_DECOR_BORDER | MWM_DECOR_RESIZEH | MWM_DECOR_TITLE | + MWM_DECOR_MENU | MWM_DECOR_MINIMIZE | MWM_DECOR_MAXIMIZE) + & (~decor); + } + + /* Now I have the un-altered decor and functions, but with the + * ALL attribute cleared and interpreted. I need to modify the + * decorations that are affected by the functions */ + if(!(t->functions & MWM_FUNC_RESIZE)) + decor &= ~MWM_DECOR_RESIZEH; + /* MWM_FUNC_MOVE has no impact on decorations. */ + if(!(t->functions & MWM_FUNC_MINIMIZE)) + decor &= ~MWM_DECOR_MINIMIZE; + if(!(t->functions & MWM_FUNC_MAXIMIZE)) + decor &= ~MWM_DECOR_MAXIMIZE; + /* MWM_FUNC_CLOSE has no impact on decorations. */ + + /* This rule is implicit, but its easier to deal with if + * I take care of it now */ + if(decor & (MWM_DECOR_MENU| MWM_DECOR_MINIMIZE | MWM_DECOR_MAXIMIZE)) + decor |= MWM_DECOR_TITLE; + + /* Selected the mwm-decor field, now trim down, based on + * .fvwmrc entries */ + if ((tflags & NOTITLE_FLAG)|| + ((!(Scr.flags & DecorateTransients)) && (t->flags & TRANSIENT))) + decor &= ~MWM_DECOR_TITLE; + + if ((tflags & NOBORDER_FLAG)|| + ((!(Scr.flags&DecorateTransients)) && (t->flags & TRANSIENT))) + decor &= ~MWM_DECOR_RESIZEH; + + if((Scr.flags & MWMDecorHints) && (t->flags & TRANSIENT)) + { + decor &= ~(MWM_DECOR_MAXIMIZE|MWM_DECOR_MINIMIZE); + } + +#ifdef SHAPE + if(t->wShaped) + decor &= ~(BORDER|MWM_DECOR_RESIZEH); +#endif + /* Assume no decorations, and build up */ + t->flags &= ~(BORDER|TITLE); + t->boundary_width = 0; + t->corner_width = 0; + t->title_height = 0; + + if(decor & MWM_DECOR_BORDER) + { + /* A narrow border is displayed (5 pixels - 2 relief, 1 top, + * (2 shadow) */ + t->boundary_width = border_width; + } + if(decor & MWM_DECOR_TITLE) + { + /* A title barm with no buttons in it + * window gets a 1 pixel wide black border. */ + t->flags |= TITLE; + t->title_height = Scr.TitleHeight; + } + if(decor & MWM_DECOR_RESIZEH) + { + /* A wide border, with corner tiles is desplayed + * (10 pixels - 2 relief, 2 shadow) */ + t->flags |= BORDER; + t->boundary_width = resize_width; + t->corner_width = Scr.TitleHeight + t->boundary_width; + } + if(!(decor & MWM_DECOR_MENU)) + { + /* title-bar menu button omitted + * window gets 1 pixel wide black border */ + t->left_w[0] = None; + } + if(!(decor & MWM_DECOR_MINIMIZE)) + { + /* title-bar + iconify button, no menu button. + * window gets 1 pixel wide black border */ + t->right_w[1] = None; + } + if(!(decor & MWM_DECOR_MAXIMIZE)) + { + /* title-bar + maximize button, no menu button, no iconify. + * window has 1 pixel wide black border */ + t->right_w[0] = None; + } + if (t->buttons & BUTTON1) t->left_w[0]=None; + if (t->buttons & BUTTON3) t->left_w[1]=None; + if (t->buttons & BUTTON5) t->left_w[2]=None; + if (t->buttons & BUTTON7) t->left_w[3]=None; + if (t->buttons & BUTTON9) t->left_w[4]=None; + + if (t->buttons & BUTTON2) t->right_w[0]=None; + if (t->buttons & BUTTON4) t->right_w[1]=None; + if (t->buttons & BUTTON6) t->right_w[2]=None; + if (t->buttons & BUTTON8) t->right_w[3]=None; + if (t->buttons & BUTTON10)t->right_w[4]=None; + + t->nr_left_buttons = Scr.nr_left_buttons; + t->nr_right_buttons = Scr.nr_right_buttons; + + for(i=0;ileft_w[i] == None) + t->nr_left_buttons--; + + for(i=0;iright_w[i] == None) + t->nr_right_buttons--; + + if(Scr.flags & MWMBorders) + t->bw = 0; + else if(t->boundary_width <= 0) + { + t->boundary_width = 0; + t->bw = 0; + } + else + { + t->bw = BW; + t->boundary_width = t->boundary_width - 1; + } + if(t->title_height > 0) + t->title_height += t->bw; + if(t->boundary_width == 0) + t->flags &= ~BORDER; +} + +/**************************************************************************** + * + * Checks the function described in menuItem mi, and sees if it + * is an allowed function for window Tmp_Win, + * according to the motif way of life. + * + * This routine is used to determine whether or not to grey out menu items. + * + ****************************************************************************/ +int check_allowed_function(MenuItem *mi) +{ + /* Complex functions are a little tricky... ignore them for now */ + + if ((Tmp_win)&& + (!(Tmp_win->flags & DoesWmDeleteWindow))&&(mi->func == F_DELETE)) + return 0; + + /* Move is a funny hint. Keeps it out of the menu, but you're still allowed + * to move. */ + if((mi->func == F_MOVE)&&(Tmp_win)&&(!(Tmp_win->functions & MWM_FUNC_MOVE))) + return 0; + + if((mi->func == F_RESIZE)&&(Tmp_win)&& + (!(Tmp_win->functions & MWM_FUNC_RESIZE))) + return 0; + + if((mi->func == F_ICONIFY)&&(Tmp_win)&& + (!(Tmp_win->flags & ICONIFIED))&& + (!(Tmp_win->functions & MWM_FUNC_MINIMIZE))) + return 0; + + if((mi->func == F_MAXIMIZE)&&(Tmp_win)&& + (!(Tmp_win->functions & MWM_FUNC_MAXIMIZE))) + return 0; + + if((mi->func == F_DELETE)&&(Tmp_win)&& + (!(Tmp_win->functions & MWM_FUNC_CLOSE))) + return 0; + + if((mi->func == F_CLOSE)&&(Tmp_win)&& + (!(Tmp_win->functions & MWM_FUNC_CLOSE))) + return 0; + + if((mi->func == F_DESTROY)&&(Tmp_win)&& + (!(Tmp_win->functions & MWM_FUNC_CLOSE))) + return 0; + + if(mi->func == F_FUNCTION) + { + /* Hard part! What to do now? */ + /* Hate to do it, but for lack of a better idea, + * check based on the menu entry name */ + if((Tmp_win)&&(!(Tmp_win->functions & MWM_FUNC_MOVE))&& + (mystrncasecmp(mi->item,MOVE_STRING,strlen(MOVE_STRING))==0)) + return 0; + + if((Tmp_win)&&(!(Tmp_win->functions & MWM_FUNC_RESIZE))&& + (mystrncasecmp(mi->item,RESIZE_STRING1,strlen(RESIZE_STRING1))==0)) + return 0; + + if((Tmp_win)&&(!(Tmp_win->functions & MWM_FUNC_RESIZE))&& + (mystrncasecmp(mi->item,RESIZE_STRING2,strlen(RESIZE_STRING2))==0)) + return 0; + + if((Tmp_win)&&(!(Tmp_win->functions & MWM_FUNC_MINIMIZE))&& + (!(Tmp_win->flags & ICONIFIED))&& + (mystrncasecmp(mi->item,MINIMIZE_STRING,strlen(MINIMIZE_STRING))==0)) + return 0; + + if((Tmp_win)&&(!(Tmp_win->functions & MWM_FUNC_MINIMIZE))&& + (mystrncasecmp(mi->item,MINIMIZE_STRING2,strlen(MINIMIZE_STRING2))==0)) + return 0; + + if((Tmp_win)&&(!(Tmp_win->functions & MWM_FUNC_MAXIMIZE))&& + (mystrncasecmp(mi->item,MAXIMIZE_STRING,strlen(MAXIMIZE_STRING))==0)) + return 0; + + if((Tmp_win)&&(!(Tmp_win->functions & MWM_FUNC_CLOSE))&& + (mystrncasecmp(mi->item,CLOSE_STRING1,strlen(CLOSE_STRING1))==0)) + return 0; + + if((Tmp_win)&&(!(Tmp_win->functions & MWM_FUNC_CLOSE))&& + (mystrncasecmp(mi->item,CLOSE_STRING2,strlen(CLOSE_STRING2))==0)) + return 0; + + if((Tmp_win)&&(!(Tmp_win->functions & MWM_FUNC_CLOSE))&& + (mystrncasecmp(mi->item,CLOSE_STRING3,strlen(CLOSE_STRING3))==0)) + return 0; + + if((Tmp_win)&&(!(Tmp_win->functions & MWM_FUNC_CLOSE))&& + (mystrncasecmp(mi->item,CLOSE_STRING4,strlen(CLOSE_STRING4))==0)) + return 0; + + } + + + return 1; +} + + +/**************************************************************************** + * + * Checks the function "function", and sees if it + * is an allowed function for window t, according to the motif way of life. + * This routine is used to decide if we should refuse to perform a function. + * + ****************************************************************************/ +int check_allowed_function2(int function, FvwmWindow *t) +{ + + if(Scr.flags & MWMHintOverride) + return 1; + + + if ((t)&&(!(t->flags & DoesWmDeleteWindow))&&(function == F_DELETE)) + return 0; + + if((function == F_RESIZE)&&(t)&& + (!(t->functions & MWM_FUNC_RESIZE))) + return 0; + + if((function == F_ICONIFY)&&(t)&& + (!(t->flags & ICONIFIED))&& + (!(t->functions & MWM_FUNC_MINIMIZE))) + return 0; + + if((function == F_MAXIMIZE)&&(t)&& + (!(t->functions & MWM_FUNC_MAXIMIZE))) + return 0; + + if((function == F_DELETE)&&(t)&& + (!(t->functions & MWM_FUNC_CLOSE))) + return 0; + + if((function == F_DESTROY)&&(t)&& + (!(t->functions & MWM_FUNC_CLOSE))) + return 0; + + return 1; +} + + + diff --git a/fvwm/events.c b/fvwm/events.c new file mode 100644 index 0000000..02ca33e --- /dev/null +++ b/fvwm/events.c @@ -0,0 +1,1460 @@ +/**************************************************************************** + * This module is based on Twm, but has been siginificantly modified + * by Rob Nation + ****************************************************************************/ +/*****************************************************************************/ +/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ +/** Salt Lake City, Utah **/ +/** Portions Copyright 1989 by the Massachusetts Institute of Technology **/ +/** Cambridge, Massachusetts **/ +/** **/ +/** All Rights Reserved **/ +/** **/ +/** Permission to use, copy, modify, and distribute this software and **/ +/** its documentation for any purpose and without fee is hereby **/ +/** granted, provided that the above copyright notice appear in all **/ +/** copies and that both that copyright notice and this permis- **/ +/** sion notice appear in supporting documentation, and that the **/ +/** names of Evans & Sutherland and M.I.T. not be used in advertising **/ +/** in publicity pertaining to distribution of the software without **/ +/** specific, written prior permission. **/ +/** **/ +/** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/ +/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/ +/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/ +/** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/ +/** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ +/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ +/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ +/** OR PERFORMANCE OF THIS SOFTWARE. **/ +/*****************************************************************************/ + + +/*********************************************************************** + * + * fvwm event handling + * + ***********************************************************************/ + +#include "../configure.h" + +#ifdef ISC +#include +#endif + +#include +#include +#include +#include +#include +#include +/* Some people say that AIX and AIXV3 need 3 preceding underscores, other say + * no. I'll do both */ +#if defined ___AIX || defined _AIX || defined __QNX__ || defined ___AIXV3 || defined AIXV3 || defined _SEQUENT_ +#include +#endif + +#include "fvwm.h" +#include +#include "menus.h" +#include "misc.h" +#include "parse.h" +#include "screen.h" +#ifdef SHAPE +#include +#endif /* SHAPE */ +#include "module.h" + +#ifndef NO_PAGER +extern FvwmWindow *FindCounterpart(Window target); +#endif /* NO_PAGER */ + +unsigned int mods_used = (ShiftMask | ControlMask | Mod1Mask | + Mod2Mask| Mod3Mask| Mod4Mask| Mod5Mask); +extern int menuFromFrameOrWindowOrTitlebar; + + +int Context = C_NO_CONTEXT; /* current button press context */ +int Button = 0; +FvwmWindow *ButtonWindow; /* button press window structure */ +XEvent Event; /* the current event */ +FvwmWindow *Tmp_win; /* the current fvwm window */ + +int last_event_type=0; +Window last_event_window=0; + +#ifdef SHAPE +extern int ShapeEventBase; +void HandleShapeNotify(void); +#endif /* SHAPE */ + +Window PressedW; + +/*********************************************************************** + * + * Procedure: + * DispatchEvent - handle a single X event stored in global var Event + * + ************************************************************************/ +void DispatchEvent() +{ + Window w = Event.xany.window; + + StashEventTime(&Event); + + if (XFindContext (dpy, w, FvwmContext, (caddr_t *) &Tmp_win) == XCNOENT) + Tmp_win = NULL; + last_event_type = Event.type; + last_event_window = w; + + switch(Event.type) + { + case Expose: + HandleExpose(); + break; + case DestroyNotify: + HandleDestroyNotify(); + break; + case MapRequest: + HandleMapRequest(); + break; + case MapNotify: + HandleMapNotify(); + break; + case UnmapNotify: + HandleUnmapNotify(); + break; + case MotionNotify: + HandleMotionNotify(); + break; + case ButtonPress: + HandleButtonPress(); + break; + case ButtonRelease: + HandleButtonRelease(); + break; + case EnterNotify: + HandleEnterNotify(); + break; + case LeaveNotify: + HandleLeaveNotify(); + break; + case FocusIn: + HandleFocusIn(); + break; + case ConfigureRequest: + HandleConfigureRequest(); + break; + case ClientMessage: + HandleClientMessage(); + break; + case PropertyNotify: + HandlePropertyNotify(); + break; + case KeyPress: + HandleKeyPress(); + break; + case VisibilityNotify: + HandleVisibilityNotify(); + break; + case ColormapNotify: + HandleColormapNotify(); + break; + default: +#ifdef SHAPE + if(Event.type == (ShapeEventBase + ShapeNotify)) + HandleShapeNotify(); +#endif /* SHAPE */ + + break; + } + return; +} + + +/*********************************************************************** + * + * Procedure: + * HandleEvents - handle X events + * + ************************************************************************/ +void HandleEvents() +{ + while (TRUE) + { + last_event_type = 0; + if(My_XNextEvent(dpy, &Event)) + { + DispatchEvent (); + } + } +} + +/*********************************************************************** + * + * Procedure: + * Find the Fvwm context for the Event. + * + ************************************************************************/ +int GetContext(FvwmWindow *t, XEvent *e, Window *w) +{ + int Context,i; + + if(!t) + return C_ROOT; + + Context = C_NO_CONTEXT; + *w= e->xany.window; + + if(*w == Scr.NoFocusWin) + return C_ROOT; + + /* Since key presses and button presses are grabbed in the frame + * when we have re-parented windows, we need to find out the real + * window where the event occured */ + if((e->type == KeyPress)&&(e->xkey.subwindow != None)) + *w = e->xkey.subwindow; + + if((e->type == ButtonPress)&&(e->xbutton.subwindow != None)&& + ((e->xbutton.subwindow == t->w)||(e->xbutton.subwindow == t->Parent))) + *w = e->xbutton.subwindow; + + if (*w == Scr.Root) + Context = C_ROOT; + if (t) + { + if (*w == t->title_w) + Context = C_TITLE; + if ((*w == t->w)||(*w == t->Parent)) + Context = C_WINDOW; + if (*w == t->icon_w) + Context = C_ICON; + if (*w == t->icon_pixmap_w) + Context = C_ICON; + if (*w == t->frame) + Context = C_SIDEBAR; + for(i=0;i<4;i++) + if(*w == t->corners[i]) + { + Context = C_FRAME; + Button = i; + } + for(i=0;i<4;i++) + if(*w == t->sides[i]) + { + Context = C_SIDEBAR; + Button = i; + } + for(i=0;ileft_w[i]) + { + Context = (1<right_w[i]) + { + Context = (1<w, + Tmp_win->frame,(unsigned long)Tmp_win,0,0,0,0); + } +} + +/*********************************************************************** + * + * Procedure: + * HandleKeyPress - key press event handler + * + ************************************************************************/ +void HandleKeyPress() +{ + FuncKey *key; + unsigned int modifier; + Window dummy; + + Context = GetContext(Tmp_win,&Event,&dummy); + + modifier = (Event.xkey.state & mods_used); + for (key = Scr.FuncKeyRoot.next; key != NULL; key = key->next) + { + ButtonWindow = Tmp_win; + /* Here's a real hack - some systems have two keys with the + * same keysym and different keycodes. This converts all + * the cases to one keycode. */ + Event.xkey.keycode = + XKeysymToKeycode(dpy,XKeycodeToKeysym(dpy,Event.xkey.keycode,0)); + if ((key->keycode == Event.xkey.keycode) && + ((key->mods == (modifier&(~LockMask)))|| + (key->mods == AnyModifier)) && + (key->cont & Context)) + { + ExecuteFunction(key->func, key->action, Event.xany.window,Tmp_win, + &Event,Context,key->val1,key->val2, + key->val1_unit,key->val2_unit, + key->menu,-1); + return; + } + } + + /* if we get here, no function key was bound to the key. Send it + * to the client if it was in a window we know about. + */ + if (Tmp_win) + { + if(Event.xkey.window != Tmp_win->w) + { + Event.xkey.window = Tmp_win->w; + XSendEvent(dpy, Tmp_win->w, False, KeyPressMask, &Event); + } + } + ButtonWindow = NULL; +} + + +/*********************************************************************** + * + * Procedure: + * HandlePropertyNotify - property notify event handler + * + ***********************************************************************/ +#define MAX_NAME_LEN 200L /* truncate to this many */ +#define MAX_ICON_NAME_LEN 200L /* ditto */ + +void HandlePropertyNotify() +{ + char *prop = NULL; + Atom actual = None; + int actual_format; + unsigned long nitems, bytesafter; + + if ((!Tmp_win)||(XGetGeometry(dpy, Tmp_win->w, &JunkRoot, &JunkX, &JunkY, + &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth) == 0)) + return; + + switch (Event.xproperty.atom) + { + case XA_WM_NAME: + if (XGetWindowProperty (dpy, Tmp_win->w, Event.xproperty.atom, 0L, + MAX_NAME_LEN, False, XA_STRING, &actual, + &actual_format, &nitems, &bytesafter, + (unsigned char **) &prop) != Success || + actual == None) + return; + if (!prop) prop = NoName; + free_window_names (Tmp_win, True, False); + + Tmp_win->name = prop; + BroadcastName(M_WINDOW_NAME,Tmp_win->w,Tmp_win->frame, + (unsigned long)Tmp_win,Tmp_win->name); + + /* fix the name in the title bar */ + if(!(Tmp_win->flags & ICONIFIED)) + SetTitleBar(Tmp_win,(Scr.Hilite==Tmp_win),True); + + /* + * if the icon name is NoName, set the name of the icon to be + * the same as the window + */ + if (Tmp_win->icon_name == NoName) + { + Tmp_win->icon_name = Tmp_win->name; + BroadcastName(M_ICON_NAME,Tmp_win->w,Tmp_win->frame, + (unsigned long)Tmp_win,Tmp_win->icon_name); + RedoIconName(Tmp_win); + } + break; + + case XA_WM_ICON_NAME: + if (XGetWindowProperty (dpy, Tmp_win->w, Event.xproperty.atom, 0, + MAX_ICON_NAME_LEN, False, XA_STRING, &actual, + &actual_format, &nitems, &bytesafter, + (unsigned char **) &prop) != Success || + actual == None) + return; + if (!prop) prop = NoName; + free_window_names (Tmp_win, False, True); + Tmp_win->icon_name = prop; + BroadcastName(M_ICON_NAME,Tmp_win->w,Tmp_win->frame, + (unsigned long)Tmp_win,Tmp_win->icon_name); + RedoIconName(Tmp_win); + break; + + case XA_WM_HINTS: + if (Tmp_win->wmhints) + XFree ((char *) Tmp_win->wmhints); + Tmp_win->wmhints = XGetWMHints(dpy, Event.xany.window); + + if(Tmp_win->wmhints == NULL) + return; + + if((Tmp_win->wmhints->flags & IconPixmapHint)|| + (Tmp_win->wmhints->flags & IconWindowHint)) + if(Tmp_win->icon_bitmap_file == Scr.DefaultIcon) + Tmp_win->icon_bitmap_file = (char *)0; + + if((Tmp_win->wmhints->flags & IconPixmapHint)|| + (Tmp_win->wmhints->flags & IconWindowHint)) + { + if (!(Tmp_win->flags & SUPPRESSICON)) + { + if (Tmp_win->icon_w) + XDestroyWindow(dpy,Tmp_win->icon_w); + XDeleteContext(dpy, Tmp_win->icon_w, FvwmContext); + if(Tmp_win->flags & ICON_OURS) + { + if(Tmp_win->icon_pixmap_w != None) + { + XDestroyWindow(dpy,Tmp_win->icon_pixmap_w); + XDeleteContext(dpy, Tmp_win->icon_pixmap_w, FvwmContext); + } + } + else + XUnmapWindow(dpy,Tmp_win->icon_pixmap_w); + } + Tmp_win->icon_w = None; + Tmp_win->icon_pixmap_w = None; + Tmp_win->iconPixmap = (Window)NULL; + if(Tmp_win->flags & ICONIFIED) + { + Tmp_win->flags &= ~ICONIFIED; + Tmp_win->flags &= ~ICON_UNMAPPED; + CreateIconWindow(Tmp_win,Tmp_win->icon_x_loc,Tmp_win->icon_y_loc); + Broadcast(M_ICONIFY,7,Tmp_win->w,Tmp_win->frame, + (unsigned long)Tmp_win, + Tmp_win->icon_x_loc, + Tmp_win->icon_y_loc, + Tmp_win->icon_w_width, + Tmp_win->icon_w_height); + BroadcastConfig(M_CONFIGURE_WINDOW,Tmp_win); + + if (!(Tmp_win->flags & SUPPRESSICON)) + { + LowerWindow(Tmp_win); + AutoPlace(Tmp_win); + if(Tmp_win->Desk == Scr.CurrentDesk) + { + if(Tmp_win->icon_w) + XMapWindow(dpy, Tmp_win->icon_w); + if(Tmp_win->icon_pixmap_w != None) + XMapWindow(dpy, Tmp_win->icon_pixmap_w); + } + } + Tmp_win->flags |= ICONIFIED; + DrawIconWindow(Tmp_win); + } + } + break; + + case XA_WM_NORMAL_HINTS: + GetWindowSizeHints (Tmp_win); + BroadcastConfig(M_CONFIGURE_WINDOW,Tmp_win); + break; + + default: + if(Event.xproperty.atom == _XA_WM_PROTOCOLS) + FetchWmProtocols (Tmp_win); + else if (Event.xproperty.atom == _XA_WM_COLORMAP_WINDOWS) + { + FetchWmColormapWindows (Tmp_win); /* frees old data */ + ReInstallActiveColormap(); + } + else if(Event.xproperty.atom == _XA_WM_STATE) + { + if((Scr.flags & ClickToFocus)&&(Tmp_win == Scr.Focus)&& + (Tmp_win != NULL)) + { + Scr.Focus = NULL; + SetFocus(Tmp_win->w,Tmp_win); + ClearCirculatedFlag(); + } + } + break; + } +} + + +/*********************************************************************** + * + * Procedure: + * HandleClientMessage - client message event handler + * + ************************************************************************/ +void HandleClientMessage() +{ + XEvent button; + + if ((Event.xclient.message_type == _XA_WM_CHANGE_STATE)&& + (Tmp_win)&&(Event.xclient.data.l[0]==IconicState)&& + !(Tmp_win->flags & ICONIFIED)) + { + XQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, + &(button.xmotion.x_root), + &(button.xmotion.y_root), + &JunkX, &JunkY, &JunkMask); + button.type = 0; + ExecuteFunction(F_ICONIFY, NULLSTR, Event.xany.window, + Tmp_win, &button, C_FRAME,0,0, 0,0, + (MenuRoot *)0,-1); + } +} + +/*********************************************************************** + * + * Procedure: + * HandleExpose - expose event handler + * + ***********************************************************************/ +void HandleExpose() +{ + if (Event.xexpose.count != 0) + return; + + if (Tmp_win) + { +#ifndef NO_PAGER + if((Tmp_win->w == Scr.Pager_w)|| + (Tmp_win->w == Scr.CPagerWin)) + { + ReallyRedrawPager(); + } +#endif + if ((Event.xany.window == Tmp_win->title_w)) + { + SetTitleBar(Tmp_win,(Scr.Hilite == Tmp_win),False); + } + else + { + SetBorder(Tmp_win,(Scr.Hilite == Tmp_win),True,True,Event.xany.window); + } + } +#ifndef NO_PAGER + else + { + if(FindCounterpart(Event.xany.window)) + ReallyRedrawPager(); + } +#endif + return; +} + + + +/*********************************************************************** + * + * Procedure: + * HandleDestroyNotify - DestroyNotify event handler + * + ***********************************************************************/ +void HandleDestroyNotify() +{ + Destroy(Tmp_win); +} + + + + +/*********************************************************************** + * + * Procedure: + * HandleMapRequest - MapRequest event handler + * + ************************************************************************/ +void HandleMapRequest() +{ + extern long isIconicState; + + Event.xany.window = Event.xmaprequest.window; + + if(XFindContext(dpy, Event.xany.window, FvwmContext, + (caddr_t *)&Tmp_win)==XCNOENT) + Tmp_win = NULL; + + XFlush(dpy); + + /* If the window has never been mapped before ... */ + if(!Tmp_win) + { + /* Add decorations. */ + Tmp_win = AddWindow(Event.xany.window); + if (Tmp_win == NULL) + return; + } + + /* If it's not merely iconified, and we have hints, use them. */ + if (!(Tmp_win->flags & ICONIFIED)) + { + int state; + + if(Tmp_win->wmhints && (Tmp_win->wmhints->flags & StateHint)) + state = Tmp_win->wmhints->initial_state; + else + state = NormalState; + + if(Tmp_win->flags & STARTICONIC) + state = IconicState; + + if(isIconicState != DontCareState) + state = isIconicState; + + XGrabServer (dpy); + switch (state) + { + case DontCareState: + case NormalState: + case InactiveState: + default: + if (Tmp_win->Desk == Scr.CurrentDesk) + { + XMapWindow(dpy, Tmp_win->w); + XMapWindow(dpy, Tmp_win->frame); + Tmp_win->flags |= MAP_PENDING; + SetMapStateProp(Tmp_win, NormalState); + if(Scr.flags & ClickToFocus) + { + SetFocus(Tmp_win->w,Tmp_win); + ClearCirculatedFlag(); + } + } + else + { + XMapWindow(dpy, Tmp_win->w); + SetMapStateProp(Tmp_win, NormalState); + } + break; + + case IconicState: + Iconify(Tmp_win, 0, 0); + break; + } + XSync(dpy,0); + XUngrabServer(dpy); + } + /* If no hints, or currently an icon, just "deiconify" */ + else + { + DeIconify(Tmp_win); + } + KeepOnTop(); +} + + +/*********************************************************************** + * + * Procedure: + * HandleMapNotify - MapNotify event handler + * + ***********************************************************************/ +void HandleMapNotify() +{ + if (!Tmp_win) + { + return; + } + + /* + * Need to do the grab to avoid race condition of having server send + * MapNotify to client before the frame gets mapped; this is bad because + * the client would think that the window has a chance of being viewable + * when it really isn't. + */ + XGrabServer (dpy); + if (Tmp_win->icon_w) + XUnmapWindow(dpy, Tmp_win->icon_w); + if(Tmp_win->icon_pixmap_w != None) + XUnmapWindow(dpy, Tmp_win->icon_pixmap_w); + XMapSubwindows(dpy, Tmp_win->frame); + + if(Tmp_win->Desk == Scr.CurrentDesk) + { + XMapWindow(dpy, Tmp_win->frame); + } + + if(Tmp_win->flags & ICONIFIED) + Broadcast(M_DEICONIFY,3,Tmp_win->w,Tmp_win->frame, + (unsigned long)Tmp_win,0,0,0,0); + else + { + Broadcast(M_MAP,3,Tmp_win->w,Tmp_win->frame, + (unsigned long)Tmp_win,0,0,0,0); + } + + if(Scr.flags & ClickToFocus) + { + SetFocus(Tmp_win->w,Tmp_win); + ClearCirculatedFlag(); + } + if((!(Tmp_win->flags &(BORDER|TITLE)))&&(Tmp_win->boundary_width <2)) + { + SetBorder(Tmp_win,False,True,True,Tmp_win->frame); + } + XSync(dpy,0); + XUngrabServer (dpy); + XFlush (dpy); + Tmp_win->flags |= MAPPED; + Tmp_win->flags &= ~MAP_PENDING; + Tmp_win->flags &= ~ICONIFIED; + Tmp_win->flags &= ~ICON_UNMAPPED; + KeepOnTop(); +} + + +/*********************************************************************** + * + * Procedure: + * HandleUnmapNotify - UnmapNotify event handler + * + ************************************************************************/ +void HandleUnmapNotify() +{ + int dstx, dsty; + Window dumwin; + XEvent dummy; + extern FvwmWindow *colormap_win; + + /* + * The July 27, 1988 ICCCM spec states that a client wishing to switch + * to WithdrawnState should send a synthetic UnmapNotify with the + * event field set to (pseudo-)root, in case the window is already + * unmapped (which is the case for fvwm for IconicState). Unfortunately, + * we looked for the FvwmContext using that field, so try the window + * field also. + */ + if (!Tmp_win) + { + Event.xany.window = Event.xunmap.window; + if (XFindContext(dpy, Event.xany.window, + FvwmContext, (caddr_t *)&Tmp_win) == XCNOENT) + Tmp_win = NULL; + } + + if(!Tmp_win) + return; + + if(Tmp_win == Scr.Hilite) + Scr.Hilite = NULL; + + if(Scr.PreviousFocus == Tmp_win) + Scr.PreviousFocus = NULL; + + if((Tmp_win == Scr.Focus)&&(Scr.flags & ClickToFocus)) + { + if(Tmp_win->next) + SetFocus(Tmp_win->next->w,Tmp_win->next); + else + SetFocus(Scr.NoFocusWin,NULL); + } + + if(Scr.Focus == Tmp_win) + SetFocus(Scr.NoFocusWin,NULL); + + if(Tmp_win == Scr.pushed_window) + Scr.pushed_window = NULL; + + ClearCirculatedFlag(); + if(Tmp_win == colormap_win) + colormap_win = NULL; + + if ((!(Tmp_win->flags & MAPPED)&&!(Tmp_win->flags&ICONIFIED))) + { + return; + } + + XGrabServer(dpy); + + if(XCheckTypedWindowEvent (dpy, Event.xunmap.window, DestroyNotify,&dummy)) + { + Destroy(Tmp_win); + XUngrabServer (dpy); + return; + } + + /* + * The program may have unmapped the client window, from either + * NormalState or IconicState. Handle the transition to WithdrawnState. + * + * We need to reparent the window back to the root (so that fvwm exiting + * won't cause it to get mapped) and then throw away all state (pretend + * that we've received a DestroyNotify). + */ + if (XTranslateCoordinates (dpy, Event.xunmap.window, Scr.Root, + 0, 0, &dstx, &dsty, &dumwin)) + { + XEvent ev; + Bool reparented; + + reparented = XCheckTypedWindowEvent (dpy, Event.xunmap.window, + ReparentNotify, &ev); + SetMapStateProp (Tmp_win, WithdrawnState); + if (reparented) + { + if (Tmp_win->old_bw) + XSetWindowBorderWidth (dpy, Event.xunmap.window, Tmp_win->old_bw); + if((!(Tmp_win->flags & SUPPRESSICON))&& + (Tmp_win->wmhints && (Tmp_win->wmhints->flags & IconWindowHint))) + XUnmapWindow (dpy, Tmp_win->wmhints->icon_window); + } + else + { + RestoreWithdrawnLocation (Tmp_win,False); + } + XRemoveFromSaveSet (dpy, Event.xunmap.window); + XSelectInput (dpy, Event.xunmap.window, NoEventMask); + Destroy(Tmp_win); /* do not need to mash event before */ + /* + * Flush any pending events for the window. + */ + /* Bzzt! it could be about to re-map */ +/* while(XCheckWindowEvent(dpy, Event.xunmap.window, + StructureNotifyMask | PropertyChangeMask | + ColormapChangeMask | VisibilityChangeMask | + EnterWindowMask | LeaveWindowMask, &dummy)); + */ + } /* else window no longer exists and we'll get a destroy notify */ + XUngrabServer (dpy); + + XFlush (dpy); +} + + +/*********************************************************************** + * + * Procedure: + * HandleMotionNotify - MotionNotify event handler + * + **********************************************************************/ +void HandleMotionNotify() +{ +#ifndef NO_PAGER + extern Bool EnablePagerRedraw; + + /* here is the code for dragging the viewport around within the pager.*/ + if((Tmp_win)&&(Tmp_win->w == Scr.Pager_w)&& + (!(Tmp_win->flags & ICONIFIED))) + { + if(Event.xmotion.state == Button3MotionMask) + { + EnablePagerRedraw = False; + SwitchPages(FALSE,FALSE); + } + } +#endif +} + +/*********************************************************************** + * + * Procedure: + * HandleButtonPress - ButtonPress event handler + * + ***********************************************************************/ +void HandleButtonPress() +{ +#ifndef NO_PAGER + extern Bool EnablePagerRedraw; +#endif + unsigned int modifier; + MouseButton *MouseEntry; + char *Action; + Window x; + int LocalContext; + + /* click to focus stuff goes here */ + if((Scr.flags & ClickToFocus)&&(Tmp_win != Scr.Ungrabbed)&& + ((Event.xbutton.state& + (ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) == 0)) + { + if(Tmp_win) + { + SetFocus(Tmp_win->w,Tmp_win); + ClearCirculatedFlag(); + if(Scr.AutoRaiseDelay > 0) + { + SetTimer(Scr.AutoRaiseDelay); + } + else + { +#ifdef CLICKY_MODE_1 + if((Event.xany.window != Tmp_win->w)&& + (Event.xbutton.subwindow != Tmp_win->w)&& + (Event.xany.window != Tmp_win->Parent)&& + (Event.xbutton.subwindow != Tmp_win->Parent)) +#endif + { + if(Scr.AutoRaiseDelay == 0) + RaiseWindow(Tmp_win); + } + } + + KeepOnTop(); + + /* Why is this here? Seems to cause breakage with + * non-focusing windows! */ + if(!(Tmp_win->flags & ICONIFIED)) + { + XSync(dpy,0); + XAllowEvents(dpy,ReplayPointer,CurrentTime); + XSync(dpy,0); + return; + } + + } + } + XSync(dpy,0); + XAllowEvents(dpy,ReplayPointer,CurrentTime); + XSync(dpy,0); + + /* here is the code for moving windows in the pager.*/ +#ifndef NO_PAGER + if((Tmp_win)&&(Tmp_win->w == Event.xbutton.window)&& + (Tmp_win->w == Scr.Pager_w)&&(Event.xbutton.button == Button2)) + { + PagerMoveWindow(); + return; + } + if((Tmp_win)&&(Tmp_win->w == Scr.Pager_w)&& + (!(Tmp_win->flags & ICONIFIED))&& + (Event.xbutton.button == Button3)&& + (Event.xany.window == Scr.Pager_w)) + { +#ifndef NO_PAGER + EnablePagerRedraw = False; +#endif + SwitchPages(FALSE,FALSE); + } +#endif + + Context = GetContext(Tmp_win,&Event, &PressedW); + LocalContext = Context; + x= PressedW; + if(Context == C_TITLE) + SetTitleBar(Tmp_win,(Scr.Hilite == Tmp_win),False); + else + SetBorder(Tmp_win,(Scr.Hilite == Tmp_win),True,True,PressedW); + + ButtonWindow = Tmp_win; + + /* we have to execute a function or pop up a menu + */ + + modifier = (Event.xbutton.state & mods_used); + /* need to search for an appropriate mouse binding */ + MouseEntry = Scr.MouseButtonRoot; + while(MouseEntry != (MouseButton *)0) + { + if(((MouseEntry->Button == Event.xbutton.button)||(MouseEntry->Button == 0))&& + (MouseEntry->Context & Context)&& + ((MouseEntry->Modifier == AnyModifier)|| + (MouseEntry->Modifier == (modifier& (~LockMask))))) + { + /* got a match, now process it */ + if (MouseEntry->func != (int)NULL) + { + Action = MouseEntry->item ? MouseEntry->item->action : NULL; + ExecuteFunction(MouseEntry->func, Action, Event.xany.window, + Tmp_win, &Event, Context,MouseEntry->val1, + MouseEntry->val2, + MouseEntry->val1_unit,MouseEntry->val2_unit, + MouseEntry->menu,-1); + break; + } + } + MouseEntry = MouseEntry->NextButton; + } + PressedW = None; + if(LocalContext!=C_TITLE) + SetBorder(ButtonWindow,(Scr.Hilite == ButtonWindow),True,True,x); + else + SetTitleBar(ButtonWindow,(Scr.Hilite==ButtonWindow),False); + ButtonWindow = NULL; +} + +/*********************************************************************** + * + * Procedure: + * HandleButtonRelease - ButtonRelease event handler + * + ***********************************************************************/ +void HandleButtonRelease() +{ +#ifndef NO_PAGER + extern Bool EnablePagerRedraw; + if((Tmp_win)&&(Event.xany.window == Scr.Pager_w)&& + (!(Tmp_win->flags & ICONIFIED))) + { + switch(Event.xbutton.button) + { + default: + case Button1: + SwitchPages(TRUE,TRUE); + break; + case Button3: + EnablePagerRedraw = True; + SwitchPages(FALSE,FALSE); + RedrawPager(); + break; + } + } +#endif +} + + +/*********************************************************************** + * + * Procedure: + * HandleEnterNotify - EnterNotify event handler + * + ************************************************************************/ +void HandleEnterNotify() +{ + XEnterWindowEvent *ewp = &Event.xcrossing; + XEvent d; + + /* look for a matching leaveNotify which would nullify this enterNotify */ + if(XCheckTypedWindowEvent (dpy, ewp->window, LeaveNotify, &d)) + { + StashEventTime(&d); + if((d.xcrossing.mode==NotifyNormal)&& + (d.xcrossing.detail!=NotifyInferior)) + return; + } + +/* an EnterEvent in one of the PanFrameWindows activates the Paging */ +#ifndef NON_VIRTUAL + if (ewp->window==Scr.PanFrameTop.win + || ewp->window==Scr.PanFrameLeft.win + || ewp->window==Scr.PanFrameRight.win + || ewp->window==Scr.PanFrameBottom.win ) + { + int delta_x=0, delta_y=0; + /* this was in the HandleMotionNotify before, HEDU */ + HandlePaging(Scr.EdgeScrollX,Scr.EdgeScrollY, + &Event.xcrossing.x_root,&Event.xcrossing.y_root, + &delta_x,&delta_y,True); + return; + } +#endif /* NON_VIRTUAL */ + + if(Event.xany.window == Scr.Root) + { + if((!(Scr.flags & ClickToFocus))&&(!(Scr.flags & SloppyFocus))) + { + SetFocus(Scr.NoFocusWin,NULL); + ClearCirculatedFlag(); + } + InstallWindowColormaps(NULL); + return; + } + + /* make sure its for one of our windows */ + if (!Tmp_win) + return; + + if(!(Scr.flags & ClickToFocus)) + { + if(Scr.Focus != Tmp_win) + { + if((Scr.AutoRaiseDelay > 0)&&(!(Tmp_win->flags & VISIBLE))) + SetTimer(Scr.AutoRaiseDelay); + SetFocus(Tmp_win->w,Tmp_win); + ClearCirculatedFlag(); + } + else + SetFocus(Tmp_win->w,Tmp_win); + } + if((!(Tmp_win->flags & ICONIFIED))&&(Event.xany.window == Tmp_win->w)) + InstallWindowColormaps(Tmp_win); + else + InstallWindowColormaps(NULL); + return; +} + + +/*********************************************************************** + * + * Procedure: + * HandleLeaveNotify - LeaveNotify event handler + * + ************************************************************************/ +void HandleLeaveNotify() +{ + /* If we leave the root window, then we're really moving + * another screen on a multiple screen display, and we + * need to de-focus and unhighlight to make sure that we + * don't end up with more than one highlighted window at a time */ + if(Event.xcrossing.window == Scr.Root) + { + if(Event.xcrossing.mode == NotifyNormal) + { + if (Event.xcrossing.detail != NotifyInferior) + { + if(Scr.Focus != NULL) + { + SetFocus(Scr.NoFocusWin,NULL); + } + if(Scr.Hilite != NULL) + SetBorder(Scr.Hilite,False,True,True,None); + } + } + } +} + + +/*********************************************************************** + * + * Procedure: + * HandleConfigureRequest - ConfigureRequest event handler + * + ************************************************************************/ +void HandleConfigureRequest() +{ + XWindowChanges xwc; + unsigned long xwcm; + int x, y, width, height; + XConfigureRequestEvent *cre = &Event.xconfigurerequest; + + /* + * Event.xany.window is Event.xconfigurerequest.parent, so Tmp_win will + * be wrong + */ + Event.xany.window = cre->window; /* mash parent field */ + if (XFindContext (dpy, cre->window, FvwmContext, (caddr_t *) &Tmp_win) == + XCNOENT) + Tmp_win = NULL; + + /* + * According to the July 27, 1988 ICCCM draft, we should ignore size and + * position fields in the WM_NORMAL_HINTS property when we map a window. + * Instead, we'll read the current geometry. Therefore, we should respond + * to configuration requests for windows which have never been mapped. + */ + if (!Tmp_win || (Tmp_win->icon_w == cre->window)) + { + xwcm = cre->value_mask & + (CWX | CWY | CWWidth | CWHeight | CWBorderWidth); + xwc.x = cre->x; + xwc.y = cre->y; + if((Tmp_win)&&((Tmp_win->icon_w == cre->window))) + { + Tmp_win->icon_xl_loc = cre->x; + Tmp_win->icon_x_loc = cre->x + + (Tmp_win->icon_w_width - Tmp_win->icon_p_width)/2; + Tmp_win->icon_y_loc = cre->y - Tmp_win->icon_p_height; + if(!(Tmp_win->flags & ICON_UNMAPPED)) + Broadcast(M_ICON_LOCATION,7,Tmp_win->w,Tmp_win->frame, + (unsigned long)Tmp_win, + Tmp_win->icon_x_loc,Tmp_win->icon_y_loc, + Tmp_win->icon_w_width, + Tmp_win->icon_w_height + Tmp_win->icon_p_height); + } + xwc.width = cre->width; + xwc.height = cre->height; + xwc.border_width = cre->border_width; + XConfigureWindow(dpy, Event.xany.window, xwcm, &xwc); + + if(Tmp_win) + { + xwc.x = Tmp_win->icon_x_loc; + xwc.y = Tmp_win->icon_y_loc - Tmp_win->icon_p_height; + xwcm = cre->value_mask & (CWX | CWY); + if(Tmp_win->icon_pixmap_w != None) + XConfigureWindow(dpy, Tmp_win->icon_pixmap_w, xwcm, &xwc); + xwc.x = Tmp_win->icon_x_loc; + xwc.y = Tmp_win->icon_y_loc; + xwcm = cre->value_mask & (CWX | CWY); + if(Tmp_win->icon_w != None) + XConfigureWindow(dpy, Tmp_win->icon_w, xwcm, &xwc); + } + return; + } + + if (cre->value_mask & CWStackMode) + { + FvwmWindow *otherwin; + + xwc.sibling = (((cre->value_mask & CWSibling) && + (XFindContext (dpy, cre->above, FvwmContext, + (caddr_t *) &otherwin) == XCSUCCESS)) + ? otherwin->frame : cre->above); + xwc.stack_mode = cre->detail; + XConfigureWindow (dpy, Tmp_win->frame, + cre->value_mask & (CWSibling | CWStackMode), &xwc); + } + +#ifdef SHAPE + { + int xws, yws, xbs, ybs; + unsigned wws, hws, wbs, hbs; + int boundingShaped, clipShaped; + + XShapeQueryExtents (dpy, Tmp_win->w,&boundingShaped, &xws, &yws, &wws, + &hws,&clipShaped, &xbs, &ybs, &wbs, &hbs); + Tmp_win->wShaped = boundingShaped; + } +#endif /* SHAPE */ + + /* Don't modify frame_XXX fields before calling SetupWindow! */ + x = Tmp_win->frame_x; + y = Tmp_win->frame_y; + width = Tmp_win->frame_width; + height = Tmp_win->frame_height; + + /* for restoring */ + if (cre->value_mask & CWBorderWidth) + { + Tmp_win->old_bw = cre->border_width; + } + /* override even if border change */ + + if (cre->value_mask & CWX) + x = cre->x - Tmp_win->boundary_width - Tmp_win->bw; + if (cre->value_mask & CWY) + y = cre->y - Tmp_win->boundary_width - Tmp_win->title_height - Tmp_win->bw; + if (cre->value_mask & CWWidth) + width = cre->width + 2*Tmp_win->boundary_width; + if (cre->value_mask & CWHeight) + height = cre->height+Tmp_win->title_height+2*Tmp_win->boundary_width; + + /* + * SetupWindow (x,y) are the location of the upper-left outer corner and + * are passed directly to XMoveResizeWindow (frame). The (width,height) + * are the inner size of the frame. The inner width is the same as the + * requested client window width; the inner height is the same as the + * requested client window height plus any title bar slop. + */ + SetupFrame (Tmp_win, x, y, width, height,FALSE); + KeepOnTop(); + +#ifndef NO_PAGER + RedrawPager(); +#endif +} + +/*********************************************************************** + * + * Procedure: + * HandleShapeNotify - shape notification event handler + * + ***********************************************************************/ +#ifdef SHAPE +void HandleShapeNotify (void) +{ + XShapeEvent *sev = (XShapeEvent *) &Event; + + if (!Tmp_win) + return; + if (sev->kind != ShapeBounding) + return; + Tmp_win->wShaped = sev->shaped; + SetShape(Tmp_win,Tmp_win->frame_width); +} +#endif /* SHAPE*/ + +/*********************************************************************** + * + * Procedure: + * HandleVisibilityNotify - record fully visible windows for + * use in the RaiseLower function and the OnTop type windows. + * + ************************************************************************/ +void HandleVisibilityNotify() +{ + XVisibilityEvent *vevent = (XVisibilityEvent *) &Event; + + if(Tmp_win) + { + if(vevent->state == VisibilityUnobscured) + Tmp_win->flags |= VISIBLE; + else + Tmp_win->flags &= ~VISIBLE; + + /* For the most part, we'll raised partially obscured ONTOP windows + * here. The exception is ONTOP windows that are obscured by + * other ONTOP windows, which are raised in KeepOnTop(). This + * complicated set-up saves us from continually re-raising + * every on top window */ + if(((vevent->state == VisibilityPartiallyObscured)|| + (vevent->state == VisibilityFullyObscured))&& + (Tmp_win->flags&ONTOP)&&(Tmp_win->flags & RAISED)) + { + RaiseWindow(Tmp_win); + Tmp_win->flags &= ~RAISED; + } + } +} + + +/************************************************************************** + * + * For auto-raising windows, this routine is called + * + *************************************************************************/ +volatile int alarmed; +void enterAlarm(int nonsense) +{ + alarmed = True; + signal(SIGALRM, enterAlarm); +} + + +/*************************************************************************** + * + * Waits for next X event, or for an auto-raise timeout. + * + ****************************************************************************/ +int My_XNextEvent(Display *dpy, XEvent *event) +{ + extern int fd_width, x_fd; + struct itimerval value; + fd_set in_fdset,out_fdset; + Window child; + Window targetWindow; + int i,count; + int retval; + + /* Do this prior to the select() call, in case the timer already expired, + * in which case the select would never return. */ + if(alarmed) + { + alarmed = False; + XQueryPointer(dpy,Scr.Root,&JunkRoot,&child,&JunkX,&JunkY,&JunkX, + &JunkY,&JunkMask ); + if((Scr.Focus != NULL)&&(child == Scr.Focus->frame)) + { + if(!(Scr.Focus->flags & VISIBLE)) + { + RaiseWindow(Scr.Focus); + KeepOnTop(); +#ifndef NO_PAGER + RedrawPager(); +#endif + } + } + return 0; + } + +#ifndef HAVE_GETITIMER + value.it_value.tv_usec = 0; + value.it_value.tv_sec = 0; +#else + getitimer(ITIMER_REAL,&value); +#endif + + FD_ZERO(&in_fdset); + FD_SET(x_fd,&in_fdset); + FD_ZERO(&out_fdset); + for(i=0; i=0) + { + FD_SET(readPipes[i], &in_fdset); + } + } + + for(i=0; i= 0) + { + if((retval>0)&&(FD_ISSET(readPipes[i], &in_fdset))) + { + if((count = + read(readPipes[i],&targetWindow, sizeof(Window))) >0) + { + HandleModuleInput(targetWindow,i); + } + if(count <= 0) + { + KillModule(i,10); + } + } + } + if(writePipes[i] >= 0) + { + if((retval>0)&&(FD_ISSET(writePipes[i], &out_fdset))) + { + FlushQueue(i); + } + } + } + return 0; +} + diff --git a/fvwm/functions.c b/fvwm/functions.c new file mode 100644 index 0000000..a29b653 --- /dev/null +++ b/fvwm/functions.c @@ -0,0 +1,1711 @@ +/**************************************************************************** + * This module is based on Twm, but has been siginificantly modified + * by Rob Nation + ****************************************************************************/ +/*****************************************************************************/ +/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ +/** Salt Lake City, Utah **/ +/** Portions Copyright 1989 by the Massachusetts Institute of Technology **/ +/** Cambridge, Massachusetts **/ +/** **/ +/** All Rights Reserved **/ +/** **/ +/** Permission to use, copy, modify, and distribute this software and **/ +/** its documentation for any purpose and without fee is hereby **/ +/** granted, provided that the above copyright notice appear in all **/ +/** copies and that both that copyright notice and this permis- **/ +/** sion notice appear in supporting documentation, and that the **/ +/** names of Evans & Sutherland and M.I.T. not be used in advertising **/ +/** in publicity pertaining to distribution of the software without **/ +/** specific, written prior permission. **/ +/** **/ +/** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/ +/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/ +/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/ +/** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/ +/** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ +/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ +/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ +/** OR PERFORMANCE OF THIS SOFTWARE. **/ +/*****************************************************************************/ +/*********************************************************************** + * + * fvwm menu code + * + ***********************************************************************/ + +#include "../configure.h" + +#include +#include +#include +#include +#include + +#include "fvwm.h" +#include "menus.h" +#include "misc.h" +#include "parse.h" +#include "screen.h" +#include "module.h" + +extern XEvent Event; +extern FvwmWindow *Tmp_win; +extern int menuFromFrameOrWindowOrTitlebar; +extern DoHandlePageing; + +extern char **g_argv; + + + +/*********************************************************************** + * + * Procedure: + * ExecuteFunction - execute a fvwm built in function + * + * Inputs: + * func - the function to execute + * action - the menu action to execute + * w - the window to execute this function on + * tmp_win - the fvwm window structure + * event - the event that caused the function + * context - the context in which the button was pressed + * val1,val2 - the distances to move in a scroll operation + * + ***********************************************************************/ +void ExecuteFunction(int func,char *action, Window in_w, FvwmWindow *tmp_win, + XEvent *eventp, unsigned long context,long val1,long val2, + int val1_unit, int val2_unit, MenuRoot *menu, int Module) +{ + FvwmWindow *t,*temp; + char *junk, *junkC; + unsigned long junkN; + int junkD; + int x,y; + Window w; +#ifndef NON_VIRTUAL + int delta_x,delta_y; +#endif + int warp_x=0,warp_y=0; +#ifndef NO_PAGER + Pixel TextColor,BackColor; + Pixmap BackPixmap; +#endif + + /* Defer Execution may wish to alter this value */ + w = in_w; + + switch (func) + { + case F_NOP: + case F_TITLE: + break; + + case F_BEEP: + XBell(dpy, Scr.screen); + break; + + case F_RESIZE: + if (DeferExecution(eventp,&w,&tmp_win,&context, MOVE, ButtonPress)) + break; + + if(tmp_win == NULL) + break; + if(check_allowed_function2(func,tmp_win) == 0) + { + XBell(dpy, Scr.screen); + break; + } + tmp_win->flags &= ~MAXIMIZED; + resize_window(w,tmp_win,val1,val2,val1_unit,val2_unit); + break; + + case F_MOVE: + if (DeferExecution(eventp,&w,&tmp_win,&context, MOVE,ButtonPress)) + break; + + if(tmp_win == NULL) + break; + + move_window(eventp,w,tmp_win,context,val1,val2,val1_unit,val2_unit); + break; + +#ifndef NON_VIRTUAL + case F_SCROLL: + if((val1 > -100000)&&(val1 < 100000)) + x=Scr.Vx + val1*val1_unit/100; + else + x = Scr.Vx + (val1/1000)*val1_unit/100; + + if((val2 > -100000)&&(val2 < 100000)) + y=Scr.Vy + val2*val2_unit/100; + else + y = Scr.Vy + (val2/1000)*val2_unit/100; + + if(((val1 <= -100000)||(val1 >= 100000))&&(x>Scr.VxMax)) + { + x = 0; + y += Scr.MyDisplayHeight; + if(y > Scr.VyMax) + y=0; + } + if(((val1 <= -100000)||(val1 >= 100000))&&(x<0)) + { + x = Scr.VxMax; + y -= Scr.MyDisplayHeight; + if(y < 0) + y=Scr.VyMax; + } + if(((val2 <= -100000)||(val2>= 100000))&&(y>Scr.VyMax)) + { + y = 0; + x += Scr.MyDisplayWidth; + if(x > Scr.VxMax) + x=0; + } + if(((val2 <= -100000)||(val2>= 100000))&&(y<0)) + { + y = Scr.VyMax; + x -= Scr.MyDisplayWidth; + if(x < 0) + x=Scr.VxMax; + } + MoveViewport(x,y,True); + break; +#endif + case F_MOVECURSOR: + XQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, + &x,&y,&JunkX, &JunkY, &JunkMask); +#ifndef NON_VIRTUAL + delta_x = 0; + delta_y = 0; + warp_x = 0; + warp_y = 0; + if(x >= Scr.MyDisplayWidth -2) + { + delta_x = Scr.EdgeScrollX; + warp_x = Scr.EdgeScrollX - 4; + } + if(y>= Scr.MyDisplayHeight -2) + { + delta_y = Scr.EdgeScrollY; + warp_y = Scr.EdgeScrollY - 4; + } + if(x < 2) + { + delta_x = -Scr.EdgeScrollX; + warp_x = -Scr.EdgeScrollX + 4; + } + if(y < 2) + { + delta_y = -Scr.EdgeScrollY; + warp_y = -Scr.EdgeScrollY + 4; + } + if(Scr.Vx + delta_x < 0) + delta_x = -Scr.Vx; + if(Scr.Vy + delta_y < 0) + delta_y = -Scr.Vy; + if(Scr.Vx + delta_x > Scr.VxMax) + delta_x = Scr.VxMax - Scr.Vx; + if(Scr.Vy + delta_y > Scr.VyMax) + delta_y = Scr.VyMax - Scr.Vy; + if((delta_x!=0)||(delta_y!=0)) + { + MoveViewport(Scr.Vx + delta_x,Scr.Vy+delta_y,True); + XWarpPointer(dpy, Scr.Root, Scr.Root, 0, 0, Scr.MyDisplayWidth, + Scr.MyDisplayHeight, + x - warp_x, + y - warp_y); + } +#endif + XWarpPointer(dpy, Scr.Root, Scr.Root, 0, 0, Scr.MyDisplayWidth, + Scr.MyDisplayHeight, x + val1*val1_unit/100-warp_x, + y+val2*val2_unit/100 - warp_y); + + break; + case F_ICONIFY: + if (DeferExecution(eventp,&w,&tmp_win,&context, SELECT, ButtonRelease)) + break; + + if(tmp_win == NULL) + break; + if (tmp_win->flags & ICONIFIED) + { + if(val1 <=0) + DeIconify(tmp_win); + } + else + { + if(check_allowed_function2(func,tmp_win) == 0) + { + XBell(dpy, Scr.screen); + break; + } + if(val1 >=0) + { + if(check_allowed_function2(func,tmp_win) == 0) + { + XBell(dpy, Scr.screen); + break; + } + Iconify(tmp_win,eventp->xbutton.x_root-5,eventp->xbutton.y_root-5); + } + } + break; + + case F_RAISE: + if (DeferExecution(eventp,&w,&tmp_win,&context, SELECT,ButtonRelease)) + break; + + if(tmp_win) + RaiseWindow(tmp_win); + + if (LookInList(Scr.TheList,tmp_win->name, &tmp_win->class, &junk, &junkD, + &junkD, &junkD, &junkC, &junkC, &junkN)& STAYSONTOP_FLAG) + tmp_win->flags |= ONTOP; + KeepOnTop(); + break; + + case F_LOWER: + if (DeferExecution(eventp,&w,&tmp_win,&context, SELECT, ButtonRelease)) + break; + + if(tmp_win == NULL) + break; + LowerWindow(tmp_win); + + tmp_win->flags &= ~ONTOP; + break; + + case F_DESTROY: + if (DeferExecution(eventp,&w,&tmp_win,&context, DESTROY, ButtonRelease)) + break; + + if(tmp_win == NULL) + break; + if(check_allowed_function2(func,tmp_win) == 0) + { + XBell(dpy, Scr.screen); + break; + } +#ifndef NO_PAGER + /* Dont delete the pager - it crashes the program! */ + if((tmp_win->w == Scr.Pager_w)||(tmp_win == Scr.FvwmPager)) + break; +#endif + + if (XGetGeometry(dpy, tmp_win->w, &JunkRoot, &JunkX, &JunkY, + &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth) == 0) + Destroy(tmp_win); + else + XKillClient(dpy, tmp_win->w); + XSync(dpy,0); + break; + + case F_DELETE: + if (DeferExecution(eventp,&w,&tmp_win,&context, DESTROY,ButtonRelease)) + break; + + if(tmp_win == NULL) + break; + if(check_allowed_function2(func,tmp_win) == 0) + { + XBell(dpy, Scr.screen); + break; + } + +#ifndef NO_PAGER + /* Dont delete the pager - it crashes the program! */ + if((tmp_win->w == Scr.Pager_w)||(tmp_win == Scr.FvwmPager)) + break; +#endif + if (tmp_win->flags & DoesWmDeleteWindow) + { + send_clientmessage (tmp_win->w, _XA_WM_DELETE_WINDOW, CurrentTime); + break; + } + else + XBell (dpy, Scr.screen); + XSync(dpy,0); + break; + + case F_CLOSE: + if (DeferExecution(eventp,&w,&tmp_win,&context, DESTROY,ButtonRelease)) + break; + + if(tmp_win == NULL) + break; + if(check_allowed_function2(func,tmp_win) == 0) + { + XBell(dpy, Scr.screen); + break; + } + +#ifndef NO_PAGER + /* Dont delete the pager - it crashes the program! */ + if((tmp_win->w == Scr.Pager_w)||(tmp_win == Scr.FvwmPager)) + break; +#endif + if (tmp_win->flags & DoesWmDeleteWindow) + { + send_clientmessage (tmp_win->w, _XA_WM_DELETE_WINDOW, CurrentTime); + break; + } + else if (XGetGeometry(dpy, tmp_win->w, &JunkRoot, &JunkX, &JunkY, + &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth) == 0) + Destroy(tmp_win); + else + XKillClient(dpy, tmp_win->w); + XSync(dpy,0); + break; + + case F_RESTART: + Done(1, action); + break; + + case F_EXEC: + XGrabPointer(dpy, Scr.Root, True, + ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, + Scr.Root, Scr.FvwmCursors[WAIT], CurrentTime); + XSync (dpy,0); + + if (!(fork())) /* child process */ + if (execl("/bin/sh", "/bin/sh", "-c", action, (char *)0)==-1) + exit(100); + XUngrabPointer(dpy,CurrentTime); + XSync (dpy,0); + break; + + case F_REFRESH: + { + XSetWindowAttributes attributes; + unsigned long valuemask; + + valuemask = (CWBackPixel); + attributes.background_pixel = Scr.StdColors.fore; + attributes.backing_store = NotUseful; + w = XCreateWindow (dpy, Scr.Root, 0, 0, + (unsigned int) Scr.MyDisplayWidth, + (unsigned int) Scr.MyDisplayHeight, + (unsigned int) 0, + CopyFromParent, (unsigned int) CopyFromParent, + (Visual *) CopyFromParent, valuemask, + &attributes); + XMapWindow (dpy, w); + XDestroyWindow (dpy, w); + XFlush (dpy); + } + break; + + case F_STICK: + /* stick/unstick a window */ + if (DeferExecution(eventp,&w,&tmp_win,&context,SELECT,ButtonRelease)) + break; + + if(tmp_win == NULL) + break; + + if(tmp_win->flags & STICKY) + { + tmp_win->flags &= ~STICKY; + if(tmp_win->BackPixel == Scr.StickyColors.back) + { + tmp_win->ReliefPixel = Scr.StdRelief.fore; + tmp_win->ShadowPixel = Scr.StdRelief.back; + tmp_win->BackPixel = Scr.StdColors.back; + } + if(tmp_win->TextPixel == Scr.StickyColors.fore) + tmp_win->TextPixel = Scr.StdColors.fore; + } + else + { + tmp_win->flags |=STICKY; + if(tmp_win->BackPixel == Scr.StdColors.back) + { + tmp_win->BackPixel = Scr.StickyColors.back; + tmp_win->ShadowPixel = Scr.StickyRelief.back; + tmp_win->ReliefPixel = Scr.StickyRelief.fore; + } + if(tmp_win->TextPixel == Scr.StdColors.fore) + tmp_win->TextPixel = Scr.StickyColors.fore; + } + if(Scr.Hilite != tmp_win) + { + /* Need to make SetBorder change the window back color */ + temp=Scr.Hilite; + SetBorder(tmp_win,True,True,True,None); + SetBorder(tmp_win,False,True,True,None); + SetBorder(temp,True,True,True,None); + } + BroadcastConfig(M_CONFIGURE_WINDOW,tmp_win); +#ifndef NO_PAGER + MoveResizePagerView(tmp_win); + + /* Need to re-draw pager_view in case the window + * is unsticking */ + if(Scr.Hilite == tmp_win) + { + TextColor = Scr.HiColors.fore; + BackPixmap= Scr.gray_pixmap; + BackColor = Scr.HiColors.back; + } + else + { + TextColor = Scr.StdColors.fore; + BackPixmap = Scr.light_gray_pixmap; + BackColor = Scr.StdColors.back; + } + if(Scr.d_depth < 2) + XSetWindowBackgroundPixmap(dpy,tmp_win->pager_view,BackPixmap); + else + XSetWindowBackground(dpy,tmp_win->pager_view,BackColor); + XClearWindow(dpy,tmp_win->pager_view); + if((tmp_win->icon_name != NULL)&&(Scr.PagerFont.height > 0)) + { + NewFontAndColor(Scr.PagerFont.font->fid,TextColor,BackColor); + XDrawString (dpy, tmp_win->pager_view,Scr.FontGC,2,Scr.PagerFont.y+2, + tmp_win->icon_name, strlen(tmp_win->icon_name)); + } +#endif + break; + +#ifndef NON_VIRTUAL + case F_GOTO_PAGE: + /* back up 1 virtual desktop page */ + x=val1*Scr.MyDisplayWidth; + y=val2*Scr.MyDisplayHeight; + MoveViewport(x,y,True); + break; +#endif +#ifndef NON_VIRTUAL + case F_TOGGLE_PAGE: + if (DoHandlePageing) + { + DoHandlePageing = 0; + Broadcast(M_TOGGLE_PAGING,1,0,0,0,0,0,0,0); + } + else + { + DoHandlePageing = 1; + Broadcast(M_TOGGLE_PAGING,1,1,0,0,0,0,0,0); + } + checkPanFrames(); + break; +#endif + + case F_CIRCULATE_UP: + t=Circulate(tmp_win,action,UP); + if(t)FocusOn(t,0); + break; + + case F_CIRCULATE_DOWN: + t=Circulate(tmp_win,action,DOWN); + if(t)FocusOn(t,0); + break; + + case F_WARP: + t=Circulate(tmp_win,action,DOWN); + if((t)&&(t->flags & ICONIFIED)) + { + FocusOn(t,0); + DeIconify(t); + } + if(t)FocusOn(t,0); + break; + + case F_WAIT: + { + Bool done = False; + if(val1 == 0) + val1 = 1; + while(!done) + { + if(My_XNextEvent(dpy, &Event)) + { + DispatchEvent (); + if(Event.type == MapNotify) + { + if((Tmp_win)&&(matchWildcards(action,Tmp_win->name)==True)) + done = True; + if((Tmp_win)&&(Tmp_win->class.res_class)&& + (matchWildcards(action,Tmp_win->class.res_class)==True)) + done = True; + if((Tmp_win)&&(Tmp_win->class.res_name)&& + (matchWildcards(action,Tmp_win->class.res_name)==True)) + done = True; + } + } + } + } + XSync(dpy,0); + break; + case F_RAISE_IT: + if(val1 != 0) + { + FocusOn((FvwmWindow *)val1,0); + if (((FvwmWindow *)(val1))->flags & ICONIFIED) + { + DeIconify((FvwmWindow *)val1); + FocusOn((FvwmWindow *)val1,0); + } + } + + break; + case F_FOCUS: + if (DeferExecution(eventp,&w,&tmp_win,&context,SELECT,ButtonRelease)) + break; + FocusOn(tmp_win,0); + break; + + case F_CHANGE_WINDOWS_DESK: + if (DeferExecution(eventp,&w,&tmp_win,&context,SELECT,ButtonRelease)) + break; + if(tmp_win == NULL) + break; + + changeWindowsDesk(tmp_win,val1); + break; + case F_DESK: + changeDesks(val1,val2); + break; + case F_MODULE: + if(eventp->type != KeyPress) + UngrabEm(); + if(tmp_win) + executeModule(action, (FILE *)NULL,(char **)tmp_win->w,(int *)context); + else + executeModule(action, (FILE *)NULL,(char **)0, (int *)context); + /* If we execute a module, don't wait for buttons to come up, + * that way, a pop-up menu could be implemented */ + Module = 0; + break; + + case F_RAISELOWER: + if (DeferExecution(eventp,&w,&tmp_win,&context, SELECT,ButtonRelease)) + break; + if(tmp_win == NULL) + break; + + if((tmp_win == Scr.LastWindowRaised)|| + (tmp_win->flags & VISIBLE)) + { + LowerWindow(tmp_win); + tmp_win->flags &= ~ONTOP; + } + else + { + RaiseWindow(tmp_win); + if (LookInList(Scr.TheList,tmp_win->name, &tmp_win->class,&junk, + &junkD,&junkD, &junkD, &junkC,&junkC,&junkN)&STAYSONTOP_FLAG) + tmp_win->flags |= ONTOP; + KeepOnTop(); + } + break; + + case F_POPUP: + ActiveItem = NULL; + ActiveMenu = NULL; + menuFromFrameOrWindowOrTitlebar = FALSE; + do_menu(menu); + break; + + case F_MAXIMIZE: + if (DeferExecution(eventp,&w,&tmp_win,&context, SELECT,ButtonRelease)) + break; + if(tmp_win == NULL) + break; + + if(check_allowed_function2(func,tmp_win) == 0) + { + XBell(dpy, Scr.screen); + break; + } + Maximize(tmp_win,val1,val2,val1_unit,val2_unit); + break; + + case F_QUIT: + Done(0, NULL); + break; + + case F_WINDOWLIST: + do_windowList(val1,val2); + break; + + case F_FUNCTION: + ComplexFunction(w, tmp_win, eventp, context,menu); + break; + + case F_QUICKIE: + QuickRestart(); + break; + case F_SEND_WINDOW_LIST: + if(Module >= 0) + { + SendPacket(Module,M_TOGGLE_PAGING,1,DoHandlePageing,0,0,0,0,0,0); + SendPacket(Module,M_NEW_DESK,1,Scr.CurrentDesk,0,0,0,0,0,0); + SendPacket(Module,M_NEW_PAGE,3,Scr.Vx,Scr.Vy,Scr.CurrentDesk, + 0,0,0,0); + if(Scr.Hilite != NULL) + SendPacket(Module,M_FOCUS_CHANGE,3,Scr.Hilite->w,Scr.Hilite->frame, + (unsigned long)Scr.Hilite,0,0,0,0); + else + SendPacket(Module,M_FOCUS_CHANGE,3,0,0,0,0,0,0,0); + for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) + { + SendConfig(Module,M_CONFIGURE_WINDOW,t); + SendName(Module,M_WINDOW_NAME,t->w,t->frame, + (unsigned long)t,t->name); + SendName(Module,M_ICON_NAME,t->w,t->frame, + (unsigned long)t,t->icon_name); + SendName(Module,M_RES_CLASS,t->w,t->frame, + (unsigned long)t,t->class.res_class); + SendName(Module,M_RES_NAME,t->w,t->frame, + (unsigned long)t,t->class.res_name); + + if((t->flags & ICONIFIED)&&(!(t->flags & ICON_UNMAPPED))) + SendPacket(Module,M_ICONIFY,7,t->w,t->frame, + (unsigned long)t, + t->icon_x_loc,t->icon_y_loc, + t->icon_w_width, + t->icon_w_height+t->icon_p_height); + if((t->flags & ICONIFIED) && (t->flags & ICON_UNMAPPED)) + SendPacket(Module,M_ICONIFY,7,t->w,t->frame, + (unsigned long)t,0,0,0,0); + } + if(Scr.Hilite == NULL) + { + Broadcast(M_FOCUS_CHANGE,3,0,0,0,0,0,0,0); + } + else + { + Broadcast(M_FOCUS_CHANGE,3,Scr.Hilite->w, + Scr.Hilite->frame,(unsigned long)Scr.Hilite,0,0,0,0); + } + SendPacket(Module,M_END_WINDOWLIST,0,0,0,0,0,0,0,0); + } + } + + /* Only wait for an all-buttons-up condition after calls from + * regular built-ins, not from complex-functions or modules. */ + if(Module == -1) + WaitForButtonsUp(); + + return; +} + +FvwmWindow *Circulate(FvwmWindow *tmp_win, char *action,Bool Direction) +{ + FvwmWindow *t,*selected; + Bool found; + int count,pass=1; + int base, best; + + while(pass< 3) + { + if(tmp_win) + base = tmp_win->focus_sequence; + else + base = -1; + if(Direction == DOWN) + best = -1; + else + best = 10000; + selected = tmp_win; + + /* move focus to the next window */ + found = FALSE; + t = tmp_win; + count = 0; + while(count < 3) + { + if(Direction == DOWN) + { + if((t == (FvwmWindow *)0)||(t->next == NULL)) + { + t = Scr.FvwmRoot.next; + count++; + } + else + t =t->next; + } + else /* Direction Up */ + { + if ((t == (FvwmWindow *)0)||(t == &Scr.FvwmRoot)|| + (t->prev == &Scr.FvwmRoot)||(t->prev == (FvwmWindow *)NULL)) + { + for(t=Scr.FvwmRoot.next;t->next != (FvwmWindow *)NULL;t=t->next); + count++; + } + else + t=t->prev; + } + found = TRUE; + + if(t->Desk != Scr.CurrentDesk) + found = False; + + if((!(Scr.flags & Lenience))&& + (t)&&(t->wmhints)&&(t->wmhints->flags&InputHint)&& + (t->wmhints->input == False)&& + !(t->flags & DoesWmTakeFocus)) + found = False; + + if (t->flags & CIRCULATESKIP) + found = FALSE; + /* optional skip over icons */ + + if((t->flags & ICONIFIED)&&(Scr.flags & CirculateSkipIcons)) + found = FALSE; + + + /* Make CirculateUp and CirculateDown take args. by Y.NOMURA */ + if (action && (strlen(action) > 0)&& + !(matchWildcards(action, t->name)) && + !(matchWildcards(action, t->icon_name))&& + t->class.res_name && + !(matchWildcards(action, t->class.res_name))) + found = FALSE; + if((found)&&(Direction == DOWN)&&(t->focus_sequence > best)) + { + best = t->focus_sequence; + selected = t; + } + if((found)&&(Direction != DOWN)&&(t->focus_sequence < best) + &&(t->focus_sequence > base)) + { + best = t->focus_sequence; + selected = t; + } + } + if((selected)&&(selected == tmp_win)&&(base > 0)) + { + if(Direction == DOWN) + { + ClearCirculatedFlag(); + tmp_win->focus_sequence = 0; + } + else + { + FvwmWindow *temp; + + temp = Scr.FvwmRoot.next; + while(temp != NULL) + { + temp->focus_sequence++; + if(temp == tmp_win)temp->focus_sequence = 0; + temp = temp->next; + } + } + pass++; + } + else + pass = 3; + } + + return selected; +} + + +/*********************************************************************** + * + * Procedure: + * DeferExecution - defer the execution of a function to the + * next button press if the context is C_ROOT + * + * Inputs: + * eventp - pointer to XEvent to patch up + * w - pointer to Window to patch up + * tmp_win - pointer to FvwmWindow Structure to patch up + * context - the context in which the mouse button was pressed + * func - the function to defer + * cursor - the cursor to display while waiting + * finishEvent - ButtonRelease or ButtonPress; tells what kind of event to + * terminate on. + * + ***********************************************************************/ +int DeferExecution(XEvent *eventp, Window *w,FvwmWindow **tmp_win, + unsigned long *context, int cursor, int FinishEvent) + +{ + int done; + int finished = 0; + Window dummy; + Window original_w; + + original_w = *w; + + if((*context != C_ROOT)&&(*context != C_NO_CONTEXT)) + { + if((FinishEvent == ButtonPress)||((FinishEvent == ButtonRelease) && + (eventp->type != ButtonPress))) + { + return FALSE; + } + } + if(!GrabEm(cursor)) + { + XBell(dpy,Scr.screen); + return True; + } + + while (!finished) + { + done = 0; + /* block until there is an event */ + XMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask | + ExposureMask |KeyPressMask | VisibilityChangeMask | + ButtonMotionMask| PointerMotionMask/* | EnterWindowMask | + LeaveWindowMask*/, eventp); + StashEventTime(eventp); + + if(eventp->type == KeyPress) + Keyboard_shortcuts(eventp,FinishEvent); + if(eventp->type == FinishEvent) + finished = 1; + if(eventp->type == ButtonPress) + { + XAllowEvents(dpy,ReplayPointer,CurrentTime); + done = 1; + } + if(eventp->type == ButtonRelease) + done = 1; + if(eventp->type == KeyPress) + done = 1; + + if(!done) + { + DispatchEvent(); + } + + } + + + *w = eventp->xany.window; + if(((*w == Scr.Root)||(*w == Scr.NoFocusWin)) + && (eventp->xbutton.subwindow != (Window)0)) + { + *w = eventp->xbutton.subwindow; + eventp->xany.window = *w; + } + if (*w == Scr.Root) + { + *context = C_ROOT; + XBell(dpy,Scr.screen); + UngrabEm(); + return TRUE; + } + if (XFindContext (dpy, *w, FvwmContext, (caddr_t *)tmp_win) == XCNOENT) + { + *tmp_win = NULL; + XBell(dpy,Scr.screen); + UngrabEm(); + return (TRUE); + } + + if(*w == (*tmp_win)->Parent) + *w = (*tmp_win)->w; + + if(original_w == (*tmp_win)->Parent) + original_w = (*tmp_win)->w; + + /* this ugly mess attempts to ensure that the release and press + * are in the same window. */ + if((*w != original_w)&&(original_w != Scr.Root)&& + (original_w != None)&&(original_w != Scr.NoFocusWin)) + if(!((*w == (*tmp_win)->frame)&& + (original_w == (*tmp_win)->w))) + { + *context = C_ROOT; + XBell(dpy,Scr.screen); + UngrabEm(); + return TRUE; + } + + *context = GetContext(*tmp_win,eventp,&dummy); + + UngrabEm(); + return FALSE; +} + + +/**************************************************************************** + * + * This is used to tell applications which windows on the screen are + * top level appication windows, and which windows are the icon windows + * that go with them. + * + ****************************************************************************/ +void SetMapStateProp(FvwmWindow *tmp_win, int state) +{ + unsigned long data[2]; /* "suggested" by ICCCM version 1 */ + + data[0] = (unsigned long) state; + data[1] = (unsigned long) tmp_win->icon_w; +/* data[2] = (unsigned long) tmp_win->icon_pixmap_w;*/ + + XChangeProperty (dpy, tmp_win->w, _XA_WM_STATE, _XA_WM_STATE, 32, + PropModeReplace, (unsigned char *) data, 2); + return; +} + +/**************************************************************************** + * + * Keeps the "StaysOnTop" windows on the top of the pile. + * This is achieved by clearing a flag for OnTop windows here, and waiting + * for a visibility notify on the windows. Eception: OnTop windows which are + * obscured by other OnTop windows, which need to be raised here. + * + ****************************************************************************/ +void KeepOnTop() +{ + FvwmWindow *t; + + /* flag that on-top windows should be re-raised */ + for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) + { + if((t->flags & ONTOP)&&!(t->flags & VISIBLE)) + { + RaiseWindow(t); + t->flags &= ~RAISED; + } + else + t->flags |= RAISED; + } +} + + +/*************************************************************************** + * + * Moves the viewport within thwe virtual desktop + * + ***************************************************************************/ +#ifndef NON_VIRTUAL +void MoveViewport(int newx, int newy, Bool grab) +{ + FvwmWindow *t; + int deltax,deltay; + + if(grab) + XGrabServer(dpy); + + + if(newx > Scr.VxMax) + newx = Scr.VxMax; + if(newy > Scr.VyMax) + newy = Scr.VyMax; + if(newx <0) + newx = 0; + if(newy <0) + newy = 0; + + deltay = Scr.Vy - newy; + deltax = Scr.Vx - newx; + + Scr.Vx = newx; + Scr.Vy = newy; + Broadcast(M_NEW_PAGE,3,Scr.Vx,Scr.Vy,Scr.CurrentDesk,0,0,0,0); + + if((deltax!=0)||(deltay!=0)) + { + for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) + { + /* If the window is iconified, and sticky Icons is set, + * then the window should essentially be sticky */ + if(!((t->flags & ICONIFIED)&&(Scr.flags & StickyIcons)) && + (!(t->flags & STICKY))) + { + if(!(Scr.flags & StickyIcons)) + { + t->icon_x_loc += deltax; + t->icon_xl_loc += deltax; + t->icon_y_loc += deltay; + if(t->icon_pixmap_w != None) + XMoveWindow(dpy,t->icon_pixmap_w,t->icon_x_loc, + t->icon_y_loc); + if(t->icon_w != None) + XMoveWindow(dpy,t->icon_w,t->icon_x_loc, + t->icon_y_loc+t->icon_p_height); + if(!(t->flags &ICON_UNMAPPED)) + Broadcast(M_ICON_LOCATION,7,t->w,t->frame, + (unsigned long)t, + t->icon_x_loc,t->icon_y_loc, + t->icon_w_width, + t->icon_w_height+t->icon_p_height); + } + } + if(!(t->flags & STICKY)) + SetupFrame (t, t->frame_x+ deltax, t->frame_y + deltay, + t->frame_width, t->frame_height,FALSE); + } + for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) + { + /* If its an icon, and its sticking, autoplace it so + * that it doesn't wind up on top a a stationary + * icon */ + if(((t->flags & STICKY)||(Scr.flags & StickyIcons))&& + (t->flags & ICONIFIED)&&(!(t->flags & ICON_MOVED))&& + (!(t->flags & ICON_UNMAPPED))) + AutoPlace(t); + } + + } + /* fix up the viewport indicator */ + MoveResizeViewPortIndicator(); +#ifndef NON_VIRTUAL + checkPanFrames(); + + /* do this with PanFrames too ??? HEDU */ + while(XCheckTypedEvent(dpy,MotionNotify,&Event)) + StashEventTime(&Event); +#endif + if(grab) + XUngrabServer(dpy); +} +#endif + + +/************************************************************************** + * + * Moves focus to specified window + * + *************************************************************************/ +void FocusOn(FvwmWindow *t,int DeIconifyOnly) +{ +#ifndef NON_VIRTUAL + int dx,dy; + int cx,cy; +#endif + int x,y; + + if(t == (FvwmWindow *)0) + return; + + if(t->Desk != Scr.CurrentDesk) + { + changeDesks(0,t->Desk); + } + +#ifndef NON_VIRTUAL + if(t->flags & ICONIFIED) + { + cx = t->icon_xl_loc + t->icon_w_width/2; + cy = t->icon_y_loc + t->icon_p_height + ICON_HEIGHT/2; + } + else + { + cx = t->frame_x + t->frame_width/2; + cy = t->frame_y + t->frame_height/2; + } + + /* Put center of window on the visible screen */ + if((!DeIconifyOnly)&&(Scr.flags & CenterOnCirculate)) + { + dx = cx - Scr.MyDisplayWidth/2 + Scr.Vx; + dy = cy - Scr.MyDisplayHeight/2 + Scr.Vy; + } + else + { + dx = (cx + Scr.Vx)/Scr.MyDisplayWidth*Scr.MyDisplayWidth; + dy = (cy +Scr.Vy)/Scr.MyDisplayHeight*Scr.MyDisplayHeight; + } + MoveViewport(dx,dy,True); +#endif + + if(t->flags & ICONIFIED) + { + x = t->icon_xl_loc + t->icon_w_width/2; + y = t->icon_y_loc + t->icon_p_height + ICON_HEIGHT/2; + } + else + { + x = t->frame_x; + y = t->frame_y; + } + if(!(Scr.flags & ClickToFocus)) + XWarpPointer(dpy, None, Scr.Root, 0, 0, 0, 0, x+2,y+2); + RaiseWindow(t); + KeepOnTop(); + + /* If the window is still not visible, make it visible! */ + if(((t->frame_x + t->frame_height)< 0)||(t->frame_y + t->frame_width < 0)|| + (t->frame_x >Scr.MyDisplayWidth)||(t->frame_y>Scr.MyDisplayHeight)) + { + SetupFrame(t,0,0,t->frame_width, t->frame_height,False); + if(!(Scr.flags & ClickToFocus)) + XWarpPointer(dpy, None, Scr.Root, 0, 0, 0, 0, 2,2); + } + UngrabEm(); + SetFocus(t->w,t); +} + + + +/*********************************************************************** + * + * Procedure: + * (Un)Maximize a window. + * + ***********************************************************************/ +void Maximize(FvwmWindow *tmp_win,int val1,int val2, + int val1_unit,int val2_unit) +{ + int new_width, new_height,new_x,new_y; + + if (tmp_win->flags & MAXIMIZED) + { + tmp_win->flags &= ~MAXIMIZED; + SetupFrame(tmp_win, tmp_win->orig_x, tmp_win->orig_y, tmp_win->orig_wd, + tmp_win->orig_ht,TRUE); + SetBorder(tmp_win,True,True,True,None); + } + else + { + new_width = tmp_win->frame_width; + new_height = tmp_win->frame_height; + new_x = tmp_win->frame_x; + new_y = tmp_win->frame_y; + if(val1 >0) + { + new_width = val1*val1_unit/100-2; + new_x = 0; + } + if(val2 >0) + { + new_height = val2*val2_unit/100-2; + new_y = 0; + } + if((val1==0)&&(val2==0)) + { + new_x = 0; + new_y = 0; + new_height = Scr.MyDisplayHeight-2; + new_width = Scr.MyDisplayWidth-2; + } + tmp_win->flags |= MAXIMIZED; + ConstrainSize (tmp_win, &new_width, &new_height); + SetupFrame(tmp_win,new_x,new_y,new_width,new_height,TRUE); + SetBorder(tmp_win,Scr.Hilite == tmp_win,True,True,tmp_win->right_w[0]); + } +#ifndef NO_PAGER + RedrawPager(); +#endif +} + +/***************************************************************************** + * + * Grab the pointer and keyboard + * + ****************************************************************************/ +Bool GrabEm(int cursor) +{ + int i=0,val=0; + unsigned int mask; + + XSync(dpy,0); + /* move the keyboard focus prior to grabbing the pointer to + * eliminate the enterNotify and exitNotify events that go + * to the windows */ + if(Scr.PreviousFocus == NULL) + Scr.PreviousFocus = Scr.Focus; + SetFocus(Scr.NoFocusWin,NULL); + mask = ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|PointerMotionMask + | EnterWindowMask | LeaveWindowMask; + while((i<1000)&&(val=XGrabPointer(dpy, Scr.Root, True, mask, + GrabModeAsync, GrabModeAsync, Scr.Root, + Scr.FvwmCursors[cursor], CurrentTime)!= + GrabSuccess)) + { + i++; + /* If you go too fast, other windows may not get a change to release + * any grab that they have. */ + sleep_a_little(1000); + } + + /* If we fall out of the loop without grabbing the pointer, its + time to give up */ + XSync(dpy,0); + if(val!=GrabSuccess) + { + return False; + } + return True; +} + + +/***************************************************************************** + * + * UnGrab the pointer and keyboard + * + ****************************************************************************/ +void UngrabEm() +{ + Window w; + + XSync(dpy,0); + XUngrabPointer(dpy,CurrentTime); + + if(Scr.PreviousFocus != NULL) + { + w = Scr.PreviousFocus->w; + + /* if the window still exists, focus on it */ + if (w) + { + SetFocus(w,Scr.PreviousFocus); + } + Scr.PreviousFocus = NULL; + } + XSync(dpy,0); +} + + +/***************************************************************************** + * + * Waits Scr.ClickTime, or until it is evident that the user is not + * clicking, but is moving the cursor + * + ****************************************************************************/ +Bool IsClick(int x,int y,unsigned EndMask, XEvent *d) +{ + int xcurrent,ycurrent,total = 0; + + xcurrent = x; + ycurrent = y; + while((total < Scr.ClickTime)&& + (x - xcurrent < 5)&&(x - xcurrent > -5)&& + (y - ycurrent < 5)&&(y - ycurrent > -5)) + { + sleep_a_little(10000); + total+=10; + if(XCheckMaskEvent (dpy,EndMask, d)) + { + StashEventTime(d); + return True; + } + if(XCheckMaskEvent (dpy,ButtonMotionMask|PointerMotionMask, d)) + { + xcurrent = d->xmotion.x_root; + ycurrent = d->xmotion.y_root; + StashEventTime(d); + } + } + return False; +} + +/***************************************************************************** + * + * Builtin which determines if the button press was a click or double click... + * + ****************************************************************************/ +void ComplexFunction(Window w, FvwmWindow *tmp_win, XEvent *eventp, + unsigned long context, MenuRoot *mr) +{ + char type = MOTION; + char c; + XEvent *ev; + MenuItem *mi; + XEvent d; + Bool Persist = False; + Bool HaveDoubleClick = False; + Bool NeedsTarget = False; + int x, y ; + + if(mr == NULL) + return; + + /* These built-ins require a selected window + * The function code is >= 100 and < 1000 + * F_RESIZE + * F_MOVE + * F_ICONIFY + * F_RAISE + * F_LOWER + * F_DESTROY + * F_DELETE + * F_STICK + * F_RAISELOWER + * F_MAXIMIZE + * F_FOCUS + * + * These do not: + * The function code is < 100 + * F_NOP + * F_TITLE + * F_BEEP + * F_SCROLL + * F_MOVECURSOR + * F_RESTART + * F_EXEC + * F_REFRESH + * F_GOTO_PAGE + * F_TOGGLE_PAGE + * F_CIRCULATE_UP + * F_CIRCULATE_DOWN + * F_WARP + * F_DESK + * F_MODULE + * F_POPUP + * F_QUIT + * F_WINDOWLIST + * F_FUNCTION + * F_SEND_WINDOW_LIST + */ + + mi = mr->first; + while(mi != NULL) + { + /* make lower case */ + c = *(mi->item); + if((mi->func >= 100)&&(mi->func < 1000)) + NeedsTarget = True; + if(isupper(c)) + c=tolower(c); + if(c==DOUBLE_CLICK) + HaveDoubleClick = True; + else if(c == IMMEDIATE) + { + if(tmp_win) + w = tmp_win->frame; + else + w = None; + ExecuteFunction(mi->func, mi->action,w, + tmp_win, eventp, context,mi->val1,mi->val2, + mi->val1_unit,mi->val2_unit, + mi->menu,-1); + } + else + Persist = True; + mi = mi->next; + } + + if(!Persist) + return; + + /* Only defer execution if there is a possibility of needing + * a window to operate on */ + if(NeedsTarget) + { + if (DeferExecution(eventp,&w,&tmp_win,&context, SELECT,ButtonPress)) + { + WaitForButtonsUp(); + return; + } + } + + if(!GrabEm(SELECT)) + { + XBell(dpy,Scr.screen); + return; + } + XQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, + &x,&y,&JunkX, &JunkY, &JunkMask); + + /* A window has already been selected */ + ev = eventp; + + /* Wait and see if we have a click, or a move */ + /* wait 100 msec, see if the used releases the button */ + if(IsClick(x,y,ButtonReleaseMask,&d)) + { + type = CLICK; + ev = &d; + } + + /* If it was a click, wait to see if its a double click */ + if((HaveDoubleClick) && (type == CLICK) && + (IsClick(x,y,ButtonPressMask, &d))) + { + type = ONE_AND_A_HALF_CLICKS; + ev = &d; + } + if((HaveDoubleClick) && (type == ONE_AND_A_HALF_CLICKS) && + (IsClick(x,y,ButtonReleaseMask, &d))) + { + type = DOUBLE_CLICK; + ev = &d; + } + /* some functions operate on button release instead of + * presses. These gets really weird for complex functions ... */ + if(eventp->type == ButtonPress) + eventp->type = ButtonRelease; + + mi = mr->first; + while(mi != NULL) + { + /* make lower case */ + c = *(mi->item); + if(isupper(c)) + c=tolower(c); + if(c == type) + { + if(tmp_win) + w = tmp_win->frame; + else + w = None; + ExecuteFunction(mi->func, mi->action,w, + tmp_win, eventp, context, + mi->val1,mi->val2, + mi->val1_unit,mi->val2_unit,mi->menu,-2); + } + mi = mi->next; + } + WaitForButtonsUp(); + UngrabEm(); +} + + +/* For Ultrix 4.2 */ +#include +#include + + +/************************************************************************** + * + * Move to a new desktop + * + *************************************************************************/ +void changeDesks(int val1,int val2) +{ + int oldDesk; + FvwmWindow *t; + FvwmWindow *FocusWin = 0; + static FvwmWindow *StickyWin = 0; + + oldDesk = Scr.CurrentDesk; + + if(val1 != 0) + { + Scr.CurrentDesk = Scr.CurrentDesk + val1; + } + else + { + Scr.CurrentDesk = val2; + if(Scr.CurrentDesk == oldDesk) + return; + } + + Broadcast(M_NEW_DESK,1,Scr.CurrentDesk,0,0,0,0,0,0); + /* Scan the window list, mapping windows on the new Desk, + * unmapping windows on the old Desk */ + XGrabServer(dpy); + for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) + { + /* Only change mapping for non-sticky windows */ + if(!((t->flags & ICONIFIED)&&(Scr.flags & StickyIcons)) && + (!(t->flags & STICKY))&&(!(t->flags & ICON_UNMAPPED))) + { + if(t->Desk == oldDesk) { + if (Scr.Focus == t) + t->FocusDesk = oldDesk; + else + t->FocusDesk = -1; + UnmapIt(t); + } else if(t->Desk == Scr.CurrentDesk) { + MapIt(t); + if (t->FocusDesk == Scr.CurrentDesk) { + FocusWin = t; + } + } + } + else + { + /* Window is sticky */ + t->Desk = Scr.CurrentDesk; + if (Scr.Focus == t) { + t->FocusDesk = oldDesk; + StickyWin = t; + } + } + } + XUngrabServer(dpy); + for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) + { + /* If its an icon, and its sticking, autoplace it so + * that it doesn't wind up on top a a stationary + * icon */ + if(((t->flags & STICKY)||(Scr.flags & StickyIcons))&& + (t->flags & ICONIFIED)&&(!(t->flags & ICON_MOVED))&& + (!(t->flags & ICON_UNMAPPED))) + AutoPlace(t); + } + /* Better re-draw the pager now */ + RedrawPager(); + + if(Scr.flags & ClickToFocus) { +#ifndef NO_REMEMBER_FOCUS + if (FocusWin) + SetFocus(FocusWin->w, FocusWin); + else if (StickyWin && (StickyWin->flags && STICKY)) + SetFocus(StickyWin->w, StickyWin); + else +#endif + SetFocus(Scr.NoFocusWin,NULL); + } +} + + + +/************************************************************************** + * + * Move to a new desktop + * + *************************************************************************/ +void changeWindowsDesk(FvwmWindow *t,int val1) +{ + if(val1 == t->Desk) + return; + + /* Scan the window list, mapping windows on the new Desk, + * unmapping windows on the old Desk */ + /* Only change mapping for non-sticky windows */ + if(!((t->flags & ICONIFIED)&&(Scr.flags & StickyIcons)) && + (!(t->flags & STICKY))&&(!(t->flags & ICON_UNMAPPED))) + { + if(t->Desk == Scr.CurrentDesk) + { + t->Desk = val1; + UnmapIt(t); + } + else if(val1 == Scr.CurrentDesk) + { + t->Desk = val1; + /* If its an icon, auto-place it */ + if(t->flags & ICONIFIED) + AutoPlace(t); + MapIt(t); + } + else + t->Desk = val1; + + } + /* Better re-draw the pager now */ + BroadcastConfig(M_CONFIGURE_WINDOW,t); + RedrawPager(); +} + + +/************************************************************************** + * + * Unmaps a window on transition to a new desktop + * + *************************************************************************/ +void UnmapIt(FvwmWindow *t) +{ + XWindowAttributes winattrs; + unsigned long eventMask; + /* + * Prevent the receipt of an UnmapNotify, since that would + * cause a transition to the Withdrawn state. + */ + XGetWindowAttributes(dpy, t->w, &winattrs); + eventMask = winattrs.your_event_mask; + XSelectInput(dpy, t->w, eventMask & ~StructureNotifyMask); + if(t->flags & ICONIFIED) + { + if(t->icon_pixmap_w != None) + XUnmapWindow(dpy,t->icon_pixmap_w); + if(t->icon_w != None) + XUnmapWindow(dpy,t->icon_w); + } + else if(t->flags & (MAPPED|MAP_PENDING)) + { + XUnmapWindow(dpy,t->frame); + } + XSelectInput(dpy, t->w, eventMask); + MoveResizePagerView(t); +} + +/************************************************************************** + * + * Maps a window on transition to a new desktop + * + *************************************************************************/ +void MapIt(FvwmWindow *t) +{ + if(t->flags & ICONIFIED) + { + if(t->icon_pixmap_w != None) + XMapWindow(dpy,t->icon_pixmap_w); + if(t->icon_w != None) + XMapWindow(dpy,t->icon_w); + } + else if(t->flags & MAPPED) + { + XMapWindow(dpy,t->frame); + t->flags |= MAP_PENDING; + XMapWindow(dpy, t->Parent); + } + MoveResizePagerView(t); +} + + + +void QuickRestart(void) +{ + extern char *m4_options; + extern char *display_name; + int i; + FvwmWindow *tmp,*next; + extern unsigned PopupCount; + extern int have_the_colors; + MenuRoot *PopupTable[MAXPOPUPS]; + extern MenuRoot *ActiveMenu; + extern MenuItem *ActiveItem; + extern int menu_on; + XEvent event; + + PopDownMenu(); + PopDownMenu(); + UngrabEm(); + InstallWindowColormaps (&Scr.FvwmRoot); /* force reinstall */ + + Reborder(); + tmp = Scr.FvwmRoot.next; + while (tmp != NULL) + { + next = tmp->next; + Destroy(tmp); + tmp = next; + } + XSync(dpy,0); + for(i=0;i +#include +#include +#include +#include +#include +#include "fvwm.h" +#include "menus.h" +#include "misc.h" +#include "screen.h" +#include "parse.h" +#include +#include +/* need to get prototype for XrmUniqueQuark for XUniqueContext call */ +#include + +#ifdef SHAPE +#include +#endif /* SHAPE */ + +#if defined (sparc) && defined (SVR4) +/* Solaris has sysinfo instead of gethostname. */ +#include +#endif + +#define MAXHOSTNAME 255 + +#include "../version.h" + +ScreenInfo Scr; /* structures for the screen */ +Display *dpy; /* which display are we talking to */ +extern char *config_file; + +XErrorHandler CatchRedirectError(Display *, XErrorEvent *); +XErrorHandler FvwmErrorHandler(Display *, XErrorEvent *); +void newhandler(int sig); +void CreateCursors(void); +void NoisyExit(int); +void ChildDied(int nonsense); +void SaveDesktopState(void); + +XContext FvwmContext; /* context for fvwm windows */ +XContext MenuContext; /* context for fvwm menus */ + +XClassHint NoClass; /* for applications with no class */ + +int JunkX = 0, JunkY = 0; +Window JunkRoot, JunkChild; /* junk window */ +unsigned int JunkWidth, JunkHeight, JunkBW, JunkDepth, JunkMask; + +/* assorted gray bitmaps for decorative borders */ +#define g_width 2 +#define g_height 2 +static char g_bits[] = {0x02, 0x01}; + +#define l_g_width 4 +#define l_g_height 2 +static char l_g_bits[] = {0x08, 0x02}; +Bool debugging = False,PPosOverride; + +#define s_g_width 4 +#define s_g_height 4 +static char s_g_bits[] = {0x01, 0x02, 0x04, 0x08}; +char **g_argv; + +#ifdef M4 +int m4_enable; /* use m4? */ +int m4_prefix; /* Do GNU m4 prefixing (-P) */ +char m4_options[BUFSIZ]; /* Command line options to m4 */ +char m4_prog[BUFSIZ]; /* Name of the m4 program */ +int m4_default_quotes; /* Use default m4 quotes */ +char m4_startquote[16]; /* Left quote characters for m4 */ +char m4_endquote[16]; /* Right quote characters for m4 */ +#endif + +#ifndef NO_PAGER +extern Pixel PagerForeColor; +#endif + +#ifdef SHAPE +int ShapeEventBase, ShapeErrorBase; +#endif + +long isIconicState = 0; +extern XEvent Event; +Bool Restarting = False; +int fd_width, x_fd; +char *display_name = NULL; + +/*********************************************************************** + * + * Procedure: + * main - start of fvwm + * + *********************************************************************** + */ +void main(int argc, char **argv) +{ + unsigned long valuemask; /* mask for create windows */ + XSetWindowAttributes attributes; /* attributes for create windows */ + void InternUsefulAtoms (void); + void InitVariables(void); + void enterAlarm(int); + int i; + extern int x_fd; + int len; + char *display_string; + char message[255]; + char num[10]; + + Bool single = False; + Bool option_error = FALSE; + +#ifdef M4 + /* Set the defaults for m4 processing */ + + m4_enable = TRUE; + m4_prefix = FALSE; + strcpy(m4_prog, "m4"); + *m4_options = '\0'; + m4_default_quotes = 1; + strcpy(m4_startquote, "`"); + strcpy(m4_endquote, "'"); +#endif + + for (i = 1; i < argc; i++) + { + if (mystrncasecmp(argv[i],"-debug",6)==0) + debugging = True; + else if (mystrncasecmp(argv[i],"-s",2)==0) + { + single = True; + } + else if (mystrncasecmp(argv[i],"-d",2)==0) + { + if (++i >= argc) + usage(); + display_name = argv[i]; + } + else if (mystrncasecmp(argv[i],"-f",2)==0) + { + if (++i >= argc) + usage(); + config_file = argv[i]; + } +#ifdef M4 + else if (mystrncasecmp(argv[i], "-no-m4", 6) == 0) + { + m4_enable = FALSE; + } + else if (mystrncasecmp(argv[i], "-m4-prefix", 10) == 0) + { + m4_prefix = TRUE; + } + else if (mystrncasecmp(argv[i],"-m4opt", 6) == 0) + { + if (++i < argc) + { + strcat(m4_options, argv[i]); + strcat(m4_options, " "); + } + } + else if (mystrncasecmp(argv[i], "-m4-squote", 6) == 0) + { + if (++i < argc) + { + strcpy(m4_startquote, argv[i]); + m4_default_quotes = 0; + } + } + else if (mystrncasecmp(argv[i], "-m4-equote", 6) == 0) + { + if (++i < argc) + { + strcpy(m4_endquote, argv[i]); + m4_default_quotes = 0; + } + } + else if (mystrncasecmp(argv[i], "-m4prog", 7) == 0) + { + if (++i < argc) + { + strcpy(m4_prog, argv[i]); + } + } +#endif + else if (mystrncasecmp(argv[i], "-version", 8) == 0) + { + fprintf(stderr, "Fvwm Version %s\n", VERSION); + } + else + { + fprintf(stderr, "fvwm: Unknown option: `%s'\n", argv[i]); + option_error = TRUE; + } + } + + if (option_error) + { + usage(); + } + + g_argv = argv; + + newhandler (SIGINT); + newhandler (SIGHUP); + newhandler (SIGQUIT); + newhandler (SIGTERM); + signal (SIGUSR1, Restart); + + signal (SIGPIPE, DeadPipe); + signal(SIGALRM,enterAlarm); + + ReapChildren(); + + if (!(dpy = XOpenDisplay(display_name))) + { + fvwm_err("can't open display %s", XDisplayName(display_name), + NULL,NULL); + exit (1); + } + x_fd = XConnectionNumber(dpy); + + if (fcntl(x_fd, F_SETFD, 1) == -1) + { + fvwm_err("close-on-exec failed",NULL,NULL,NULL); + exit (1); + } + Scr.screen= DefaultScreen(dpy); + Scr.NumberOfScreens = ScreenCount(dpy); + + if(!single) + { + for(i=0;iascent+Scr.WindowFont.font->descent+3; + + XSync(dpy, 0); + if(debugging) + XSynchronize(dpy,1); + + Scr.SizeStringWidth = XTextWidth (Scr.StdFont.font, + " +8888 x +8888 ", 15); + attributes.border_pixel = Scr.StdColors.fore; + attributes.background_pixel = Scr.StdColors.back; + attributes.bit_gravity = NorthWestGravity; + valuemask = (CWBorderPixel | CWBackPixel | CWBitGravity); + if(!(Scr.flags & MWMMenus)) + { + Scr.SizeWindow = XCreateWindow (dpy, Scr.Root, + 0, 0, + (unsigned int)(Scr.SizeStringWidth + + SIZE_HINDENT*2), + (unsigned int) (Scr.StdFont.height + + SIZE_VINDENT*2), + (unsigned int) 0, 0, + (unsigned int) CopyFromParent, + (Visual *) CopyFromParent, + valuemask, &attributes); + } + else + { + Scr.SizeWindow = XCreateWindow (dpy, Scr.Root, + Scr.MyDisplayWidth/2 - + (Scr.SizeStringWidth + + SIZE_HINDENT*2)/2, + Scr.MyDisplayHeight/2 - + (Scr.StdFont.height + + SIZE_VINDENT*2)/2, + (unsigned int)(Scr.SizeStringWidth + + SIZE_HINDENT*2), + (unsigned int) (Scr.StdFont.height + + SIZE_VINDENT*2), + (unsigned int) 0, 0, + (unsigned int) CopyFromParent, + (Visual *) CopyFromParent, + valuemask, &attributes); + } +#ifndef NON_VIRTUAL + initPanFrames(); +#endif + CaptureAllWindows(); +#ifndef NON_VIRTUAL + checkPanFrames(); +#endif + XUngrabServer(dpy); + MoveResizeViewPortIndicator(); + fd_width = GetFdWidth(); + + + if(Restarting) + { + if(Scr.RestartFunction != NULL) + ExecuteFunction(F_FUNCTION,NULL,None,NULL,&Event,C_ROOT,0,0, + 0,0,Scr.RestartFunction,-1); + } + else + { + if(Scr.InitFunction != NULL) + ExecuteFunction(F_FUNCTION,NULL,None,NULL,&Event,C_ROOT,0,0, + 0,0,Scr.InitFunction,-1); + } + + HandleEvents(); + return; +} + +/*********************************************************************** + * + * Procedure: + * CaptureAllWindows + * + * Decorates all windows at start-up + * + ***********************************************************************/ + +void CaptureAllWindows(void) +{ + int i,j; + unsigned int nchildren; + Window root, parent, *children; + + PPosOverride = TRUE; + + if(!XQueryTree(dpy, Scr.Root, &root, &parent, &children, &nchildren)) + return; + + /* + * weed out icon windows + */ + for (i = 0; i < nchildren; i++) + { + if (children[i]) + { + XWMHints *wmhintsp = XGetWMHints (dpy, children[i]); + if (wmhintsp) + { + if (wmhintsp->flags & IconWindowHint) + { + for (j = 0; j < nchildren; j++) + { + if (children[j] == wmhintsp->icon_window) + { + children[j] = None; + break; + } + } + } + XFree ((char *) wmhintsp); + } + } + } + /* + * map all of the non-override windows + */ + + for (i = 0; i < nchildren; i++) + { + if (children[i] && MappedNotOverride(children[i])) + { + XUnmapWindow(dpy, children[i]); + Event.xmaprequest.window = children[i]; + HandleMapRequest (); + } + } + + isIconicState = DontCareState; + + if(nchildren > 0) + XFree((char *)children); + + /* after the windows already on the screen are in place, + * don't use PPosition */ + PPosOverride = FALSE; +} + +/*********************************************************************** + * + * Procedure: + * MappedNotOverride - checks to see if we should really + * put a fvwm frame on the window + * + * Returned Value: + * TRUE - go ahead and frame the window + * FALSE - don't frame the window + * + * Inputs: + * w - the window to check + * + ***********************************************************************/ + +int MappedNotOverride(Window w) +{ + XWindowAttributes wa; + Atom atype; + int aformat; + unsigned long nitems, bytes_remain; + unsigned char *prop; + + isIconicState = DontCareState; + + if(!XGetWindowAttributes(dpy, w, &wa)) + return False; + + if(XGetWindowProperty(dpy,w,_XA_WM_STATE,0L,3L,False,_XA_WM_STATE, + &atype,&aformat,&nitems,&bytes_remain,&prop)==Success) + { + if(prop != NULL) + { + isIconicState = *(long *)prop; + XFree(prop); + } + } +#ifndef NO_PAGER + if(w == Scr.Pager_w) + return True; +#endif + return (((isIconicState == IconicState)||(wa.map_state != IsUnmapped)) && + (wa.override_redirect != True)); +} + + +/*********************************************************************** + * + * Procedure: + * InternUsefulAtoms: + * Dont really know what it does + * + *********************************************************************** + */ +Atom _XA_MIT_PRIORITY_COLORS; +Atom _XA_WM_CHANGE_STATE; +Atom _XA_WM_STATE; +Atom _XA_WM_COLORMAP_WINDOWS; +Atom _XA_WM_PROTOCOLS; +Atom _XA_WM_TAKE_FOCUS; +Atom _XA_WM_DELETE_WINDOW; +Atom _XA_WM_DESKTOP; +Atom _XA_MwmAtom; + +void InternUsefulAtoms (void) +{ + /* + * Create priority colors if necessary. + */ + _XA_MIT_PRIORITY_COLORS = XInternAtom(dpy, "_MIT_PRIORITY_COLORS", False); + _XA_WM_CHANGE_STATE = XInternAtom (dpy, "WM_CHANGE_STATE", False); + _XA_WM_STATE = XInternAtom (dpy, "WM_STATE", False); + _XA_WM_COLORMAP_WINDOWS = XInternAtom (dpy, "WM_COLORMAP_WINDOWS", False); + _XA_WM_PROTOCOLS = XInternAtom (dpy, "WM_PROTOCOLS", False); + _XA_WM_TAKE_FOCUS = XInternAtom (dpy, "WM_TAKE_FOCUS", False); + _XA_WM_DELETE_WINDOW = XInternAtom (dpy, "WM_DELETE_WINDOW", False); + _XA_WM_DESKTOP = XInternAtom (dpy, "WM_DESKTOP", False); + _XA_MwmAtom=XInternAtom(dpy,"_MOTIF_WM_HINTS",False); + return; +} + +/*********************************************************************** + * + * Procedure: + * newhandler: Installs new signal handler + * + ************************************************************************/ +void newhandler(int sig) +{ + if (signal (sig, SIG_IGN) != SIG_IGN) + signal (sig, SigDone); +} + + +/************************************************************************* + * Restart on a signal + ************************************************************************/ +void Restart(int nonsense) +{ + Done(1, *g_argv); + SIGNAL_RETURN; +} + +/*********************************************************************** + * + * Procedure: + * CreateCursors - Loads fvwm cursors + * + *********************************************************************** + */ +void CreateCursors(void) +{ + /* define cursors */ + Scr.FvwmCursors[POSITION] = XCreateFontCursor(dpy,XC_top_left_corner); + Scr.FvwmCursors[DEFAULT] = XCreateFontCursor(dpy, XC_top_left_arrow); + Scr.FvwmCursors[SYS] = XCreateFontCursor(dpy, XC_hand2); + Scr.FvwmCursors[TITLE_CURSOR] = XCreateFontCursor(dpy, XC_top_left_arrow); + Scr.FvwmCursors[MOVE] = XCreateFontCursor(dpy, XC_fleur); + Scr.FvwmCursors[MENU] = XCreateFontCursor(dpy, XC_sb_left_arrow); + Scr.FvwmCursors[WAIT] = XCreateFontCursor(dpy, XC_watch); + Scr.FvwmCursors[SELECT] = XCreateFontCursor(dpy, XC_dot); + Scr.FvwmCursors[DESTROY] = XCreateFontCursor(dpy, XC_pirate); + Scr.FvwmCursors[LEFT] = XCreateFontCursor(dpy, XC_left_side); + Scr.FvwmCursors[RIGHT] = XCreateFontCursor(dpy, XC_right_side); + Scr.FvwmCursors[TOP] = XCreateFontCursor(dpy, XC_top_side); + Scr.FvwmCursors[BOTTOM] = XCreateFontCursor(dpy, XC_bottom_side); + Scr.FvwmCursors[TOP_LEFT] = XCreateFontCursor(dpy,XC_top_left_corner); + Scr.FvwmCursors[TOP_RIGHT] = XCreateFontCursor(dpy,XC_top_right_corner); + Scr.FvwmCursors[BOTTOM_LEFT] = XCreateFontCursor(dpy,XC_bottom_left_corner); + Scr.FvwmCursors[BOTTOM_RIGHT] =XCreateFontCursor(dpy,XC_bottom_right_corner); +} + +/*********************************************************************** + * + * Procedure: + * InitVariables - initialize fvwm variables + * + ************************************************************************/ +void InitVariables(void) +{ + FvwmContext = XUniqueContext(); + MenuContext = XUniqueContext(); + NoClass.res_name = NoName; + NoClass.res_class = NoName; + + Scr.d_depth = DefaultDepth(dpy, Scr.screen); + Scr.FvwmRoot.w = Scr.Root; + Scr.FvwmRoot.next = 0; + XGetWindowAttributes(dpy,Scr.Root,&(Scr.FvwmRoot.attr)); + Scr.root_pushes = 0; + Scr.pushed_window = &Scr.FvwmRoot; + Scr.FvwmRoot.number_cmap_windows = 0; + + + Scr.MyDisplayWidth = DisplayWidth(dpy, Scr.screen); + Scr.MyDisplayHeight = DisplayHeight(dpy, Scr.screen); + + Scr.NoBoundaryWidth = 1; + Scr.BoundaryWidth = BOUNDARY_WIDTH; + Scr.CornerWidth = CORNER_WIDTH; + Scr.Hilite = NULL; + Scr.Focus = NULL; + Scr.Ungrabbed = NULL; + + Scr.StdFont.font = NULL; + Scr.StdFont.name = "fixed"; + Scr.WindowFont.name = "fixed"; + + Scr.VScale = 32; +#ifndef NON_VIRTUAL + Scr.VxMax = 3; + Scr.VyMax = 3; +#else + Scr.VxMax = 1; + Scr.VyMax = 1; +#endif + Scr.Vx = Scr.Vy = 0; + + /* Sets the current desktop number to zero */ + /* Multiple desks are available even in non-virtual + * compilations */ + { + Atom atype; + int aformat; + unsigned long nitems, bytes_remain; + unsigned char *prop; + + Scr.CurrentDesk = 0; + if ((XGetWindowProperty(dpy, Scr.Root, _XA_WM_DESKTOP, 0L, 1L, True, + _XA_WM_DESKTOP, &atype, &aformat, &nitems, + &bytes_remain, &prop))==Success) + { + if(prop != NULL) + { + Restarting = True; + Scr.CurrentDesk = *(unsigned long *)prop; + } + } + } + + Scr.EdgeScrollX = Scr.EdgeScrollY = -100000; + Scr.ScrollResistance = Scr.MoveResistance = 0; + Scr.OpaqueSize = 5; + Scr.ClickTime = 150; + Scr.AutoRaiseDelay = 0; + + /* set major operating modes */ + Scr.flags = 0; + Scr.NumBoxes = 0; + + Scr.randomx = Scr.randomy = 0; + Scr.buttons2grab = 7; + +#ifndef NO_PAGER + Scr.PagerFont.name = NULL; + Scr.PagerFont.height = 0; + Scr.PagerFont.y = 0; + Scr.FvwmPager = (FvwmWindow *)0; + Scr.Pager_w = None; + Scr.CPagerWin = None; +#endif + Scr.InitFunction = NULL; + Scr.RestartFunction = NULL; + Scr.left_button_styles[0][0] = 55; + Scr.left_button_styles[1][0] = 22; + Scr.left_button_styles[0][1] = -35; + Scr.left_button_styles[1][1] = -10; + Scr.left_button_styles[0][2] = 1; + Scr.left_button_styles[1][2] = 1; + Scr.left_button_styles[0][3] = 35; + Scr.left_button_styles[1][3] = 10; + Scr.left_button_styles[0][4] = 56; + Scr.left_button_styles[1][4] = 25; + + Scr.right_button_styles[0][0] = 55; + Scr.right_button_styles[1][0] = 55; + Scr.right_button_styles[0][1] = 22; + Scr.right_button_styles[1][1] = 22; + Scr.right_button_styles[0][2] = 1; + Scr.right_button_styles[1][2] = 1; + Scr.right_button_styles[0][3] = 50; + Scr.right_button_styles[1][3] = 50; + Scr.right_button_styles[0][4] = 28; + Scr.right_button_styles[1][4] = 28; + return; +} + + + +/*********************************************************************** + * + * Procedure: + * Reborder - Removes fvwm border windows + * + ************************************************************************/ +void Reborder(void) +{ + FvwmWindow *tmp; /* temp fvwm window structure */ + int i; + extern unsigned PopupCount; + extern MenuRoot *PopupTable[MAXPOPUPS]; + + /* put a border back around all windows */ + XGrabServer (dpy); + +#ifndef NO_PAGER + if(Scr.Pager_w != None) + XDestroyWindow(dpy,Scr.Pager_w); +#endif + + InstallWindowColormaps (&Scr.FvwmRoot); /* force reinstall */ + for (tmp = Scr.FvwmRoot.next; tmp != NULL; tmp = tmp->next) + { + XUnmapWindow(dpy,tmp->frame); + RestoreWithdrawnLocation (tmp,True); + XDestroyWindow(dpy,tmp->frame); + } + + for(i=0;iw != None) + XDestroyWindow(dpy,PopupTable[i]->w); + + XUngrabServer (dpy); + XSetInputFocus (dpy, PointerRoot, RevertToPointerRoot,CurrentTime); + XSync(dpy,0); + +} + +/*********************************************************************** + * + * Procedure: NoisyExit + * Print error messages and die. (segmentation violation) + * + **********************************************************************/ +void NoisyExit(int nonsense) +{ + XErrorEvent event; + + fvwm_err("Seg Fault",NULL,NULL,NULL); + event.error_code = 0; + event.request_code = 0; + FvwmErrorHandler(dpy, &event); + + /* Attempt to do a re-start of fvwm */ + Done(0,NULL); +} + + + + + +/*********************************************************************** + * + * Procedure: + * Done - cleanup and exit fvwm + * + *********************************************************************** + */ +void SigDone(int nonsense) +{ + Done(0, NULL); + SIGNAL_RETURN; +} + +void Done(int restart, char *command) +{ +#ifndef NON_VIRTUAL + MoveViewport(0,0,False); +#endif + + /* Close all my pipes */ + ClosePipes(); + + Reborder (); + +#ifdef M4 + if (m4_enable) + { + extern char *fvwm_file; + + /* With m4 processing, a temporary file was created to hold the + processed file. Delete the file now because we don't need it + any more. It will be created again during restart. */ + unlink(fvwm_file); + } +#endif + + if(restart) + { + SaveDesktopState(); /* I wonder why ... */ + + /* Really make sure that the connection is closed and cleared! */ + XSelectInput(dpy, Scr.Root, 0 ); + XSync(dpy, 0); + XCloseDisplay(dpy); + + { + char *my_argv[10]; + int i,done,j; + + i=0; + j=0; + done = 0; + while((g_argv[j] != NULL)&&(i<8)) + { + if(strcmp(g_argv[j],"-s")!=0) + { + my_argv[i] = g_argv[j]; + i++; + j++; + } + else + j++; + } + if(strstr(command,"fvwm")!= NULL) + my_argv[i++] = "-s"; + while(i<10) + my_argv[i++] = NULL; + + /* really need to destroy all windows, explicitly, + * not sleep, but this is adequate for now */ + sleep(1); + ReapChildren(); + execvp(command,my_argv); + } + fprintf(stderr, "FVWM: Call of '%s' failed!!!!\n",command); + execvp(g_argv[0], g_argv); /* that _should_ work */ + fprintf(stderr, "FVWM: Call of '%s' failed!!!!\n", g_argv[0]); + } + else + { + XCloseDisplay(dpy); + exit(0); + } +} + +/*********************************************************************** + * + * Procedure: + * CatchRedirectError - Figures out if there's another WM running + * + ************************************************************************/ +XErrorHandler CatchRedirectError(Display *dpy, XErrorEvent *event) +{ + fvwm_err("another WM is running",NULL,NULL,NULL); + exit(1); +} + + +/*********************************************************************** + * + * Procedure: + * FvwmErrorHandler - displays info on internal errors + * + ************************************************************************/ +XErrorHandler FvwmErrorHandler(Display *dpy, XErrorEvent *event) +{ + extern int last_event_type; + + /* some errors are acceptable, mostly they're caused by + * trying to update a lost window */ + if((event->error_code == BadWindow)||(event->request_code == X_GetGeometry)|| + (event->error_code==BadDrawable)||(event->request_code==X_SetInputFocus)|| + (event->request_code==X_GrabButton)|| + (event->request_code==X_ChangeWindowAttributes)|| + (event->request_code == X_InstallColormap)) + return 0 ; + + + fvwm_err("internal error",NULL,NULL,NULL); + fprintf(stderr," Request %d, Error %d\n", event->request_code, + event->error_code); + fprintf(stderr," EventType: %d",last_event_type); + fprintf(stderr,"\n"); + return 0; +} + +void fvwm_err(char *message, char *arg1, char *arg2, char *arg3) +{ + fprintf(stderr,"fvwm: "); + fprintf(stderr,message,arg1,arg2,arg3); + fprintf(stderr,"\n"); +} + +void usage(void) +{ +#ifdef M4 +#define USAGE "Fvwm Ver %s\n\nusage: fvwm [-d dpy] [-debug] [-f config_file] [-s] [-no-m4] [-m4-prefix] [-m4opt option] [-m4-squote squote] [-m4-equote equote] [-m4prog m4prog]\n" +#else +#define USAGE "Fvwm Ver %s\n\nusage: fvwm [-d dpy] [-debug] [-f config_file] [-s]\n" +#endif + + fprintf(stderr,USAGE,VERSION); + +} + + + + +#ifndef NON_VIRTUAL +/* the root window is surrounded by four window slices, which are InputOnly. + * So you can see 'through' them, but they eat the input. An EnterEvent in + * one of these windows causes a Paging. The windows have the according cursor + * pointing in the pan direction or are hidden if there is no more panning + * in that direction. This is mostly intended to get a panning even atop + * of Motif applictions, which does not work yet. It seems Motif windows + * eat all mouse events. + * + * Hermann Dunkel, HEDU, dunkel@cul-ipn.uni-kiel.de 1/94 +*/ + +/*************************************************************************** + * checkPanFrames hides PanFrames if they are on the very border of the + * VIRTUELL screen and EdgeWrap for that direction is off. + * (A special cursor for the EdgeWrap border could be nice) HEDU + ****************************************************************************/ +void checkPanFrames(void) +{ + extern Bool DoHandlePageing; + int wrapX = (Scr.flags & EdgeWrapX); + int wrapY = (Scr.flags & EdgeWrapY); + + /* Remove Pan frames if paging by edge-scroll is permanently or + * temporarily disabled */ + if((Scr.EdgeScrollY == 0)||(!DoHandlePageing)) + { + XUnmapWindow(dpy,Scr.PanFrameTop.win); + Scr.PanFrameTop.isMapped=False; + XUnmapWindow (dpy,Scr.PanFrameBottom.win); + Scr.PanFrameBottom.isMapped=False; + } + if((Scr.EdgeScrollX == 0)||(!DoHandlePageing)) + { + XUnmapWindow(dpy,Scr.PanFrameLeft.win); + Scr.PanFrameLeft.isMapped=False; + XUnmapWindow (dpy,Scr.PanFrameRight.win); + Scr.PanFrameRight.isMapped=False; + } + if(((Scr.EdgeScrollX == 0)&&(Scr.EdgeScrollY == 0))||(!DoHandlePageing)) + return; + + /* LEFT, hide only if EdgeWrap is off */ + if (Scr.Vx==0 && Scr.PanFrameLeft.isMapped && (!wrapX)) + { + XUnmapWindow(dpy,Scr.PanFrameLeft.win); + Scr.PanFrameLeft.isMapped=False; + } + else if (Scr.Vx > 0 && Scr.PanFrameLeft.isMapped==False) + { + XMapRaised(dpy,Scr.PanFrameLeft.win); + Scr.PanFrameLeft.isMapped=True; + } + /* RIGHT, hide only if EdgeWrap is off */ + if (Scr.Vx == Scr.VxMax && Scr.PanFrameRight.isMapped && (!wrapX)) + { + XUnmapWindow (dpy,Scr.PanFrameRight.win); + Scr.PanFrameRight.isMapped=False; + } + else if (Scr.Vx < Scr.VxMax && Scr.PanFrameRight.isMapped==False) + { + XMapRaised(dpy,Scr.PanFrameRight.win); + Scr.PanFrameRight.isMapped=True; + } + /* TOP, hide only if EdgeWrap is off */ + if (Scr.Vy==0 && Scr.PanFrameTop.isMapped && (!wrapY)) + { + XUnmapWindow(dpy,Scr.PanFrameTop.win); + Scr.PanFrameTop.isMapped=False; + } + else if (Scr.Vy > 0 && Scr.PanFrameTop.isMapped==False) + { + XMapRaised(dpy,Scr.PanFrameTop.win); + Scr.PanFrameTop.isMapped=True; + } + /* BOTTOM, hide only if EdgeWrap is off */ + if (Scr.Vy == Scr.VyMax && Scr.PanFrameBottom.isMapped && (!wrapY)) + { + XUnmapWindow (dpy,Scr.PanFrameBottom.win); + Scr.PanFrameBottom.isMapped=False; + } + else if (Scr.Vy < Scr.VyMax && Scr.PanFrameBottom.isMapped==False) + { + XMapRaised(dpy,Scr.PanFrameBottom.win); + Scr.PanFrameBottom.isMapped=True; + } +} + +/**************************************************************************** + * + * Gotta make sure these things are on top of everything else, or they + * don't work! + * + ***************************************************************************/ +void raisePanFrames(void) +{ + if (Scr.PanFrameTop.isMapped) XRaiseWindow(dpy,Scr.PanFrameTop.win); + if (Scr.PanFrameLeft.isMapped) XRaiseWindow(dpy,Scr.PanFrameLeft.win); + if (Scr.PanFrameRight.isMapped) XRaiseWindow(dpy,Scr.PanFrameRight.win); + if (Scr.PanFrameBottom.isMapped) XRaiseWindow(dpy,Scr.PanFrameBottom.win); +} + +/**************************************************************************** + * + * Creates the windows for edge-scrolling + * + ****************************************************************************/ +void initPanFrames() +{ + XSetWindowAttributes attributes; /* attributes for create */ + unsigned long valuemask; + + attributes.event_mask = (EnterWindowMask | LeaveWindowMask | + VisibilityChangeMask); + valuemask= (CWEventMask | CWCursor ); + + attributes.cursor = Scr.FvwmCursors[TOP]; + Scr.PanFrameTop.win = + XCreateWindow (dpy, Scr.Root, + 0,0, + Scr.MyDisplayWidth,PAN_FRAME_THICKNESS, + 0, /* no border */ + CopyFromParent, InputOnly, + CopyFromParent, + valuemask, &attributes); + attributes.cursor = Scr.FvwmCursors[LEFT]; + Scr.PanFrameLeft.win = + XCreateWindow (dpy, Scr.Root, + 0,PAN_FRAME_THICKNESS, + PAN_FRAME_THICKNESS, + Scr.MyDisplayHeight-2*PAN_FRAME_THICKNESS, + 0, /* no border */ + CopyFromParent, InputOnly, CopyFromParent, + valuemask, &attributes); + attributes.cursor = Scr.FvwmCursors[RIGHT]; + Scr.PanFrameRight.win = + XCreateWindow (dpy, Scr.Root, + Scr.MyDisplayWidth-PAN_FRAME_THICKNESS,PAN_FRAME_THICKNESS, + PAN_FRAME_THICKNESS, + Scr.MyDisplayHeight-2*PAN_FRAME_THICKNESS, + 0, /* no border */ + CopyFromParent, InputOnly, CopyFromParent, + valuemask, &attributes); + attributes.cursor = Scr.FvwmCursors[BOTTOM]; + Scr.PanFrameBottom.win = + XCreateWindow (dpy, Scr.Root, + 0,Scr.MyDisplayHeight-PAN_FRAME_THICKNESS, + Scr.MyDisplayWidth,PAN_FRAME_THICKNESS, + 0, /* no border */ + CopyFromParent, InputOnly, CopyFromParent, + valuemask, &attributes); + Scr.PanFrameTop.isMapped=Scr.PanFrameLeft.isMapped= + Scr.PanFrameRight.isMapped= Scr.PanFrameBottom.isMapped=False; + + Scr.usePanFrames=True; +} +#endif /* NON_VIRTUAL */ + +/**************************************************************************** + * + * Save Desktop State + * + ****************************************************************************/ +void SaveDesktopState() +{ + FvwmWindow *t; + unsigned long data[1]; + + for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) + { + data[0] = (unsigned long) t->Desk; + XChangeProperty (dpy, t->w, _XA_WM_DESKTOP, _XA_WM_DESKTOP, 32, + PropModeReplace, (unsigned char *) data, 1); + } + + data[0] = (unsigned long) Scr.CurrentDesk; + XChangeProperty (dpy, Scr.Root, _XA_WM_DESKTOP, _XA_WM_DESKTOP, 32, + PropModeReplace, (unsigned char *) data, 1); + + XSync(dpy, 0); +} + + diff --git a/fvwm/fvwm.h b/fvwm/fvwm.h new file mode 100644 index 0000000..87d1dd6 --- /dev/null +++ b/fvwm/fvwm.h @@ -0,0 +1,288 @@ +/**************************************************************************** + * This module is based on Twm, but has been siginificantly modified + * by Rob Nation + ****************************************************************************/ +/*****************************************************************************/ +/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ +/** Salt Lake City, Utah **/ +/** Portions Copyright 1989 by the Massachusetts Institute of Technology **/ +/** Cambridge, Massachusetts **/ +/** **/ +/** All Rights Reserved **/ +/** **/ +/** Permission to use, copy, modify, and distribute this software and **/ +/** its documentation for any purpose and without fee is hereby **/ +/** granted, provided that the above copyright notice appear in all **/ +/** copies and that both that copyright notice and this permis- **/ +/** sion notice appear in supporting documentation, and that the **/ +/** names of Evans & Sutherland and M.I.T. not be used in advertising **/ +/** in publicity pertaining to distribution of the software without **/ +/** specific, written prior permission. **/ +/** **/ +/** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/ +/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/ +/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/ +/** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/ +/** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ +/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ +/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ +/** OR PERFORMANCE OF THIS SOFTWARE. **/ +/*****************************************************************************/ + + +/*********************************************************************** + * fvwm include file + ***********************************************************************/ + +#ifndef _FVWM_ +#define _FVWM_ + +#include +#include +#include + +#ifndef WithdrawnState +#define WithdrawnState 0 +#endif + +/* use PanFrames! this replaces the 3 pixel margin with PanFrame windows +it should not be an option, once it works right. HEDU 2/2/94 */ +#define PAN_FRAME_THICKNESS 2 /* or just 1 ? */ + +/* the maximum number of mouse buttons fvwm knows about */ +/* don't think that upping this to 5 will make everything + * hunky-dory with 5 button mouses */ +#define MAX_BUTTONS 3 + +#include + +#ifdef SIGNALRETURNSINT +#define SIGNAL_T int +#define SIGNAL_RETURN return 0 +#else +#define SIGNAL_T void +#define SIGNAL_RETURN return +#endif + +#define BW 1 /* border width */ +#define BOUNDARY_WIDTH 7 /* border width */ +#define CORNER_WIDTH 16 /* border width */ + +# define HEIGHT_EXTRA 4 /* Extra height for texts in popus */ +# define HEIGHT_EXTRA_TITLE 4 /* Extra height for underlining title */ +# define HEIGHT_SEPARATOR 4 /* Height of separator lines */ + +#define SCROLL_REGION 2 /* region around screen edge that */ + /* triggers scrolling */ + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#define NULLSTR ((char *) NULL) + +/* contexts for button presses */ +#define C_NO_CONTEXT 0 +#define C_WINDOW 1 +#define C_TITLE 2 +#define C_ICON 4 +#define C_ROOT 8 +#define C_FRAME 16 +#define C_SIDEBAR 32 +#define C_L1 64 +#define C_L2 128 +#define C_L3 256 +#define C_L4 512 +#define C_L5 1024 +#define C_R1 2048 +#define C_R2 4096 +#define C_R3 8192 +#define C_R4 16384 +#define C_R5 32768 +#define C_RALL (C_R1|C_R2|C_R3|C_R4|C_R5) +#define C_LALL (C_L1|C_L2|C_L3|C_L4|C_L5) +#define C_ALL (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) + +typedef struct MyFont +{ + char *name; /* name of the font */ + XFontStruct *font; /* font structure */ + int height; /* height of the font */ + int y; /* Y coordinate to draw characters */ +} MyFont; + +typedef struct ColorPair +{ + Pixel fore; + Pixel back; +} ColorPair; + + +/* for each window that is on the display, one of these structures + * is allocated and linked into a list + */ +typedef struct FvwmWindow +{ + struct FvwmWindow *next; /* next fvwm window */ + struct FvwmWindow *prev; /* prev fvwm window */ + Window w; /* the child window */ + int old_bw; /* border width before reparenting */ + Window frame; /* the frame window */ + Window Parent; /* Ugly Ugly Ugly - it looks like you + * HAVE to reparent the app window into + * a window whose size = app window, + * or else you can't keep xv and matlab + * happy at the same time! */ + Window title_w; /* the title bar window */ + Window sides[4]; + Window corners[4]; /* Corner pieces */ + int nr_left_buttons; + int nr_right_buttons; + Window left_w[5]; + Window right_w[5]; + Window icon_w; /* the icon window */ + Window icon_pixmap_w; /* the icon window */ +#ifndef NO_PAGER + Window pager_view; +#endif +#ifdef SHAPE + int wShaped; /* is this a shaped window */ +#endif + int frame_x; /* x position of frame */ + int frame_y; /* y position of frame */ + int frame_width; /* width of frame */ + int frame_height; /* height of frame */ + int boundary_width; + int corner_width; + int bw; + int title_x; + int title_y; + int title_height; /* height of the title bar */ + int title_width; /* width of the title bar */ + int icon_x_loc; /* icon window x coordinate */ + int icon_xl_loc; /* icon label window x coordinate */ + int icon_y_loc; /* icon window y coordiante */ + int icon_w_width; /* width of the icon window */ + int icon_w_height; /* height of the icon window */ + int icon_t_width; /* width of the icon title window */ + int icon_p_width; /* width of the icon pixmap window */ + int icon_p_height; /* height of the icon pixmap window */ + Pixmap iconPixmap; /* pixmap for the icon */ + int iconDepth; /* Drawable depth for the icon */ + Pixmap icon_maskPixmap; /* pixmap for the icon mask */ + char *name; /* name of the window */ + char *icon_name; /* name of the icon */ + XWindowAttributes attr; /* the child window attributes */ + XSizeHints hints; /* normal hints */ + XWMHints *wmhints; /* WM hints */ + XClassHint class; + int Desk; /* Tells which desktop this window is on */ + int FocusDesk; /* Where (if at all) was it focussed */ + int DeIconifyDesk; /* Desk to deiconify to, for StubbornIcons */ + Window transientfor; + + unsigned long flags; + char *icon_bitmap_file; + + int orig_x; /* unmaximized x coordinate */ + int orig_y; /* unmaximized y coordinate */ + int orig_wd; /* unmaximized window width */ + int orig_ht; /* unmaximized window height */ + + int xdiff,ydiff; /* used to restore window position on exit*/ + int *mwm_hints; + int functions; + Window *cmap_windows; /* Colormap windows property */ + int number_cmap_windows; /* Should generally be 0 */ + int focus_sequence; + Pixel ReliefPixel; + Pixel ShadowPixel; + Pixel TextPixel; + Pixel BackPixel; + unsigned long buttons; + +} FvwmWindow; + +/*************************************************************************** + * window flags definitions + ***************************************************************************/ +#define STICKY 1 /* Does window stick to glass? */ +#define ONTOP 2 /* does window stay on top */ +#define BORDER 4 /* Is this decorated with border*/ +#define TITLE 8 /* Is this decorated with title */ +#define MAPPED 16 /* is it mapped? */ +#define ICONIFIED 32 /* is it an icon now? */ +#define TRANSIENT 64 /* is it a transient window? */ +#define RAISED 128 /* if its a sticky window, does it need to be raised*/ +#define VISIBLE 256 /* is the window fully visible */ +#define ICON_OURS 512 /* is the icon window supplied by the app? */ +#define XPM_FLAG 1024 /* is the icon window an xpm? */ +#define PIXMAP_OURS 2048 /* is the icon pixmap ours to free? */ +#define SHAPED_ICON 4096 /* is the icon shaped? */ +#define MAXIMIZED 8192 /* is the window maximized? */ +#define DoesWmTakeFocus 16384 +#define DoesWmDeleteWindow 32768 +/* has the icon been moved by the user? */ +#define ICON_MOVED 65536 +/* was the icon unmapped, even though the window is still iconified + * (Transients) */ +#define ICON_UNMAPPED 131072 +#define WINDOWLISTSKIP 262144 +#define SUPPRESSICON 524288 +#define CIRCULATESKIP 1048576 +#define STARTICONIC 2097152 +/* Sent an XMapWindow, but didn't receive a MapNotify yet.*/ +#define MAP_PENDING 4194304 +#define NOICON_TITLE 8388608 + +/* flags to suppress/enable title bar buttons */ +#define BUTTON1 1 +#define BUTTON2 2 +#define BUTTON3 4 +#define BUTTON4 8 +#define BUTTON5 16 +#define BUTTON6 32 +#define BUTTON7 64 +#define BUTTON8 128 +#define BUTTON9 256 +#define BUTTON10 512 + +#include +extern void Reborder(void); +extern void SigDone(int); +extern void Restart(int nonsense); +extern void Done(int, char *); + +extern Display *dpy; + +extern XClassHint NoClass; + +extern XContext FvwmContext; + +extern Window JunkRoot, JunkChild; +extern int JunkX, JunkY; +extern unsigned int JunkWidth, JunkHeight, JunkBW, JunkDepth, JunkMask; + +#ifdef PAN_FRAMES +extern void checkPanFrames(); +extern void raisePanFrames(); +#endif + +extern Atom _XA_MIT_PRIORITY_COLORS; +extern Atom _XA_WM_CHANGE_STATE; +extern Atom _XA_WM_STATE; +extern Atom _XA_WM_COLORMAP_WINDOWS; +extern Atom _XA_WM_PROTOCOLS; +extern Atom _XA_WM_TAKE_FOCUS; +extern Atom _XA_WM_SAVE_YOURSELF; +extern Atom _XA_WM_DELETE_WINDOW; +extern Atom _XA_WM_DESKTOP; +extern Atom _XA_FVWM_STICKS_TO_GLASS; +extern Atom _XA_FVWM_CLIENT; + +#endif /* _FVWM_ */ + + + diff --git a/fvwm/fvwm.man b/fvwm/fvwm.man new file mode 100644 index 0000000..5daf3a0 --- /dev/null +++ b/fvwm/fvwm.man @@ -0,0 +1,1701 @@ +.\" t +.\" @(#)fvwm.1 1/12/94 +.de EX \"Begin example +.ne 5 +.if n .sp 1 +.if t .sp .5 +.nf +.in +.5i +.. +.de EE +.fi +.in -.5i +.if n .sp 1 +.if t .sp .5 +.. +.ta .3i .6i .9i 1.2i 1.5i 1.8i +.TH FVWM 1.2 "Jan 28, 1994" +.UC +.SH NAME +fvwm \- F(?) Virtual Window Manager for X11 +.SH SYNOPSIS +\fBfvwm\fP [ \fIoptions\fP ] +.SH DESCRIPTION +\fIFvwm\fP is a window manager for X11. It is a derivative of \fItwm\fP, +redesigned +to minimize memory consumption, provide a 3-D look to window frames, and +provide a simple virtual desktop. Memory consumption is estimated at about +one-half to one-third the memory consumption of \fItwm\fP, due primarily to a +redesign of \fItwm\fP's method of storing mouse bindings. In +addition, many of the configurable options of \fItwm\fP have been removed. + +The name "FVWM" used to stand for something, but I forgot what. (Feeble, +famous, foobar? It doesn't really matter, this is an acronym based society +anyway.) + +.SH SPECIAL NOTE FOR XFREE86 USERS +XFree86 provides a virtual screen whose operation can be confusing +when used in conjunction with \fIfvwm\fP. With XFree86 all windows +which appear on the virtual screen actually get drawn into video +memory (whether or not they appear on the physical screen), so the +virtual screen size is limited by available video memory. + +With \fIfvwm\fP's virtual desktop, windows which do not appear on the +screen do not actually get drawn into video RAM. The size of the +virtual desktop is limited to about 32,000 by 32,000 pixels, but it is +probably impractical to use a virtual desktop more than about 5 times +the visible screen in each direction. Note that memory usage is a +function of the number of windows which exist - the size of the +desktop makes no difference. + +When becoming familiar with \fIfvwm\fP it is recommended that you +disable XFree86's virtual screen by setting the virtual screen size to +the physical screen size. After you become familiar with \fIfvwm\fP +you may want to re-enable XFree86's virtual screen. + +.SH COPYRIGHTS +Since \fIfvwm\fP is derived from \fItwm\fP code it shares \fItwm\fP's +copyrights. + +\fIfvwm\fP is copyright 1988 by Evans and Sutherland Computer +Corporation, Salt Lake City, Utah, and 1989 by the Massachusetts +Institute of Technology, Cambridge, Massachusetts, All rights +reserved. It is also copyright 1993 and 1994 by Robert Nation. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Evans & Sutherland and +M.I.T. not be used in advertising in publicity pertaining to +distribution of the software without specific, written prior +permission. + +ROBERT NATION, EVANS & SUTHERLAND, AND M.I.T. DISCLAIM ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR +M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES +OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +.SH ANATOMY OF A WINDOW +\fIFvwm\fP puts a decorative border around most windows. This border +consists of a bar on each side and a small "L" shaped section on each +corner. There is an additional top bar called the title bar which is +used to display the name of the window. In addition, there are up to +10 title-bar buttons. The top, side, and bottom bars are collectively +known as the side-bars. The corner pieces are called the frame. + +Unless the standard defaults files are modified, pressing mouse button +1 in the title or side-bars will begin a move operation on the +window. Pressing button 1 in the corner frame pieces will begin a +resize operation. Pressing button 2 anywhere in the border brings up +an extensive list of window operations. + +Up to ten title-bar buttons may exist. Their use is completely user +definable. The default configuration has a title-bar button on each +side of the title-bar. The one on the left is used to bring up a list +of window options, regardless of which mouse button is used. The one +on the right is used to iconify the window. The number of title-bar +buttons used depends on which ones have mouse actions bound to +them. See the section on the "Mouse" configuration parameter below. + + +.SH THE VIRTUAL DESKTOP +\fIFvwm\fP provides multiple virtual desktops for users who wish to +use them. The screen is a viewport onto a desktop which may be larger +than the screen. Several distinct desktops can be accessed (concept: +one desktop for each project, or one desktop for each application, +when view applications are distinct). Since each desktop can be +larger than the physical screen, windows which are larger than the +screen or large groups of related windows can easily be viewed. + +The size of the virtual desktops can be specified at start-up. All +virtual desktops must be the same size. The total number of distinct +desktops need not be specified, but is limited to approximately 4 +billion total. All windows on the current desktop can be displayed in +a Pager, a miniature view of the current desktop. Windows which are +not on the current desktop can be listed, along with their geometries, +in a window list, accessible as a pop-up menu. + +"Sticky" windows are windows which transcend the virtual desktop by +"Sticking to the screen's glass." They always stay put on the screen. +This is convenient for things like clocks and xbiff's, so you only need +to run one such gadget and it always stays with you. + +Window geometries are specified relative to the current viewport. That +is: +.EX +xterm -geometry +0+0 +.EE +will always show up in the upper-left hand +corner of the visible portion of the screen. It is permissible to +specify geometries which place windows on the virtual desktop, but off +the screen. For example, if the visible screen is 1000 by 1000 pixels, +and the desktop size is 3x3, and the current viewport is at the upper +left hand corner of the desktop, then invoking: +.EX +xterm -geometry +1000+1000 +.EE +will place the window just off of the lower right hand +corner of the screen. It can be found by moving the mouse to the lower +right hand corner of the screen and waiting for it to scroll into +view. There is currently no way to cause a window to map onto a +desktop other than the currently active desk. + +A geometry specified as something like: +.EX +xterm -geometry -5-5 +.EE +will +generally place the window's lower right hand corner 5 pixels from the +lower right corner of the visible portion of the screen. Not all +applications support window geometries with negative offsets. + +Some applications, like xterm and xfontsel, allow the user to specify +the start-up desk on the command line: +.EX +xterm -xrm "*Desk:1" +.EE +will start +an xterm on desk number 1. Not all applications understand this +option, however. + +.SH INITIALIZATION +During initialization, \fIfvwm\fP will search for a configuration file which +describes key and button bindings, and a few other things. The format of +these files will be described later. First, \fIfvwm\fP will search for a file +named .fvwmrc in the users home directory. Failing that, it will look for +/usr/lib/X11/fvwm/system.fvwmrc for system-wide defaults. If that file is not +found, \fIfvwm\fP will exit. + +\fIFvwm\fP will set two environment variables which will be inherited +by its children. These are $DISPLAY which describes the display on +which \fIfvwm\fP is running. $DISPLAY may be unix:0.0 or :0.0, which doesn't +work too well when passed through rsh to another machine, so +$HOSTDISPLAY will also be set and will use a network-ready +description of the display. $HOSTDISPLAY will always use the TCP/IP +transport protocol (even for a local connection) so $DISPLAY should be +used for local connections, as it may use Unix-domain sockets, which +are faster. + +.SH SHAPED WINDOWS +If you typically use shaped windows such as xeyes or oclock, you have +several options. You can make them all undecorated (NoBorder oclock +and NoTitle oclock, for example) or you can use the default +configuration and leave them decorated, in which case a decorative +border and a solid-color backdrop are shown. Alternately, you can +compile in the SHAPE extensions by changing a flag in the Makefile, +in which case you get the shaped window with no backdrop, and a title +bar floats above the window. The shaped window extensions increase the +window manager's memory consumption by about 60 Kbytes when no shaped +windows are present but have little effect when shaped windows are +present. + +.SH ICONS +The basic \fIFvwm\fP configuration uses monochrome bitmap icons, +similar to \fItwm\fP. If XPM extensions are compiled in, then color icons +similar to ctwm, MS-Windows, or the Macintosh icons can be +used. In order to use these options you will need the XPM package, as +described in the Makefile.noImake and the Imakefile. + +If both the SHAPE and XPM options are compiled in you will get shaped +color icons, which are very spiffy. + +.SH MODULES +A module is a separate program which runs as a separate Unix process +but transmits commands to \fIfvwm\fP to execute. Future releases are +expected to provide a means for these modules to extract window +information from \fIfvwm\fP. Users can write their own modules to do +any weird or bizarre manipulations without affecting the integrity of +\fIfvwm\fP itself. + +Modules MUST be spawned by \fIfvwm\fP so that it can set up two pipes for +\fIfvwm\fP and the module to communicate with. The pipes will already be +open for the module when it starts and the file descriptors for the +pipes are provided as command line arguments. + +Modules can be spawned during \fIfvwm\fP initialization via the Module +option, or at any time during the X session by use of the Module +built-in. Modules can exist for the duration of the X session, or can +perform a single task and exit. If the module is still active when +\fIfvwm\fP is told to quit, then \fIfvwm\fP will close the +communication pipes and wait to receive a SIGCHLD from the module, +indicating that it has detected the pipe closure and has exited. If +modules fail to detect the pipe closure \fIfvwm\fP will exit after +approximately 30 seconds anyway. The number of simultaneously +executing modules is limited by the operating system's maximum number +of simultaneously open files, usually between 60 and 256. + +Modules simply transmit text commands to the \fIfvwm\fP built-in command +engine. Text commands are formatted just as in the case of a mouse +binding in the .fvwmrc setup file. Certain auxiliary information is +also transmitted, as in the sample module GoodStuff. The GoodStuff +module is documented in its own man page. + +.SH ICCCM COMPLIANCE +\fIFvwm\fP attempts to be ICCCM 1.1 compliant. As of this (1.20l) colormap +handling is not completely ICCCM compliant. In addition, ICCCM states +that it should be possible for applications to receive ANY keystroke, +which is not consistent with the keyboard shortcut approach used in +\fIfvwm\fP and most other window managers. + +.SH M4 PREPROCESSING +.PP +If \fIfvwm\fP is compiled with the M4 option, \fIfvwm\fP uses +\fIm4(1)\fP to preprocess its setup files before parsing. This way you +can use \fIm4\fP macros to perform operations at runtime. This makes +it very easy to work with different displays with +different characteristics. + +For example, depending on your mood, you might want +different color schemes. One way of doing this is by using the +\fI-m4opt\fP to specify your mood. For a sunny mood use \fI-m4opt +-DSunny\fP; for a dark mood use \fI-m4opt -DDark\fP. Your .fvwmrc file +might then contain: +.EX 0 +ifdef(`Sunny',` +StdForeColor Black +StdBackColor LightSkyBlue +HiForeColor yellow +HiBackColor PeachPuff1 +PagerBackColor BlanchedAlmond ') + +ifdef(`Dark',` +StdForeColor Black +StdBackColor #60a0c0 +HiForeColor black +HiBackColor #c06077 +PagerBackColor #5c54c0 +PagerForeColor orchid +StickyForeColor Black +StickyBackColor #60c0a0 ') +.EE + +The following \fIm4\fP symbols are predefined by \fIfvwm\fP: +.TP 24 +.B "BITS_PER_RGB" +The number of significant bits in an RGB color. (log base 2 of the number +of distinct colors that can be created. This is often different from the +number of colors that can be displayed at once.) +.TP 24 +.B "CLASS" +Your visual class. Will return one of \fBStaticGray\fP, \fBGrayScale\fP, +\fBStaticColor\fP, \fBPseudoColor\fP, \fBTrueColor\fP, \fBDirectColor\fP, +or, if it cannot determine what you have, \fBNonStandard\fP. +.TP 24 +.B "CLIENTHOST" +The machine that is running the clients. +.TP 24 +.B "COLOR" +This will be either 'Yes' or 'No'. This is just a wrapper around the CLASS +definition. Returns 'Yes' on \fB*Color\fP and 'No' on \fBStaticGray\fP +and \fBGrayScale\fP. +.TP 24 +.B "FVWMDIR" +This is set to the path where the modules were configured to be installed. +.TP 24 +.B "FVWM_VERSION" +This is a string containing the version of \fIfvwm\fP. +.TP 24 +.B "HEIGHT" +The height of your display in pixels. +.TP 24 +.B "HOME" +The user's home directory. Obtained from the environment. +.TP 24 +.B "HOSTNAME" +The canonical hostname running the clients (ie. a fully-qualified +version of \fBCLIENTHOST\fP). +.TP 24 +.B "OPTIONS" +This is a string of compile time options used. Each option is separated +from the other by a space. +.TP 24 +.B "PLANES" +The number of bit planes your display supports in the default root window. +.TP 24 +.B "RELEASE" +The release number of your X server. For MIT X11R5 this is \fB5\fP. +.TP 24 +.B "REVISION" +The X minor protocol revision. As seen by ProtocolRevision(3). +.TP 24 +.B "SERVERHOST" +This variable is set to the name of the machine that is running the X +server. +.TP 24 +.B "TWM_TYPE" +Tells which \fItwm\fP offshoot is running. It will always be set to +the string "fvwm" in this program. This is useful for protecting +parts of your \fI.twmrc\fP file that \fIfvwm\fP proper won't understand +(like \fBWorkSpaces\fP) so that it is still usable with other +\fItwm\fP programs. +.TP 24 +.B "USER" +The name of the user running the program. Obtained from the environment. +.TP 24 +.B "VENDOR" +The vendor of your X server. For example: \fBMIT X Consortium\fP. +.TP 24 +.B "VERSION" +The X major protocol version. As seen by ProtocolVersion(3). +.TP 24 +.B "WIDTH" +The width of your display in pixels. +.TP 24 +.B "X_RESOLUTION" +The X resolution of your display in pixels per meter. +.TP 24 +.B "Y_RESOLUTION" +The Y resolution of your display in pixels per meter. +.PP +You may well find that if you research the \fIm4(1)\fP manual well +and understand the power of \fIm4\fP, this will be a \fBvery\fP +useful and powerful tool. But if you use any of the symbols +which are predefined by \fIm4\fP, you are in severe danger! For example, +Sun's \fIm4\fP predefines \fBinclude\fP, so if you use that name in your .fvwmrc, +you are out of luck. The correct solution to this problem is to put a +set of quotes around the troublesome word: \fB`include'\fP. +.PP +To help alleviate this problem, the following options may be useful. +To change the quoting characters used by \fIm4\fP, use the options +\fI-m4-squote\fP and \fI-m4-equote\fP. Be sure to specify both +options otherwise \fIm4\fP will be confused. When these are given, a +\fIchangequote\fP macro is given before the users fvwmrc file is +processed. +.PP +\fBNOTE:\fP Some versions of \fIm4\fP are broken with respect to +changing quoting characters and included files. When the quoting +strings are longer than one character, the macro "include(<>)", +where "<<" and ">>" are the quoting characters, contains extra +characters around the contents of the included file. This will +confuse fvwm. SunOS 4.1.3 is known to have this problem. +.PP +If you are using GNU \fIm4\fP an additional option is available. By +specifying \fI-m4-prefix\fP when starting \fIfvwm\fP, \fIm4\fP is +instructed to prefix all builtin macros with \fIm4_\fP. Thus, +\fIinclude\fP becomes \fIm4_include\fP. +.PP +The availability of the m4 preprocessing is subject to the compilation +define M4. + +.SH OPTIONS +These are the command line options that are recoginzed by \fIfvwm\fP: +.IP "\fB-f\fP \fIconfig_file\fP" +Causes \fIfvwm\fP to use \fIconfig_file\fP in the user's home directory +instead of .fvwmrc as the window manager configuration file. +.IP "\fB-debug\fP" +Puts X transactions in synchronous mode, which dramatically slows things +down, but guarantees that \fIfvwm\fP's internal error messages are correct. +.IP "\fB-d\fP \fIdisplayname\fP" +Manage the display called "displayname" instead of the name obtained from +the environment variable $DISPLAY. +.IP "\fB-s\fP" +On a multi-screen display, run \fIfvwm\fP only on the screen named in +the $DISPLAY environment variable or provided through the -d +option. Normally, \fIfvwm\fP will attempt to start up on all screens +of a multi-screen display. +.IP "\fB-version\fP" +Print the version of \fIfvwm\fP to stderr. +.PP +The following options are available only if fvwm is compiled with the +M4 option. +.IP "\fB-no-m4\fP" +Do not use \fIm4\fP to preprocess the .fvwmrc. The default is to preprocess +the startup file using \fIm4(1)\fP. +.IP "\fB-m4-prefix\fP" +If GNU \fIm4\fP is available, cause \fIm4\fP to prefix all builtin commands with +\fIm4_\fP. +.IP "\fB-m4opt\fP \fIoption\fP" +Pass this option to \fIm4\fP. The \fIoption\fP can be any string of +characters without spaces. This option can occur multiple times. If +GNU \fIm4\fP is available, \fBDO NOT\fP pass the \fI-P\fP option here. +Use \fB-m4-prefix\fP instead. +.IP "\fB-m4-squote\fP \fIstring\fP" +Use this given \fBstring\fP as the starting quote characters. You +must also specify \fB-m4-equote\fI. +.IP "\fB-m4-equote\fP \fIstring\fP" +Use this given \fBstring\fP as the ending quote characters. You +must also specify \fB-m4-squote\fI. +.IP "\fB-m4prog\fP \fIpath\fP +Use \fIpath\fP as the location of the desired m4 processor. By +default, m4prog is set to "m4" which must exist somewhere on the +user's path. This option allows the user to explicitly choose the +version of m4 to use. + +.SH CONFIGURATION FILES +The configuration file is used to describe mouse and button bindings, +colors, the virtual display size, and related items. This section +describes the configuration options. Lines beginning with '#' will be +ignored by \fIfvwm\fP. Lines starting with '*' are expected to contain +module configuration commands (rather than configuration commands for +\fIfvwm\fP itself). + +.IP "AppsBackingStore" +Causes application windows to request backing store. This +option compromises the ICCCM compliance of the window manager. While +this option can speed things up in an X-terminal, where redraws of +windows are expensive, it may not help much on regular workstations. + +.IP "AutoRaise \fIdelay\fP" +Enables auto-raising of windows and specifies the time delay (in +milliseconds) between when a window acquires the input focus and when +it is automatically raised. This option works in focus-follows-mouse +mode, and in click-to-focus mode if the focus is changed by clicking +in the application window instead of a decoration window. In +click-to-focus mode, you can suppress the raise-on-focus behavior by +specifying a negative delay value. + +.IP "BackingStore" +Causes \fIfvwm\fP decorations to request backing store. See the discussion +on AppsBackingStore. + +.IP "BoundaryWidth \fIWidth\fP" +Changes the boundary width on decorated windows to the specified value. +The default is 6 pixels. + +The Style command provides another (more general) method for +specifying BoundaryWidth. + +.IP "ButtonStyle \fIbutton# Width\fPx\fIHeight\fP" +Defines the rectangular decoration shape to be used in a title-bar button. +\fIbutton#\fP is the title-bar button number, and is between 0 and 9. +A description of title-bar button numbers is given in the Mouse section below. +Width is the percentage of the full button width which is to be used. Height +is the percentage of the full height to be used. Negative numbers cause the +shading to be inverted. + +And that's not all! If you use a line like: +.EX +ButtonStyle : 2 4 50x30@1 70x70@0 30x70@0 50x30@1 +.EE +then the button 2 decoration will use a 4-point pattern consisting of +a line from (x=50,y=30) to (70,70) in the shadow color (@0), and +then to (30,70) in the shadow color, and finally to (50,30) in the +highlight color (@1). Is that too confusing? See the sample system.fvwmrc. + +.IP "CenterOnCirculate" +When circulating, the desktop page containing the window which the +pointer is moving to is automatically selected. If CenterOnCirculate +is selected then \fIfvwm\fP will do its best to center the target +window in the desktop viewport, rather than just lining up to the +closest page. + +.IP "CirculateSkip \fIwindowname\fP" +Causes windows with the indicated name to be skipped over when the +circulate-up or circulate-down functions are invoked. \fIwindowname\fP +can be a window's name or its class. + +The Style command provides another (more general) method for +specifying CirculateSkip. + +.IP "CirculateSkipIcons" +Causes circulate and warp operations to skip over iconified windows. + +.IP "ClickTime \fIdelay\fP" +Specifies the maximum delay (in milliseconds) between a button press and +a button release for the Function built-in to consider the action a +mouse click. The default delay is 150 milliseconds. + +.IP "ClickToFocus" +Normally keyboard input goes to the window the mouse pointer is in. If +this option is set the keyboard input stays with one window until the +mouse is clicked with the pointer positioned in a new window. + +.IP "Cursor \fI cursor_num cursor_type\fP" +This provides a very awkward way of changing cursor styles. \fICursor_num\fP +tells which cursor you are changing, and is a number between 0 and 12, as +follows: +.nf +.sp +.in +.25i + 0 POSITION - used when initially placing windows. + 1 TITLE - used in a window title-bar. + 2 DEFAULT - used in windows that don't set their cursor. + 3 SYS - used in one of the title-bar buttons. + 4 MOVE - used when moving or resizing windows. + 5 WAIT - used during an EXEC builtin command. + 6 MENU - used in menus. + 7 SELECT - used for various builtin commands such as iconify. + 8 DESTROY - used for DESTROY and DELETE built-ins. + 9 TOP - used in the top side-bar of a window. +10 RIGHT - used in the right side-bar of a window. +11 BOTTOM - used in the bottom side-bar of a window. +12 LEFT - used in the left side-bar of a window. +13 TOP_LEFT - used in the top left corner of a window. +14 TOP_RIGHT - used in the top right corner of a window. +15 BOTTOM_LEFT - used in the bottom left corner of a window. +16 BOTTOM_RIGHT - used in the bottom right corner of a window. +.in -.25i +.sp +.fi +The \fIcursor_type\fP argument is a number which tells the cursor +shape to use. The available numbers can be found in +/usr/include/X11/cursorfont.h and are currently even numbers between 0 +and 152. At the current time, the following cursor types are +available: +.nf +.sp +.in +.25i +0 X_cursor 2 arrow +4 based_arrow_down 6 based_arrow_up +8 boat 10 bogosity +12 bottom_left_corner 14 bottom_right_corner +16 bottom_side 18 bottom_tee +20 box_spiral 22 center_ptr +24 circle 26 clock +28 coffee_mug 30 cross +32 cross_reverse 34 crosshair +36 diamond_cross 38 dot +40 dotbox 42 double_arrow +44 draft_large 46 draft_small +48 draped_box 50 exchange +52 fleur 54 gobbler +56 gumby 58 hand1 +60 hand2 62 heart +64 icon 66 iron_cross +68 left_ptr 70 left_side +72 left_tee 74 leftbutton +76 ll_angle 78 lr_angle +80 man 82 middlebutton +84 mouse 86 pencil +88 pirate 90 plus +92 question_arrow 94 right_ptr +96 right_side 98 right_tee +100 rightbutton 102 rtl_logo +104 sailboat 106 sb_down_arrow +108 sb_h_double_arrow 110 sb_left_arrow +112 sb_right_arrow 114 sb_up_arrow +116 sb_v_double_arrow 118 shuttle +120 sizing 122 spider +124 spraycan 126 star +128 target 130 tcross +132 top_left_arrow 134 top_left_corner +136 top_right_corner 138 top_side +140 top_tee 142 trek +144 ul_angle 146 umbrella +148 ur_angle 150 watch +152 xterm +.in -.25i +.sp +.fi + +.IP "DecorateTransients" +Causes transient windows, which are normally left undecorated, to be given the +usual \fIfvwm\fP decorations. Note that some pop-up windows, such as the xterm +menus, are not managed by the window manager and still do not receive +decorations. + +.IP "DeskTopScale \fIScale\fP" +Defines the virtual desktop scale with respect to the screen. + +.IP "DeskTopSize \fIHorizontal\fPx\fIVertical\fP" +Defines the virtual desktop size in units of the physical screen size. + +.IP "DontMoveOff" +Prevents windows from being moved off or initially placed off of the desktop. +A few programs will not work correctly if you use this option. This only keeps +windows from being completely lost off the edge of the desktop. It insists on +keeping 16 pixels on the desktop but doesn't care a bit about keeping the +whole window on the desk. See EdgeResistance if you don't like having windows +partially off the screen. + +.IP "EdgeResistance \fIscrolling moving\fP" +Tells how hard it should be to change the desktop viewport by moving the +mouse over the edge of the screen and how hard it should be to move a +window over the edge of the screen. + +The first parameter tells how milliseconds the pointer must spend on the screen +edge before \fIfvwm\fP will move the viewport. This is intended for people who +use "EdgeScroll 100 100" but find themselves accidentally flipping pages when +they don't want to. + +The second parameter +tells how many pixels over the edge of the screen a window's edge must +move before it actually moves partially off the screen. + +Note that, with "EdgeScroll 0 0", it is still possible to move or resize windows +across the edge of the current screen. By making the first parameter to +EdgeResistance 10000 this type of motion is impossible. With EdgeResistance +less than 10000 but greater than 0 moving over pages becomes difficult +but not impossible. + +.IP "EdgeScroll \fIhorizontal vertical\fP" +Specifies the percentage of a page to scroll when the cursor hits the edge of +a page. If you don't want any paging or scrolling when you hit the edge of a +page include "EdgeScroll 0 0" in your .fvwmrc file. If you want whole pages, use +"EdgeScroll 100 100". Both horizontal and vertical should be positive numbers. + +If the horizontal and vertical percentages are multiplied by 1000 +then scrolling will wrap around at the edge of the desktop. If +"EdgeScroll 100000 100000" is used \fIfvwm\fP will scroll by whole pages, +wrapping around at the edge of the desktop. + +.IP "Font \fIfontname\fP" +Makes \fIfvwm\fP use font \fIfontname\fP instead of "fixed" for menus, +the resize indicators, and icon labels (if IconFont is not specified). + +.IP "Function \fIFunctionName\fP" +Starts the definition of a complex function, composed of the \fIfvwm\fP +built-in functions, which will later be bound to a mouse button or +key. \fIFunctionName\fP must be enclosed in quotes. Function entries +are included on lines following the Function keyword. The definition +ends with the key word EndFunction. Function entries are specified as +shown in the following example. The first word on each line is the +built-in function which will be performed, followed the type of event +which should trigger the action (enclosed in quotes), followed by any +additional arguments needed by the built-in function. Menus can be +specified by using the Popup built-in as long as the menu was defined +earlier in the configuration file. + +The trigger actions which are recognized are Immediate, Motion, Click, +and DoubleClick. Immediate actions are executed as soon as the +function is activated, even if a window has not been selected. If +there are actions other than immediate ones, \fIfvwm\fP will wait to +see if the user is clicking, double-clicking, or dragging the +mouse. After the decision is made, \fIfvwm\fP will execute only the +built-ins from the function definition whose trigger action matches the +action performed by the user. + +If the following example were bound to button 1 in a window title-bar, +then, when button 1 is pressed, \fIfvwm\fP would wait 150 msec to see +if the button is released. If the button is not released \fIfvwm\fP +will start a move operation. When the move operation is complete a +raise operation will be performed. If a button release is detected +then \fIfvwm\fP will wait another 150 msec for a second click. If only +one click is detected then the window will be raised. If two clicks +are detected the window will be alternately raised and lowered. The +150 msec wait duration can be altered using the ClickTime option. +.EX +Function "Move-or-Raise" + Move "Motion" + Raise "Motion" + Raise "Click" + RaiseLower "DoubleClick" +EndFunction +.EE +The clicking and double clicking concepts do not carry through to using +keyboard shortcuts. + +Two special functions exist: InitFunction and RestartFunction. The +InitFunction will be called when \fIfvwm\fP is started for the first +time in any X session and can be used to start modules, set +background patterns, and begin programs. The restart function will be +called when \fIfvwm\fP is restarted. It can be used to start modules +and set background patterns but probably should not be used to start +programs. + +.IP "HiBackColor \fIcolorname\fP" +Sets the background color of the selected window to +\fIcolorname\fP. When using a monochrome screen this option is +ignored and white is used. + +.IP "HiForeColor \fIcolorname\fP" +Sets the color of the selected window's title to \fIcolorname\fP. When +using a monochrome screen this option is ignored and black is used. + +.IP "Icon \fIwindowname bitmap-file\fP" +Specifies the bitmap to be used for a window when it is iconified. +The \fIwindowname\fP can be an application's window name or class name +and must be enclosed in quotes. The \fIbitmap-file\fP is either the +full path name to a standard X11 bitmap file or a file in the +IconPath or PixmapPath. The specified bitmap/pixmap is used in +preference to any icon supplied by the window itself. + +If \fIfvwm\fP is compiled with XPM support for color icons then \fIbitmap\fP +can be an XPM pixmap file. + +\fIwindowname\fP should be enclosed in double quotes but \fIbitmap-file\fP +should not. Environment variables should not be used in the \fIbitmap-file\fP +specification. + +If \fIwindowname\fP is an empty string then the specified file is the +default icon, and will be used if no other icon bitmap or pixmap can be found: +.EX +Icon "" my-favorite-icon +.EE + +The Style command provides another (more general) method for +specifying Icon. + +.IP "IconBox \fIleft top right bottom\fP" +Defines regions of the screen in which to place icons. Up to four icon +boxes can be defined. If an IconBox line is provided then icons will +automatically be placed in them, if possible. Each time a window is +iconified a new place is found for it. Icon boxes are searched for +space going left to right, then top to bottom. Icons will not be +auto-placed on top of other icons but they may be placed underneath +application windows. If \fIleft\fP or \fIright\fP is negative, then +\fIfvwm\fP will add the screen width to it. If \fItop\fP or +\fIbottom\fP is negative, then \fIfvwm\fP will add the screen height +to it. NOTE: -0 is not parsed as the right or bottom pixel on the +screen. You have to use -1 instead. + +If no IconBox line is provided or all icon boxes are full, then \fIfvwm\fP +will place icons near the current pointer location. + +.IP "IconFont \fIfontname\fP" +Makes \fIfvwm\fP use font \fIfontname\fP for icon labels. If omitted, +the menu font (specified by the Font configuration parameter) will be +used instead. + +.IP "IconPath \fIpath\fP" +Specifies a colon separated list of full path names of directories +where bitmap (monochrome) icons can be found. Each path should start +with a slash. Note: if the M4 patches are included when \fIfvwm\fP is +built, then \fIm4\fP will want to mangle the word "include" which will +frequently show up in the IconPath or PixmapPath command. To fix this +add undefine(`include') prior to the IconPath command. + +.IP "Key \fIkeyname Context Modifiers Function\fP" +Binds a keyboard key to a specified \fIfvwm\fP built-in function. +Definition is the same as for a mouse binding except that the mouse button +number is replaced with a key name. The \fIkeyname\fP is one of the entries +from /usr/include/X11/keysymdef.h, with the leading XK_ omitted. The +\fIContext\fP and \fIModifiers\fP fields are defined as in the mouse binding. + +Binding a key to a title-bar button will not cause that button to appear +unless a mouse binding also exists. + +.IP "Lenience" +The ICCCM states that if an application sets the input field of the +wm_hints structure to False, then it never wants the window manager to +give it the input focus. The only application that I know of which +needs this is sxpm, and that is a silly bug with a trivial fix and +has no overall effect on the program anyway. Rumor is that some older +applications have problems too. + +If this parameter is set then \fIfvwm\fP will ignore this ICCCM convention. + +.IP "MenuBackColor \fIcolorname\fP" +Sets the menu background color. When using monochrome this option is +ignored. This option is only available if \fIfvwm\fP is compiled with +MENUCOLOR defined. + +.IP "MenuForeColor \fIcolorname\fP" +Sets the menu foreground color. When using monochrome this option is +ignored. This option is only available if \fIfvwm\fP is compiled with +MENUCOLOR defined. + +.IP "MenuStippleColor \fIcolorname\fP" +Sets the color for shaded out entries in menus (for functions which +are not allowed on the currently selected window). When using +monochrome this option is ignored and a stipple pattern is used. +This option is only available if \fIfvwm\fP is compiled with MENUCOLOR +defined. + +.IP "Module \fIModuleName\fP" +Specifies a module which should be spawned during initialization. At +the current time the available modules are FvwmAudio, FvwmBacker, +FvwmBanner, FvwmClean, FvwmDebug, FvwmIconBox, FvwmIdent, +FvwmPager, FvwmSave, FvwmSaveDesk, FvwmScroll, FvwmWinList, and +GoodStuff. These modules have their own man pages. \fIModule\fP can +also be used as a built-in. Modules can be short lived transient +programs or, like GoodStuff, can remain for the +duration of the X session. Modules will be terminated by the window +manager prior to restarts and quits, if possible. See the introductory +section on modules. + +.IP "ModulePath" +Specifies a colon separated list of paths for \fIfvwm\fP to search +when looking for a module to load. Individual directories do not need +trailing slashes. + +.IP "Mouse \fIButton Context Modifiers Function\fP" +Defines a mouse binding. \fIButton\fP is the mouse button number. If +\fIButton\fP is zero then any button will perform the specified function. +\fIContext\fP describes where the binding applies. Valid contexts +are R for the root window, W for an application window, T for a window title +bar, S for a window side, top, or bottom bar, F for a window frame +(the corners), I for an Icon window, or 0 through 9 for title-bar buttons, or +any combination of these letters. A is for any context except for title-bar +buttons. For instance, a context of FST will apply when the mouse is anywhere +in a window's border except the title-bar buttons. + +\fIModifiers\fP is any combination of N for no modifiers, C for +control, S for shift, M for Meta, or A for any modifier. For example, +a modifier of SM will apply when both the Meta and shift keys are +down. X11 modifiers mod1 through mod5 are represented as the digits +1 through 5. + +\fIFunction\fP is one of \fIfvwm\fP's built-in functions. + +The title bar buttons are numbered with odd numbered buttons on the +left side of the title bar and even numbers on the +right. Smaller-numbered buttons are displayed toward the outside of +the window while larger-numbered buttons appear toward the middle of +the window (0 is short for 10). In summary, the buttons are +numbered: +.EX +1 3 5 7 9 0 8 6 4 2 +.EE +The highest odd numbered button which has +an action bound to it determines the number of buttons drawn on the left +side of the title bar. The highest even number determines the number or right +side buttons which are drawn. Actions can be bound to either mouse buttons or +keyboard keys. + +.IP "MWMBorders" +Substitutes MWM style 1 pixel wide relief lines instead of \fIfvwm\fP's 2 pixel +borders. + +.IP "MWMButtons" +Disables button press feedback for all decorations except the title bar +and title-bar buttons, as in MWM. + +.IP "MWMDecorHints" +Causes \fIfvwm\fP to read the MOTIF_WM_HINTS atom from application +windows and to parse and attempt to replicate the Motif behavior with +regard to window decorations. Note that mwm allows function hints to +affect window decorations but these effects are not replicated by +this option. + +.IP "MWMFunctionHints" +Causes \fIfvwm\fP to read the MOTIF_WM_HINTS atom from application +windows and to parse and attempt to replicate the Motif behavior with +regard to allowed window functions. Unlike mwm, which simply removes +prohibited functions from the window's menus, \fIfvwm\fP simply shades +out the prohibited functions. Also, because \fIfvwm\fP implements some +functions in user defined macros that mwm implements internally, the +mapping of prohibited functions is partially based on the menu item +label. + +.IP "MWMHintOverride" +If MWMFunctionHints is used then maximization and iconfication are +prohibited for transients. Also, windows can specify that the +window manager should not destroy or delete them. Since these MWM +rules are kind of stupid, especially with regard to the transient +windows, I provide this MWMHintOverride option. When it is used menu +items will be shaded out if MWM would prohibit their use, but the +user can go ahead and select that item and it will operate as +expected. + +The override should be used cautiously because some applications will +break if you override their mwm hints. + +.IP "MWMMenus" +Substitutes MWM look and feel menus in place of the standard +\fIfvwm\fP versions. This option also triggers a few other mwm-style +options, such as centering the size/resize window on the screen, +instead of leaving it in the upper left, and switches the +resize-on-initial-placement trigger action to shift-button-1 instead +of the \fItwm\fP style press-button-2 + +.IP "NoBorder \fIwindowname\fP" +Keeps \fIfvwm\fP from putting decorative borders on windows +named \fIwindowname\fP. This command has no effect on the title-bar. +This is handy for clocks and similar gadgets that you don't want to take up too +much space. \fIwindowname\fP can be a window's name or its class. + +If you specify both NoBorder \fIwindowname\fP and NoTitle \fIwindowname\fP +for the same window in your .fvwmrc file the window will be completely +undecorated. + +\fIWindowname\fP can contain the wildcards "*" and "?" which match +window names in the normal Unix filename matching manner. Actual "*", +"?", and "\\" characters in a window name can be entered by preceding the +character with a "\\". + +The Style command provides another (more general) method for +specifying NoBorder. + +.IP "NoBoundaryWidth \fIWidth\fP" +Changes the width of the decorations for windows with no titles and no borders. +The default is 1. Any positive or zero value is acceptable. +Decorations for these undecorated windows have the same context +as the side-bars on normally decorated windows. + +The Style command provides another (more general) method for +specifying NoBoundaryWidth. + +.IP "NoPPosition" +Instructs \fIfvwm\fP to ignore the PPosition field when adding new windows. +Adherence to the PPosition field is required for some applications, +but if you don't have one of those its a real headache. + +.IP "NoTitle \fIwindowname\fP" +Keeps \fIfvwm\fP from putting a title-bar in the decorations for +windows named \fIwindowname\fP. This is handy for clocks and similar +gadgets that you don't want to take up too much +space. \fIwindowname\fP can be a window's name or its class. + +\fIWindowname\fP can contain the wildcards "*" and "?" which match +window names in the normal Unix filename matching manner. Actual "*", +"?", and "\\" characters in a window name can be entered by preceding the +character with a "\\". + +The Style command provides another (more general) method for +specifying NoTitle. + +.IP "OpaqueMove \fIpercentage\fP" +Tells \fIfvwm\fP the maximum size window with which opaque window movement should be +used. The percentage is percent of the total screen area. With "OpaqueMove 0" +all windows will be moved using the traditional rubber-band outline. With +"OpaqueMove 100" all windows will be move as solid windows. The default is +"OpaqueMove 5", which allows small windows to be moved in an opaque manner but +large windows are moved as rubber-bands. + +.IP "OpaqueResize" +Causes resize operations to be done with the window itself instead of +an outline. + +.IP "Pager \fI X_Location Y_Location\fP" +Enables a paging style of moving across the desktop. A Pager window +(not a pop-up) will appear at (X_Location, Y_Location). Miniature +versions of all the non-sticky windows on the virtual desktop are +shown in the pager. The color of the miniature version is the same as +the color of the full-size window's border. + +In the Pager window, pressing mouse button 1 will move the desktop viewport +to the selected page (in click-to-focus mode; it will also move the keyboard +focus to the window whose miniature you click on). +Pressing button 2 on a window in the pager will begin a window move, using the +miniature to quickly move the window anywhere on the desktop. +Pressing button 3 will move the top-left corner of the viewport +to the location of the button press, even if it does not line up with a page. +Dragging button 3 will cause the selected viewport to scroll as you move the +pointer. The Pager is automatically sticky but does not automatically +stay on top. + +.IP "PagerForeColor \fIcolorname\fP" +Causes the pager foreground color to be \fIcolorname\fP instead of black. +This is the color used to highlight the current viewport in the pager window. +On a monochrome screen this option is ignored. If the NO_PAGER option is set +when building \fIfvwm\fP this option is unavailable. + +.IP "PagerBackColor \fIcolorname\fP" +Causes the pager background color to be \fIcolorname\fP instead of white. +On a monochrome screen this option is ignored. If the NO_PAGER option is set +when building \fIfvwm\fP this option is unavailable. + +.IP "PagerFont \fIfontname\fP" +Makes \fIfvwm\fP use font \fIfontname\fP for writing window icon names in the +window's representation in the pager. If this option is omitted no +names are written in the pager windows. + +.IP "PagingDefault \fIpagingdefaultvalue\fP" +Tells \fIfvwm\fP if it should start up with paging enabled or disabled. +"PagingDefault 0" will start \fIfvwm\fP with paging disabled; "PagingDefault 1" +will start \fIfvwm\fP with paging enabled by default. + +.IP "PixmapPath \fIpath\fP" +Specifies a colon separated list of full path names of directories +where pixmap (color) icons can be found. Each path should start with a +slash. + +.IP "Popup \fIPopupName\fP" +Starts the definition of a pop-up menu which will later be bound to a mouse +button or key. \fIPopupName\fP must be enclosed in quotes. +Menu entries are included +on lines following the Popup keyword. The menu definition ends with the key +word EndPopup. Menu entries are specified as shown in the following example. +The first word on each line is the built-in function which will be performed, +followed by the caption (enclosed in quotes) which will be shown in the menu, +followed by any additional arguments needed by the built-in function. Sub-menus +can be specified by using the Popup built-in as long as the sub-menu +was defined earlier in the configuration file. +.EX +Popup "Window Ops" + Title "Window Ops" + Move "Move" + Resize "Resize" + Raise "Raise" + Lower "Lower" + Iconify "(De)Iconify" + Nop " " + Destroy "Destroy" + Title "HARDCOPY" + Exec "Hardcopy" exec xdpr & + Exec "Hardcopy RV" exec xdpr -rv & +EndMenu +.EE +Note that if a tab character is embedded in the caption of a menu entry then +the text following the tab will be entered into a second column in the menu +and the entire menu will be left-adjusted. This is intended for shortcut +labeling. The tab character must really be a tab. If it is expanded into +spaces it will not work! For example: +.EX +Popup "Window Ops" + Title "Window Ops Alt-F1" + . + . + . +.EE +Is the start of a left adjusted menu. Alt-F1 will be placed toward the +right side of the menu. + +Shortcut keys may be specified in the menu definition by preceding the +character with an ampersand. The ampersand will not be displayed but +the character after it will be displayed underlined, and if the user +presses the corresponding key then that item will be activated as if +the user had clicked on it with the mouse. Only alphabetic and +numeric characters may be used as shortcut keys. The shift state of +the keyboard is ignored when testing shortcut characters. For +example: +.EX +Popup "Window Ops" + Maximize "Ma&ximise" 100 100 +EndMenu +.EE +When this menu is popped up the 'x' will be underlined and pressing +the 'x' key will cause the current window to be maximized. Shortcut +keys are not operative unless MENU_HOTKEYS was defined when +building \fIfvwm\fP. If WINDOWLIST_HOTKEYS was also defined then hot keys +are automatically added to the WindowList when it is displayed. + +.IP "RandomPlacement" +Causes windows which would normally require user placement to be +automatically placed in ever-so-slightly random locations. For the +best of all possible worlds use both RandomPlacement and +SmartPlacement. + +.IP "SaveUnders" +Causes the \fIfvwm\fP decoration frames to request save-unders. This can +significantly improve the performance during opaque moves but it +causes a significant increase in memory usage. + +.IP "SloppyFocus" +This focusing mode is like focus-follows-mouse (the default) +except that the focus will not be removed from a window until your +mouse enters a new window. Exiting a window to enter the root window +will leave the focus unchanged. + +.IP "SmartPlacement" +Causes windows which would normally require user placement to be +automatically placed in a smart location - a location in which they do +not overlap any other windows on the screen. If no such position can +be found user placement or random placement will be used as a +fall-back method. For the best of all possible worlds use both +RandomPlacement and SmartPlacement. + +.IP "StartsOnDesk \fIwindowname desk-number\fP" +This command causes windows whose name or class is \fIwindowname\fP to +be initially placed on desktop number \fIdesk-number\fP. +\fIwindowname\fP should be enclosed in double quotes. If the window +requires interactive placement, an outline will be displayed on the +current desk but the window will appear on the specified desk. + +\fIWindowname\fP can contain the wildcards "*" and "?" which match +window names in the normal Unix filename matching manner. Actual "*", +"?", and "\\" characters in a window name can be entered by preceding the +character with a "\\". + +The Style command provides another (more general) method for +specifying StartsOnDesk. + +.IP "StaysOnTop \fIwindowname\fP" +These windows always try to stay on top of the other windows. This might be +handy for clocks or mailboxes that you would always like to be visible. If the +window is explicitly lowered it will not try to force its way back to the top +until it is explicitly raised. \fIwindowname\fP can be a window's name or its +class. + +\fIWindowname\fP can contain the wildcards "*" and "?" which match +window names in the normal Unix filename matching manner. Actual "*", +"?", and "\\" characters in a window name can be entered by preceding the +character with a "\\". + +The Style command provides another (more general) method for +specifying StaysOnTop. + +.IP "StdBackColor \fIcolorname\fP" +Sets the background color for menus and non-selected +windows to \fIcolorname\fP. When using a monochrome screen this option is +ignored and white is used. + +The Style command provides another (more general) method for +specifying StdBackColor. + +.IP "StdForeColor \fIcolorname\fP" +Sets the foreground color for menus and non-selected window +titles to \fIcolorname\fP. When using a monochrome screen this option is +ignored and black is used. + +The Style command provides another (more general) method for +specifying StdForeColor. + +.IP "StickyBackColor \fIcolorname\fP" +Sets the background color for non-selected sticky +windows to \fIcolorname\fP. When using a monochrome screen this option is +ignored and white is used. Only available if -DMORE_COLORS is used +when compiling. + +.IP "StickyForeColor \fIcolorname\fP" +Sets the foreground color for non-selected sticky window +titles to \fIcolorname\fP. When using a monochrome screen this option is +ignored and black is used. Only available if -DMORE_COLORS is used +when compiling. + +.IP "Sticky \fIwindowname\fP" +Sticky windows "stick to the screen's glass." That is, they don't move the +the viewport into the virtual desktop changes. \fIwindowname\fP can be a +window's name or its class. + +\fIWindowname\fP can contain the wildcards "*" and "?" which match +window names in the normal Unix filename matching manner. Actual "*", +"?", and "\\" characters in a window name can be entered by preceding the +character with a "\\". + +The Style command provides another (more general) method for +specifying Sticky. + +.IP "StickyIcons" +Causes icons to always stick to the screen's glass. That is, icons always +follow you around the desktop. When a window is de-iconified it gets +un-stuck. Some people find this a useful way of moving windows around. + +.IP "StubbornIcons" +Changes de-iconification behavior a bit. Instead of having windows +always de-iconify themselves on the current page they de-iconify into +their original position. + +.IP "StubbornIconPlacement" +When used with IconBoxes, causes icons to avoid placing themselves +underneath existing windows. + +.IP "StubbornPlacement" +When using SmartPlacement, causes new windows to avoid placing +themselves over icons. + +.IP "Style \fIwindowname options\fP" +This command is intended to replace the commands NoBorder, NoTitle, +StartsOnDesk, Sticky, StaysOnTop, Icon, WindowListSkip, CirculateSkip, +SuppressIcons, BoundaryWidth, NoBoundaryWidth, StdForeColor, and +StdBackColor with a single flexible and comprehensive command. This +command is used to set attributes of a window to values other than the +default or to set the window manager default styles. + +\fIwindowname\fP can be a window's name, class, or resource string. It +can contain the wildcards * and/or ?, which are matched in the usual +Unix filename manner. + +\fIoptions\fP is a comma separated list containing some or all of the +keywords BorderWidth, HandleWidth,NoIcon/Icon, NoTitle/Title, +NoHandles/Handles, WindowListSkip/WindowListHit, +CirculateSkip/CirculateHit, StaysOnTop/StaysPut, Sticky/Slippery, +StartIconic/StartNormal, Color, ForeColor, BackColor, +StartsOnDesk/StartsAnyWhere, IconTitle/NoIconTitle, and +NoButton/Button. + +In the above list some options are listed as +style-option/opposite-style-option. The opposite-style-option for +entries that have them describes the \fIfvwm\fP default behavior and can be +used if you want to change the \fIfvwm\fP default behavior. + +Icon takes an (optional) unquoted string argument which is the icon +bitmap or pixmap to use. + +StartsOnDesk takes a numeric argument which +is the desktop number on which the window should be initially placed. + +BorderWidth takes a numeric argument which is the width of the border +to place the window if it does not have resize-handles. + +HandleWidth +takes a numeric argument which is the width of the border to place the +window if it does have resize-handles. + +Button and NoButton take a +numeric argument which is the number of the title-bar button which is +to be included/omitted. + +Color takes two arguments. The first is the window-label text color +and the second is the window decoration's normal background color. +The two colors are separated with a slash. If the use of a slash +causes problems then the seperate ForeColor and BackColor options +can be used. + +An example: +.EX +# Change default fvwm behavior to no title-bars on windows! +# Also define a default icon. +Style "*" NoTitle,Icon unknown1.xpm, BorderWidth 4,HandleWidth 5 + +# now, window specific changes: +Style "Fvwm*" NoHandles,Sticky,WindowListSkip,BorderWidth 0 +Style "Fvwm Pager" StaysOnTop, BorderWidth 0 +Style "*lock" NoHandles,Sticky,StaysOnTop,WindowListSkip +Style "xbiff" Sticky, WindowListSkip +Style "GoodStuff" NoHandles,Sticky,WindowListSkip +Style "sxpm" NoHandles +Style "makerkit" + +# Put title-bars back on xterms only! +Style "xterm" Title, Color black/grey + +Style "rxvt" Icon term.xpm +Style "xterm" Icon rterm.xpm +Style "xcalc" Icon xcalc.xpm +Style "xbiff" Icon mail1.xpm +Style "xmh" Icon mail1.xpm, StartsOnDesk 2 +Style "xman" Icon xman.xpm +Style "matlab" Icon math4.xpm, StartsOnDesk 3 +Style "xmag" Icon magnifying_glass2.xpm +Style "xgraph" Icon graphs.xpm +Style "GoodStuff" Icon toolbox.xpm + +Style "Maker" StartsOnDesk 1 +Style "signal" StartsOnDesk 3 +.EE +Note that all properties for a window will be OR'ed together. In the +above example "FvwmPager" gets the property StaysOnTop via an exact +window name match but also gets NoHandles, Sticky, and +WindowListSkip by a match to "Fvwm*". It will get NoTitle by virtue of +a match to "*". If conflicting styles are specified for a window, then +the last style specified will be used. + +If the NoIcon attribute is set then the specified window will simply +disappear when it is iconified. The window can be recovered through +the window-list. If Icon is set without an argument then the NoIcon +attribute is cleared but no icon is specified. An example which +allows only the FvwmPager module icon to exist: +.EX +Style "*" NoIcon +Style "Fvwm Pager" Icon +.EE + +.IP "SuppressIcons" +Prevents icon windows from being created or drawn. When used with the +window-list this provides a sort of icon manager. + +The Style command provides another (more general) method for +specifying SuppressIcons. + +.IP "WindowFont \fIfontname\fP" +Makes \fIfvwm\fP use font \fIfontname\fP instead of "fixed" for the window +title bar. + +.IP "WindowListSkip \fIwindowname\fP" +Causes windows with the indicated name to be left out of the window list. + +\fIWindowname\fP can contain the wildcards "*" and "?" which match +window names in the normal Unix filename matching manner. Actual "*", +"?", and "\\" characters in a window name can be entered by preceding the +character with a "\\". + +The Style command provides another (more general) method for +specifying WindowListSkip. + +.IP "XORvalue \fInumber\fP" +Changes the value with which bits are XOR'ed when doing rubber-band +window moving or resizing. Setting this value is a trial-and-error +process. + +.SH BUILT IN FUNCTIONS +\fIFvwm\fP supports a set of built-in functions which can be bound to +keyboard or mouse buttons: + +.IP "Beep" +Makes the computer beep. + +.IP "CirculateDown [ \fIname window_name\fP ]" +Causes the pointer to move to the next window in the list of windows for which +CirculateSkip has not not been specified. + +If the +optional arguments are supplied then the focus will move to the +first window whose name (or icon name or class) matches \fIwindow_name\fP. +The optional argument \fIname\fP is required if \fIwindow_name\fP is supplied +and is enclosed in quotes. This argument is the name which appears +in menus if the function is called from a menu, but serves no purpose +if the function is not called from a menu. + +.IP "CirculateUp [ \fIname window_name\fP ]" +Causes the pointer to move to the previous window in the list of windows for +which CirculateSkip has not not been specified. + +If the +optional arguments are supplied then the focus will move to the +first window whose name (or icon name or class) matches \fIwindow_name\fP. +The optional argument \fIname\fP is required if \fIwindow_name\fP is supplied +and is enclosed in quotes. This argument is the name which appears +in menus if the function is called from a menu, but serves no purpose +if the function is not called from a menu + +Here's an example that move the focus to an xterm window when Alt-F1 is pressed: +.EX +Key F1 A M CirculateUp "whatever" xterm +.EE + +.IP "Close" +If the window accepts the delete window protocol a message is sent to +the window asking it to gracefully remove itself. If the window does +not understand the delete window protocol then the window is +destroyed. + +.IP "CursorMove \fIhorizonal vertical\fP" +Moves the mouse pointer by \fIhorizontal\fP pages in the +X direction and \fIvertical\fP pages in the Y direction. Either or both +entries may be negative. Both horizontal and vertical values are expressed +in percent of pages, so "CursorMove 100 100" means to move down and left by one +full page. "CursorMove 50 25" means to move left half a page and down a +quarter of a page. The CursorMove function should not be called from +pop-up menus. + +.IP "Delete" +Sends a message to a window asking that it remove itself, frequently causing +the application to exit. + +.IP "Desk \fIarg1 arg2\fP" +Changes to another desktop (workspace, room). + +If \fIarg1\fP is non zero then the next desktop number will be the current +desktop number plus \fIarg1\fP. Desktop numbers can be negative. + +If \fIarg1\fP is zero then the new desktop number will be \fIarg2\fP. + +The number of active desktops is determined dynamically. Only desktops +which contain windows or are currently being displayed are +active. Desktop numbers must be between 2147483647 and -2147483648 (is +that enough?). + +.IP "Destroy" +Destroys a window. Guaranteed to get rid of the window, but is a fairly violent +way to terminate an application. + +.IP "Exec \fIname command\fP" +Executes \fIcommand\fP. \fIcommand\fP is not quoted but \fIname\fP is. +\fIname\fP is the name that appears in a menu, if that is where the function is +called from. \fIname\fP is required even if the function is not called from a +menu. + +The following example binds function key F1 in the root window, with no +modifiers, to the exec function. The program rxvt will be started +with an assortment of options. +.EX +Key F1 R N Exec "rxvt" exec rxvt -fg yellow -bg blue -e /bin/tcsh & +.EE + +.IP "Focus" +Moves the viewport or window as needed to make the selected window visible. +Sets the keyboard focus to the selected window. Raises the window if +needed to make it visible. Warps the pointer into +the selected window in focus-follows-mouse mode. +Does not de-iconify. This function is primarily for use with +a module such as FvwmWinList. + +.IP "Function \fI\"FunctionName\"\fP" +Used to bind a previously defined function to a key or mouse button. + +The following example binds mouse button 1 to a function called +"Move-or-Raise", whose definition was provided as an example earlier in +this man page. After performing this binding \fIfvwm\fP will execute to +move-or-raise function whenever button 1 is pressed in a window title-bar. +.EX +Mouse 1 T A Function "Move-or-Raise" +.EE + +.IP "GotoPage x y" +Moves the desktop viewport to page (x,y). The upper left page is (0,0), the +upper right is (N,0), where N is one less than the current number of horizontal +pages specified in the DeskTopSize command. The lower left page is (0,M), +and the lower right page is (N,M), where M is the desktop's vertical size +as specified in the DeskTopSize command. The GotoPage function should not be +used in a pop-up menu. + +.IP "Iconify [ \fIvalue\fP ]" +Iconifies a window if it is not already iconified or de-iconifies it +if it is already iconified. If the optional argument \fIvalue\fP is +positive the only iconification will be allowed. It the optional +argument is negative only de-iconification will be allowed. + +.IP "Lower" +Allows the user to lower a window. + +.IP "Maximize [ \fI horizontal vertical\fP ]" +Without its optional arguments Maximize causes the window to alternately +switch from a full-screen size to its normal size. + +With the optional arguments horizontal and vertical, which are +expressed as percentage of a full screen, the user can control the new +size of the window. If horizontal is greater than 0 then the +horizontal dimension of the window will be set to +horizontal*screen_width/100. The vertical resizing is similar. For +example, the following will add a title-bar button to switch a window +to the full vertical size of the screen: +.EX +Mouse 0 4 A Maximize 0 100 +.EE +The following causes windows to be stretched to the full width: +.EX +Mouse 0 4 A Maximize 100 0 +.EE +This makes a window that is half the screen size in each direction: +.EX +Mouse 0 4 A Maximize 50 50 +.EE +Values larger than 100 can be used with caution. + +If the letter "p" is appended to each coordinate (horizontal and/or +vertical), then the scroll amount will be measured in pixels. + +.IP "Module \fIname ModuleName\fP" +Specifies a module which should be spawned. Modules can be +short lived transient programs or can +remain for the duration of the X session. Modules will be terminated by +the window manager prior to restarts and quits, if possible. +\fIname\fP is a double-qouted string which has absolutely no +significance, but must exist. + +.IP "Move [ \fIx y\fP ]" +Allows the user to move a window. If called from somewhere in a window or its +border, then that window will be moved. If called from the root window then +the user will be allowed to select the target window. + +If the optional arguments x and y are provided, then the window will +be moved so that its upper left corner is at location (x,y). The +units of x and y are percent-of-screen, unless a letter "p" is +appended to each coordinate, in which case the location is specified +in pixels. + +Examples: +.EX +Mouse 1 T A Move +Mouse 2 T A Move 10 10 +Mouse 3 T A Move 10p 10p +.EE +In the first example, an interactive move is indicated. In the second, +the window whose title-bar is selected will be moved so that its upper +left hand corner is 10 percent of the screen width in from the left of +the screen, and 10 percent down from the top. The final example moves +the window to coordinate (10,10) pixels. + +.IP "Nop" +Does nothing. This is used to insert a blank line or separator in a menu. If +the menu item specification is Nop " ", then a blank line is inserted. If it +looks like Nop "", then a separator line is inserted. + +.IP "Popup \fI\"PopupName\"\fP" +This built-in has two purposes: to bind a menu to a key or mouse +button, and to bind a sub-menu into a menu. The formats for the two +purposes differ slightly. + +To bind a previously defined pop-up menu to a key or mouse button: +.sp +.in +.25i +The following example binds mouse buttons 2 and 3 to a pop-up called +"Window Ops", whose definition was provided as an example earlier in +this man page. The menu will pop up if the buttons 2 or 3 are pressed +in the window frame, side-bar, or title-bar, with no modifiers (none +of shift, control, or meta). +.EX +Mouse 2 FST N Popup "Window Ops" +Mouse 3 FST N Popup "Window Ops" +.EE +Pop-ups can be bound to keys through the use of the key modifier. Pop-ups can +be operated without using the mouse by binding to keys and operating via the +up arrow, down arrow, and enter keys. +.in -.25i +.sp +To bind a previously defined pop-up menu to another menu, for use as a +sub-menu: +.sp +.in +.25i +The following example defines a sub menu, "Quit-Verify" and binds it into a +main menu, called "Utilities": +.EX +Popup "Quit-Verify" + Title "Really Quit Fvwm?" + Quit "Yes, Really Quit" + Restart "Restart Fvwm" fvwm + Nop "" + Nop "No, Don't Quit" +EndPopup + +Popup "Utilities" + Title "Utilities" + Exec "Xterm" exec xterm & + Exec "Rxvt" exec rxvt & + Exec "Top" exec rxvt -T Top -n Top -e top & + Exec "Calculator" exec xcalc & + Exec "Xman" exec xman & + Exec "Xmag" exec xmag & + Nop "" + Popup "Exit Fvwm" Quit-Verify +EndPopup +.EE +Sub-menus must be defined prior to the main menu in which they are bound. +Sub-menu nesting can be arbitrarily deep. +.in -.25i +.sp + +.IP "Quit" +Exits \fIfvwm\fP, generally causing X to exit too. + +.IP "Raise" +Allows the user to raise a window. + +.IP "RaiseLower" +Alternately raises and lowers a window. + +.IP "Refresh" +Causes all windows on the screen to redraw themselves. + +.IP "Resize [ \fIx y\fP ]" +Allows the user to resize a window. + +If the optional arguments x and y are provided, then the window will +be moved so that its upper left corner is at location (x,y). The +units of x and y are percent-of-screen, unless a letter "p" is +appended to each coordinate, in which case the location is specified +in pixels. + +.IP "Restart \fIname WindowManagerName\fP " +Causes \fIfvwm\fP to restart itself if WindowManagerName is "fvwm", or +to switch to an alternate window manager if WindowManagerName is other +than "fvwm". If the window manager is not in your default search +path, then you should use the full path name for +\fIWindowManagerName\fP. + +\fIWindowManagerName \fP is not quoted but \fIname\fP is. +\fIname\fP is the name that appears in a menu, if that is where the function is +called from. \fIname\fP is required even if the function is not called from a +menu. + +This command should not have a trailing ampersand or any command line +arguments and should not make use +of any environmental variables. Of the following examples, the first three are +sure losers, but the third is OK: +.EX +Key F1 R N Restart " " fvwm & +Key F1 R N Restart " " $(HOME)/bin/fvwm +Key F1 R N Restart " " twm -f .mystartupfile +Key F1 R N Restart " " /home/nation/bin/fvwm +.EE + +.IP "Stick" +Makes a window sticky if it is not already sticky, or non-sticky if it +is already sticky. + +.IP "Scroll \fIhorizonal vertical\fP" +Scrolls the virtual desktop's viewport by \fIhorizontal\fP pages in the +x-direction and \fIvertical\fP pages in the y-direction. Either or both +entries may be negative. Both horizontal and vertical values are expressed +in percent of pages, so "Scroll 100 100" means to scroll down and left by one +full page. "Scroll 50 25" means to scroll left half a page and down a quarter of +a page. The scroll function should not be called from pop-up menus. Normally, +scrolling stops at the edge of the desktop. + +If the horizontal and vertical percentages are multiplied by 1000 then +scrolling will wrap around at the edge of the desktop. If "Scroll 100000 0" is +executed over and over \fIfvwm\fP will move to the next desktop page on each +execution and will wrap around at the edge of the desktop, so that every +page is hit in turn. + +If the letter "p" is appended to each coordinate (horizontal and/or +vertical), then the scroll amount will be measured in pixels. + +.IP "Title" +Does nothing. This is used to insert a title line in a popup or menu. + +.IP TogglePage +Temporarily disables edge scrolling. Edge scrolling can be re-enabled +by calling this again. + +.IP "Wait \fIname\fP" +This built-in is intended to be used in \fIfvwm\fP functions only. It causes +execution of a function to pause until a new window name \fIname\fP +appears. \fIFvwm\fP remains fully functional during a wait. This is +particularly useful in the InitFunction if you are trying to start +windows on specific desktops: +.EX +Function "InitFunction" + Exec "I" exec xterm -geometry 80x64+0+0 + Wait "I" xterm + Desk "I" 0 2 + Exec "I" exec xmh -font fixed -geometry 507x750+0+0 & + Wait "I" xmh + Desk "I" 0 0 +EndFunction +.EE +The above function starts an xterm on the current desk, waits for it +to map itself, then switches to desk 2 and starts an xmh. After the +xmh window appears control moves to desk 0. + +.IP "Warp [ \fIname window_name\fP ]" +Same as CirculateDown but de-iconifies any iconified windows as it focuses +on them. + +.IP "WindowsDesk \fInew_desk\fP" +Moves the selected window the the desktop specified as \fInew_desk\fP. + +.IP "WindowList \fIarg1 arg2\fP" +Generates a pop-up menu (and pops it up) in which the title and geometry of +each of the windows currently on the desk top are shown. The geometry of +iconified windows is shown in brackets. Selecting an item from the window list +pop-up menu will cause that window to be moved onto the desktop if it is +currently not on it, will move the desktop viewport to the page containing the +upper left hand corner of the window, will de-iconify the window if it is +iconified, and will raise the window. + +If \fIarg1\fP is an even number then the windows will be listed using +the window name (the name that shows up in the title-bar). If it is +odd then the window's icon name is used. + +If \fIarg1\fP is less than 2 then all windows on all desktops (except +those listed in WindowListSkip directives) will be shown. + +If \fIarg1\fP is 2 or 3 then only windows on the current desktop will +be shown. + +If \fIarg1\fP is 4 or 5 then only windows on desktop number \fIarg2\fP will +be shown. + +.SH KEYBOARD SHORTCUTS +All (I think) window manager operations can be performed from the keyboard +so mouseless operation should be possible. In addition to scrolling +around the virtual desktop by binding the Scroll built-in to appropriate keys, +pop-ups, move, resize, and most other built-ins can be bound to keys. Once a +built-in function is started the pointer is moved by using the up, down, +left, and right arrows, and the action is terminated by pressing return. +Holding down the shift key will cause the pointer movement to go in larger +steps and holding down the control key will cause the cursor movement to +go in smaller steps. Standard emacs and vi cursor +movement controls (^n, ^p, ^f, ^b, and ^j, ^k, ^h, ^l) can be used +instead of the arrow keys. + +.SH SUPPLIED CONFIGURATION +A sample configuration file, system.fvwmrc, is supplied with the \fIfvwm\fP +distribution. It is well commented and can be used as a source of examples +for \fIfvwm\fP configuration. + + +.SH USE ON MULTI-SCREEN DISPLAYS +If the -s command line argument is not given, \fIfvwm\fP will +automatically start up on every screen on the specified display. After +\fIfvwm\fP starts each screen is treated independently. Restarts of +\fIfvwm\fP need to be performed separately on each screen. The use of +EdgeScroll 0 0 is strongly recommended for multi-screen displays. + +You may need to quit on each screen to quit from the X session completely. + +Multi-screen support is only available if \fIfvwm\fP is compiled with +-DMULTIPLE_SCREENS + + +.SH BUGS +As of fvwm 0.99 there were exactly 39.342 unidentified bugs. Identified +bugs have mostly been fixed, though. Since then 9.34 bugs have been fixed. +Assuming that there are at least 10 unidentified bugs for every identified +one, that leaves us with 39.342 - 9.32 + 10 * 9.34 = 123.402 unidentified +bugs. If we follow this to its logical conclusion we will have +an infinite number of unidentified bugs before the number of bugs +can start to diminish, at which point the program will be bug-free. +Since this is a computer program infinity = 3.4028e+38 if +you don't insist on double-precision. At the current rate of bug discovery +we should expect to achieve this point in 3.37e+27 years. I guess I better +plan on passing this thing on to my children.... + +Binding a key to a window decoration but not to the window itself is +discouraged because when the key-press event finally gets to the window +it will be marked as SYNTHETIC and will be ignored by many applications. + +Bug reports can be sent to fvwm@wonderland.org. + + +.SH AUTHOR +Robert Nation with help from +many people, based on \fItwm\fP code, which was written by Thomas LaStrange. diff --git a/fvwm/icons.c b/fvwm/icons.c new file mode 100644 index 0000000..090ecae --- /dev/null +++ b/fvwm/icons.c @@ -0,0 +1,917 @@ +/**************************************************************************** + * This module is mostly all new + * by Rob Nation + * A little of it is borrowed from ctwm. + * Copyright 1993 Robert Nation. No restrictions are placed on this code, + * as long as the copyright notice is preserved + ****************************************************************************/ +/*********************************************************************** + * + * fvwm icon code + * + ***********************************************************************/ + +#include "../configure.h" + +#include +#include +#include +#include + +#ifdef NeXT +#include +#endif + +#include +#ifdef XPM +#include +#endif /* XPM */ +#include "fvwm.h" +#include "menus.h" +#include "misc.h" +#include "parse.h" +#include "screen.h" +#include "module.h" + +#ifdef SHAPE +#include +#endif /* SHAPE */ + + +void GrabIconButtons(FvwmWindow *, Window); +void GrabIconKeys(FvwmWindow *, Window); +MyFont *IconFont; + +/**************************************************************************** + * + * Creates an icon window as needed + * + ****************************************************************************/ +void CreateIconWindow(FvwmWindow *tmp_win, int def_x, int def_y) +{ + int final_x, final_y; + unsigned long valuemask; /* mask for create windows */ + XSetWindowAttributes attributes; /* attributes for create windows */ + + tmp_win->flags |= ICON_OURS; + tmp_win->flags &= ~XPM_FLAG; + tmp_win->flags &= ~PIXMAP_OURS; + tmp_win->flags &= ~SHAPED_ICON; + tmp_win->icon_pixmap_w = None; + tmp_win->iconPixmap = None; + tmp_win->iconDepth = 0; + + if(tmp_win->flags & SUPPRESSICON) + return; + + /* First, see if it was specified in the .fvwmrc */ + tmp_win->icon_p_height = 0; + tmp_win->icon_p_width = 0; + + /* First, check for a monochrome bitmap */ + if(tmp_win->icon_bitmap_file != NULL) + GetBitmapFile(tmp_win); + + /* Next, check for a color pixmap */ + if((tmp_win->icon_bitmap_file != NULL)&& + (tmp_win->icon_p_height == 0)&&(tmp_win->icon_p_width == 0)) + GetXPMFile(tmp_win); + + /* Next, See if the app supplies its own icon window */ + if((tmp_win->icon_p_height == 0)&&(tmp_win->icon_p_width == 0)&& + (tmp_win->wmhints) && (tmp_win->wmhints->flags & IconWindowHint)) + GetIconWindow(tmp_win); + + /* Finally, try to get icon bitmap from the application */ + if((tmp_win->icon_p_height == 0)&&(tmp_win->icon_p_width == 0)&& + (tmp_win->wmhints)&&(tmp_win->wmhints->flags & IconPixmapHint)) + GetIconBitmap(tmp_win); + + /* figure out the icon window size */ + if (!(tmp_win->flags & NOICON_TITLE)||(tmp_win->icon_p_height == 0)) + { + tmp_win->icon_t_width = XTextWidth(IconFont->font,tmp_win->icon_name, + strlen(tmp_win->icon_name)); + tmp_win->icon_w_height = ICON_HEIGHT; + } + else + { + tmp_win->icon_t_width = 0; + tmp_win->icon_w_height = 0; + } + if((tmp_win->flags & ICON_OURS)&&(tmp_win->icon_p_height >0)) + { + tmp_win->icon_p_width += 4; + tmp_win->icon_p_height +=4; + } + + if(tmp_win->icon_p_width == 0) + tmp_win->icon_p_width = tmp_win->icon_t_width+6; + tmp_win->icon_w_width = tmp_win->icon_p_width; + + final_x = def_x; + final_y = def_y; + if(final_x <0) + final_x = 0; + if(final_y <0) + final_y = 0; + + if(final_x + tmp_win->icon_w_width >=Scr.MyDisplayWidth) + final_x = Scr.MyDisplayWidth - tmp_win->icon_w_width-1; + if(final_y + tmp_win->icon_w_height >=Scr.MyDisplayHeight) + final_y = Scr.MyDisplayHeight - tmp_win->icon_w_height-1; + + tmp_win->icon_x_loc = final_x; + tmp_win->icon_xl_loc = final_x; + tmp_win->icon_y_loc = final_y; + + /* clip to fit on screen */ + attributes.background_pixel = Scr.StdColors.back; + valuemask = CWBorderPixel | CWCursor | CWEventMask | CWBackPixel; + attributes.border_pixel = Scr.StdColors.fore; + attributes.cursor = Scr.FvwmCursors[DEFAULT]; + attributes.event_mask = (ButtonPressMask | ButtonReleaseMask | + VisibilityChangeMask | + ExposureMask | KeyPressMask|EnterWindowMask | + FocusChangeMask ); + if (!(tmp_win->flags & NOICON_TITLE)||(tmp_win->icon_p_height == 0)) + tmp_win->icon_w = + XCreateWindow(dpy, Scr.Root, final_x, final_y+tmp_win->icon_p_height, + tmp_win->icon_w_width, tmp_win->icon_w_height,0, + CopyFromParent, + CopyFromParent,CopyFromParent,valuemask,&attributes); + + if((tmp_win->flags & ICON_OURS)&&(tmp_win->icon_p_width>0)&& + (tmp_win->icon_p_height>0)) + { + tmp_win->icon_pixmap_w = + XCreateWindow(dpy, Scr.Root, final_x, final_y, tmp_win->icon_p_width, + tmp_win->icon_p_height, 0, CopyFromParent, + CopyFromParent,CopyFromParent,valuemask,&attributes); + } + else + { + attributes.event_mask = (ButtonPressMask | ButtonReleaseMask | + VisibilityChangeMask | + KeyPressMask|EnterWindowMask | + FocusChangeMask | LeaveWindowMask ); + + valuemask = CWEventMask; + XChangeWindowAttributes(dpy,tmp_win->icon_pixmap_w, + valuemask,&attributes); + } + + +#ifdef XPM +#ifdef SHAPE + if (tmp_win->flags & SHAPED_ICON) + { + XShapeCombineMask(dpy, tmp_win->icon_pixmap_w, ShapeBounding,2, 2, + tmp_win->icon_maskPixmap, ShapeSet); + } +#endif +#endif + + if(tmp_win->icon_w != None) + { + XSaveContext(dpy, tmp_win->icon_w, FvwmContext, (caddr_t)tmp_win); + XDefineCursor(dpy, tmp_win->icon_w, Scr.FvwmCursors[DEFAULT]); + GrabIconButtons(tmp_win,tmp_win->icon_w); + GrabIconKeys(tmp_win,tmp_win->icon_w); + } + if(tmp_win->icon_pixmap_w != None) + { + XSaveContext(dpy, tmp_win->icon_pixmap_w, FvwmContext, (caddr_t)tmp_win); + XDefineCursor(dpy, tmp_win->icon_pixmap_w, Scr.FvwmCursors[DEFAULT]); + GrabIconButtons(tmp_win,tmp_win->icon_pixmap_w); + GrabIconKeys(tmp_win,tmp_win->icon_pixmap_w); + } + return; +} + +/**************************************************************************** + * + * Draws the icon window + * + ****************************************************************************/ +void DrawIconWindow(FvwmWindow *Tmp_win) +{ + GC Shadow, Relief; + Pixel TextColor,BackColor; + int x ; + + if(Tmp_win->flags & SUPPRESSICON) + return; + + if(Tmp_win->icon_w != None) + flush_expose (Tmp_win->icon_w); + if(Tmp_win->icon_pixmap_w != None) + flush_expose (Tmp_win->icon_pixmap_w); + + if(Scr.Hilite == Tmp_win) + { + if(Scr.d_depth < 2) + Relief = Scr.HiShadowGC; + else + Relief = Scr.HiReliefGC; + Shadow = Scr.HiShadowGC; + /* resize the icon name window */ + if(Tmp_win->icon_w != None) + { + Tmp_win->icon_w_width = Tmp_win->icon_t_width+6; + if(Tmp_win->icon_w_width < Tmp_win->icon_p_width) + Tmp_win->icon_w_width = Tmp_win->icon_p_width; + Tmp_win->icon_xl_loc = Tmp_win->icon_x_loc - + (Tmp_win->icon_w_width - Tmp_win->icon_p_width)/2; + } + TextColor = Scr.HiColors.fore; + BackColor = Scr.HiColors.back; + } + else + { + if((Tmp_win->flags & STICKY)&&(Scr.d_depth < 2)) + { + Relief = Scr.StickyShadowGC; + Shadow = Scr.StickyShadowGC; + } + else if(Scr.d_depth < 2) + { + Relief = Scr.StdShadowGC; + Shadow = Scr.StdShadowGC; + } + else + { + if(Tmp_win->BackPixel != Scr.StdColors.back) + { + Globalgcv.foreground = Tmp_win->ReliefPixel; + Globalgcm = GCForeground; + XChangeGC(dpy,Scr.ScratchGC1,Globalgcm,&Globalgcv); + Relief = Scr.ScratchGC1; + + Globalgcv.foreground = Tmp_win->ShadowPixel; + XChangeGC(dpy,Scr.ScratchGC2,Globalgcm,&Globalgcv); + Shadow = Scr.ScratchGC2; + } + else + { + Relief = Scr.StdReliefGC; + Shadow = Scr.StdShadowGC; + } + } + /* resize the icon name window */ + if(Tmp_win->icon_w != None) + { + Tmp_win->icon_w_width = Tmp_win->icon_p_width; + Tmp_win->icon_xl_loc = Tmp_win->icon_x_loc; + } + TextColor = Tmp_win->TextPixel; + BackColor = Tmp_win->BackPixel; + + } + if((Tmp_win->flags & ICON_OURS)&&(Tmp_win->icon_pixmap_w != None)) + XSetWindowBackground(dpy,Tmp_win->icon_pixmap_w, + BackColor); + if(Tmp_win->icon_w != None) + XSetWindowBackground(dpy,Tmp_win->icon_w,BackColor); + + /* write the icon label */ + NewFontAndColor(IconFont->font->fid,TextColor,BackColor); + + if(Tmp_win->icon_pixmap_w != None) + XMoveWindow(dpy,Tmp_win->icon_pixmap_w,Tmp_win->icon_x_loc, + Tmp_win->icon_y_loc); + if(Tmp_win->icon_w != None) + { + XMoveResizeWindow(dpy, Tmp_win->icon_w, Tmp_win->icon_xl_loc, + Tmp_win->icon_y_loc+Tmp_win->icon_p_height, + Tmp_win->icon_w_width,ICON_HEIGHT); + + XClearWindow(dpy,Tmp_win->icon_w); + } + + if((Tmp_win->iconPixmap != None)&&(!(Tmp_win->flags & SHAPED_ICON))) + RelieveWindow(Tmp_win,Tmp_win->icon_pixmap_w,0,0, + Tmp_win->icon_p_width, Tmp_win->icon_p_height, + Relief,Shadow, FULL_HILITE); + + /* need to locate the icon pixmap */ + if(Tmp_win->iconPixmap != None) + { + if(Tmp_win->iconDepth == Scr.d_depth) + { + XCopyArea(dpy,Tmp_win->iconPixmap,Tmp_win->icon_pixmap_w,Scr.FontGC, + 0,0,Tmp_win->icon_p_width-4, Tmp_win->icon_p_height-4,2,2); + } + else + XCopyPlane(dpy,Tmp_win->iconPixmap,Tmp_win->icon_pixmap_w,Scr.FontGC,0, + 0,Tmp_win->icon_p_width-4, Tmp_win->icon_p_height-4,2,2,1); + } + + if(Tmp_win->icon_w != None) + { + /* text position */ + x = (Tmp_win->icon_w_width - Tmp_win->icon_t_width)/2; + if(x<3)x=3; + + XDrawString (dpy, Tmp_win->icon_w, Scr.FontGC, x, + Tmp_win->icon_w_height-IconFont->height+IconFont->y-3, + Tmp_win->icon_name, strlen(Tmp_win->icon_name)); + RelieveWindow(Tmp_win,Tmp_win->icon_w,0,0,Tmp_win->icon_w_width, + ICON_HEIGHT,Relief,Shadow, FULL_HILITE); + } +} + +/*********************************************************************** + * + * Procedure: + * RedoIconName - procedure to re-position the icon window and name + * + ************************************************************************/ +void RedoIconName(FvwmWindow *Tmp_win) +{ +#ifndef NO_PAGER + if(Scr.PagerFont.height > 0) + { + XClearWindow(dpy,Tmp_win->pager_view); + RedrawPager(); + } +#endif + + if(Tmp_win->flags & SUPPRESSICON) + return; + + if (Tmp_win->icon_w == (int)NULL) + return; + + Tmp_win->icon_t_width = XTextWidth(IconFont->font,Tmp_win->icon_name, + strlen(Tmp_win->icon_name)); + /* clear the icon window, and trigger a re-draw via an expose event */ + if (Tmp_win->flags & ICONIFIED) + XClearArea(dpy, Tmp_win->icon_w, 0, 0, 0, 0, True); + return; +} + + + + +/*********************************************************************** + * + * Procedure: + * AutoPlace - Find a home for an icon + * + ************************************************************************/ +void AutoPlace(FvwmWindow *t) +{ + int test_x=0, test_y=0,tw,th,tx,ty,i,temp_h,temp_w; + int base_x, base_y; + int width,height; + FvwmWindow *test_window; + Bool loc_ok; + int real_x=10, real_y=10; + + /* New! Put icon in same page as the center of the window */ + /* Not a good idea for StickyIcons */ + if((Scr.flags & StickyIcons)||(t->flags & STICKY)) + { + base_x = 0; + base_y = 0; + } + else + { + base_x=((t->frame_x+Scr.Vx+(t->frame_width>>1))/Scr.MyDisplayWidth)* + Scr.MyDisplayWidth - Scr.Vx; + base_y=((t->frame_y+Scr.Vy+(t->frame_height>>1))/Scr.MyDisplayHeight)* + Scr.MyDisplayHeight - Scr.Vy; + } + if(t->flags & ICON_MOVED) + { + /* just make sure the icon is on this screen */ + t->icon_x_loc = t->icon_x_loc % Scr.MyDisplayWidth + base_x; + t->icon_y_loc = t->icon_y_loc % Scr.MyDisplayHeight + base_y; + if(t->icon_x_loc < 0) + t->icon_x_loc += Scr.MyDisplayWidth; + if(t->icon_y_loc < 0) + t->icon_y_loc += Scr.MyDisplayHeight; + } + else if (t->wmhints && t->wmhints->flags & IconPositionHint) + { + t->icon_x_loc = t->wmhints->icon_x; + t->icon_y_loc = t->wmhints->icon_y; + } + else + { + width = t->icon_p_width; + height = t->icon_w_height + t->icon_p_height; + loc_ok = False; + + /* check all boxes in order */ + i=0; + while((i= (Scr.IconBoxes[i][2] - Scr.IconBoxes[i][0])) + temp_w = 0; + if(height >= (Scr.IconBoxes[i][3] - Scr.IconBoxes[i][1])) + temp_h = 0; + + while(((test_y + temp_h) < (Scr.IconBoxes[i][3]+base_y))&&(!loc_ok)) + { + + test_x = Scr.IconBoxes[i][0]+base_x; + while(((test_x + temp_w) < (Scr.IconBoxes[i][2]+base_x))&& + (!loc_ok)) + { + real_x = test_x; + real_y = test_y; + + if(test_x + width > (Scr.MyDisplayWidth-2+base_x)) + real_x = Scr.MyDisplayWidth - width -2 + base_x; + if(test_y + height > (Scr.MyDisplayHeight-2+base_y)) + real_y = Scr.MyDisplayHeight - height -2+base_y; + if(test_x Desk == t->Desk) + { + if((test_window->flags&ICONIFIED)&& + (test_window->icon_w||test_window->icon_pixmap_w)&& + (test_window != t)) + { + tw=test_window->icon_p_width; + th=test_window->icon_p_height+ + test_window->icon_w_height; + tx = test_window->icon_x_loc; + ty = test_window->icon_y_loc; + + if((tx<(real_x+width+3))&&((tx+tw+3) > real_x)&& + (ty<(real_y+height+3))&&((ty+th + 3)>real_y)) + { + loc_ok = False; + } + } + if(Scr.flags & StubbornIconPlacement) + { + if(!(test_window->flags&ICONIFIED)&& + (test_window!=t)) + { + tw=test_window->frame_width; + th=test_window->frame_height; + tx = test_window->frame_x; + ty = test_window->frame_y; + + if((tx < (real_x+width+3))&& + ((tx+tw+3)>real_x)&& + (ty < (real_y+height+3))&& + ((ty+th+3)>real_y)) + { + loc_ok = False; + } + } + } + } + test_window = test_window->next; + } + test_x +=3; + } + test_y +=3; + } + i++; + } + if(loc_ok == False) + return; + t->icon_x_loc = real_x; + t->icon_y_loc = real_y; + } + + if(t->icon_pixmap_w) + XMoveWindow(dpy,t->icon_pixmap_w,t->icon_x_loc, t->icon_y_loc); + + t->icon_w_width = t->icon_p_width; + t->icon_xl_loc = t->icon_x_loc; + + if (t->icon_w != None) + XMoveResizeWindow(dpy, t->icon_w, t->icon_xl_loc, + t->icon_y_loc+t->icon_p_height, + t->icon_w_width,ICON_HEIGHT); + Broadcast(M_ICON_LOCATION,7,t->w,t->frame, + (unsigned long)t, + t->icon_x_loc,t->icon_y_loc, + t->icon_w_width, t->icon_w_height+ t->icon_p_height); +} + +/*********************************************************************** + * + * Procedure: + * GrabIconButtons - grab needed buttons for the icon window + * + * Inputs: + * tmp_win - the fvwm window structure to use + * + ***********************************************************************/ +void GrabIconButtons(FvwmWindow *tmp_win, Window w) +{ + MouseButton *MouseEntry; + + MouseEntry = Scr.MouseButtonRoot; + while(MouseEntry != (MouseButton *)0) + { + if((MouseEntry->func != (int)0)&&(MouseEntry->Context & C_ICON)) + { + if(MouseEntry->Button >0) + XGrabButton(dpy, MouseEntry->Button, MouseEntry->Modifier, w, + True, ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, None, + Scr.FvwmCursors[DEFAULT]); + else + { + XGrabButton(dpy, 1, MouseEntry->Modifier, w, + True, ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, None, + Scr.FvwmCursors[DEFAULT]); + XGrabButton(dpy, 2, MouseEntry->Modifier, w, + True, ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, None, + Scr.FvwmCursors[DEFAULT]); + XGrabButton(dpy, 3, MouseEntry->Modifier, w, + True, ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, None, + Scr.FvwmCursors[DEFAULT]); + } + } + + MouseEntry = MouseEntry->NextButton; + } + return; +} + + + +/*********************************************************************** + * + * Procedure: + * GrabIconKeys - grab needed keys for the icon window + * + * Inputs: + * tmp_win - the fvwm window structure to use + * + ***********************************************************************/ +void GrabIconKeys(FvwmWindow *tmp_win,Window w) +{ + FuncKey *tmp; + for (tmp = Scr.FuncKeyRoot.next; tmp != NULL; tmp = tmp->next) + { + if (tmp->cont & C_ICON) + XGrabKey(dpy, tmp->keycode, tmp->mods, w, True, + GrabModeAsync, GrabModeAsync); + } + return; +} + + +/**************************************************************************** + * + * Looks for a monochrome icon bitmap file + * + ****************************************************************************/ +void GetBitmapFile(FvwmWindow *tmp_win) +{ + char *path = NULL; + int HotX,HotY; + extern char *IconPath; + + path = findIconFile(tmp_win->icon_bitmap_file, IconPath,R_OK); + + if(path == NULL)return; + if(XReadBitmapFile (dpy, Scr.Root,path, + (unsigned int *)&tmp_win->icon_p_width, + (unsigned int *)&tmp_win->icon_p_height, + &tmp_win->iconPixmap, + &HotX, &HotY) != BitmapSuccess) + { + tmp_win->icon_p_width = 0; + tmp_win->icon_p_height = 0; + } + + free(path); +} + +/**************************************************************************** + * + * Looks for a color XPM icon file + * + ****************************************************************************/ +void GetXPMFile(FvwmWindow *tmp_win) +{ +#ifdef XPM + XWindowAttributes root_attr; + XpmAttributes xpm_attributes; + extern char *PixmapPath; + char *path = NULL; + + path = findIconFile(tmp_win->icon_bitmap_file, PixmapPath,R_OK); + if(path == NULL)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, + &tmp_win->iconPixmap, + &tmp_win->icon_maskPixmap, + &xpm_attributes) == XpmSuccess) + { + tmp_win->icon_p_width = xpm_attributes.width; + tmp_win->icon_p_height = xpm_attributes.height; + tmp_win->flags |= XPM_FLAG; + tmp_win->flags |= PIXMAP_OURS; + tmp_win->iconDepth = Scr.d_depth; +#ifdef SHAPE + if (tmp_win->icon_maskPixmap) + tmp_win->flags |= SHAPED_ICON; +#endif + } + free(path); +#endif /* XPM */ +} + +/**************************************************************************** + * + * Looks for an application supplied icon window + * + ****************************************************************************/ +void GetIconWindow(FvwmWindow *tmp_win) +{ + /* We are guaranteed that wmhints is non-null when calling this + * routine */ + if(XGetGeometry(dpy, tmp_win->wmhints->icon_window, &JunkRoot, + &JunkX, &JunkY,(unsigned int *)&tmp_win->icon_p_width, + (unsigned int *)&tmp_win->icon_p_height, + &JunkBW, &JunkDepth)==0) + { + fprintf(stderr,"Help! Bad Icon Window!\n"); + } + tmp_win->icon_p_width += JunkBW<<1; + tmp_win->icon_p_height += JunkBW<<1; + /* + * Now make the new window the icon window for this window, + * and set it up to work as such (select for key presses + * and button presses/releases, set up the contexts for it, + * and define the cursor for it). + */ + tmp_win->icon_pixmap_w = tmp_win->wmhints->icon_window; +#ifdef SHAPE + if (tmp_win->wmhints->flags & IconMaskHint) + { + tmp_win->flags |= SHAPED_ICON; + tmp_win->icon_maskPixmap = tmp_win->wmhints->icon_mask; + } +#endif + /* Make sure that the window is a child of the root window ! */ + /* Olwais screws this up, maybe others do too! */ + XReparentWindow(dpy, tmp_win->icon_pixmap_w, Scr.Root, 0,0); + tmp_win->flags &= ~ICON_OURS; +} + + +/**************************************************************************** + * + * Looks for an application supplied bitmap or pixmap + * + ****************************************************************************/ +void GetIconBitmap(FvwmWindow *tmp_win) +{ + /* We are guaranteed that wmhints is non-null when calling this + * routine */ + XGetGeometry(dpy, tmp_win->wmhints->icon_pixmap, &JunkRoot, &JunkX, &JunkY, + (unsigned int *)&tmp_win->icon_p_width, + (unsigned int *)&tmp_win->icon_p_height, &JunkBW, &JunkDepth); + tmp_win->iconPixmap = tmp_win->wmhints->icon_pixmap; + tmp_win->iconDepth = JunkDepth; +#ifdef SHAPE + if (tmp_win->wmhints->flags & IconMaskHint) + { + tmp_win->flags |= SHAPED_ICON; + tmp_win->icon_maskPixmap = tmp_win->wmhints->icon_mask; + } +#endif +} + + + +/*********************************************************************** + * + * Procedure: + * DeIconify a window + * + ***********************************************************************/ +void DeIconify(FvwmWindow *tmp_win) +{ + FvwmWindow *t,*tmp; + int new_x,new_y,w2,h2; + + /* now de-iconify transients */ + for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) + { + if ((t == tmp_win)|| + ((t->flags & TRANSIENT) &&(t->transientfor == tmp_win->w))) + { + t->flags |= MAPPED; + if(Scr.Hilite == t) + SetBorder (t, False,True,True,None); + /* make sure that the window is on this screen */ + if((t->frame_x < 0)||(t->frame_y<0)|| + (t->frame_x >= Scr.MyDisplayWidth)|| + (t->frame_y >= Scr.MyDisplayHeight)) + + { + /* try to put at least half the window + * in the current screen, if the current desktop + * is the windows desktop */ + if(Scr.flags & StubbornIcons) + t->Desk = t->DeIconifyDesk; + else + t->Desk = Scr.CurrentDesk; + + if(t->Desk == Scr.CurrentDesk) + { + new_x = t->frame_x; + new_y = t->frame_y; + w2 = (t->frame_width>>1); + h2 = (t->frame_height>>1); + if(!(Scr.flags & StubbornIcons)) + { + if (( new_x < -w2) || (new_x > (Scr.MyDisplayWidth-w2 ))) + { + new_x = new_x % Scr.MyDisplayWidth; + if ( new_x < -w2 ) + new_x += Scr.MyDisplayWidth; + } + if ((new_y < -h2) || (new_y > (Scr.MyDisplayHeight-h2 ))) + { + new_y = new_y % Scr.MyDisplayHeight; + if ( new_y < -h2 ) + new_y += Scr.MyDisplayHeight; + } + } + SetupFrame(t,new_x,new_y, + t->frame_width,t->frame_height,False); + } + } + XMapWindow(dpy, t->w); + if(t->Desk == Scr.CurrentDesk) + { + XMapWindow(dpy, t->frame); + t->flags |= MAP_PENDING; + } + XMapWindow(dpy, t->Parent); + SetMapStateProp(t, NormalState); + t->flags &= ~ICONIFIED; + t->flags &= ~ICON_UNMAPPED; + /* Need to make sure the border is colored correctly, + * in case it was stuck or unstuck while iconified. */ + tmp = Scr.Hilite; + Scr.Hilite = t; + SetBorder(t,False,True,True,None); + Scr.Hilite = tmp; + XRaiseWindow(dpy,t->w); + if (t->icon_w) + XUnmapWindow(dpy, t->icon_w); + if (t->icon_pixmap_w) + XUnmapWindow(dpy, t->icon_pixmap_w); + Broadcast(M_DEICONIFY,3,t->w,t->frame,(unsigned long)t,0,0,0,0); + } + } + RaiseWindow(tmp_win); + + if((Scr.flags & StubbornIcons)||(Scr.flags & ClickToFocus)) + FocusOn(tmp_win,1); + + KeepOnTop(); + + MoveResizePagerView(tmp_win); + return; +} + + +/**************************************************************************** + * + * Iconifies the selected window + * + ****************************************************************************/ +void Iconify(FvwmWindow *tmp_win, int def_x, int def_y) +{ + FvwmWindow *t; + XWindowAttributes winattrs; + unsigned long eventMask; + + XGetWindowAttributes(dpy, tmp_win->w, &winattrs); + eventMask = winattrs.your_event_mask; + + if((tmp_win)&&(tmp_win == Scr.Hilite)&& + (Scr.flags & ClickToFocus)&&(tmp_win->next)) + { + SetFocus(tmp_win->next->w,tmp_win->next); + ClearCirculatedFlag(); + } + + + /* iconify transients first */ + for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) + { + if ((t==tmp_win)|| + ((t->flags & TRANSIENT) && (t->transientfor == tmp_win->w))) + { + /* + * Prevent the receipt of an UnmapNotify, since that would + * cause a transition to the Withdrawn state. + */ + t->flags &= ~MAPPED; + XSelectInput(dpy, t->w, eventMask & ~StructureNotifyMask); + XUnmapWindow(dpy, t->w); + XSelectInput(dpy, t->w, eventMask); + XUnmapWindow(dpy, t->frame); + t->DeIconifyDesk = t->Desk; + if (t->icon_w) + XUnmapWindow(dpy, t->icon_w); + if (t->icon_pixmap_w) + XUnmapWindow(dpy, t->icon_pixmap_w); + + SetMapStateProp(t, IconicState); + SetBorder (t, False,False,False,None); + if(t != tmp_win) + { + t->flags |= ICONIFIED|ICON_UNMAPPED; + + Broadcast(M_ICONIFY,7,t->w,t->frame, + (unsigned long)t, + -10000, -10000, + t->icon_w_width, + t->icon_w_height+t->icon_p_height); + BroadcastConfig(M_CONFIGURE_WINDOW,t); + } + if(t!= tmp_win) + MoveResizePagerView(t); + } + } + if (tmp_win->icon_w == None) + if(tmp_win->flags & ICON_MOVED) + CreateIconWindow(tmp_win,tmp_win->icon_x_loc,tmp_win->icon_y_loc); + else + CreateIconWindow(tmp_win, def_x, def_y); + + AutoPlace(tmp_win); + tmp_win->flags |= ICONIFIED; + tmp_win->flags &= ~ICON_UNMAPPED; + Broadcast(M_ICONIFY,7,tmp_win->w,tmp_win->frame, + (unsigned long)tmp_win, + tmp_win->icon_x_loc,tmp_win->icon_y_loc, + tmp_win->icon_w_width, + tmp_win->icon_w_height+tmp_win->icon_p_height); + BroadcastConfig(M_CONFIGURE_WINDOW,tmp_win); + + LowerWindow(tmp_win); + if(tmp_win->Desk == Scr.CurrentDesk) + { + if (tmp_win->icon_w != None) + XMapWindow(dpy, tmp_win->icon_w); + + if(tmp_win->icon_pixmap_w != None) + XMapWindow(dpy, tmp_win->icon_pixmap_w); + KeepOnTop(); + MoveResizePagerView(tmp_win); + } + if((Scr.flags & ClickToFocus)||(Scr.flags & SloppyFocus)) + { + if ((tmp_win)&&(tmp_win == Scr.Focus)) + { + if(Scr.PreviousFocus == Scr.Focus) + Scr.PreviousFocus = NULL; + if((Scr.flags & ClickToFocus)&&(tmp_win->next)) + SetFocus(tmp_win->next->w, tmp_win->next); + else + { + SetFocus(Scr.NoFocusWin, NULL); + } + ClearCirculatedFlag(); + } + } + return; +} + + diff --git a/fvwm/menus.c b/fvwm/menus.c new file mode 100644 index 0000000..0309ec7 --- /dev/null +++ b/fvwm/menus.c @@ -0,0 +1,783 @@ +/**************************************************************************** + * This module is based on Twm, but has been siginificantly modified + * by Rob Nation + ****************************************************************************/ +/*****************************************************************************/ +/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ +/** Salt Lake City, Utah **/ +/** Portions Copyright 1989 by the Massachusetts Institute of Technology **/ +/** Cambridge, Massachusetts **/ +/** **/ +/** All Rights Reserved **/ +/** **/ +/** Permission to use, copy, modify, and distribute this software and **/ +/** its documentation for any purpose and without fee is hereby **/ +/** granted, provided that the above copyright notice appear in all **/ +/** copies and that both that copyright notice and this permis- **/ +/** sion notice appear in supporting documentation, and that the **/ +/** names of Evans & Sutherland and M.I.T. not be used in advertising **/ +/** in publicity pertaining to distribution of the software without **/ +/** specific, written prior permission. **/ +/** **/ +/** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/ +/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/ +/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/ +/** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/ +/** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ +/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ +/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ +/** OR PERFORMANCE OF THIS SOFTWARE. **/ +/*****************************************************************************/ + + +/*********************************************************************** + * + * fvwm menu code + * + ***********************************************************************/ +#include "../configure.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "fvwm.h" +#include "menus.h" +#include "misc.h" +#include "parse.h" +#include "screen.h" + +int menu_on=0; + +MenuRoot *ActiveMenu = NULL; /* the active menu */ +MenuItem *ActiveItem = NULL; /* the active menu item */ + +int menuFromFrameOrWindowOrTitlebar = FALSE; + +extern int Context,Button; +extern FvwmWindow *ButtonWindow, *Tmp_win; +extern XEvent Event; +int Stashed_X, Stashed_Y,MenuY=0; + +void DrawTrianglePattern(Window,GC,GC,GC,int,int,int,int); +void DrawSeparator(Window, GC,GC,int, int,int,int,int); +void DrawUnderline(Window w, GC gc, int x, int y, char *txt, int off); +int UpdateMenu(void); + +extern XContext MenuContext; + +/**************************************************************************** + * + * Initiates a menu pop-up + * + ***************************************************************************/ +int do_menu (MenuRoot *menu) +{ + int prevStashedX=0,prevStashedY=0; + MenuRoot *PrevActiveMenu=0; + MenuItem *PrevActiveItem=0; + int retval=MENU_NOP; + int x,y; + + /* this condition could get ugly */ + if(menu->in_use) + return MENU_ERROR; + + /* In case we wind up with a move from a menu which is + * from a window border, we'll return to here to start + * the move */ + XQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, + &x, &y, &JunkX, &JunkY, &JunkMask); + + if(menu_on) + { + prevStashedX = Stashed_X; + prevStashedY = Stashed_Y; + + PrevActiveMenu = ActiveMenu; + PrevActiveItem = ActiveItem; + if(ActiveMenu) + if(Scr.flags & MWMMenus) + x = Stashed_X+ (ActiveMenu->width >> 1) + (menu->width >> 1) - 3; + if(ActiveItem) + y = ActiveItem->y_offset + MenuY + (Scr.EntryHeight >>1); + } + else + { + if(!GrabEm(MENU)) + { + XBell(dpy,Scr.screen); + return MENU_DONE; + } + if(Scr.flags & MWMMenus) + x += (menu->width >> 1) - 3; + } + if (PopUpMenu (menu, x, y)) + { + retval = UpdateMenu(); + } + else + XBell (dpy, Scr.screen); + + ActiveMenu = PrevActiveMenu; + ActiveItem = PrevActiveItem; + if((ActiveItem)&&(menu_on)) + ActiveItem->state = 1; + Stashed_X = prevStashedX; + Stashed_Y = prevStashedY; + + + if(!menu_on) + { + UngrabEm(); + WaitForButtonsUp(); + } + return retval; +} + +/*********************************************************************** + * + * Procedure: + * RelieveRectangle - add relief lines to a rectangular window + * + ***********************************************************************/ +void RelieveRectangle(Window win,int x,int y,int w, int h,GC Hilite,GC Shadow) +{ + XDrawLine(dpy, win, Hilite, x, y, w+x-1, y); + XDrawLine(dpy, win, Hilite, x, y, x, h+y-1); + + XDrawLine(dpy, win, Shadow, x, h+y-1, w+x-1, h+y-1); + XDrawLine(dpy, win, Shadow, w+x-1, y, w+x-1, h+y-1); +} + +/*********************************************************************** + * + * Procedure: + * RelieveHalfRectangle - add relief lines to the sides only of a + * rectangular window + * + ***********************************************************************/ +void RelieveHalfRectangle(Window win,int x,int y,int w,int h, + GC Hilite,GC Shadow) +{ + XDrawLine(dpy, win, Hilite, x, y-1, x, h+y); + XDrawLine(dpy, win, Hilite, x+1, y, x+1, h+y-1); + + XDrawLine(dpy, win, Shadow, w+x-1, y-1, w+x-1, h+y); + XDrawLine(dpy, win, Shadow, w+x-2, y, w+x-2, h+y-1); +} + + +/*********************************************************************** + * + * Procedure: + * PaintEntry - draws a single entry in a poped up menu + * + ***********************************************************************/ +void PaintEntry(MenuRoot *mr, MenuItem *mi) +{ + int y_offset,text_y,d, y_height; + GC ShadowGC, ReliefGC, currentGC; + + y_offset = mi->y_offset; + y_height = mi->y_height; + text_y = y_offset + Scr.StdFont.y; + + ShadowGC = Scr.MenuShadowGC; + if(Scr.d_depth<2) + ReliefGC = Scr.MenuShadowGC; + else + ReliefGC = Scr.MenuReliefGC; + + + if(Scr.flags & MWMMenus) + { + if((!mi->prev)||(!mi->prev->state)) + XClearArea(dpy, mr->w, 0,y_offset-1,mr->width,y_height+2,0); + else + XClearArea(dpy, mr->w, 0,y_offset+1,mr->width,y_height-1,0); + if ((mi->state)&&(mi->func != F_TITLE)&&(mi->func != F_NOP)&&*mi->item) + { + RelieveRectangle(mr->w, 3, y_offset, mr->width-5, mi->y_height, + ReliefGC,ShadowGC); + RelieveRectangle(mr->w, 2, y_offset-1, mr->width-3, mi->y_height+2, + ReliefGC,ShadowGC); + } + RelieveHalfRectangle(mr->w, 0, y_offset-1, mr->width, + y_height+2, ReliefGC, ShadowGC); + } + else + { + XClearArea(dpy, mr->w, 0,y_offset,mr->width,y_height,0); + if ((mi->state)&&(mi->func != F_TITLE)&&(mi->func != F_NOP)&&*mi->item) + RelieveRectangle(mr->w, 2, y_offset, mr->width-4, mi->y_height, + ReliefGC,ShadowGC); + RelieveHalfRectangle(mr->w, 0, y_offset, mr->width, + y_height, ReliefGC, ShadowGC); + } + if(mi->func == F_TITLE) + { + if(Scr.flags & MWMMenus) + { + text_y += HEIGHT_EXTRA>>1; + XDrawLine(dpy, mr->w, ShadowGC, 2, y_offset+y_height-2, + mr->width-3, y_offset+y_height-2); + XDrawLine(dpy, mr->w, ShadowGC, 2, y_offset+y_height-4, + mr->width-3, y_offset+y_height-4); + } + else + { + if(mi->next != NULL) + { + DrawSeparator(mr->w,ShadowGC,ReliefGC,5, y_offset+y_height-3, + mr->width-6, y_offset+y_height-3,1); + } + if(mi != mr->first) + { + text_y += HEIGHT_EXTRA_TITLE>>1; + DrawSeparator(mr->w,ShadowGC,ReliefGC,5, y_offset+1, + mr->width-6, y_offset+1,1); + } + } + } + else + text_y += HEIGHT_EXTRA>>1; + if(mi->func == F_NOP && *mi->item==0) + { + if(Scr.flags & MWMMenus) + DrawSeparator(mr->w,ShadowGC,ReliefGC,2,y_offset-1+HEIGHT_SEPARATOR/2, + mr->width-3,y_offset-1+HEIGHT_SEPARATOR/2,0); + else + DrawSeparator(mr->w,ShadowGC,ReliefGC,5,y_offset-1+HEIGHT_SEPARATOR/2, + mr->width-6,y_offset-1+HEIGHT_SEPARATOR/2,1); + } + if(mi->next == NULL) + DrawSeparator(mr->w,ShadowGC,ShadowGC,1,mr->height-2, + mr->width-2, mr->height-2,1); + if(mi == mr->first) + DrawSeparator(mr->w,ReliefGC,ReliefGC,0,0, mr->width-1,0,-1); + + if(check_allowed_function(mi)) + currentGC = Scr.MenuGC; + else + /* should be a shaded out word, no just re-colored. */ + currentGC = Scr.MenuStippleGC; + + if(*mi->item) + XDrawString(dpy, mr->w, currentGC,mi->x,text_y, mi->item, mi->strlen); + if(mi->strlen2>0) + XDrawString(dpy, mr->w, currentGC,mi->x2,text_y, mi->item2,mi->strlen2); + + /* pete@tecc.co.uk: If the item has a hot key, underline it */ + if (mi->hotkey > 0) + DrawUnderline(mr->w, currentGC,mi->x,text_y,mi->item,mi->hotkey - 1); + if (mi->hotkey < 0) + DrawUnderline(mr->w, currentGC,mi->x2,text_y,mi->item2, -1 - mi->hotkey); + + d=(Scr.EntryHeight-7)/2; + if(mi->func == F_POPUP) + if(mi->state) + DrawTrianglePattern(mr->w, ShadowGC, ReliefGC, ShadowGC,mr->width-d-8, + y_offset+d-1, mr->width-d-1, y_offset+d+7); + else + DrawTrianglePattern(mr->w, ReliefGC, ShadowGC, ReliefGC,mr->width-d-8, + y_offset+d-1, mr->width-d-1, y_offset+d+7); + return; +} + +/**************************************************************************** + * Procedure: + * DrawUnderline() - Underline a character in a string (pete@tecc.co.uk) + * + * Calculate the pixel offsets to the start of the character position we + * want to underline and to the next character in the string. Shrink by + * one pixel from each end and the draw a line that long two pixels below + * the character... + * + ****************************************************************************/ +void DrawUnderline(Window w, GC gc, int x, int y, char *txt, int posn) +{ + int off1 = XTextWidth(Scr.StdFont.font, txt, posn); + int off2 = XTextWidth(Scr.StdFont.font, txt, posn + 1) - 1; + + XDrawLine(dpy, w, gc, x + off1, y + 2, x + off2, y + 2); +} +/**************************************************************************** + * + * Draws two horizontal lines to form a separator + * + ****************************************************************************/ +void DrawSeparator(Window w, GC TopGC, GC BottomGC,int x1,int y1,int x2,int y2, + int extra_off) +{ + XDrawLine(dpy, w, TopGC , x1, y1, x2, y2); + XDrawLine(dpy, w, BottomGC, x1-extra_off, y1+1,x2+extra_off,y2+1); +} + +/**************************************************************************** + * + * Draws a little Triangle pattern within a window + * + ****************************************************************************/ +void DrawTrianglePattern(Window w,GC GC1,GC GC2,GC GC3,int l,int u,int r,int b) +{ + int m; + + m = (u + b)/2; + + XDrawLine(dpy,w,GC1,l,u,l,b); + + XDrawLine(dpy,w,GC2,l,b,r,m); + XDrawLine(dpy,w,GC3,r,m,l,u); +} + +/*********************************************************************** + * + * Procedure: + * PaintMenu - draws the entire menu + * + ***********************************************************************/ +void PaintMenu(MenuRoot *mr, XEvent *e) +{ + MenuItem *mi; + + for (mi = mr->first; mi != NULL; mi = mi->next) + { + /* be smart about handling the expose, redraw only the entries + * that we need to + */ + if (e->xexpose.y < (mi->y_offset + mi->y_height) && + (e->xexpose.y + e->xexpose.height) > mi->y_offset) + { + PaintEntry(mr, mi); + } + } + XSync(dpy, 0); + return; +} + +MenuRoot *PrevMenu = NULL; +MenuItem *PrevItem = NULL; +int PrevY=0; + + +/*********************************************************************** + * + * Procedure: + * Updates menu display to reflect the highlighted item + * + ***********************************************************************/ +int FindEntry(void) +{ + MenuItem *mi; + MenuRoot *actual_mr; + int retval = MENU_NOP; + MenuRoot *PrevPrevMenu; + MenuItem *PrevPrevItem; + int PrevPrevY; + int x, y, ChildY; + Window Child; + + XQueryPointer( dpy, Scr.Root, &JunkRoot, &Child, + &JunkX,&ChildY, &x, &y, &JunkMask); + XQueryPointer( dpy, ActiveMenu->w, &JunkRoot, &JunkChild, + &JunkX, &ChildY, &x, &y, &JunkMask); + + /* look for the entry that the mouse is in */ + for(mi=ActiveMenu->first; mi; mi=mi->next) + if(y>=mi->y_offset && yy_offset+mi->y_height) + break; + if(x<0 || x>ActiveMenu->width) + mi = NULL; + + + /* if we weren't on the active entry, let's turn the old active one off */ + if ((ActiveItem)&&(mi!=ActiveItem)) + { + ActiveItem->state = 0; + PaintEntry(ActiveMenu, ActiveItem); + } + /* if we weren't on the active item, change the active item and turn it on */ + if ((mi!=ActiveItem)&&(mi != NULL)) + { + mi->state = 1; + PaintEntry(ActiveMenu, mi); + } + ActiveItem = mi; + + if(ActiveItem) + { + /* create a new sub-menu */ + if((ActiveItem->func == F_POPUP)&& + ((Scr.flags & MWMMenus)||(x>(3*ActiveMenu->width>>2)))) + { + PrevPrevMenu = PrevMenu; + PrevPrevItem = PrevItem; + PrevPrevY = PrevY; + PrevY = MenuY; + PrevMenu = ActiveMenu; + PrevItem = ActiveItem; + retval = do_menu(ActiveItem->menu); + /* Unfortunately, this is needed (why?) for multi-screen operation */ + flush_expose(ActiveMenu->w); + for (mi = ActiveMenu->first; mi != NULL; mi = mi->next) + { + PaintEntry(ActiveMenu, mi); + } + XSync(dpy, 0); + MenuY = PrevY; + PrevMenu = PrevPrevMenu; + PrevItem = PrevPrevItem; + PrevY = PrevPrevY; + } + } + /* end a sub-menu */ + if (XFindContext (dpy, Child,MenuContext,(caddr_t *)&actual_mr)==XCNOENT) + { + return retval; + } + + if(actual_mr != ActiveMenu) + { + if(actual_mr == PrevMenu) + { + if((PrevItem->y_offset + PrevY > ChildY)|| + ((PrevItem->y_offset+PrevItem->y_height + PrevY) < ChildY)) + { + return SUBMENU_DONE; + } + } + else + return SUBMENU_DONE; + } + return retval; +} + +/*********************************************************************** + * Procedure + * menuShortcuts() - Menu keyboard processing (pete@tecc.co.uk) + * + * Function called from UpdateMenu instead of Keyboard_Shortcuts() + * when a KeyPress event is received. If the key is alphanumeric, + * then the menu is scanned for a matching hot key. Otherwise if + * it was the escape key then the menu processing is aborted. + * If none of these conditions are true, then the default processing + * routine is called. + ***********************************************************************/ +void menuShortcuts(XEvent *ev) +{ + MenuItem *mi; + KeySym keysym = XLookupKeysym(&ev->xkey,0); + + /* Try to match hot keys */ + if (((keysym >= XK_a) && (keysym <= XK_z)) || /* Only consider alphabetic */ + ((keysym >= XK_0) && (keysym <= XK_9))) /* ...or numeric keys */ + { + /* Search menu for matching hotkey */ + for (mi = ActiveMenu->first; mi; mi = mi->next) + { + char key; + if (mi->hotkey == 0) continue; /* Item has no hotkey */ + key = (mi->hotkey > 0) ? /* Extract hot character */ + mi->item[mi->hotkey - 1] : mi->item2[-1 - mi->hotkey]; + + /* Convert to lower case to match the keysym */ + if (isupper(key)) key = tolower(key); + + if (keysym == key) + { /* Are they equal? */ + ActiveItem = mi; /* Yes: Make this the active item */ + ev->type = ButtonRelease; /* Force a menu exit */ + return; + } + } + } + + switch(keysym) /* Other special keyboard handling */ + { + case XK_Escape: /* Escape key pressed. Abort */ + ActiveItem = NULL; /* No selection */ + ev->type = ButtonRelease; /* Make the menu exit */ + break; + + /* Nothing special --- Allow other shortcuts (cursor movement) */ + default: + Keyboard_shortcuts(ev,ButtonRelease); + break; + } +} + +/*********************************************************************** + * + * Procedure: + * Updates menu display to reflect the highlighted item + * + * Returns: + * 0 on error condition + * 1 on return from submenu to parent menu + * 2 on button release return + * + ***********************************************************************/ +int UpdateMenu(void) +{ + int done,func; + int retval; + MenuRoot *actual_mr; + + FindEntry(); + while (TRUE) + { + /* block until there is an event */ + XMaskEvent(dpy, ButtonPressMask|ButtonReleaseMask|ExposureMask | + KeyPressMask|VisibilityChangeMask|ButtonMotionMask, &Event); + StashEventTime(&Event); + done = 0; + if (Event.type == MotionNotify) + { + /* discard any extra motion events before a release */ + while((XCheckMaskEvent(dpy,ButtonMotionMask|ButtonReleaseMask, + &Event))&&(Event.type != ButtonRelease)); + } + /* Handle a limited number of key press events to allow mouseless + * operation */ + if(Event.type == KeyPress) + menuShortcuts(&Event); + + switch(Event.type) + { + case ButtonRelease: + /* The following lines holds the menu when the button is released */ + if ((Scr.flags & MWMMenus) && !ActiveItem && (menu_on > 1)) + { + int x,y; + XQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, + &JunkX, &JunkY, &x, &y, &JunkMask); + if((XFindContext(dpy, JunkChild,MenuContext, + (caddr_t *)&actual_mr)!=XCNOENT)&& + (actual_mr != ActiveMenu)) + { + done = 1; + break; + } + } + PopDownMenu(); + if(ActiveItem) + { + func = ActiveItem->func; + done = 1; + if(ButtonWindow) + { + ExecuteFunction(func, ActiveItem->action, + ButtonWindow->frame, + ButtonWindow, &Event, Context, + ActiveItem->val1,ActiveItem->val2, + ActiveItem->val1_unit,ActiveItem->val2_unit, + ActiveItem->menu,-1); + } + else + { + ExecuteFunction(func,ActiveItem->action, + None,None, &Event, + Context,ActiveItem->val1, + ActiveItem->val2, + ActiveItem->val1_unit,ActiveItem->val2_unit, + ActiveItem->menu,-1); + + } + } + ActiveItem = NULL; + ActiveMenu = NULL; + menuFromFrameOrWindowOrTitlebar = FALSE; + return MENU_DONE; + + case KeyPress: + case VisibilityNotify: + case ButtonPress: + done=1; + break; + + case MotionNotify: + done = 1; + + retval = FindEntry(); + if((retval == MENU_DONE)||(retval == SUBMENU_DONE)) + { + PopDownMenu(); + ActiveItem = NULL; + ActiveMenu = NULL; + menuFromFrameOrWindowOrTitlebar = FALSE; + } + + if(retval == MENU_DONE) + return MENU_DONE; + else if (retval == SUBMENU_DONE) + return MENU_NOP; + + break; + + case Expose: + /* grab our expose events, let the rest go through */ + if((XFindContext(dpy, Event.xany.window,MenuContext, + (caddr_t *)&actual_mr)!=XCNOENT)) + { + PaintMenu(actual_mr,&Event); + done = 1; + } + break; + + default: + break; + } + + if(!done)DispatchEvent(); + XFlush(dpy); + } +} + + +/*********************************************************************** + * + * Procedure: + * PopUpMenu - pop up a pull down menu + * + * Inputs: + * menu - the root pointer of the menu to pop up + * x, y - location of upper left of menu + * center - whether or not to center horizontally over position + * + ***********************************************************************/ +Bool PopUpMenu (MenuRoot *menu, int x, int y) +{ + + if ((!menu)||(menu->w == None)||(menu->items == 0)||(menu->in_use)) + return False; + + menu_on++; + InstallRootColormap(); + + Stashed_X = x; + Stashed_Y = y; + + /* pop up the menu */ + ActiveMenu = menu; + ActiveItem = NULL; + + x -= (menu->width >> 1); + y -= (Scr.EntryHeight >> 1); + + if((Tmp_win)&&(menu_on == 1)&&(Context&C_LALL)) + { + y = Tmp_win->frame_y+Tmp_win->boundary_width+Tmp_win->title_height+1; + x = Tmp_win->frame_x + Tmp_win->boundary_width + + Button*Tmp_win->title_height+1; + } + if((Tmp_win)&&(menu_on==1)&&(Context&C_RALL)) + { + y = Tmp_win->frame_y+Tmp_win->boundary_width+Tmp_win->title_height+1; + x = Tmp_win->frame_x +Tmp_win->frame_width - Tmp_win->boundary_width- + Button*Tmp_win->title_height - menu->width+1; + } + if((Tmp_win)&&(menu_on==1)&&(Context&C_TITLE)) + { + y = Tmp_win->frame_y+Tmp_win->boundary_width+Tmp_win->title_height+1; + if(x < Tmp_win->frame_x + Tmp_win->title_x) + x = Tmp_win->frame_x + Tmp_win->title_x; + if((x + menu->width) > + (Tmp_win->frame_x + Tmp_win->title_x +Tmp_win->title_width)) + x = Tmp_win->frame_x + Tmp_win->title_x +Tmp_win->title_width- + menu->width +1; + } + + /* clip to screen */ + if (x + menu->width > Scr.MyDisplayWidth-2) + x = Scr.MyDisplayWidth - menu->width-2; + if (x < 0) x = 0; + + if (y + menu->height > Scr.MyDisplayHeight-2) + { + y = Scr.MyDisplayHeight - menu->height-2; + /* Warp pointer to middle of top line */ + /* Not with MWMMenus! */ + if((!(Scr.flags & MWMMenus))||(menu_on < 2)) + XWarpPointer(dpy, Scr.Root, Scr.Root, 0, 0, Scr.MyDisplayWidth, + Scr.MyDisplayHeight, + x + (menu->width>>1), (y + (Scr.EntryHeight >> 1))); + } + if (y < 0) y = 0; + + MenuY = y; + XMoveWindow(dpy, menu->w, x, y); + XMapRaised(dpy, menu->w); + menu->in_use = True; + return True; +} + + +/*********************************************************************** + * + * Procedure: + * PopDownMenu - unhighlight the current menu selection and + * take down the menus + * + ***********************************************************************/ +void PopDownMenu() +{ + if (ActiveMenu == NULL) + return; + + menu_on--; + if (ActiveItem) + ActiveItem->state = 0; + + XUnmapWindow(dpy, ActiveMenu->w); + + UninstallRootColormap(); + XFlush(dpy); + if (Context & (C_WINDOW | C_FRAME | C_TITLE | C_SIDEBAR)) + menuFromFrameOrWindowOrTitlebar = TRUE; + else + menuFromFrameOrWindowOrTitlebar = FALSE; + ActiveMenu->in_use = FALSE; +} + +/*************************************************************************** + * + * Wait for all mouse buttons to be released + * This can ease some confusion on the part of the user sometimes + * + * Discard superflous button events during this wait period. + * + ***************************************************************************/ +void WaitForButtonsUp() +{ + Bool AllUp = False; + XEvent JunkEvent; + unsigned int mask; + + while(!AllUp) + { + XAllowEvents(dpy,ReplayPointer,CurrentTime); + XQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, + &JunkX, &JunkY, &JunkX, &JunkY, &mask); + + if((mask& + (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask))==0) + AllUp = True; + } + XSync(dpy,0); + while(XCheckMaskEvent(dpy, + ButtonPressMask|ButtonReleaseMask|ButtonMotionMask, + &JunkEvent)) + { + StashEventTime (&JunkEvent); + XAllowEvents(dpy,ReplayPointer,CurrentTime); + } + +} + + + diff --git a/fvwm/menus.h b/fvwm/menus.h new file mode 100644 index 0000000..027bf20 --- /dev/null +++ b/fvwm/menus.h @@ -0,0 +1,144 @@ +/**************************************************************************** + * This module is based on Twm, but has been siginificantly modified + * by Rob Nation + ****************************************************************************/ +/*****************************************************************************/ +/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ +/** Salt Lake City, Utah **/ +/** Portions Copyright 1989 by the Massachusetts Institute of Technology **/ +/** Cambridge, Massachusetts **/ +/** **/ +/** All Rights Reserved **/ +/** **/ +/** Permission to use, copy, modify, and distribute this software and **/ +/** its documentation for any purpose and without fee is hereby **/ +/** granted, provided that the above copyright notice appear in all **/ +/** copies and that both that copyright notice and this permis- **/ +/** sion notice appear in supporting documentation, and that the **/ +/** names of Evans & Sutherland and M.I.T. not be used in advertising **/ +/** in publicity pertaining to distribution of the software without **/ +/** specific, written prior permission. **/ +/** **/ +/** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/ +/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/ +/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/ +/** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/ +/** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ +/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ +/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ +/** OR PERFORMANCE OF THIS SOFTWARE. **/ +/*****************************************************************************/ + + +/*********************************************************************** + * + * $XConsortium: menus.h,v 1.24 89/12/10 17:46:26 jim Exp $ + * + * twm menus include file + * + * 17-Nov-87 Thomas E. LaStrange File created + * + ***********************************************************************/ + +#ifndef _MENUS_ +#define _MENUS_ + +#define MAX_FILE_SIZE 4096 /* max chars to read from file for cut */ +#define MAXPOPUPS 50 + + +typedef struct MenuItem +{ + struct MenuItem *next; /* next menu item */ + struct MenuItem *prev; /* prev menu item */ + char *item; /* the character string displayed on left*/ + char *item2; /* the character string displayed on right*/ + char *action; /* action to be performed */ + short item_num; /* item number of this menu */ + short x; /* x coordinate for text (item) */ + short x2; /* x coordinate for text (item2) */ + short y_offset; /* y coordinate for item */ + short y_height; /* y height for item */ + short func; /* twm built in function */ + long val1; /* values needed for F_SCROLL */ + long val2; + long val1_unit; /* units for val1, val2 */ + long val2_unit; /* pixels (unit=1) or percent of screen + * (unit = Scr.MyDisplayWidth/Height */ + short state; /* video state, 0 = normal, 1 = reversed */ + short strlen; /* strlen(item) */ + short strlen2; /* strlen(item2) */ + short hotkey; /* Hot key offset (pete@tecc.co.uk). + 0 - No hot key + +ve - offset to hot key char in item + -ve - offset to hot key char in item2 + (offsets have 1 added, so +1 or -1 + refer to the *first* character) + */ + struct MenuRoot *menu; /* sub-menu */ +} MenuItem; + +typedef struct MenuRoot +{ + struct MenuItem *first; /* first item in menu */ + struct MenuItem *last; /* last item in menu */ + struct MenuRoot *next; /* next in list of root menus */ + char *name; /* name of root */ + Window w; /* the window of the menu */ + short height; /* height of the menu */ + short width; /* width of the menu for 1st col */ + short width2; /* width of the menu for 2nd col */ + short items; /* number of items in the menu */ + Bool in_use; +} MenuRoot; + +typedef struct MouseButton +{ + int func; /* the function number */ + MenuRoot *menu; /* menu if func is F_POPUP */ + MenuItem *item; /* action to perform if func != F_POPUP */ + int Button; + int Context; + int Modifier; + int val1; + int val2; + long val1_unit; /* units for val1, val2 */ + long val2_unit; /* pixels (unit=1) or percent of screen + * (unit = Scr.MyDisplayWidth/Height */ + struct MouseButton *NextButton; +} MouseButton; + +typedef struct FuncKey +{ + struct FuncKey *next; /* next in the list of function keys */ + char *name; /* key name */ + KeyCode keycode; /* X keycode */ + int cont; /* context */ + int mods; /* modifiers */ + int func; /* function to perform */ + int val1; /* values needed for F_SCROLL */ + int val2; + long val1_unit; /* units for val1, val2 */ + long val2_unit; /* pixels (unit=1) or percent of screen */ + MenuRoot *menu; /* menu if func is F_POPUP */ + char *action; /* action string (if any) */ +} FuncKey; + +#define MENU_ERROR -1 +#define MENU_NOP 0 +#define MENU_DONE 1 +#define SUBMENU_DONE 2 + + +/* Types of events for the FUNCTION builtin */ +#define MOTION 'm' +#define IMMEDIATE 'i' +#define CLICK 'c' +#define DOUBLE_CLICK 'd' +#define ONE_AND_A_HALF_CLICKS 'o' + +extern MenuRoot *ActiveMenu; +extern MenuItem *ActiveItem; + + +#endif /* _MENUS_ */ diff --git a/fvwm/misc.c b/fvwm/misc.c new file mode 100644 index 0000000..517fa03 --- /dev/null +++ b/fvwm/misc.c @@ -0,0 +1,445 @@ +/**************************************************************************** + * This module is based on Twm, but has been siginificantly modified + * by Rob Nation + ****************************************************************************/ +/*****************************************************************************/ +/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ +/** Salt Lake City, Utah **/ +/** Portions Copyright 1989 by the Massachusetts Institute of Technology **/ +/** Cambridge, Massachusetts **/ +/** **/ +/** All Rights Reserved **/ +/** **/ +/** Permission to use, copy, modify, and distribute this software and **/ +/** its documentation for any purpose and without fee is hereby **/ +/** granted, provided that the above copyright notice appear in all **/ +/** copies and that both that copyright notice and this permis- **/ +/** sion notice appear in supporting documentation, and that the **/ +/** names of Evans & Sutherland and M.I.T. not be used in advertising **/ +/** in publicity pertaining to distribution of the software without **/ +/** specific, written prior permission. **/ +/** **/ +/** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/ +/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/ +/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/ +/** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/ +/** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ +/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ +/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ +/** OR PERFORMANCE OF THIS SOFTWARE. **/ +/*****************************************************************************/ + + +/************************************************************************** + * + * Assorted odds and ends + * + **************************************************************************/ + + +#include "../configure.h" + +#include +#include +#include +#include +#include +#include + +#include "fvwm.h" +#include +#include "menus.h" +#include "misc.h" +#include "parse.h" +#include "screen.h" +#include "module.h" + +XGCValues Globalgcv; +unsigned long Globalgcm; + + +/************************************************************************** + * + * Releases dynamically allocated space used to store window/icon names + * + **************************************************************************/ +void free_window_names (FvwmWindow *tmp, Bool nukename, Bool nukeicon) +{ + if (!tmp) + return; + + if (nukename && nukeicon) + { + if (tmp->name == tmp->icon_name) + { + if (tmp->name != NoName) + XFree (tmp->name); + tmp->name = NULL; + tmp->icon_name = NULL; + } + else + { + if (tmp->name != NoName) + XFree (tmp->name); + tmp->name = NULL; + if (tmp->icon_name != NoName) + XFree (tmp->icon_name); + tmp->icon_name = NULL; + } + } + else if (nukename) + { + if (tmp->name != tmp->icon_name && tmp->name != NoName) + XFree (tmp->name); + tmp->name = NULL; + } + else + { /* if (nukeicon) */ + if (tmp->icon_name != tmp->name && tmp->icon_name != NoName) + XFree (tmp->icon_name); + tmp->icon_name = NULL; + } + + return; +} + +/*************************************************************************** + * + * Handles destruction of a window + * + ****************************************************************************/ +void Destroy(FvwmWindow *Tmp_win) +{ + int i; + extern FvwmWindow *ButtonWindow; + extern FvwmWindow *colormap_win; + /* + * Warning, this is also called by HandleUnmapNotify; if it ever needs to + * look at the event, HandleUnmapNotify will have to mash the UnmapNotify + * into a DestroyNotify. + */ + if(!Tmp_win) + return; + + XUnmapWindow(dpy, Tmp_win->frame); + XSync(dpy,0); + + if(Tmp_win == Scr.Hilite) + Scr.Hilite = NULL; + + Broadcast(M_DESTROY_WINDOW,3,Tmp_win->w,Tmp_win->frame, + (unsigned long)Tmp_win,0,0,0,0); + + if(Scr.PreviousFocus == Tmp_win) + Scr.PreviousFocus = NULL; + + if(ButtonWindow == Tmp_win) + ButtonWindow = NULL; + + if((Tmp_win == Scr.Focus)&&(Scr.flags & ClickToFocus)) + { + if(Tmp_win->next) + SetFocus(Tmp_win->next->w, Tmp_win->next); + else + SetFocus(Scr.NoFocusWin, NULL); + } + + if(Scr.Focus == Tmp_win) + SetFocus(Scr.NoFocusWin, NULL); + + ClearCirculatedFlag(); + + if(Tmp_win == Scr.pushed_window) + Scr.pushed_window = NULL; + + if(Tmp_win == colormap_win) + colormap_win = NULL; + + XDestroyWindow(dpy, Tmp_win->frame); + XDeleteContext(dpy, Tmp_win->frame, FvwmContext); + + XDestroyWindow(dpy, Tmp_win->Parent); + + XDeleteContext(dpy, Tmp_win->Parent, FvwmContext); + + XDeleteContext(dpy, Tmp_win->w, FvwmContext); + + if ((Tmp_win->icon_w)&&(Tmp_win->flags & PIXMAP_OURS)) + XFreePixmap(dpy, Tmp_win->iconPixmap); + + +#ifndef NO_PAGER + if ((Scr.Pager_w)&& !(Tmp_win->flags & STICKY)) + XDestroyWindow(dpy, Tmp_win->pager_view); +#endif + + if (Tmp_win->icon_w) + { + XDestroyWindow(dpy, Tmp_win->icon_w); + XDeleteContext(dpy, Tmp_win->icon_w, FvwmContext); + } + if((Tmp_win->flags &ICON_OURS)&&(Tmp_win->icon_pixmap_w != None)) + XDestroyWindow(dpy, Tmp_win->icon_pixmap_w); + if(Tmp_win->icon_pixmap_w != None) + XDeleteContext(dpy, Tmp_win->icon_pixmap_w, FvwmContext); + + if (Tmp_win->flags & TITLE) + { + XDeleteContext(dpy, Tmp_win->title_w, FvwmContext); + for(i=0;ileft_w[i], FvwmContext); + for(i=0;iright_w[i] != None) + XDeleteContext(dpy, Tmp_win->right_w[i], FvwmContext); + } + if (Tmp_win->flags & BORDER) + { + for(i=0;i<4;i++) + XDeleteContext(dpy, Tmp_win->sides[i], FvwmContext); + for(i=0;i<4;i++) + XDeleteContext(dpy, Tmp_win->corners[i], FvwmContext); + } + + Tmp_win->prev->next = Tmp_win->next; + if (Tmp_win->next != NULL) + Tmp_win->next->prev = Tmp_win->prev; + free_window_names (Tmp_win, True, True); + if (Tmp_win->wmhints) + XFree ((char *)Tmp_win->wmhints); + if (Tmp_win->class.res_name && Tmp_win->class.res_name != NoName) + XFree ((char *)Tmp_win->class.res_name); + if (Tmp_win->class.res_class && Tmp_win->class.res_class != NoName) + XFree ((char *)Tmp_win->class.res_class); + if(Tmp_win->mwm_hints) + XFree((char *)Tmp_win->mwm_hints); + + if(Tmp_win->cmap_windows != (Window *)NULL) + XFree((void *)Tmp_win->cmap_windows); + + free((char *)Tmp_win); + +#ifndef NO_PAGER + RedrawPager(); +#endif + XSync(dpy,0); + return; +} + + + +/************************************************************************** + * + * Removes expose events for a specific window from the queue + * + *************************************************************************/ +int flush_expose (Window w) +{ + XEvent dummy; + int i=0; + + while (XCheckTypedWindowEvent (dpy, w, Expose, &dummy))i++; + return i; +} + + + +/*********************************************************************** + * + * Procedure: + * RestoreWithdrawnLocation + * + * Puts windows back where they were before fvwm took over + * + ************************************************************************/ +void RestoreWithdrawnLocation (FvwmWindow *tmp,Bool restart) +{ + int a,b,w2,h2; + unsigned int bw,mask; + XWindowChanges xwc; + + if(!tmp) + return; + + if (XGetGeometry (dpy, tmp->w, &JunkRoot, &xwc.x, &xwc.y, + &JunkWidth, &JunkHeight, &bw, &JunkDepth)) + { + XTranslateCoordinates(dpy,tmp->frame,Scr.Root,xwc.x,xwc.y, + &a,&b,&JunkChild); + xwc.x = a + tmp->xdiff; + xwc.y = b + tmp->ydiff; + xwc.border_width = tmp->old_bw; + mask = (CWX | CWY|CWBorderWidth); + + /* We can not assume that the window is currently on the screen. + * Although this is normally the case, it is not always true. The + * most common example is when the user does something in an + * application which will, after some amount of computational delay, + * cause the window to be unmapped, but then switches screens before + * this happens. The XTranslateCoordinates call above will set the + * window coordinates to either be larger than the screen, or negative. + * This will result in the window being placed in odd, or even + * unviewable locations when the window is remapped. The followin code + * forces the "relative" location to be within the bounds of the display. + * + * gpw -- 11/11/93 + * + * Unfortunately, this does horrendous things during re-starts, + * hence the "if(restart) clause (RN) + * + * Also, fixed so that it only does this stuff if a window is more than + * half off the screen. (RN) + */ + + if(!restart) + { + /* Don't mess with it if its partially on the screen now */ + if((tmp->frame_x < 0)||(tmp->frame_y<0)|| + (tmp->frame_x >= Scr.MyDisplayWidth)|| + (tmp->frame_y >= Scr.MyDisplayHeight)) + { + w2 = (tmp->frame_width>>1); + h2 = (tmp->frame_height>>1); + if (( xwc.x < -w2) || (xwc.x > (Scr.MyDisplayWidth-w2 ))) + { + xwc.x = xwc.x % Scr.MyDisplayWidth; + if ( xwc.x < -w2 ) + xwc.x += Scr.MyDisplayWidth; + } + if ((xwc.y < -h2) || (xwc.y > (Scr.MyDisplayHeight-h2 ))) + { + xwc.y = xwc.y % Scr.MyDisplayHeight; + if ( xwc.y < -h2 ) + xwc.y += Scr.MyDisplayHeight; + } + } + } + XReparentWindow (dpy, tmp->w,Scr.Root,xwc.x,xwc.y); + + if((tmp->flags & ICONIFIED)&&(!(tmp->flags & SUPPRESSICON))) + { + if (tmp->icon_w) + XUnmapWindow(dpy, tmp->icon_w); + if (tmp->icon_pixmap_w) + XUnmapWindow(dpy, tmp->icon_pixmap_w); + } + + XConfigureWindow (dpy, tmp->w, mask, &xwc); + XSync(dpy,0); + } +} + + +/*************************************************************************** + * + * Start/Stops the auto-raise timer + * + ****************************************************************************/ +void SetTimer(int delay) +{ +#ifdef HAVE_SETITIMER + struct itimerval value; + + value.it_value.tv_usec = 1000*(delay%1000); + value.it_value.tv_sec = delay/1000; + value.it_interval.tv_usec = 0; + value.it_interval.tv_sec = 0; + setitimer(ITIMER_REAL,&value,NULL); +#endif +} + +/*************************************************************************** + * + * ICCCM Client Messages - Section 4.2.8 of the ICCCM dictates that all + * client messages will have the following form: + * + * event type ClientMessage + * message type _XA_WM_PROTOCOLS + * window tmp->w + * format 32 + * data[0] message atom + * data[1] time stamp + * + ****************************************************************************/ +void send_clientmessage (Window w, Atom a, Time timestamp) +{ + XClientMessageEvent ev; + + ev.type = ClientMessage; + ev.window = w; + ev.message_type = _XA_WM_PROTOCOLS; + ev.format = 32; + ev.data.l[0] = a; + ev.data.l[1] = timestamp; + XSendEvent (dpy, w, False, 0L, (XEvent *) &ev); +} + + + + + +/**************************************************************************** + * + * Records the time of the last processed event. Used in XSetInputFocus + * + ****************************************************************************/ +Time lastTimestamp = CurrentTime; /* until Xlib does this for us */ + +Bool StashEventTime (XEvent *ev) +{ + Time NewTimestamp = CurrentTime; + + switch (ev->type) + { + case KeyPress: + case KeyRelease: + NewTimestamp = ev->xkey.time; + break; + case ButtonPress: + case ButtonRelease: + NewTimestamp = ev->xbutton.time; + break; + case MotionNotify: + NewTimestamp = ev->xmotion.time; + break; + case EnterNotify: + case LeaveNotify: + NewTimestamp = ev->xcrossing.time; + break; + case PropertyNotify: + NewTimestamp = ev->xproperty.time; + break; + case SelectionClear: + NewTimestamp = ev->xselectionclear.time; + break; + case SelectionRequest: + NewTimestamp = ev->xselectionrequest.time; + break; + case SelectionNotify: + NewTimestamp = ev->xselection.time; + break; + default: + return False; + } + if(NewTimestamp > lastTimestamp) + lastTimestamp = NewTimestamp; + return True; +} + + +/****************************************************************************** + * + * Cleare the CIRCULATED field of the window flags. + * + *****************************************************************************/ +void ClearCirculatedFlag() +{ + FvwmWindow *temp; + int i=0; + + temp = Scr.FvwmRoot.next; + while(temp != NULL) + { + temp->focus_sequence = i++; + temp = temp->next; + } +} diff --git a/fvwm/misc.h b/fvwm/misc.h new file mode 100644 index 0000000..07dc9f5 --- /dev/null +++ b/fvwm/misc.h @@ -0,0 +1,331 @@ +/*****************************************************************************/ +/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ +/** Salt Lake City, Utah **/ +/** Portions Copyright 1989 by the Massachusetts Institute of Technology **/ +/** Cambridge, Massachusetts **/ +/** **/ +/** All Rights Reserved **/ +/** **/ +/** Permission to use, copy, modify, and distribute this software and **/ +/** its documentation for any purpose and without fee is hereby **/ +/** granted, provided that the above copyright notice appear in all **/ +/** copies and that both that copyright notice and this permis- **/ +/** sion notice appear in supporting documentation, and that the **/ +/** names of Evans & Sutherland and M.I.T. not be used in advertising **/ +/** in publicity pertaining to distribution of the software without **/ +/** specific, written prior permission. **/ +/** **/ +/** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/ +/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/ +/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/ +/** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/ +/** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ +/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ +/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ +/** OR PERFORMANCE OF THIS SOFTWARE. **/ +/*****************************************************************************/ + + +#ifndef _MISC_ +#define _MISC_ + +#include +#include "menus.h" +#include "../libs/fvwmlib.h" + +/************************************************************************ + * ReapChildren - wait() for all dead child processes + ************************************************************************/ +#include +#ifdef HAVE_WAITPID +#define ReapChildren() while ((waitpid(-1, NULL, WNOHANG)) > 0); +#else +#define ReapChildren() while ((wait3(NULL, WNOHANG, NULL)) > 0); +#endif + +typedef struct name_list_struct +{ + struct name_list_struct *next; /* pointer to the next name */ + char *name; /* the name of the window */ + char *value; /* icon name */ + int Desk; /* Desktop number */ + unsigned long on_flags; + unsigned long off_flags; + int border_width; + int resize_width; + char *ForeColor; + char *BackColor; + + unsigned long on_buttons; + unsigned long off_buttons; + +} name_list; + +/* used for parsing configuration */ +struct config +{ + char *keyword; +#ifdef __STDC__ + void (*action)(char *, FILE *, char **, int *); +#else + void (*action)(); +#endif + char **arg; + int *arg2; +}; + +/* values for name_list flags */ +#define STICKY_FLAG 1 +#define STAYSONTOP_FLAG 2 +#define NOBORDER_FLAG 4 +#define NOTITLE_FLAG 8 +#define ICON_FLAG 32 +#define CIRCULATESKIP_FLAG 64 +#define LISTSKIP_FLAG 128 +#define STAYSONDESK_FLAG 256 +#define SUPPRESSICON_FLAG 512 +#define BW_FLAG 1024 +#define NOBW_FLAG 2048 +#define START_ICONIC_FLAG 4096 +#define FORE_COLOR_FLAG 8192 +#define BACK_COLOR_FLAG 16384 +#define NOICON_TITLE_FLAG 32768 + +/* some fancy font handling stuff */ +#define NewFontAndColor(newfont,color,backcolor) {\ + Globalgcv.font = newfont;\ + Globalgcv.foreground = color;\ + Globalgcv.background = backcolor;\ + Globalgcm = GCFont | GCForeground | GCBackground; \ + XChangeGC(dpy,Scr.FontGC,Globalgcm,&Globalgcv); \ +} + +#ifdef NO_ICONS +#define ICON_HEIGHT 1 +#else +#define ICON_HEIGHT (IconFont->height+6) +#endif + +extern XGCValues Globalgcv; +extern unsigned long Globalgcm; +extern MyFont *IconFont; +extern Time lastTimestamp; +extern XEvent Event; +extern char NoName[]; + +extern unsigned long LookInList(name_list *, char *, XClassHint *, + char **value, int *Desk, int *bw, int *nobw, + char **forecolor, char **backcolor, + unsigned long * buttons); +extern void MoveOutline(Window, int,int,int,int); +extern void DoResize(int, int, FvwmWindow *); +extern void DisplaySize(FvwmWindow *, int, int, Bool); +extern void DisplayPosition(FvwmWindow *, int, int,Bool); +extern void SetupFrame(FvwmWindow *,int,int,int,int,Bool); +extern void CreateGCs(void); +extern void InstallWindowColormaps(FvwmWindow *); +extern void InstallRootColormap(void); +extern void UninstallRootColormap(void); +extern void FetchWmProtocols(FvwmWindow *); +extern void FetchWmColormapWindows (FvwmWindow *tmp); +extern void PaintEntry(MenuRoot *, MenuItem *); +extern void PaintMenu(MenuRoot *, XEvent *); +extern void MakeMenus(const char*, char*); +extern void InitEvents(void); +extern void DispatchEvent(void); +extern void HandleEvents(void); +extern void HandleExpose(void); +extern void HandleFocusIn(void); +extern void HandleFocusOut(void); +extern void HandleDestroyNotify(void); +extern void HandleMapRequest(void); +extern void HandleMapNotify(void); +extern void HandleUnmapNotify(void); +extern void HandleMotionNotify(void); +extern void HandleButtonRelease(void); +extern void HandleButtonPress(void); +extern void HandleEnterNotify(void); +extern void HandleLeaveNotify(void); +extern void HandleConfigureRequest(void); +extern void HandleClientMessage(void); +extern void HandlePropertyNotify(void); +extern void HandleKeyPress(void); +extern void HandleVisibilityNotify(void); +extern void HandleColormapNotify(void); +extern void SetTitleBar(FvwmWindow *, Bool,Bool); +extern void RestoreWithdrawnLocation(FvwmWindow *, Bool); +extern void Destroy(FvwmWindow *); +extern void GetGravityOffsets (FvwmWindow *, int *, int *); +extern void MoveViewport(int newx, int newy,Bool); +extern FvwmWindow *AddWindow(Window w); +extern int MappedNotOverride(Window w); +extern void GrabButtons(FvwmWindow *); +extern void GrabKeys(FvwmWindow *); +extern void GetWindowSizeHints(FvwmWindow *); +extern void RedrawPager(void); +extern void ReallyRedrawPager(void); +extern void SwitchPages(Bool,Bool); +extern void NextPage(void); +extern void PrevPage(void); +extern void moveLoop(FvwmWindow *, int, int, int,int, int *, int *,Bool,Bool); + +extern void Keyboard_shortcuts(XEvent *, int); +extern void RedoIconName(FvwmWindow *); +extern void DrawIconWindow(FvwmWindow *); +extern void CreateIconWindow(FvwmWindow *tmp_win, int def_x, int def_y); + + +extern FVWM_INLINE void RelieveWindow(FvwmWindow *, Window, + int, int, int, int, GC, GC, int); +void RelieveParts(FvwmWindow *t,int i,GC hor, GC vert); +#define NO_HILITE 0x0000 +#define TOP_HILITE 0x0001 +#define RIGHT_HILITE 0x0002 +#define BOTTOM_HILITE 0x0004 +#define LEFT_HILITE 0x0008 +#define FULL_HILITE 0x000F + +extern void sleep_a_little(int); +extern void PagerMoveWindow(void); +extern void Maximize(FvwmWindow *,int,int,int, int); +extern void RaiseWindow(FvwmWindow *t); +extern void LowerWindow(FvwmWindow *t); +extern Bool GrabEm(int); +extern void UngrabEm(void); +extern MenuRoot *NewMenuRoot(char *name); +extern void AddToMenu(MenuRoot *, char *, char *, char *,int, + long,long, char, char); +extern void MakeMenu(MenuRoot *); +extern void CaptureAllWindows(void); +extern void SetTimer(int); +extern int flush_expose(Window w); +extern void ExecuteFunction(int, char *,Window, FvwmWindow *, XEvent *, + unsigned long, long, long,int,int, + MenuRoot *, int module); +extern void do_windowList(int, int); +extern void RaiseThisWindow(int); +extern int GetContext(FvwmWindow *, XEvent *, Window *dummy); +extern void ConstrainSize (FvwmWindow *, int *, int *); +extern void HandlePaging(int, int, int *, int *, int *, int *,Bool); +extern void SetShape(FvwmWindow *, int); +extern void AutoPlace(FvwmWindow *); +extern void fvwm_err(char *, char *, char *, char *); +extern void MoveResizePagerView(FvwmWindow *t); +extern void MoveResizeViewPortIndicator(void); +extern void executeModule(char *action,FILE *fd, char **arg, int *junk); +extern void SetFocus(Window,FvwmWindow *); +extern void CheckAndSetFocus(void); +extern void initModules(void); +extern void HandleModuleInput(Window w, int channel); +extern void nofont(char *name); +extern char *stripcpy(char *); +extern char *stripcpy2(char *,int, Bool); +extern char *stripcpy3(char *, Bool); +extern void match_string(struct config *, char *, char *, FILE *); +extern void no_popup(char *ptr); +extern void KillModule(int channel, int place); +extern void ClosePipes(void); +extern char *findIconFile(char *icon, char *pathlist, int mode); +extern void GetBitmapFile(FvwmWindow *tmp_win); +extern void GetXPMFile(FvwmWindow *tmp_win); +extern void GetIconWindow(FvwmWindow *tmp_win); +extern void GetIconBitmap(FvwmWindow *tmp_win); +extern void SmartPlacement(FvwmWindow *t, int width, int height,int *x,int *y); +extern void usage(void); +void Broadcast(unsigned long event_type, unsigned long num_datum, + unsigned long data1, unsigned long data2, + unsigned long data3, unsigned long data4, + unsigned long data5, unsigned long data6, + unsigned long data7); +void BroadcastConfig(unsigned long event_type, FvwmWindow *t); +void SendPacket(int channel, unsigned long event_type, unsigned long num_datum, + unsigned long data1, unsigned long data2, + unsigned long data3, unsigned long data4, + unsigned long data5, unsigned long data6, + unsigned long data7); +void SendConfig(int module, unsigned long event_type, FvwmWindow *t); +void BroadcastName(unsigned long event_type, unsigned long data1, + unsigned long data2, unsigned long data3, char *name); +void SendName(int channel, unsigned long event_type,unsigned long data1, + unsigned long data2, unsigned long data3, char *name); +void DeadPipe(int nonsense); +void GetMwmHints(FvwmWindow *t); +void SelectDecor(FvwmWindow *, unsigned long, int,int); +extern Bool PopUpMenu(MenuRoot *, int, int); +void ComplexFunction(Window, FvwmWindow *, XEvent *,unsigned long, MenuRoot *); +extern int DeferExecution(XEvent *, Window *,FvwmWindow **, unsigned long *, int, int); +void send_clientmessage (Window, Atom, Time); +void SetBorder (FvwmWindow *, Bool,Bool,Bool, Window); +void move_window(XEvent *,Window,FvwmWindow *,int,int, int,int,int); +void resize_window(Window,FvwmWindow *, int,int,int,int); +void CreateIconWindow(FvwmWindow *, int, int); +void send_clientmessage (Window, Atom, Time); +void SetMapStateProp(FvwmWindow *, int); +void SetStickyProp(FvwmWindow *, int, int, int); +void SetClientProp(FvwmWindow *); +void Iconify(FvwmWindow *, int, int); +void DeIconify(FvwmWindow *); +void PopDownMenu(void); +void KeepOnTop(void); +void show_panner(void); +void WaitForButtonsUp(void); +void FocusOn(FvwmWindow *t,int DeIconifyOnly); +Bool PlaceWindow(FvwmWindow *tmp_win, unsigned long flags,int Desk); +void free_window_names (FvwmWindow *tmp, Bool nukename, Bool nukeicon); + +int do_menu (MenuRoot *menu); +int check_allowed_function(MenuItem *mi); +int check_allowed_function2(int function, FvwmWindow *t); +void ReInstallActiveColormap(void); +void ParsePopupEntry(char *,FILE *, char **, int *); +void ParseMouseEntry(char *,FILE *, char **,int *); +void ParseKeyEntry(char *, FILE *, char **,int *); +void SetOneStyle(char *text,FILE *,char **,int *); +void AddToList(char *name, char *icon_name, unsigned long off_flags, + unsigned long on_flags, int desk,int bw, int nobw, + char *forecolor, char *backcolor, + unsigned long off_buttons, unsigned long on_buttons); + +void ParseStyle(char *text,FILE *,char **,int *); +void assign_string(char *text, FILE *fd, char **arg,int *); +void ButtonStyle(char *text, FILE *fd, char **arg,int *); +void SetFlag(char *text, FILE *fd, char **arg,int *); +void SetCursor(char *text, FILE *fd, char **arg,int *); +void SetInts(char *text, FILE *fd, char **arg,int *); +void SetBox(char *text, FILE *fd, char **arg,int *); +void set_func(char *, FILE *, char **,int *); +void copy_config(FILE **config_fd); +FVWM_INLINE void DrawPattern(Window, GC, GC, int, int,int); +Pixel GetShadow(Pixel); +Pixel GetHilite(Pixel); + + +#define UP 1 +#define DOWN 0 +extern FvwmWindow *Circulate(FvwmWindow *tmp_win, char *action,Bool Direction); +void changeDesks(int val1,int val2); +void changeWindowsDesk(FvwmWindow *t,int val1); +void MapIt(FvwmWindow *t); +void UnmapIt(FvwmWindow *t); +void do_save(void); +void checkPanFrames(void); +void raisePanFrames(void); +void initPanFrames(void); +Bool StashEventTime (XEvent *ev); +int matchWildcards(char *pattern, char *string); +int My_XNextEvent(Display *dpy, XEvent *event); +void ClearCirculatedFlag(); +void FlushQueue(int module); +void QuickRestart(void); +void AddFuncKey (char *, int, int, int, char *, int, int, MenuRoot *, + char , char); + +void InteractiveMove(Window *w, FvwmWindow *tmp_win, int *FinalX, int *FinalY, + XEvent *eventp); +#ifdef BROKEN_SUN_HEADERS +#include "sun_headers.h" +#endif +#ifdef NEEDS_ALPHA_HEADER +#include "alpha_header.h" +#endif /* NEEDS_ALPHA_HEADER */ +#endif /* _MISC_ */ diff --git a/fvwm/module.c b/fvwm/module.c new file mode 100644 index 0000000..8b71609 --- /dev/null +++ b/fvwm/module.c @@ -0,0 +1,685 @@ +/**************************************************************************** + * This module is all original code + * by Rob Nation + * Copyright 1993, Robert Nation + * You may use this code for any purpose, as long as the original + * copyright remains in the source code and all documentation + ****************************************************************************/ + +/*********************************************************************** + * + * code for launching fvwm modules. + * + ***********************************************************************/ + +#include "../configure.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fvwm.h" +#include "menus.h" +#include "misc.h" +#include "parse.h" +#include "screen.h" +#include "module.h" + + +int npipes; +int *readPipes; +int *writePipes; +int *pipeOn; +unsigned long *PipeMask; +struct queue_buff_struct **pipeQueue; + +FVWM_INLINE int PositiveWrite(int module, unsigned long *ptr, int size); +void DeleteQueueBuff(int module); +void AddToQueue(int module, unsigned long *ptr, int size, int done); + +void initModules(void) +{ + int i; + + npipes = GetFdWidth(); + + writePipes = (int *)safemalloc(sizeof(int)*npipes); + readPipes = (int *)safemalloc(sizeof(int)*npipes); + pipeOn = (int *)safemalloc(sizeof(int)*npipes); + PipeMask = (unsigned long *)safemalloc(sizeof(unsigned long)*npipes); + pipeQueue=(struct queue_buff_struct **) + safemalloc(sizeof(struct queue_buff_struct *)*npipes); + + for(i=0;i0) + { + close(writePipes[i]); + close(readPipes[i]); + } + while(pipeQueue[i] != NULL) + { + DeleteQueueBuff(i); + } + } +} + +void executeModule(char *action,FILE *fd, char **win, int *context) +{ + int fvwm_to_app[2],app_to_fvwm[2]; + int i,val; + char command[256]; + char *cptr; + char *aptr; + char *args[10]; + char *arg1 = NULL; + char arg2[40]; + char arg3[40]; + char arg5[40]; + char arg6[40]; + char *end; + extern char *ModulePath; + extern FILE *config_fd; + extern char *fvwm_file; + + if(action == NULL) + return; + strcpy(command,action); + + cptr = command; + while((isspace(*cptr))&&(*cptr != '\n')&&(*cptr != 0)) + cptr++; + + end = cptr; + while((!(isspace(*end))&&(*end != '\n'))&&(*end != 0)&&(end <(command+256))) + end++; + + if((*end == 0)||(end >= command+256)) + aptr = NULL; + else + aptr = end+1; + *end = 0; + + if(aptr) + { + while((isspace(*aptr)||(*aptr=='\n'))&&(*aptr!=0)&&(aptr<(command+256))) + aptr++; + if((*aptr == 0)||(*aptr == '\n')) + aptr = NULL; + } + + arg1 = findIconFile(cptr,ModulePath,X_OK); + if(arg1 == NULL) + { + fprintf(stderr,"Fvwm: No such module %s %s\n",ModulePath,cptr); + return; + } + + /* Look for an available pipe slot */ + i=0; + while((i=0)) + i++; + if(i>=npipes) + { + fprintf(stderr,"fvwm: Too many Accessories!\n"); + return; + } + + /* I want one-ended pipes, so I open two two-ended pipes, + * and close one end of each. I need one ended pipes so that + * I can detect when the module crashes/malfunctions */ + if(pipe(fvwm_to_app)!=0) + { + fprintf(stderr,"Fvwm: Failed to open pipe\n"); + return; + } + if(pipe(app_to_fvwm)!=0) + { + fprintf(stderr,"Fvwm: Failed to open pipe2\n"); + close(fvwm_to_app[0]); + close(fvwm_to_app[1]); + return; + } + + + val = fork(); + if(val > 0) + { + /* This fork remains running fvwm */ + /* close appropriate descriptors from each pipe so + * that fvwm will be able to tell when the app dies */ + close(app_to_fvwm[1]); + close(fvwm_to_app[0]); + + /* add these pipes to fvwm's active pipe list */ + writePipes[i] = fvwm_to_app[1]; + readPipes[i] = app_to_fvwm[0]; + pipeOn[i] = -1; + PipeMask[i] = MAX_MASK; + free(arg1); + pipeQueue[i] = NULL; + + /* make the PositiveWrite pipe non-blocking. Don't want to jam up + fvwm because of an uncooperative module */ + fcntl(writePipes[i],F_SETFL,O_NDELAY); + /* Mark the pipes close-on exec so other programs + * won`t inherit them */ + if (fcntl(readPipes[i], F_SETFD, 1) == -1) + fvwm_err("module close-on-exec failed",NULL,NULL,NULL); + if (fcntl(writePipes[i], F_SETFD, 1) == -1) + fvwm_err("module close-on-exec failed",NULL,NULL,NULL); + } + else if (val ==0) + { + /* this is the child */ + /* need to close config_fd if its still open! */ + if(config_fd != (FILE *)NULL) + /* Fixes some funny stuff with svr4 and stream IO */ + /* fclose(config_fd) */ + close(fileno(config_fd)); + + /* this fork execs the module */ + close(fvwm_to_app[1]); + close(app_to_fvwm[0]); + sprintf(arg2,"%d",app_to_fvwm[1]); + sprintf(arg3,"%d",fvwm_to_app[0]); + sprintf(arg5,"%lx",(unsigned long)win); + sprintf(arg6,"%lx",(unsigned long)context); + args[0]=arg1; + args[1]=arg2; + args[2]=arg3; + args[3]=fvwm_file; + args[4]=arg5; + args[5]=arg6; + if(aptr != NULL) + { + args[6] = aptr; + args[7] = 0; + } + else + args[6]= 0; + execvp(arg1,args); + fprintf(stderr,"Execution of module failed: %s",arg1); + perror(""); + close(app_to_fvwm[1]); + close(fvwm_to_app[0]); + exit(1); + } + else + { + fprintf(stderr,"Fork failed\n"); + free(arg1); + } + return; +} + +void HandleModuleInput(Window w, int channel) +{ + char text[256]; + int size; + int cont,n; + char *newaction = NULL; + + /* Already read a (possibly NULL) window id from the pipe, + * Now read an fvwm bultin command line */ + n = read(readPipes[channel], &size, sizeof(int)); + if(n < sizeof(int)) + { + KillModule(channel,1); + return; + } + + if(size >255) + { + fprintf(stderr,"Module command is too big (%d)\n",size); + size=255; + } + + pipeOn[channel] = 1; + + n = read(readPipes[channel],text, size); + if(n < size) + { + KillModule(channel,2); + return; + } + + text[n]=0; + n = read(readPipes[channel],&cont, sizeof(int)); + if(n < sizeof(int)) + { + KillModule(channel,3); + return; + } + if(cont == 0) + { + KillModule(channel,4); + } + if(strlen(text)>0) + { + char function[256],*ptr; + MenuRoot *mr=0; + char *item=NULL; + extern int func_val_1,func_val_2,func,Context; + extern struct config func_config[]; + extern unsigned PopupCount; + extern MenuRoot *PopupTable[MAXPOPUPS]; + FvwmWindow *tmp_win; + extern char *orig_tline; + int n,unit_val_1,unit_val_2; + char unit_1, unit_2; + + + orig_tline = text; + Event.xany.type = ButtonRelease; + Event.xany.window = w; + + func_val_1 = 0; + func_val_2 = 0; + unit_1 = 's'; + unit_2 = 's'; + n = sscanf(text,"%s %d %d",function,&func_val_1,&func_val_2); + if(n != 3) + n = sscanf(text,"%s %d%c %d%c",function,&func_val_1,&unit_1,&func_val_2,&unit_2); + + if(mystrcasecmp(function,"SET_MASK")==0) + { + PipeMask[channel] = func_val_1; + return; + } + func = F_NOP; + match_string(func_config,function,"bad mouse function:",NULL); + if((func == F_POPUP)||(func == F_FUNCTION)) + { + unsigned i; + ptr = stripcpy2(text,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; + } + } + else if((func == F_EXEC)||(func == F_RESTART)|| + (func == F_CIRCULATE_UP)||(func == F_CIRCULATE_DOWN)|| + (func == F_WARP)||(func == F_MODULE)) + { + if((func == F_EXEC)||(func == F_RESTART)||(func== F_MODULE)) + { + item = stripcpy2(text,0,True); + newaction = stripcpy3(text,True); + } + else + { + item = stripcpy2(text,0,False); + newaction = stripcpy3(text,False); + } + } + if (XFindContext (dpy, w, FvwmContext, (caddr_t *) &tmp_win) == XCNOENT) + { + tmp_win = NULL; + w = None; + } + if(tmp_win) + { + Event.xbutton.button = 1; + Event.xbutton.x_root = tmp_win->frame_x; + Event.xbutton.y_root = tmp_win->frame_y; + Event.xbutton.x = 0; + Event.xbutton.y = 0; + Event.xbutton.subwindow = None; + } + else + { + Event.xbutton.button = 1; + Event.xbutton.x_root = 0; + Event.xbutton.y_root = 0; + Event.xbutton.x = 0; + Event.xbutton.y = 0; + Event.xbutton.subwindow = None; + } + if(unit_1 == 'p') + unit_val_1 = 100; + else + unit_val_1 = Scr.MyDisplayWidth; + if(unit_2 == 'p') + unit_val_2 = 100; + else + unit_val_2 = Scr.MyDisplayHeight; + + Context = GetContext(tmp_win,&Event,&w); + ExecuteFunction(func,newaction, w, tmp_win, &Event, Context, + func_val_1,func_val_2,unit_val_1,unit_val_2,mr,channel); + } + return; +} + + +void DeadPipe(int nonsense) +{ + signal(SIGPIPE, DeadPipe); +} + + +void KillModule(int channel, int place) +{ + close(readPipes[channel]); + close(writePipes[channel]); + + readPipes[channel] = -1; + writePipes[channel] = -1; + pipeOn[channel] = -1; + while(pipeQueue[channel] != NULL) + { + DeleteQueueBuff(channel); + } + return; +} + + +void Broadcast(unsigned long event_type, unsigned long num_datum, + unsigned long data1, unsigned long data2, unsigned long data3, + unsigned long data4, unsigned long data5, unsigned long data6, + unsigned long data7) +{ + int i; + unsigned long body[10]; + + body[0] = START_FLAG; + body[1] = event_type; + body[2] = num_datum+3; + + if(num_datum>0) + body[3] = data1; + if(num_datum>1) + body[4] = data2; + if(num_datum>2) + body[5] = data3; + if(num_datum>3) + body[6] = data4; + if(num_datum>4) + body[7] = data5; + if(num_datum>5) + body[8] = data6; + if(num_datum>6) + body[9] = data7; + + for(i=0;i0) + body[3] = data1; + if(num_datum>1) + body[4] = data2; + if(num_datum>2) + body[5] = data3; + if(num_datum>3) + body[6] = data4; + if(num_datum>4) + body[7] = data5; + if(num_datum>5) + body[8] = data6; + if(num_datum>6) + body[9] = data7; + PositiveWrite(module,body,(num_datum+3)*sizeof(unsigned long)); +} + +void SendConfig(int module, unsigned long event_type, FvwmWindow *t) +{ + unsigned long body[MAX_BODY_SIZE+HEADER_SIZE]; + + body[0] = START_FLAG; + body[1] = event_type; + body[2] = 27; + body[3] = t->w; + body[4] = t->frame; + body[5] = (unsigned long)t; + body[6] = t->frame_x; + body[7] = t->frame_y; + body[8] = t->frame_width; + body[9] = t->frame_height; + body[10] = t->Desk; + body[11] = t->flags; + body[12] = t->title_height; + body[13] = t->boundary_width; + body[14] = t->hints.base_width; + body[15] = t->hints.base_height; + body[16] = t->hints.width_inc; + body[17] = t->hints.height_inc; + body[18] = t->hints.min_width; + body[19] = t->hints.min_height; + body[20] = t->hints.max_width; + body[21] = t->hints.max_height; + body[22] = t->icon_w; + body[23] = t->icon_pixmap_w; + body[24] = t->hints.win_gravity; + body[25] = t->TextPixel; + body[26] = t->BackPixel; + + PositiveWrite(module,body,27*sizeof(unsigned long)); +} + + +void BroadcastConfig(unsigned long event_type, FvwmWindow *t) +{ + unsigned long body[MAX_BODY_SIZE+HEADER_SIZE]; + int i; + + body[0] = START_FLAG; + body[1] = event_type; + body[2] = 27; + body[3] = t->w; + body[4] = t->frame; + body[5] = (unsigned long)t; + body[6] = t->frame_x; + body[7] = t->frame_y; + body[8] = t->frame_width; + body[9] = t->frame_height; + body[10] = t->Desk; + body[11] = t->flags; + body[12] = t->title_height; + body[13] = t->boundary_width; + body[14] = t->hints.base_width; + body[15] = t->hints.base_height; + body[16] = t->hints.width_inc; + body[17] = t->hints.height_inc; + body[18] = t->hints.min_width; + body[19] = t->hints.min_height; + body[20] = t->hints.max_width; + body[21] = t->hints.max_height; + body[22] = t->icon_w; + body[23] = t->icon_pixmap_w; + body[24] = t->hints.win_gravity; + body[25] = t->TextPixel; + body[26] = t->BackPixel; + + for(i=0;i +FVWM_INLINE int PositiveWrite(int module, unsigned long *ptr, int size) +{ + if((pipeOn[module]<0)||(!((PipeMask[module]) & ptr[1]))) + return -1; + + AddToQueue(module,ptr,size,0); + return size; +} + + +void AddToQueue(int module, unsigned long *ptr, int size, int done) +{ + struct queue_buff_struct *c,*e; + unsigned long *d; + + c = (struct queue_buff_struct *)safemalloc(sizeof(struct queue_buff_struct)); + c->next = NULL; + c->size = size; + c->done = done; + d = (unsigned long *)safemalloc(size); + c->data = d; + memcpy(d,ptr,size); + + e = pipeQueue[module]; + if(e == NULL) + { + pipeQueue[module] = c; + return; + } + while(e->next != NULL) + e = e->next; + e->next = c; +} + +void DeleteQueueBuff(int module) +{ + struct queue_buff_struct *a; + + if(pipeQueue[module] == NULL) + return; + a = pipeQueue[module]; + pipeQueue[module] = a->next; + free(a->data); + free(a); + return; +} + +void FlushQueue(int module) +{ + char *dptr; + struct queue_buff_struct *d; + int a; + extern int errno; + + if((pipeOn[module] <= 0)||(pipeQueue[module] == NULL)) + return; + + while(pipeQueue[module] != NULL) + { + d = pipeQueue[module]; + dptr = (char *)d->data; + while(d->done < d->size) + { + a = write(writePipes[module],&dptr[d->done], d->size - d->done); + if(a >=0) + d->done += a; + /* the write returns EWOULDBLOCK or EAGAIN if the pipe is full. + * (This is non-blocking I/O). SunOS returns EWOULDBLOCK, OSF/1 + * returns EAGAIN under these conditions. Hopefully other OSes + * return one of these values too. Solaris 2 doesn't seem to have + * a man page for write(2) (!) */ + else if ((errno == EWOULDBLOCK)||(errno == EAGAIN)||(errno==EINTR)) + { + return; + } + else + { + KillModule(module,123); + return; + } + } + DeleteQueueBuff(module); + } +} diff --git a/fvwm/module.h b/fvwm/module.h new file mode 100644 index 0000000..8f1fedc --- /dev/null +++ b/fvwm/module.h @@ -0,0 +1,48 @@ +#ifndef MODULE_H +#define MODULE_H + +struct queue_buff_struct +{ + struct queue_buff_struct *next; + unsigned long *data; + int size; + int done; +}; + +extern int npipes; +extern int *readPipes; +extern int *writePipes; +extern struct queue_buff_struct **pipeQueue; + +#define START_FLAG 0xffffffff + +#define M_TOGGLE_PAGING 1 +#define M_NEW_PAGE 2 +#define M_NEW_DESK 4 +#define M_ADD_WINDOW 8 +#define M_RAISE_WINDOW 16 +#define M_LOWER_WINDOW 32 +#define M_CONFIGURE_WINDOW 64 +#define M_FOCUS_CHANGE 128 +#define M_DESTROY_WINDOW 256 +#define M_ICONIFY 512 +#define M_DEICONIFY 1024 +#define M_WINDOW_NAME 2048 +#define M_ICON_NAME 4096 +#define M_RES_CLASS 8192 +#define M_RES_NAME 16384 +#define M_END_WINDOWLIST 32768 +#define M_ICON_LOCATION 65536 +#define M_MAP 131072 +#define MAX_MESSAGES 18 +#define MAX_MASK 262143 + +#define HEADER_SIZE 3 +#define MAX_PACKET_SIZE 27 +#define MAX_BODY_SIZE (MAX_PACKET_SIZE - HEADER_SIZE) + + +#endif /* MODULE_H */ + + + diff --git a/fvwm/move.c b/fvwm/move.c new file mode 100644 index 0000000..29a2f56 --- /dev/null +++ b/fvwm/move.c @@ -0,0 +1,503 @@ +/* + * This module is all original code + * by Rob Nation + * Copyright 1993, Robert Nation + * You may use this code for any purpose, as long as the original + * copyright remains in the source code and all documentation + ****************************************************************************/ + +/*********************************************************************** + * + * code for moving windows + * + ***********************************************************************/ + +#include "../configure.h" + +#include +#include +#include +#include +#include "fvwm.h" +#include "menus.h" +#include "misc.h" +#include "parse.h" +#include "screen.h" +#include "module.h" + +extern XEvent Event; +extern int menuFromFrameOrWindowOrTitlebar; +Bool NeedToResizeToo; + +/**************************************************************************** + * + * Start a window move operation + * + ****************************************************************************/ +void move_window(XEvent *eventp,Window w,FvwmWindow *tmp_win,int context, + int val1, int val2, int val1_unit,int val2_unit) +{ + int FinalX, FinalY; + + /* gotta have a window */ + if(tmp_win == NULL) + return; + + w = tmp_win->frame; + if(tmp_win->flags & ICONIFIED) + { + if(tmp_win->icon_pixmap_w != None) + { + XUnmapWindow(dpy,tmp_win->icon_w); + w = tmp_win->icon_pixmap_w; + } + else + w = tmp_win->icon_w; + } + + if((val1 !=0)||(val2 != 0)) + { + FinalX = val1*val1_unit/100; + FinalY = val2*val2_unit/100; + } + else + InteractiveMove(&w,tmp_win,&FinalX,&FinalY,eventp); + + if (w == tmp_win->frame) + { + SetupFrame (tmp_win, FinalX, FinalY, + tmp_win->frame_width, tmp_win->frame_height,FALSE); + } + else /* icon window */ + { + tmp_win->flags |= ICON_MOVED; + tmp_win->icon_x_loc = FinalX ; + tmp_win->icon_xl_loc = FinalX - + (tmp_win->icon_w_width - tmp_win->icon_p_width)/2; + tmp_win->icon_y_loc = FinalY; + Broadcast(M_ICON_LOCATION,7,tmp_win->w,tmp_win->frame, + (unsigned long)tmp_win, + tmp_win->icon_x_loc,tmp_win->icon_y_loc, + tmp_win->icon_w_width, tmp_win->icon_w_height + +tmp_win->icon_p_height); + XMoveWindow(dpy,tmp_win->icon_w, + tmp_win->icon_xl_loc, FinalY+tmp_win->icon_p_height); + if(tmp_win->icon_pixmap_w != None) + { + XMapWindow(dpy,tmp_win->icon_w); + XMoveWindow(dpy, tmp_win->icon_pixmap_w, tmp_win->icon_x_loc,FinalY); + XMapWindow(dpy,w); + } + + } + +#ifndef NO_PAGER + RedrawPager(); +#endif + + return; +} + + + +/**************************************************************************** + * + * Move the rubberband around, return with the new window location + * + ****************************************************************************/ +void moveLoop(FvwmWindow *tmp_win, int XOffset, int YOffset, int Width, + int Height, int *FinalX, int *FinalY,Bool opaque_move, + Bool AddWindow) +{ + Bool finished = False; + Bool done; + int xl,yt,delta_x,delta_y; +#ifndef NO_PAGER + unsigned int pagerwidth,pagerheight; + int ww,wh; + int wx,wy; + int MaxH,MaxW; + int last_x = -10000, last_y = -10000; + +#endif + XQueryPointer(dpy, Scr.Root, &JunkRoot, &JunkChild,&xl, &yt, + &JunkX, &JunkY, &JunkMask); + xl += XOffset; + yt += YOffset; + + if(((!opaque_move)&&(!(Scr.flags & MWMMenus)))||(AddWindow)) + MoveOutline(Scr.Root, xl, yt, Width,Height); + + DisplayPosition(tmp_win,xl+Scr.Vx,yt+Scr.Vy,True); + + while (!finished) + { + /* block until there is an interesting event */ + XMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask | KeyPressMask | + PointerMotionMask | ButtonMotionMask | ExposureMask, &Event); + StashEventTime(&Event); + + /* discard any extra motion events before a logical release */ + if (Event.type == MotionNotify) + { + while(XCheckMaskEvent(dpy, PointerMotionMask | ButtonMotionMask | + ButtonPressMask |ButtonRelease, &Event)) + { + StashEventTime(&Event); + if(Event.type == ButtonRelease) break; + } + } + + done = FALSE; + /* Handle a limited number of key press events to allow mouseless + * operation */ + if(Event.type == KeyPress) + Keyboard_shortcuts(&Event,ButtonRelease); + switch(Event.type) + { + case KeyPress: + done = TRUE; + break; + case ButtonPress: + XAllowEvents(dpy,ReplayPointer,CurrentTime); + if(((Event.xbutton.button == 2)&&(!(Scr.flags & MWMMenus)))|| + ((Event.xbutton.button == 1)&&(Scr.flags & MWMMenus)&& + (Event.xbutton.state & ShiftMask))) + { + NeedToResizeToo = True; + /* Fallthrough to button-release */ + } + else + { + done = 1; + break; + } + case ButtonRelease: + if(!opaque_move) + MoveOutline(Scr.Root, 0, 0, 0, 0); + xl = Event.xmotion.x_root + XOffset; + yt = Event.xmotion.y_root + YOffset; + + /* Resist moving windows over the edge of the screen! */ + if(((xl + Width) >= Scr.MyDisplayWidth)&& + ((xl + Width) < Scr.MyDisplayWidth+Scr.MoveResistance)) + xl = Scr.MyDisplayWidth - Width - tmp_win->bw; + if((xl <= 0)&&(xl > -Scr.MoveResistance)) + xl = 0; + if(((yt + Height) >= Scr.MyDisplayHeight)&& + ((yt + Height) < Scr.MyDisplayHeight+Scr.MoveResistance)) + yt = Scr.MyDisplayHeight - Height - tmp_win->bw; + if((yt <= 0)&&(yt > -Scr.MoveResistance)) + yt = 0; + + *FinalX = xl; + *FinalY = yt; + + done = TRUE; + finished = TRUE; + break; + + case MotionNotify: + /* update location of the pager_view window */ +#ifndef NO_PAGER + if((Scr.FvwmPager != NULL)&& + (xl < Scr.FvwmPager->frame_x + Scr.FvwmPager->frame_width)&& + (xl+Width > Scr.FvwmPager->frame_x)&& + (yt < Scr.FvwmPager->frame_y + Scr.FvwmPager->frame_height)&& + (yt+ Height > Scr.FvwmPager->frame_y)&&(!opaque_move)) + MoveOutline(Scr.Root,0,0,0,0); +#endif + xl = Event.xmotion.x_root; + yt = Event.xmotion.y_root; + HandlePaging(Scr.MyDisplayWidth,Scr.MyDisplayHeight,&xl,&yt, + &delta_x,&delta_y,False); + /* redraw the rubberband */ + xl += XOffset; + yt += YOffset; + + /* Resist moving windows over the edge of the screen! */ + if(((xl + Width) >= Scr.MyDisplayWidth)&& + ((xl + Width) < Scr.MyDisplayWidth+Scr.MoveResistance)) + xl = Scr.MyDisplayWidth - Width - tmp_win->bw; + if((xl <= 0)&&(xl > -Scr.MoveResistance)) + xl = 0; + if(((yt + Height) >= Scr.MyDisplayHeight)&& + ((yt + Height) < Scr.MyDisplayHeight+Scr.MoveResistance)) + yt = Scr.MyDisplayHeight - Height - tmp_win->bw; + if((yt <= 0)&&(yt > -Scr.MoveResistance)) + yt = 0; + +#ifndef NO_PAGER + if(Scr.FvwmPager) + { + pagerwidth = Scr.FvwmPager->frame_width - + 2*Scr.FvwmPager->boundary_width; + pagerheight = Scr.FvwmPager->frame_height - + Scr.FvwmPager->title_height - 2*Scr.FvwmPager->boundary_width; + + MaxW = Scr.VxMax + Scr.MyDisplayWidth; + MaxH = Scr.VyMax + Scr.MyDisplayHeight; + + if(!(tmp_win->flags & STICKY)&& + (!(tmp_win->flags&ICONIFIED)|| + (!(tmp_win->flags&SUPPRESSICON)))&& + (!(tmp_win->flags&ICONIFIED)||(!(Scr.flags & StickyIcons)))) + { + /* show the actual window */ + wx = (xl + Scr.Vx)*(int)pagerwidth/MaxW; + wy = (yt + Scr.Vy)*(int)pagerheight/MaxH; + if((last_x - wx >= 2)||(last_x - wx <= -2)|| + (last_y - wy >= 2)||(last_y - wy <= -2)) + { + ww = Width*(int)pagerwidth/MaxW; + wh = Height*(int)pagerheight/MaxH; + if(ww<2)ww=2; + if(wh<2)wh=2; + XMoveResizeWindow(dpy, + tmp_win->pager_view, wx, wy, ww, wh); + last_x = wx; + last_y = wy; + } + } + } +#endif + + if(!opaque_move) + MoveOutline(Scr.Root, xl, yt, Width,Height); + else + { + if (tmp_win->flags & ICONIFIED) + { + tmp_win->icon_x_loc = xl ; + tmp_win->icon_xl_loc = xl - + (tmp_win->icon_w_width - tmp_win->icon_p_width)/2; + tmp_win->icon_y_loc = yt; + if(tmp_win->icon_pixmap_w != None) + XMoveWindow (dpy, tmp_win->icon_pixmap_w, + tmp_win->icon_x_loc,yt); + else if (tmp_win->icon_w != None) + XMoveWindow(dpy, tmp_win->icon_w,tmp_win->icon_xl_loc, + yt+tmp_win->icon_p_height); + + } + else + XMoveWindow(dpy,tmp_win->frame,xl,yt); + } + DisplayPosition(tmp_win,xl+Scr.Vx,yt+Scr.Vy,False); + done = TRUE; + break; + + default: + break; + } + if(!done) + { + if(!opaque_move) + MoveOutline(Scr.Root,0,0,0,0); + DispatchEvent(); + if(!opaque_move) + MoveOutline(Scr.Root, xl, yt, Width, Height); + } + } +} + +/*********************************************************************** + * + * Procedure: + * DisplayPosition - display the position in the dimensions window + * + * Inputs: + * tmp_win - the current fvwm window + * x, y - position of the window + * + ************************************************************************/ + +void DisplayPosition (FvwmWindow *tmp_win, int x, int y,int Init) +{ + char str [100]; + int offset; + + (void) sprintf (str, " %+-4d %+-4d ", x, y); + if(Init) + { + XClearWindow(dpy,Scr.SizeWindow); + if(Scr.d_depth >= 2) + RelieveWindow(tmp_win,Scr.SizeWindow,0,0, + Scr.SizeStringWidth+ SIZE_HINDENT*2, + Scr.StdFont.height + SIZE_VINDENT*2, + Scr.StdReliefGC,Scr.StdShadowGC, FULL_HILITE); + } + else + { + XClearArea(dpy,Scr.SizeWindow,SIZE_HINDENT,SIZE_VINDENT,Scr.SizeStringWidth, + Scr.StdFont.height,False); + } + + offset = (Scr.SizeStringWidth + SIZE_HINDENT*2 + - XTextWidth(Scr.StdFont.font,str,strlen(str)))/2; + XDrawString (dpy, Scr.SizeWindow, Scr.NormalGC, + offset, + Scr.StdFont.font->ascent + SIZE_VINDENT, + str, strlen(str)); +} + + +/**************************************************************************** + * + * For menus, move, and resize operations, we can effect keyboard + * shortcuts by warping the pointer. + * + ****************************************************************************/ +void Keyboard_shortcuts(XEvent *Event, int ReturnEvent) +{ + int x,y,x_root,y_root; + int move_size,x_move,y_move; + KeySym keysym; + + /* Pick the size of the cursor movement */ + move_size = Scr.EntryHeight; + if(Event->xkey.state & ControlMask) + move_size = 1; + if(Event->xkey.state & ShiftMask) + move_size = 100; + + keysym = XLookupKeysym(&Event->xkey,0); + + x_move = 0; + y_move = 0; + switch(keysym) + { + case XK_Up: + case XK_k: + case XK_p: + y_move = -move_size; + break; + case XK_Down: + case XK_n: + case XK_j: + y_move = move_size; + break; + case XK_Left: + case XK_b: + case XK_h: + x_move = -move_size; + break; + case XK_Right: + case XK_f: + case XK_l: + x_move = move_size; + break; + case XK_Return: + case XK_space: + /* beat up the event */ + Event->type = ReturnEvent; + break; + default: + break; + } + XQueryPointer( dpy, Scr.Root, &JunkRoot, &Event->xany.window, + &x_root, &y_root, &x, &y, &JunkMask); + + if((x_move != 0)||(y_move != 0)) + { + /* beat up the event */ + XWarpPointer(dpy, None, Scr.Root, 0, 0, 0, 0, x_root+x_move, + y_root+y_move); + + /* beat up the event */ + Event->type = MotionNotify; + Event->xkey.x += x_move; + Event->xkey.y += y_move; + Event->xkey.x_root += x_move; + Event->xkey.y_root += y_move; + } +} + + +void InteractiveMove(Window *win, FvwmWindow *tmp_win, int *FinalX, int *FinalY, XEvent *eventp) +{ + extern int Stashed_X, Stashed_Y; + int origDragX,origDragY,DragX, DragY, DragWidth, DragHeight; + int XOffset, YOffset; + Window w; + + Bool opaque_move = False; +#ifndef NO_PAGER + extern Bool pagerOn; +#endif + + + InstallRootColormap(); + if (menuFromFrameOrWindowOrTitlebar) + { + /* warp the pointer to the cursor position from before menu appeared*/ + XWarpPointer(dpy, None, Scr.Root, 0, 0, 0, 0, Stashed_X,Stashed_Y); + XFlush(dpy); + } + + + DragX = eventp->xbutton.x_root; + DragY = eventp->xbutton.y_root; + /* If this is left commented out, then the move starts from the button press + * location instead of the current location, which seems to be an + * improvement */ + /* XQueryPointer(dpy, Scr.Root, &JunkRoot, &JunkChild, + &DragX, &DragY, &JunkX, &JunkY, &JunkMask);*/ + + if(!GrabEm(MOVE)) + { + XBell(dpy,Scr.screen); + return; + } + +#ifndef NO_PAGER + pagerOn = False; +#endif + + w = tmp_win->frame; + + if(tmp_win->flags & ICONIFIED) + if(tmp_win->icon_pixmap_w != None) + { + XUnmapWindow(dpy,tmp_win->icon_w); + w = tmp_win->icon_pixmap_w; + } + else + w = tmp_win->icon_w; + + *win = w; + + XGetGeometry(dpy, w, &JunkRoot, &origDragX, &origDragY, + (unsigned int *)&DragWidth, (unsigned int *)&DragHeight, + &JunkBW, &JunkDepth); + + if(DragWidth*DragHeight < + (Scr.OpaqueSize*Scr.MyDisplayWidth*Scr.MyDisplayHeight)/100) + opaque_move = True; + else + XGrabServer(dpy); + + if((!opaque_move)&&(tmp_win->flags & ICONIFIED)) + XUnmapWindow(dpy,w); + + DragWidth += JunkBW; + DragHeight+= JunkBW; + XOffset = origDragX - DragX; + YOffset = origDragY - DragY; + XMapRaised(dpy,Scr.SizeWindow); + moveLoop(tmp_win, XOffset,YOffset,DragWidth,DragHeight, FinalX,FinalY, + opaque_move,False); + + XUnmapWindow(dpy,Scr.SizeWindow); + UninstallRootColormap(); + + if(!opaque_move) + XUngrabServer(dpy); + UngrabEm(); + + +#ifndef NO_PAGER + pagerOn = True; +#endif + +} diff --git a/fvwm/pager.c b/fvwm/pager.c new file mode 100644 index 0000000..2b00853 --- /dev/null +++ b/fvwm/pager.c @@ -0,0 +1,815 @@ +/**************************************************************************** + * This module is all new + * by Rob Nation + ****************************************************************************/ +/*********************************************************************** + * + * fvwm pager handling code + * + ***********************************************************************/ + +#include "../configure.h" + +#include +#include +#include +#include "fvwm.h" +#include "menus.h" +#include "misc.h" +#include "parse.h" +#include "screen.h" +#include "module.h" + +extern XEvent Event; + +XGCValues Globalgcv; +unsigned long Globalgcm; + +void DrawPartitionLines(void); +FvwmWindow *FindCounterpart(Window target); +Bool pagerOn = True; +Bool EnablePagerRedraw = True; +Bool DoHandlePageing = True; + +/**************************************************************************** + * Cause the pager window to be re-drawn + * + * Trying to get clever - re-draw the pager by causing an expose event, + * the really redraw only when an expose arrives. Advantage is that the + * number of re-draws will be minimized + ***************************************************************************/ +void RedrawPager() +{ +#ifndef NO_PAGER + if((Scr.FvwmPager)&&(EnablePagerRedraw)) + XClearArea(dpy,Scr.Pager_w, 0, 0, Scr.FvwmPager->frame_width, + Scr.FvwmPager->frame_height,True); +#endif +} + +void ReallyRedrawPager() +{ +#ifndef NO_PAGER + FvwmWindow *t; + Pixel TextColor,BackColor; + + if(!Scr.FvwmPager) + return; + + flush_expose (Scr.Pager_w); + flush_expose (Scr.CPagerWin); + + if(Scr.PagerFont.height > 0) + { + if(Scr.Hilite != NULL) + { + if(!(Scr.Hilite->flags & STICKY)&& (!(Scr.Hilite->flags&ICONIFIED)||(!(Scr.Hilite->flags & SUPPRESSICON)))&& + (!(Scr.Hilite->flags&ICONIFIED)||(!(Scr.flags & StickyIcons)))&& + (Scr.Hilite->icon_name != NULL)) + { + TextColor = Scr.HiColors.fore; + BackColor = Scr.HiColors.back; + NewFontAndColor(Scr.PagerFont.font->fid,TextColor,BackColor); + flush_expose(Scr.Hilite->pager_view); + XDrawImageString (dpy, Scr.Hilite->pager_view, Scr.FontGC, + 2,Scr.PagerFont.y+2, + Scr.Hilite->icon_name, strlen(Scr.Hilite->icon_name)); + } + } + + TextColor = Scr.StdColors.fore; + BackColor = Scr.StdColors.back; + NewFontAndColor(Scr.PagerFont.font->fid,TextColor,BackColor); + + + for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) + { + if(t != Scr.Hilite) + { + if(!(t->flags & STICKY)&& + (!(t->flags & ICONIFIED)||(!(t->flags & SUPPRESSICON)))&& + (!(t->flags & ICONIFIED)||(!(Scr.flags & StickyIcons)))&& + (t->icon_name != NULL)) + { + flush_expose(t->pager_view); + XDrawImageString (dpy, t->pager_view, Scr.FontGC, + 2,Scr.PagerFont.y+2, + t->icon_name, strlen(t->icon_name)); + } + } + } + } + DrawPartitionLines(); +#endif +} + +#ifndef NO_PAGER +void DrawPartitionLines(void) +{ + int y, y1, y2, x, x1, x2; + int MaxW,MaxH,width,height; + + MaxW = Scr.VxMax + Scr.MyDisplayWidth; + MaxH = Scr.VyMax + Scr.MyDisplayHeight; + + width = Scr.FvwmPager->frame_width - 2*Scr.FvwmPager->boundary_width; + height = Scr.FvwmPager->frame_height - Scr.FvwmPager->title_height + - 2*Scr.FvwmPager->boundary_width; + + x = Scr.MyDisplayWidth; + y1 = 0; + y2 = height; + while(x < MaxW) + { + x1 = x*width/MaxW; + XDrawLine(dpy,Scr.Pager_w,Scr.NormalGC,x1,y1,x1,y2); + x += Scr.MyDisplayWidth; + } + + y = Scr.MyDisplayHeight; + x1 = 0; + x2 = width; + while(y < MaxH) + { + y1 = y*height/MaxH; + XDrawLine(dpy,Scr.Pager_w,Scr.NormalGC,x1,y1,x2,y1); + y += Scr.MyDisplayHeight; + } +} +#endif + +void SwitchPages(Bool align, Bool ChangeFocus) +{ +#ifndef NO_PAGER + int x,y; + unsigned int width,height; + FvwmWindow *tmp_win; + Window dumwin; + + if(!Scr.FvwmPager) + return; + + XTranslateCoordinates (dpy, Event.xbutton.window, Scr.Pager_w, + Event.xbutton.x, Event.xbutton.y, &x, &y, &dumwin); + + width = Scr.FvwmPager->frame_width - 2*Scr.FvwmPager->boundary_width; + height = Scr.FvwmPager->frame_height - Scr.FvwmPager->title_height + - 2*Scr.FvwmPager->boundary_width; + + if(x<0)x=0; + if(y<0)y=0; + x = x * (Scr.VxMax+Scr.MyDisplayWidth)/width; + y = y * (Scr.VyMax+Scr.MyDisplayHeight)/height; + if(align) + { + x = (x/Scr.MyDisplayWidth)*Scr.MyDisplayWidth; + y = (y/Scr.MyDisplayHeight)*Scr.MyDisplayHeight; + } + if(x<0)x=0; + if(y<0)y=0; +#ifndef NON_VIRTUAL + MoveViewport(x,y,True); +#endif + if((ChangeFocus)&&(Scr.flags & ClickToFocus)) + { + tmp_win = FindCounterpart(Event.xbutton.subwindow); + if(tmp_win) + { + RaiseWindow(tmp_win); + SetFocus(tmp_win->w,tmp_win); + ClearCirculatedFlag(); + } + } +#endif +} + + +void RaiseWindow(FvwmWindow *t) +{ + FvwmWindow *t2; + int count, i; + Window *wins; + SetTimer(0); + + /* raise the target, at least */ + count = 1; + Broadcast(M_RAISE_WINDOW,3,t->w,t->frame,(unsigned long)t,0,0,0,0); + + for (t2 = Scr.FvwmRoot.next; t2 != NULL; t2 = t2->next) + { + if(t2->flags & ONTOP) + count++; + if((t2->flags & TRANSIENT) &&(t2->transientfor == t->w)&& + (t2 != t)) + { +#ifndef NO_PAGER + if((Scr.Pager_w)&& !(t2->flags & STICKY)) + XRaiseWindow(dpy,t2->pager_view); +#endif + count++; + Broadcast(M_RAISE_WINDOW,3,t2->w,t2->frame,(unsigned long) t2, + 0,0,0,0); + if ((t2->flags & ICONIFIED)&&(!(t2->flags & SUPPRESSICON))) + { + count += 2; + } + } + } + if ((t->flags & ICONIFIED)&&(!(t->flags & SUPPRESSICON))) + { + count += 2; + } + +#ifndef NO_PAGER + if((Scr.Pager_w)&& !(t->flags & STICKY)) + { + XRaiseWindow(dpy,t->pager_view); + } +#endif + + wins = (Window *)safemalloc(count*sizeof(Window)); + + i=0; + + /* ONTOP windows on top */ + for (t2 = Scr.FvwmRoot.next; t2 != NULL; t2 = t2->next) + { + if(t2->flags & ONTOP) + { + Broadcast(M_RAISE_WINDOW,3,t2->w,t2->frame,(unsigned long) t2, + 0,0,0,0); + wins[i++] = t2->frame; + } + } + + /* now raise transients */ +#ifndef DONT_RAISE_TRANSIENTS + for (t2 = Scr.FvwmRoot.next; t2 != NULL; t2 = t2->next) + { + if((t2->flags & TRANSIENT) &&(t2->transientfor == t->w)&& + (t2 != t)&&(!(t2->flags & ONTOP))) + { + wins[i++] = t2->frame; + if ((t2->flags & ICONIFIED)&&(!(t2->flags & SUPPRESSICON))) + { + if(!(t2->flags & NOICON_TITLE))wins[i++] = t2->icon_w; + wins[i++] = t2->icon_pixmap_w; + } + } + } +#endif + + + if ((t->flags & ICONIFIED)&&(!(t->flags & SUPPRESSICON))) + { + if(!(t->flags & NOICON_TITLE))wins[i++] = t->icon_w; + wins[i++] = t->icon_pixmap_w; + } + if(!(t->flags & ONTOP)) + wins[i++] = t->frame; + if(!(t->flags & ONTOP)) + Scr.LastWindowRaised = t; + + if(i > 0) + XRaiseWindow(dpy,wins[0]); + + XRestackWindows(dpy,wins,i); + free(wins); + + RedrawPager(); +#ifndef NON_VIRTUAL + raisePanFrames(); +#endif +} + + +void LowerWindow(FvwmWindow *t) +{ + XLowerWindow(dpy,t->frame); + + SetTimer(0); + + Broadcast(M_LOWER_WINDOW,3,t->w,t->frame,(unsigned long)t,0,0,0,0); +#ifndef NO_PAGER + if((Scr.Pager_w)&& !(t->flags & STICKY)) + XLowerWindow(dpy,t->pager_view); +#endif + + if((t->flags & ICONIFIED)&&(!(t->flags & SUPPRESSICON))) + { + XLowerWindow(dpy, t->icon_w); + XLowerWindow(dpy, t->icon_pixmap_w); + } + Scr.LastWindowRaised = (FvwmWindow *)0; +#ifndef NO_PAGER + if(Scr.CPagerWin) + XLowerWindow(dpy,Scr.CPagerWin); +#endif + RedrawPager(); +} + + +void PagerMoveWindow() +{ +#ifndef NO_PAGER + FvwmWindow *tmp_win; + unsigned int width, height; + int Xoff,Yoff,x,y,MaxW,MaxH,xl,yt,xl1,yt1; + Window target; + Bool done,finished = False; + /* I tried to implement a feature so that when windows which could be + * opaque moved in a normal move would get the full size windows moved in + * conjunction with the pager version of the window, but it seems to + * be buggy on some machines */ +#ifdef BROKEN_STUFF + Bool OpaqueMove = False; + int dwidth,dheight; +#endif + if(!Scr.FvwmPager) + return; + + + EnablePagerRedraw = False; + target = Event.xbutton.subwindow; + tmp_win = FindCounterpart(target); + + if(tmp_win == NULL) + return; + + + MaxW = Scr.VxMax + Scr.MyDisplayWidth; + MaxH = Scr.VyMax + Scr.MyDisplayHeight; + + width = Scr.FvwmPager->frame_width - 2*Scr.FvwmPager->boundary_width; + height = Scr.FvwmPager->frame_height - Scr.FvwmPager->title_height + - 2*Scr.FvwmPager->boundary_width; + + XQueryPointer(dpy, target, &JunkRoot, &JunkChild, + &JunkX, &JunkY, &Xoff, &Yoff, &JunkMask); + + XQueryPointer(dpy, Scr.Pager_w, &JunkRoot, &JunkChild, + &JunkX, &JunkY, &xl, &yt, &JunkMask); + if(xl<0)xl=0; + if(yt<0)yt=0; + if(xl>width)xl=width; + if(yt>height)yt=height; + xl -= Xoff; + yt -= Yoff; + xl1=xl; + yt1=yt; + + while (!finished) + { + /* block until there is an interesting event */ + XMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask | KeyPressMask | + PointerMotionMask | ButtonMotionMask | ExposureMask | + VisibilityChangeMask, &Event); + StashEventTime(&Event); + + if (Event.type == MotionNotify) + /* discard any extra motion events before a logical release */ + while(XCheckMaskEvent(dpy, PointerMotionMask | ButtonMotionMask | + ButtonRelease, &Event)) + { + StashEventTime(&Event); + if(Event.type == ButtonRelease) break; + } + + done = FALSE; + + /* Handle a limited number of key press events to allow mouseless + * operation */ + if(Event.type == KeyPress) + Keyboard_shortcuts(&Event,ButtonRelease); + switch(Event.type) + { + case ButtonPress: + case KeyPress: + /* throw away enter and leave events until release */ + done = TRUE; + break; + case ButtonRelease: + XQueryPointer(dpy, Scr.Pager_w, &JunkRoot, &JunkChild, + &JunkX, &JunkY, &xl, &yt, &JunkMask); + if(xl<0)xl=0; + if(yt<0)yt=0; + if(xl>width)xl=width; + if(yt>height)yt=height; + xl -= Xoff; + yt -= Yoff; + done = TRUE; + finished = TRUE; + break; + + case MotionNotify: + XQueryPointer(dpy, Scr.Pager_w, &JunkRoot, &JunkChild, + &JunkX, &JunkY, &xl, &yt, &JunkMask); + if(xl<0)xl=0; + if(yt<0)yt=0; + if(xl>width)xl=width; + if(yt>height)yt=height; + + /* redraw the rubberband */ + xl -= Xoff; + yt -= Yoff; + + done = TRUE; + break; + + default: + break; + } + if(!done) + { + DispatchEvent(); + } + XMoveWindow(dpy, target,xl, yt); + DrawPartitionLines(); + + } + + x = xl*MaxW/(int)width - Scr.Vx; + y = yt*MaxH/(int)height - Scr.Vy; + + MoveResizePagerView(tmp_win); + if((xl1!=xl)||(yt1 != yt)) + { + if((tmp_win->flags & ICONIFIED)&&(!(tmp_win->flags & SUPPRESSICON))) + { + tmp_win->icon_x_loc = x; + tmp_win->icon_xl_loc = x - + (tmp_win->icon_w_width - tmp_win->icon_p_width)/2; + tmp_win->icon_y_loc = y; + XMoveWindow (dpy, tmp_win->icon_w, tmp_win->icon_xl_loc, y+tmp_win->icon_p_height); + + if(tmp_win->icon_pixmap_w != None) + XMoveWindow (dpy, tmp_win->icon_pixmap_w, x,y); + + tmp_win->flags |= ICON_MOVED; + + } + else + { + /* show the actual window */ + SetupFrame(tmp_win,x,y, tmp_win->frame_width,tmp_win->frame_height,FALSE); + } + } + EnablePagerRedraw = True; + RedrawPager(); +#endif +} + + + +#ifndef NO_PAGER +FvwmWindow *FindCounterpart(Window target) +{ + FvwmWindow *t,*tmp_win=0; + + tmp_win = NULL; + for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) + { + if(t->pager_view == target) + { + tmp_win = t; + } + } + return tmp_win; +} +#endif + +/*************************************************************************** + * + * Check to see if the pointer is on the edge of the screen, and scroll/page + * if needed + ***************************************************************************/ +void HandlePaging(int HorWarpSize, int VertWarpSize, int *xl, int *yt, + int *delta_x, int *delta_y,Bool Grab) +{ +#ifndef NON_VIRTUAL + int x,y,total; +#endif + + *delta_x = 0; + *delta_y = 0; + +#ifndef NON_VIRTUAL + if (DoHandlePageing) + { + if((Scr.ScrollResistance >= 10000)|| + ((HorWarpSize ==0)&&(VertWarpSize==0))) + return; + + /* need to move the viewport */ + if(( *xl >= SCROLL_REGION)&&( *xl < Scr.MyDisplayWidth-SCROLL_REGION)&& + ( *yt >= SCROLL_REGION)&&( *yt < Scr.MyDisplayHeight-SCROLL_REGION)) + return; + + total = 0; + while(total < Scr.ScrollResistance) + { + sleep_a_little(10000); + total+=10; + if(XCheckWindowEvent(dpy,Scr.PanFrameTop.win, + LeaveWindowMask,&Event)) + { + StashEventTime(&Event); + return; + } + if(XCheckWindowEvent(dpy,Scr.PanFrameBottom.win, + LeaveWindowMask,&Event)) + { + StashEventTime(&Event); + return; + } + if(XCheckWindowEvent(dpy,Scr.PanFrameLeft.win, + LeaveWindowMask,&Event)) + { + StashEventTime(&Event); + return; + } + if(XCheckWindowEvent(dpy,Scr.PanFrameRight.win, + LeaveWindowMask,&Event)) + { + StashEventTime(&Event); + return; + } + } + + XQueryPointer(dpy, Scr.Root, &JunkRoot, &JunkChild, + &x, &y, &JunkX, &JunkY, &JunkMask); + + /* Turn off the rubberband if its on */ + MoveOutline(Scr.Root,0,0,0,0); + + /* Move the viewport */ + /* and/or move the cursor back to the approximate correct location */ + /* that is, the same place on the virtual desktop that it */ + /* started at */ + if( x= Scr.MyDisplayWidth-SCROLL_REGION) + *delta_x = HorWarpSize; + else + *delta_x = 0; + if( y= Scr.MyDisplayHeight-SCROLL_REGION) + *delta_y = VertWarpSize; + else + *delta_y = 0; + + /* Ouch! lots of bounds checking */ + if(Scr.Vx + *delta_x < 0) + { + if (!(Scr.flags & EdgeWrapX )) + { + *delta_x = -Scr.Vx; + *xl = x - *delta_x; + } + else + { + *delta_x += Scr.VxMax + Scr.MyDisplayWidth; + *xl = x + *delta_x % Scr.MyDisplayWidth + HorWarpSize; + } + } + else if(Scr.Vx + *delta_x > Scr.VxMax) + { + if (!(Scr.flags & EdgeWrapX)) + { + *delta_x = Scr.VxMax - Scr.Vx; + *xl = x - *delta_x; + } + else + { + *delta_x -= Scr.VxMax +Scr.MyDisplayWidth; + *xl = x + *delta_x % Scr.MyDisplayWidth - HorWarpSize; + } + } + else + *xl = x - *delta_x; + + if(Scr.Vy + *delta_y < 0) + { + if (!(Scr.flags & EdgeWrapY)) + { + *delta_y = -Scr.Vy; + *yt = y - *delta_y; + } + else + { + *delta_y += Scr.VyMax + Scr.MyDisplayHeight; + *yt = y + *delta_y % Scr.MyDisplayHeight + VertWarpSize; + } + } + else if(Scr.Vy + *delta_y > Scr.VyMax) + { + if (!(Scr.flags & EdgeWrapY)) + { + *delta_y = Scr.VyMax - Scr.Vy; + *yt = y - *delta_y; + } + else + { + *delta_y -= Scr.VyMax + Scr.MyDisplayHeight; + *yt = y + *delta_y % Scr.MyDisplayHeight - VertWarpSize; + } + } + else + *yt = y - *delta_y; + + if(*xl <= SCROLL_REGION) *xl = SCROLL_REGION+1; + if(*yt <= SCROLL_REGION) *yt = SCROLL_REGION+1; + if(*xl >= Scr.MyDisplayWidth - SCROLL_REGION) + *xl = Scr.MyDisplayWidth - SCROLL_REGION -1; + if(*yt >= Scr.MyDisplayHeight - SCROLL_REGION) + *yt = Scr.MyDisplayHeight - SCROLL_REGION -1; + + if((*delta_x != 0)||(*delta_y!=0)) + { + if(Grab) + XGrabServer(dpy); + XWarpPointer(dpy,None,Scr.Root,0,0,0,0,*xl,*yt); + MoveViewport(Scr.Vx + *delta_x,Scr.Vy + *delta_y,False); + XQueryPointer(dpy, Scr.Root, &JunkRoot, &JunkChild, + xl, yt, &JunkX, &JunkY, &JunkMask); + if(Grab) + XUngrabServer(dpy); + } + } +#endif +} + + + +void MoveResizeViewPortIndicator(void) +{ +#ifndef NO_PAGER + int width,height,x1,x2,y1,y2; + + if((Scr.CPagerWin)&&(Scr.FvwmPager)) + { + width = Scr.FvwmPager->frame_width - 2*Scr.FvwmPager->boundary_width; + height = Scr.FvwmPager->frame_height - Scr.FvwmPager->title_height + - 2*Scr.FvwmPager->boundary_width; + x1 = Scr.Vx * width/(Scr.VxMax+Scr.MyDisplayWidth)+1; + y1 = Scr.Vy * height/(Scr.VyMax+Scr.MyDisplayHeight)+1; + x2 = (Scr.MyDisplayWidth) * width/(Scr.VxMax+Scr.MyDisplayWidth)-1; + y2 = (Scr.MyDisplayHeight) * height/(Scr.VyMax+Scr.MyDisplayHeight)-1; + if(x1==1) + { + x1--; + x2++; + } + if(y1==1) + { + y1--; + y2++; + } + XMoveResizeWindow(dpy,Scr.CPagerWin,x1,y1,x2,y2); + } +#endif +} + + +void MoveResizePagerView(FvwmWindow *t) +{ +#ifndef NO_PAGER + unsigned int width,height; + int ww,wh; + int wx,wy; + int MaxH,MaxW; + + if((!Scr.FvwmPager)||(!pagerOn)) + return; + + width = Scr.FvwmPager->frame_width - 2*Scr.FvwmPager->boundary_width; + height = Scr.FvwmPager->frame_height - Scr.FvwmPager->title_height + - 2*Scr.FvwmPager->boundary_width; + + MaxW = Scr.VxMax + Scr.MyDisplayWidth; + MaxH = Scr.VyMax + Scr.MyDisplayHeight; + + if((!(t->flags & STICKY)&& + (!(t->flags & ICONIFIED)||(!(t->flags & SUPPRESSICON)))&& + (!(t->flags & ICONIFIED)||(!(t->flags & SUPPRESSICON))))&& + (!((t->flags & ICONIFIED)&&(t->flags &ICON_UNMAPPED)))&& + (t->Desk == Scr.CurrentDesk)) + { + if(t->flags & ICONIFIED) + { + /* show the icon loc */ + wx = (t->icon_x_loc + Scr.Vx)*(int)width/MaxW;; + wy = (t->icon_y_loc + Scr.Vy)*(int)height/MaxH; + ww = t->icon_w_width*(int)width/MaxW; + wh = (t->icon_w_height+t->icon_p_height)*(int)height/MaxH; + } + else + { + /* show the actual window */ + wx = (t->frame_x + Scr.Vx)*(int)width/MaxW; + wy = (t->frame_y + Scr.Vy)*(int)height/MaxH; + ww = t->frame_width*(int)width/MaxW; + wh = t->frame_height*(int)height/MaxH; + } + if(ww<2)ww=2; + if(wh<2)wh=2; + XMoveResizeWindow(dpy, t->pager_view, wx, wy, ww, wh); + } + else + { + /* window is sticky - make sure that the pager_view window is not + * visible */ + XMoveResizeWindow(dpy, t->pager_view, -10, -10, 5, 5); + } + RedrawPager(); +#endif +} + + +/*********************************************************************** + * + * Procedure: + * Initialize_pager - creates the pager window, if needed + * + * Inputs: + * x,y location of the window + * + ***********************************************************************/ +#ifndef NO_PAGER +char *pager_name = "Fvwm Pager"; +XSizeHints sizehints = +{ + (PMinSize | PResizeInc | PBaseSize | PWinGravity), + 0, 0, 100, 100, /* x, y, width and height */ + 1, 1, /* Min width and height */ + 0, 0, /* Max width and height */ + 1, 1, /* Width and height increments */ + {0, 0}, {0, 0}, /* Aspect ratio - not used */ + 1, 1, /* base size */ + (NorthWestGravity) /* gravity */ +}; + +void initialize_pager(int x, int y) +{ + XTextProperty name; + int width,height,window_x,window_y; + unsigned long valuemask; + XSetWindowAttributes attributes; + extern Pixel PagerBackColor; + extern Pixel PagerForeColor; + + width = (Scr.VxMax + Scr.MyDisplayWidth)/Scr.VScale; + height = (Scr.VyMax + Scr.MyDisplayHeight)/Scr.VScale; + + if(x >=0) + window_x = x; + else + { + sizehints.win_gravity = NorthEastGravity; + window_x = Scr.MyDisplayWidth - width + x -2; + } + + if(y >=0) + window_y = y; + else + { + window_y = Scr.MyDisplayHeight - height + y -2; + if(x<0) + sizehints.win_gravity = SouthEastGravity; + else + sizehints.win_gravity = SouthWestGravity; + } + valuemask = (CWBackPixel | CWBorderPixel | CWEventMask|CWCursor); + attributes.background_pixel = PagerBackColor; + attributes.border_pixel = Scr.StdColors.fore; + attributes.cursor = Scr.FvwmCursors[DEFAULT]; + attributes.event_mask = (ExposureMask | EnterWindowMask|ButtonReleaseMask| + ButtonMotionMask); + sizehints.width = width; + sizehints.height = height; + sizehints.x = window_x; + sizehints.y = window_y; + + Scr.Pager_w = XCreateWindow (dpy, Scr.Root, window_x, window_y, width, + height, (unsigned int) 1, + CopyFromParent, InputOutput, + (Visual *) CopyFromParent, + valuemask, &attributes); + XSetWMNormalHints(dpy,Scr.Pager_w,&sizehints); + XStringListToTextProperty(&pager_name,1,&name); + XSetWMName(dpy,Scr.Pager_w,&name); + XSetWMIconName(dpy,Scr.Pager_w,&name); + XFree((char *)name.value); + + attributes.event_mask = KeyPressMask | ExposureMask; + attributes.background_pixel = PagerForeColor; + attributes.cursor = Scr.FvwmCursors[DEFAULT]; + Scr.CPagerWin=XCreateWindow(dpy,Scr.Pager_w,-10, -10, 10, 10,0, + CopyFromParent, + InputOutput,CopyFromParent, + CWEventMask|CWBackPixel|CWCursor, + &attributes); + XMapRaised(dpy,Scr.CPagerWin); +} +#endif diff --git a/fvwm/parse.h b/fvwm/parse.h new file mode 100644 index 0000000..2e32430 --- /dev/null +++ b/fvwm/parse.h @@ -0,0 +1,65 @@ +/**************************************************************************** + * This module was originally based on the twm module of the same name. + * Since its use and contents have changed so dramatically, I have removed + * the original twm copyright, and inserted my own. + * + * by Rob Nation + * Copyright 1993 Robert Nation. No restrictions are placed on this code, + * as long as the copyright notice is preserved + ****************************************************************************/ + +/********************************************************************** + * + * Codes for fvwm builtins + * + **********************************************************************/ + +#ifndef _PARSE_ +#define _PARSE_ + +#define F_NOP 0 +#define F_BEEP 1 +#define F_QUIT 2 +#define F_RESTART 3 +#define F_REFRESH 4 +#define F_TITLE 5 +#define F_SCROLL 6 /* scroll the virtual desktop */ +#define F_CIRCULATE_UP 7 +#define F_CIRCULATE_DOWN 8 +#define F_TOGGLE_PAGE 9 +#define F_GOTO_PAGE 10 +#define F_WINDOWLIST 11 +#define F_MOVECURSOR 12 +#define F_FUNCTION 13 +#define F_WARP 14 +#define F_MODULE 15 +#define F_DESK 16 +#define F_CHANGE_WINDOWS_DESK 17 +#define F_EXEC 18 /* string */ +#define F_POPUP 19 /* string */ +#define F_WAIT 20 +#define F_CLOSE 21 +#define F_QUICKIE 22 + +/* Functions which require a target window */ +#define F_RESIZE 100 +#define F_RAISE 101 +#define F_LOWER 102 +#define F_DESTROY 103 +#define F_DELETE 104 +#define F_MOVE 105 +#define F_ICONIFY 106 +#define F_STICK 107 +#define F_RAISELOWER 108 +#define F_MAXIMIZE 109 +#define F_FOCUS 110 + + +/* Functions for use by modules only! */ +#define F_SEND_WINDOW_LIST 1000 + +/* Functions for internal only! */ +#define F_RAISE_IT 2000 + +#endif /* _PARSE_ */ + diff --git a/fvwm/placement.c b/fvwm/placement.c new file mode 100644 index 0000000..3d48ab2 --- /dev/null +++ b/fvwm/placement.c @@ -0,0 +1,349 @@ +/**************************************************************************** + * This module is all new + * by Rob Nation + * + * This code does smart-placement initial window placement stuff + * + * Copyright 1994 Robert Nation. No restrictions are placed on this code, + * as long as the copyright notice is preserved . No guarantees or + * warrantees of any sort whatsoever are given or implied or anything. + ****************************************************************************/ + +#include "../configure.h" + +#include +#include +#include + +#include "fvwm.h" +#include "menus.h" +#include "misc.h" +#include "parse.h" +#include "screen.h" + +void SmartPlacement(FvwmWindow *t, int width, int height, int *x, int *y) +{ + int temp_h,temp_w; + int test_x = 0,test_y = 0; + int loc_ok = False, tw,tx,ty,th; + FvwmWindow *test_window; + + temp_h = height; + temp_w = width; + + while(((test_y + temp_h) < (Scr.MyDisplayHeight))&&(!loc_ok)) + { + test_x = 0; + while(((test_x + temp_w) < (Scr.MyDisplayWidth))&&(!loc_ok)) + { + loc_ok = True; + test_window = Scr.FvwmRoot.next; + while((test_window != (FvwmWindow *)0)&&(loc_ok == True)) + { + if(test_window->Desk == Scr.CurrentDesk) + { + if(Scr.flags & StubbornPlacement) + { + if((test_window->flags & ICONIFIED)&& + (!(test_window->flags & ICON_UNMAPPED))&& + (test_window->icon_w)&& + (test_window != t)) + { + tw=test_window->icon_p_width; + th=test_window->icon_p_height+ + test_window->icon_w_height; + tx = test_window->icon_x_loc; + ty = test_window->icon_y_loc; + + if((tx<(test_x+width))&&((tx + tw) > test_x)&& + (ty<(test_y+height))&&((ty + th)>test_y)) + { + loc_ok = False; + test_x = tx + tw; + } + } + } + + if(!(test_window->flags & ICONIFIED)&&(test_window != t)) + { + tw=test_window->frame_width+2*test_window->bw; + th=test_window->frame_height+2*test_window->bw; + tx = test_window->frame_x; + ty = test_window->frame_y; + if((tx <= (test_x+width))&&((tx + tw) >= test_x)&& + (ty <= (test_y+height))&&((ty + th)>= test_y)) + { + loc_ok = False; + test_x = tx + tw; + } + } + } + test_window = test_window->next; + } + test_x +=1; + } + test_y +=1; + } + if(loc_ok == False) + { + *x = -1; + *y = -1; + return; + } + *x = test_x; + *y = test_y; +} + + +/************************************************************************** + * + * Handles initial placement and sizing of a new window + * Returns False in the event of a lost window. + * + **************************************************************************/ +Bool PlaceWindow(FvwmWindow *tmp_win, unsigned long tflag,int Desk) +{ + FvwmWindow *t; + int xl = -1,yt,DragWidth,DragHeight; + int gravx, gravy; /* gravity signs for positioning */ + extern Bool PPosOverride; + + GetGravityOffsets (tmp_win, &gravx, &gravy); + + + /* Select a desk to put the window on (in list of priority): + * 1. Sticky Windows stay on the current desk. + * 2. Windows specified with StartsOnDesk go where specified + * 3. Put it on the desk it was on before the restart. + * 4. Transients go on the same desk as their parents. + * 5. Window groups stay together (completely untested) + */ + tmp_win->Desk = Scr.CurrentDesk; + if (tflag & STICKY_FLAG) + tmp_win->Desk = Scr.CurrentDesk; + else if (tflag & STAYSONDESK_FLAG) + tmp_win->Desk = Desk; + else + { + Atom atype; + int aformat; + unsigned long nitems, bytes_remain; + unsigned char *prop; + + if((tmp_win->wmhints)&&(tmp_win->wmhints->flags & WindowGroupHint)&& + (tmp_win->wmhints->window_group != None)&& + (tmp_win->wmhints->window_group != Scr.Root)) + { + /* Try to find the group leader or another window + * in the group */ + for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) + { + if((t->w == tmp_win->wmhints->window_group)|| + ((t->wmhints)&&(t->wmhints->flags & WindowGroupHint)&& + (t->wmhints->window_group==tmp_win->wmhints->window_group))) + tmp_win->Desk = t->Desk; + } + } + if((tmp_win->flags & TRANSIENT)&&(tmp_win->transientfor!=None)&& + (tmp_win->transientfor != Scr.Root)) + { + /* Try to find the parent's desktop */ + for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) + { + if(t->w == tmp_win->transientfor) + tmp_win->Desk = t->Desk; + } + } + + if ((XGetWindowProperty(dpy, tmp_win->w, _XA_WM_DESKTOP, 0L, 1L, True, + _XA_WM_DESKTOP, &atype, &aformat, &nitems, + &bytes_remain, &prop))==Success) + { + if(prop != NULL) + { + tmp_win->Desk = *(unsigned long *)prop; + XFree(prop); + } + } + } + /* I think it would be good to switch to the selected desk + * whenever a new window pops up, except during initialization */ + if(!PPosOverride) + changeDesks(0,tmp_win->Desk); + + + /* Desk has been selected, now pick a location for the window */ + /* + * If + * o the window is a transient, or + * + * o a USPosition was requested + * + * then put the window where requested. + * + * If RandomPlacement was specified, + * then place the window in a psuedo-random location + */ + if (!(tmp_win->flags & TRANSIENT) && + !(tmp_win->hints.flags & USPosition) && + ((Scr.flags & NoPPosition)||!(tmp_win->hints.flags & PPosition)) && + !(PPosOverride) && + !((tmp_win->wmhints)&& + (tmp_win->wmhints->flags & StateHint)&& + (tmp_win->wmhints->initial_state == IconicState)) ) + { + /* Get user's window placement, unless RandomPlacement is specified */ + if(Scr.flags & RandomPlacement) + { + if(Scr.flags & SMART_PLACEMENT) + SmartPlacement(tmp_win,tmp_win->frame_width+2*tmp_win->bw, + tmp_win->frame_height+2*tmp_win->bw, + &xl,&yt); + if(xl < 0) + { + /* plase window in a random location */ + if ((Scr.randomx += Scr.TitleHeight) > Scr.MyDisplayWidth / 2) + Scr.randomx = Scr.TitleHeight; + if ((Scr.randomy += 2*Scr.TitleHeight) > Scr.MyDisplayHeight / 2) + Scr.randomy = 2 * Scr.TitleHeight; + tmp_win->attr.x = Scr.randomx - tmp_win->old_bw; + tmp_win->attr.y = Scr.randomy - tmp_win->old_bw; + } + else + { + tmp_win->attr.x = xl - tmp_win->old_bw; + tmp_win->attr.y = yt - tmp_win->old_bw; + } + /* patches 11/93 to try to keep the window on the + * screen */ + tmp_win->frame_x = tmp_win->attr.x + tmp_win->old_bw - tmp_win->bw; + tmp_win->frame_y = tmp_win->attr.y + tmp_win->old_bw - tmp_win->bw; + + if(tmp_win->frame_x + tmp_win->frame_width + + 2*tmp_win->boundary_width> Scr.MyDisplayWidth) + { + tmp_win->attr.x = Scr.MyDisplayWidth -tmp_win->attr.width + - tmp_win->old_bw +tmp_win->bw - 2*tmp_win->boundary_width; + Scr.randomx = 0; + } + if(tmp_win->frame_y + 2*tmp_win->boundary_width+tmp_win->title_height + + tmp_win->frame_height > Scr.MyDisplayHeight) + { + tmp_win->attr.y = Scr.MyDisplayHeight -tmp_win->attr.height + - tmp_win->old_bw +tmp_win->bw - tmp_win->title_height - + 2*tmp_win->boundary_width;; + Scr.randomy = 0; + } + + tmp_win->xdiff = tmp_win->attr.x - tmp_win->bw; + tmp_win->ydiff = tmp_win->attr.y - tmp_win->bw; + } + else + { + xl = -1; + yt = -1; + if(Scr.flags & SMART_PLACEMENT) + SmartPlacement(tmp_win,tmp_win->frame_width+2*tmp_win->bw, + tmp_win->frame_height+2*tmp_win->bw, + &xl,&yt); + if(xl < 0) + { + if(GrabEm(POSITION)) + { + /* Grabbed the pointer - continue */ + XGrabServer(dpy); + if(XGetGeometry(dpy, tmp_win->w, &JunkRoot, &JunkX, &JunkY, + (unsigned int *)&DragWidth, + (unsigned int *)&DragHeight, + &JunkBW, &JunkDepth) == 0) + { + free((char *)tmp_win); + XUngrabServer(dpy); + return False; + } + DragWidth += 2*tmp_win->boundary_width; + DragHeight += + tmp_win->title_height + 2*tmp_win->boundary_width; + + XMapRaised(dpy,Scr.SizeWindow); + moveLoop(tmp_win,0,0,DragWidth,DragHeight, + &xl,&yt,False,True); + XUnmapWindow(dpy,Scr.SizeWindow); + XUngrabServer(dpy); + UngrabEm(); + } + else + { + /* couldn't grab the pointer - better do something */ + XBell(dpy,Scr.screen); + xl = 0; + yt = 0; + } + } + tmp_win->attr.y = yt - tmp_win->old_bw + tmp_win->bw; + tmp_win->attr.x = xl - tmp_win->old_bw + tmp_win->bw; + tmp_win->xdiff = xl ; + tmp_win->ydiff = yt ; + } + } + else + { + /* the USPosition was specified, or the window is a transient, + * or it starts iconic so place it automatically */ + + tmp_win->xdiff = tmp_win->attr.x; + tmp_win->ydiff = tmp_win->attr.y; + /* put it where asked, mod title bar */ + /* if the gravity is towards the top, move it by the title height */ + tmp_win->attr.y -= gravy*(tmp_win->bw-tmp_win->old_bw); + tmp_win->attr.x -= gravx*(tmp_win->bw-tmp_win->old_bw); + if(gravy > 0) + tmp_win->attr.y -= 2*tmp_win->boundary_width + tmp_win->title_height; + if(gravx > 0) + tmp_win->attr.x -= 2*tmp_win->boundary_width; + } + return True; +} + + + +/************************************************************************ + * + * Procedure: + * GetGravityOffsets - map gravity to (x,y) offset signs for adding + * to x and y when window is mapped to get proper placement. + * + ************************************************************************/ +struct _gravity_offset +{ + int x, y; +}; + +void GetGravityOffsets (FvwmWindow *tmp,int *xp,int *yp) +{ + static struct _gravity_offset gravity_offsets[11] = + { + { 0, 0 }, /* ForgetGravity */ + { -1, -1 }, /* NorthWestGravity */ + { 0, -1 }, /* NorthGravity */ + { 1, -1 }, /* NorthEastGravity */ + { -1, 0 }, /* WestGravity */ + { 0, 0 }, /* CenterGravity */ + { 1, 0 }, /* EastGravity */ + { -1, 1 }, /* SouthWestGravity */ + { 0, 1 }, /* SouthGravity */ + { 1, 1 }, /* SouthEastGravity */ + { 0, 0 }, /* StaticGravity */ + }; + register int g = ((tmp->hints.flags & PWinGravity) + ? tmp->hints.win_gravity : NorthWestGravity); + + if (g < ForgetGravity || g > StaticGravity) + *xp = *yp = 0; + else + { + *xp = (int)gravity_offsets[g].x; + *yp = (int)gravity_offsets[g].y; + } + return; +} diff --git a/fvwm/resize.c b/fvwm/resize.c new file mode 100644 index 0000000..7089025 --- /dev/null +++ b/fvwm/resize.c @@ -0,0 +1,662 @@ +/**************************************************************************** + * This module is based on Twm, but has been siginificantly modified + * by Rob Nation + ****************************************************************************/ +/*****************************************************************************/ +/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ +/** Salt Lake City, Utah **/ +/** Portions Copyright 1989 by the Massachusetts Institute of Technology **/ +/** Cambridge, Massachusetts **/ +/** **/ +/** All Rights Reserved **/ +/** **/ +/** Permission to use, copy, modify, and distribute this software and **/ +/** its documentation for any purpose and without fee is hereby **/ +/** granted, provided that the above copyright notice appear in all **/ +/** copies and that both that copyright notice and this permis- **/ +/** sion notice appear in supporting documentation, and that the **/ +/** names of Evans & Sutherland and M.I.T. not be used in advertising **/ +/** in publicity pertaining to distribution of the software without **/ +/** specific, written prior permission. **/ +/** **/ +/** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/ +/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/ +/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/ +/** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/ +/** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ +/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ +/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ +/** OR PERFORMANCE OF THIS SOFTWARE. **/ +/*****************************************************************************/ + + +/*********************************************************************** + * + * window resizing borrowed from the "wm" window manager + * + ***********************************************************************/ +#include "../configure.h" + +#include +#include "fvwm.h" +#include "misc.h" +#include "screen.h" +#include "parse.h" + +static int dragx; /* all these variables are used */ +static int dragy; /* in resize operations */ +static int dragWidth; +static int dragHeight; + +static int origx; +static int origy; +static int origWidth; +static int origHeight; + +static int ymotion, xmotion; +static int last_width,last_height; +extern int menuFromFrameOrWindowOrTitlebar; +extern Window PressedW; + +/**************************************************************************** + * + * Starts a window resize operation + * + ****************************************************************************/ +void resize_window(Window w,FvwmWindow *tmp_win, int val1, int val2, int val1_unit, int val2_unit) +{ + Bool finished = FALSE, done = FALSE; + int x,y,delta_x,delta_y; + Window ResizeWindow; + extern int Stashed_X, Stashed_Y; + Bool flags; +#ifndef NO_PAGER + extern Bool pagerOn; +#endif + + if((w == None)||(tmp_win == NULL)) + return; + + /* Already checked this in functions.c, but its here too incase + * there's a resize on initial placement. */ + if(check_allowed_function2(F_RESIZE,tmp_win) == 0) + { + XBell(dpy, Scr.screen); + return; + } + /* can't resize icons */ + if(tmp_win->flags & ICONIFIED) + return; + + ResizeWindow = tmp_win->frame; + + if((val1 != 0)&&(val2 != 0)) + { + int width,height; + + dragWidth = val1*val1_unit/100; + dragHeight = val2*val2_unit/100; + + ConstrainSize (tmp_win, &dragWidth, &dragHeight); + SetupFrame (tmp_win, tmp_win->frame_x, + tmp_win->frame_y ,dragWidth, dragHeight,FALSE); + + ResizeWindow = None; +#ifndef NO_PAGER + RedrawPager(); +#endif + return; + } + + InstallRootColormap(); + if (menuFromFrameOrWindowOrTitlebar) + { + /* warp the pointer to the cursor position from before menu appeared*/ + XWarpPointer(dpy, None, Scr.Root, 0, 0, 0, 0, Stashed_X,Stashed_Y); + XFlush(dpy); + } + + if(!GrabEm(MOVE)) + { + XBell(dpy,Scr.screen); + return; + } + + if((!(Scr.flags & OpaqueResize))|| + ((Scr.flags & OpaqueResize)&&(!(tmp_win->flags & MAPPED)))) + XGrabServer(dpy); + + + /* handle problems with edge-wrapping while resizing */ + flags = Scr.flags; + Scr.flags &= ~(EdgeWrapX|EdgeWrapY); + +#ifndef NO_PAGER + pagerOn = False; +#endif + XGetGeometry(dpy, (Drawable) ResizeWindow, &JunkRoot, + &dragx, &dragy, (unsigned int *)&dragWidth, + (unsigned int *)&dragHeight, &JunkBW,&JunkDepth); + + dragx += tmp_win->bw; + dragy += tmp_win->bw; + origx = dragx; + origy = dragy; + origWidth = dragWidth; + origHeight = dragHeight; + ymotion=xmotion=0; + + /* pop up a resize dimensions window */ + XMapRaised(dpy, Scr.SizeWindow); + last_width = 0; + last_height = 0; + DisplaySize(tmp_win, origWidth, origHeight,True); + + /* Get the current position to determine which border to resize */ + if((PressedW != Scr.Root)&&(PressedW != None)) + { + if(PressedW == tmp_win->sides[0]) /* top */ + ymotion = 1; + if(PressedW == tmp_win->sides[1]) /* right */ + xmotion = -1; + if(PressedW == tmp_win->sides[2]) /* bottom */ + ymotion = -1; + if(PressedW == tmp_win->sides[3]) /* left */ + xmotion = 1; + if(PressedW == tmp_win->corners[0]) /* upper-left */ + { + ymotion = 1; + xmotion = 1; + } + if(PressedW == tmp_win->corners[1]) /* upper-right */ + { + xmotion = -1; + ymotion = 1; + } + if(PressedW == tmp_win->corners[2]) /* lower right */ + { + ymotion = -1; + xmotion = 1; + } + if(PressedW == tmp_win->corners[3]) /* lower left */ + { + ymotion = -1; + xmotion = -1; + } + } + /* draw the rubber-band window */ + if((!(Scr.flags & OpaqueResize))|| + ((Scr.flags & OpaqueResize)&&(!(tmp_win->flags & MAPPED)))) + MoveOutline (Scr.Root, dragx - tmp_win->bw, dragy - tmp_win->bw, dragWidth + 2 * tmp_win->bw, + dragHeight + 2 * tmp_win->bw); + + /* loop to resize */ + while(!finished) + { + XMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask | KeyPressMask | + ButtonMotionMask | PointerMotionMask | ExposureMask, &Event); + StashEventTime(&Event); + + if (Event.type == MotionNotify) + /* discard any extra motion events before a release */ + while(XCheckMaskEvent(dpy, ButtonMotionMask | ButtonReleaseMask | + PointerMotionMask,&Event)) + { + StashEventTime(&Event); + if (Event.type == ButtonRelease) break; + } + + done = FALSE; + /* Handle a limited number of key press events to allow mouseless + * operation */ + if(Event.type == KeyPress) + Keyboard_shortcuts(&Event,ButtonRelease); + switch(Event.type) + { + case ButtonPress: + XAllowEvents(dpy,ReplayPointer,CurrentTime); + case KeyPress: + done = TRUE; + break; + + case ButtonRelease: + finished = TRUE; + done = TRUE; + break; + + case MotionNotify: + x = Event.xmotion.x_root; + y = Event.xmotion.y_root; + /* need to move the viewport */ + HandlePaging(Scr.EdgeScrollX,Scr.EdgeScrollY,&x,&y, + &delta_x,&delta_y,False); + origx -= delta_x; + origy -= delta_y; + dragx -= delta_x; + dragy -= delta_y; + + DoResize(x, y, tmp_win); + done = TRUE; + default: + break; + } + if(!done) + { + if((!(Scr.flags & OpaqueResize))|| + ((Scr.flags & OpaqueResize)&&(!(tmp_win->flags & MAPPED)))) + MoveOutline(Scr.Root,0,0,0,0); + + DispatchEvent(); + + if((!(Scr.flags & OpaqueResize))|| + ((Scr.flags & OpaqueResize)&&(!(tmp_win->flags & MAPPED)))) + MoveOutline(Scr.Root, dragx - tmp_win->bw, dragy - tmp_win->bw, + dragWidth + 2 * tmp_win->bw, dragHeight + 2 * tmp_win->bw); + + } + } + + /* erase the rubber-band */ + if((!(Scr.flags & OpaqueResize))|| + ((Scr.flags & OpaqueResize)&&(!(tmp_win->flags & MAPPED)))) + MoveOutline(Scr.Root, 0, 0, 0, 0); + + /* pop down the size window */ + XUnmapWindow(dpy, Scr.SizeWindow); + +#ifndef NO_PAGER + pagerOn = True; +#endif + ConstrainSize (tmp_win, &dragWidth, &dragHeight); + SetupFrame (tmp_win, dragx - tmp_win->bw, + dragy - tmp_win->bw, dragWidth, dragHeight,FALSE); + + UninstallRootColormap(); + ResizeWindow = None; + XUngrabServer(dpy); + UngrabEm(); +#ifndef NO_PAGER + RedrawPager(); +#endif + Scr.flags |= flags & (EdgeWrapX|EdgeWrapY); + return; +} + + + +/*********************************************************************** + * + * Procedure: + * DoResize - move the rubberband around. This is called for + * each motion event when we are resizing + * + * Inputs: + * x_root - the X corrdinate in the root window + * y_root - the Y corrdinate in the root window + * tmp_win - the current fvwm window + * + ************************************************************************/ +void DoResize(int x_root, int y_root, FvwmWindow *tmp_win) +{ + int action=0; +#ifndef NO_PAGER + unsigned int width,height; + int ww,wh; + int wx,wy; + int MaxH,MaxW; + static int last_w = -10000, last_h = -10000; +#endif + + if ((y_root <= origy)||((ymotion == 1)&&(y_root < origy+origHeight-1))) + { + dragy = y_root; + dragHeight = origy + origHeight - y_root; + action = 1; + ymotion = 1; + } + else if ((y_root >= origy + origHeight - 1)|| + ((ymotion == -1)&&(y_root > origy))) + { + dragy = origy; + dragHeight = 1 + y_root - dragy; + action = 1; + ymotion = -1; + } + + if ((x_root <= origx)|| + ((xmotion == 1)&&(x_root < origx + origWidth - 1))) + { + dragx = x_root; + dragWidth = origx + origWidth - x_root; + action = 1; + xmotion = 1; + } + if ((x_root >= origx + origWidth - 1)|| + ((xmotion == -1)&&(x_root > origx))) + { + dragx = origx; + dragWidth = 1 + x_root - origx; + action = 1; + xmotion = -1; + } + + if (action) + { + ConstrainSize (tmp_win, &dragWidth, &dragHeight); + if (xmotion == 1) + dragx = origx + origWidth - dragWidth; + if (ymotion == 1) + dragy = origy + origHeight - dragHeight; + +#ifndef NO_PAGER + /* update size of the pager_view window */ + if((Scr.FvwmPager != NULL)&& + (dragx < Scr.FvwmPager->frame_x + Scr.FvwmPager->frame_width)&& + (dragx+dragWidth > Scr.FvwmPager->frame_x)&& + (dragy < Scr.FvwmPager->frame_y + Scr.FvwmPager->frame_height)&& + (dragy+dragHeight > Scr.FvwmPager->frame_y)&& + ((!(Scr.flags & OpaqueResize))|| + ((Scr.flags & OpaqueResize)&&(!(tmp_win->flags & MAPPED))))) + MoveOutline(Scr.Root,0,0,0,0); + if(Scr.FvwmPager) + { + width = Scr.FvwmPager->frame_width - 2*Scr.FvwmPager->boundary_width; + height = Scr.FvwmPager->frame_height - Scr.FvwmPager->title_height + - 2*Scr.FvwmPager->boundary_width; + + MaxW = Scr.VxMax + Scr.MyDisplayWidth; + MaxH = Scr.VyMax + Scr.MyDisplayHeight; + + if(!(tmp_win->flags & STICKY)&& + (!(tmp_win->flags & ICONIFIED)||(!(Scr.flags & SuppressIcons)))&& + (!(tmp_win->flags & ICONIFIED)||(!(Scr.flags & StickyIcons)))) + { + /* show the actual window */ + wx = (dragx + Scr.Vx)*(int)width/MaxW; + wy = (dragy + Scr.Vy)*(int)height/MaxH; + ww = dragWidth*(int)width/MaxW; + wh = dragHeight*(int)height/MaxH; + + if((last_w - ww >= 2)||(last_w - ww <= -2)|| + (last_h - wh >= 2)||(last_h - wh <= -2)) + { + if(ww<2)ww=2; + if(wh<2)wh=2; + XMoveResizeWindow(dpy, tmp_win->pager_view, wx, wy, ww, wh); + last_h = wh; + last_w = ww; + } + } + } +#endif + + if((!(Scr.flags & OpaqueResize))|| + ((Scr.flags & OpaqueResize)&&(!(tmp_win->flags & MAPPED)))) + { + MoveOutline(Scr.Root, dragx - tmp_win->bw,dragy - tmp_win->bw, + dragWidth + 2 * tmp_win->bw, dragHeight + 2 * tmp_win->bw); + } + else + { + SetupFrame (tmp_win, dragx - tmp_win->bw, + dragy - tmp_win->bw, dragWidth, dragHeight,FALSE); + } + } + DisplaySize(tmp_win, dragWidth, dragHeight,False); +} + + + +/*********************************************************************** + * + * Procedure: + * DisplaySize - display the size in the dimensions window + * + * Inputs: + * tmp_win - the current fvwm window + * width - the width of the rubber band + * height - the height of the rubber band + * + ***********************************************************************/ +void DisplaySize(FvwmWindow *tmp_win, int width, int height,Bool Init) +{ + char str[100]; + int dwidth,dheight,offset; + + if (last_width == width && last_height == height) + return; + + last_width = width; + last_height = height; + + dheight = height - tmp_win->title_height - 2*tmp_win->boundary_width; + dwidth = width - 2*tmp_win->boundary_width; + + dwidth -= tmp_win->hints.base_width; + dheight -= tmp_win->hints.base_height; + dwidth /= tmp_win->hints.width_inc; + dheight /= tmp_win->hints.height_inc; + + (void) sprintf (str, " %4d x %-4d ", dwidth, dheight); + offset = (Scr.SizeStringWidth + SIZE_HINDENT*2 + - XTextWidth(Scr.StdFont.font,str,strlen(str)))/2; + if(Init) + { + XClearWindow(dpy,Scr.SizeWindow); + if(Scr.d_depth >= 2) + RelieveWindow(tmp_win, + Scr.SizeWindow,0,0,Scr.SizeStringWidth+ SIZE_HINDENT*2, + Scr.StdFont.height + SIZE_VINDENT*2, + Scr.StdReliefGC,Scr.StdShadowGC,FULL_HILITE); + } + else + { + XClearArea(dpy,Scr.SizeWindow,SIZE_HINDENT,SIZE_VINDENT,Scr.SizeStringWidth, + Scr.StdFont.height,False); + } + + XDrawString (dpy, Scr.SizeWindow, Scr.NormalGC, + offset, Scr.StdFont.font->ascent + SIZE_VINDENT, str, 13); + +} + +/*********************************************************************** + * + * Procedure: + * ConstrainSize - adjust the given width and height to account for the + * constraints imposed by size hints + * + * The general algorithm, especially the aspect ratio stuff, is + * borrowed from uwm's CheckConsistency routine. + * + ***********************************************************************/ + +void ConstrainSize (FvwmWindow *tmp_win, int *widthp, int *heightp) +{ +#define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) ) +#define _min(a,b) (((a) < (b)) ? (a) : (b)) + int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta; + int baseWidth, baseHeight; + int dwidth = *widthp, dheight = *heightp; + + dwidth -= 2 *tmp_win->boundary_width; + dheight -= (tmp_win->title_height + 2*tmp_win->boundary_width); + + minWidth = tmp_win->hints.min_width; + minHeight = tmp_win->hints.min_height; + + baseWidth = tmp_win->hints.base_width; + baseHeight = tmp_win->hints.base_height; + + maxWidth = tmp_win->hints.max_width; + maxHeight = tmp_win->hints.max_height; + +/* maxWidth = Scr.VxMax + Scr.MyDisplayWidth; + maxHeight = Scr.VyMax + Scr.MyDisplayHeight;*/ + + xinc = tmp_win->hints.width_inc; + yinc = tmp_win->hints.height_inc; + + /* + * First, clamp to min and max values + */ + if (dwidth < minWidth) dwidth = minWidth; + if (dheight < minHeight) dheight = minHeight; + + if (dwidth > maxWidth) dwidth = maxWidth; + if (dheight > maxHeight) dheight = maxHeight; + + + /* + * Second, fit to base + N * inc + */ + dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth; + dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight; + + + /* + * Third, adjust for aspect ratio + */ +#define maxAspectX tmp_win->hints.max_aspect.x +#define maxAspectY tmp_win->hints.max_aspect.y +#define minAspectX tmp_win->hints.min_aspect.x +#define minAspectY tmp_win->hints.min_aspect.y + /* + * The math looks like this: + * + * minAspectX dwidth maxAspectX + * ---------- <= ------- <= ---------- + * minAspectY dheight maxAspectY + * + * If that is multiplied out, then the width and height are + * invalid in the following situations: + * + * minAspectX * dheight > minAspectY * dwidth + * maxAspectX * dheight < maxAspectY * dwidth + * + */ + + if (tmp_win->hints.flags & PAspect) + { + if (minAspectX * dheight > minAspectY * dwidth) + { + delta = makemult(minAspectX * dheight / minAspectY - dwidth, + xinc); + if (dwidth + delta <= maxWidth) + dwidth += delta; + else + { + delta = makemult(dheight - dwidth*minAspectY/minAspectX, + yinc); + if (dheight - delta >= minHeight) dheight -= delta; + } + } + + if (maxAspectX * dheight < maxAspectY * dwidth) + { + delta = makemult(dwidth * maxAspectY / maxAspectX - dheight, + yinc); + if (dheight + delta <= maxHeight) + dheight += delta; + else + { + delta = makemult(dwidth - maxAspectX*dheight/maxAspectY, + xinc); + if (dwidth - delta >= minWidth) dwidth -= delta; + } + } + } + + + /* + * Fourth, account for border width and title height + */ + *widthp = dwidth + 2*tmp_win->boundary_width; + *heightp = dheight + tmp_win->title_height + 2*tmp_win->boundary_width; + return; +} + + +/*********************************************************************** + * + * Procedure: + * MoveOutline - move a window outline + * + * Inputs: + * root - the window we are outlining + * x - upper left x coordinate + * y - upper left y coordinate + * width - the width of the rectangle + * height - the height of the rectangle + * + ***********************************************************************/ +void MoveOutline(Window root, int x, int y, int width, int height) +{ + static int lastx = 0; + static int lasty = 0; + static int lastWidth = 0; + static int lastHeight = 0; + XRectangle rects[5]; + + if (x == lastx && y == lasty && width == lastWidth && height == lastHeight) + return; + + /* undraw the old one, if any */ + if (lastWidth || lastHeight) + { + rects[0].x = lastx; + rects[0].y = lasty; + rects[0].width = lastWidth; + rects[0].height = lastHeight; + rects[1].x = lastx+1; + rects[1].y = lasty+1; + rects[1].width = lastWidth-2; + rects[1].height = lastHeight-2; + rects[2].x = lastx+2; + rects[2].y = lasty+2; + rects[2].width = lastWidth-4; + rects[2].height = lastHeight-4; + rects[3].x = lastx+3; + rects[3].y = lasty+3 + (lastHeight-6)/3; + rects[3].width = lastWidth-6; + rects[3].height = (lastHeight-6)/3; + rects[4].x = lastx+3 + (lastWidth-6)/3; + rects[4].y = lasty+3; + rects[4].width = (lastWidth-6)/3; + rects[4].height = (lastHeight-6); + XDrawRectangles(dpy,Scr.Root,Scr.DrawGC,rects,5); + } + + lastx = x; + lasty = y; + lastWidth = width; + lastHeight = height; + + /* draw the new one, if any */ + if (lastWidth || lastHeight) + { + rects[0].x = lastx; + rects[0].y = lasty; + rects[0].width = lastWidth; + rects[0].height = lastHeight; + rects[1].x = lastx+1; + rects[1].y = lasty+1; + rects[1].width = lastWidth-2; + rects[1].height = lastHeight-2; + rects[2].x = lastx+2; + rects[2].y = lasty+2; + rects[2].width = lastWidth-4; + rects[2].height = lastHeight-4; + rects[3].x = lastx+3; + rects[3].y = lasty+3 + (lastHeight-6)/3; + rects[3].width = lastWidth-6; + rects[3].height = (lastHeight-6)/3; + rects[4].x = lastx+3 + (lastWidth-6)/3; + rects[4].y = lasty+3; + rects[4].width = (lastWidth-6)/3; + rects[4].height = (lastHeight-6); + XDrawRectangles(dpy,Scr.Root,Scr.DrawGC,rects,5); + } +} + + diff --git a/fvwm/screen.h b/fvwm/screen.h new file mode 100644 index 0000000..31e1b92 --- /dev/null +++ b/fvwm/screen.h @@ -0,0 +1,247 @@ +/**************************************************************************** + * This module is based on Twm, but has been siginificantly modified + * by Rob Nation + ****************************************************************************/ +/* + * Copyright 1989 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/*********************************************************************** + * + * fvwm per-screen data include file + * + ***********************************************************************/ + +#ifndef _SCREEN_ +#define _SCREEN_ + +#include +#include +#include +#include "misc.h" +#include "menus.h" + +#define SIZE_HINDENT 5 +#define SIZE_VINDENT 3 +#define MAX_WINDOW_WIDTH 32767 +#define MAX_WINDOW_HEIGHT 32767 + + +/* Cursor types */ +#define POSITION 0 /* upper Left corner cursor */ +#define TITLE_CURSOR 1 /* title-bar cursor */ +#define DEFAULT 2 /* cursor for apps to inherit */ +#define SYS 3 /* sys-menu and iconify boxes cursor */ +#define MOVE 4 /* resize cursor */ +#if defined(__alpha) +#ifdef WAIT +#undef WAIT +#endif /*WAIT */ +#endif /*alpha */ +#define WAIT 5 /* wait a while cursor */ +#define MENU 6 /* menu cursor */ +#define SELECT 7 /* dot cursor for f.move, etc. from menus */ +#define DESTROY 8 /* skull and cross bones, f.destroy */ +#define TOP 9 +#define RIGHT 10 +#define BOTTOM 11 +#define LEFT 12 +#define TOP_LEFT 13 +#define TOP_RIGHT 14 +#define BOTTOM_LEFT 15 +#define BOTTOM_RIGHT 16 +#define MAX_CURSORS 18 + +/* Maximum number of icon boxes that are allowed */ +#define MAX_BOXES 4 + +#ifndef NON_VIRTUAL +typedef struct +{ + Window win; + int isMapped; +} PanFrame; +#endif + +typedef struct ScreenInfo +{ + + unsigned long screen; + int d_depth; /* copy of DefaultDepth(dpy, screen) */ + int NumberOfScreens; /* number of screens on display */ + int MyDisplayWidth; /* my copy of DisplayWidth(dpy, screen) */ + int MyDisplayHeight; /* my copy of DisplayHeight(dpy, screen) */ + + FvwmWindow FvwmRoot; /* the head of the fvwm window list */ + Window Root; /* the root window */ + Window SizeWindow; /* the resize dimensions window */ + Window NoFocusWin; /* Window which will own focus when no other + * windows have it */ +#ifndef NON_VIRTUAL + PanFrame PanFrameTop,PanFrameLeft,PanFrameRight,PanFrameBottom; + int usePanFrames; /* toggle to disable them */ +#endif + + Pixmap gray_bitmap; /*dark gray pattern for shaded out menu items*/ + Pixmap gray_pixmap; /* dark gray pattern for inactive borders */ + Pixmap light_gray_pixmap; /* light gray pattern for inactive borders */ + Pixmap sticky_gray_pixmap; /* light gray pattern for sticky borders */ + + MouseButton *MouseButtonRoot; + FuncKey FuncKeyRoot; + + int root_pushes; /* current push level to install root + colormap windows */ + FvwmWindow *pushed_window; /* saved window to install when pushes drops + to zero */ +#ifndef NO_PAGER + FvwmWindow *FvwmPager; + Window Pager_w; + Window CPagerWin; +#endif + Cursor FvwmCursors[MAX_CURSORS]; + + name_list *TheList; /* list of window names with attributes */ + char *DefaultIcon; /* Icon to use when no other icons are found */ + + ColorPair MenuColors; + ColorPair MenuStippleColors; + ColorPair MenuRelief; + + ColorPair StdColors; /* standard fore/back colors */ + ColorPair StickyColors; /* sticky fore/back colors */ + ColorPair StickyRelief; /* sticky hilight colors */ + ColorPair HiColors; /* standard fore/back colors */ + ColorPair StdRelief; + ColorPair HiRelief; + MyFont StdFont; /* font structure */ + MyFont WindowFont; /* font structure for window titles */ +#ifndef NO_PAGER + MyFont PagerFont; /* font struct for window labels in pager (optional)*/ +#endif + MyFont IconFont; /* for icon labels */ + + GC NormalGC; /* normal GC for menus, pager, resize window */ + GC StippleGC; /* normal GC for menus, pager, resize window */ + GC DrawGC; /* GC to draw lines for move and resize */ + GC HiReliefGC; /* GC for highlighted window relief */ + GC HiShadowGC; /* GC for highlighted window shadow */ + GC MenuGC; + GC MenuStippleGC; + GC MenuReliefGC; + GC MenuShadowGC; + GC StdReliefGC; /* GC for unselected window relief */ + GC StdShadowGC; /* GC for unselected window shadow */ + GC ScratchGC1; + GC ScratchGC2; + + GC StickyReliefGC; /* GC for unselected sticky window relief */ + GC StickyShadowGC; /* GC for unselected sticky window shadow */ + GC FontGC; /* GC for non-standard fonts */ + + int SizeStringWidth; /* minimum width of size window */ + int CornerWidth; /* corner width for decoratedwindows */ + int BoundaryWidth; /* frame width for decorated windows */ + int NoBoundaryWidth; /* frame width for decorated windows */ + int TitleHeight; /* height of the title bar window */ + FvwmWindow *Hilite; /* the fvwm window that is highlighted + * except for networking delays, this is the + * window which REALLY has the focus */ + FvwmWindow *Focus; /* Last window which Fvwm gave the focus to + * NOT the window that really has the focus */ + FvwmWindow *Ungrabbed; + FvwmWindow *PreviousFocus; /* Window which had focus before fvwm stole it + * to do moves/menus/etc. */ + int EntryHeight; /* menu entry height */ + int EdgeScrollX; /* #pixels to scroll on screen edge */ + int EdgeScrollY; /* #pixels to scroll on screen edge */ + unsigned char buttons2grab; /* buttons to grab in click to focus mode */ + unsigned long flags; + int IconBoxes[MAX_BOXES][4]; + int NumBoxes; + int randomx; /* values used for randomPlacement */ + int randomy; + unsigned VScale; /* Panner scale factor */ + FvwmWindow *LastWindowRaised; /* Last window which was raised. Used for raise + * lower func. */ + int VxMax; /* Max location for top left of virt desk*/ + int VyMax; + int Vx; /* Current loc for top left of virt desk */ + int Vy; + + int nr_left_buttons; /* number of left-side title-bar buttons */ + int nr_right_buttons; /* number of right-side title-bar buttons */ + + int left_button_styles[2][5]; + int right_button_styles[2][5]; + + int ClickTime; /*Max button-click delay for Function built-in*/ + int AutoRaiseDelay; /* Delay between setting focus and raising win*/ + int ScrollResistance; /* resistance to scrolling in desktop */ + int MoveResistance; /* res to moving windows over viewport edge */ + int OpaqueSize; + int CurrentDesk; /* The current desktop number */ + MenuRoot *InitFunction; + MenuRoot *RestartFunction; + + /* new style */ + Boolean use_new_style[10]; /* if true then use custom shapes */ + int left_num_coords[5]; + int left_x_coords[5][20]; + int left_y_coords[5][20]; + int left_line_style[5][20]; + int right_num_coords[5]; + int right_x_coords[5][20]; + int right_y_coords[5][20]; + int right_line_style[5][20]; + +} ScreenInfo; + +extern ScreenInfo Scr; + +/* for the flags value - these used to be seperate Bool's */ +#define ClickToFocus (1) /* Focus follows mouse, or click to focus?*/ +#define DecorateTransients (2) /* decorate transient windows? */ +#define DontMoveOff (4) /* make sure all windows stay on desktop*/ +#define RandomPlacement (8) /* place windows in random locations? */ +#define SuppressIcons (16) /* prevent generation of icon windows */ +#define StickyIcons (32) /* Icons always sticky? */ +#define EdgeWrapX (64) /* Should EdgeScroll wrap around? */ +#define EdgeWrapY (128) +#define CenterOnCirculate (256) /* center window when circulating? */ +#define MWMBorders (512) +#define MWMMenus (1024) +#define MWMButtons (2048) +#define MWMDecorHints (4096) +#define NoPPosition (8192) +#define SMART_PLACEMENT (16384) +#define CirculateSkipIcons (32768) +#define StubbornIcons (65536) +#define StubbornPlacement (131072) +#define StubbornIconPlacement (262144) +#define OpaqueResize (524288) +#define MWMFunctionHints (1048576) +#define MWMHintOverride (2097152) +#define BackingStore (4194304) +#define AppsBackingStore (8388608) +#define SaveUnders (16777216) +#define Lenience (33554432) +#define SloppyFocus (67108864) +#endif /* _SCREEN_ */ diff --git a/fvwm/style.c b/fvwm/style.c new file mode 100644 index 0000000..798d8b1 --- /dev/null +++ b/fvwm/style.c @@ -0,0 +1,399 @@ +/**************************************************************************** + * This module is all original code + * by Rob Nation + * Copyright 1993, Robert Nation + * You may use this code for any purpose, as long as the original + * copyright remains in the source code and all documentation + ****************************************************************************/ + +/*********************************************************************** + * + * code for parsing the fvwm style command + * + ***********************************************************************/ +#include "../configure.h" + +#include +#include +#include +#include +#include + +#include "fvwm.h" +#include "menus.h" +#include "misc.h" +#include "parse.h" +#include "screen.h" +#include "../version.h" + +void ParseStyle(char *text, FILE *fd, char **list, int *junk) +{ + extern char *orig_tline; + char *name, *line; + char *restofline,*tmp; + char *icon_name = NULL; + char *forecolor = NULL; + char *backcolor = NULL; + unsigned long off_buttons=0; + unsigned long on_buttons=0; + int butt; + + int len,desknumber = 0,bw=0, nobw = 0; + unsigned long off_flags = 0; + unsigned long on_flags = 0; + + name = stripcpy2(text,FALSE,TRUE); + /* in case there was no argument! */ + if(name == NULL) + return; + + restofline = stripcpy3(text,FALSE); + line = restofline; + + if(restofline == NULL)return; + while((*restofline != 0)&&(*restofline != '\n')) + { + while(isspace(*restofline))restofline++; + if(mystrncasecmp(restofline,"ICON",4)==0) + { + restofline +=4; + while(isspace(*restofline))restofline++; + tmp = restofline; + len = 0; + while((tmp != NULL)&&(*tmp != 0)&&(*tmp != ',')&&(*tmp != '\n')) + { + tmp++; + len++; + } + if(len > 0) + { + icon_name = safemalloc(len+1); + strncpy(icon_name,restofline,len); + icon_name[len] = 0; + off_flags |= ICON_FLAG; + on_flags |= SUPPRESSICON_FLAG; + } + else + on_flags |= SUPPRESSICON_FLAG; + restofline = tmp; + } + if(mystrncasecmp(restofline,"COLOR",5)==0) + { + restofline +=5; + while(isspace(*restofline))restofline++; + tmp = restofline; + len = 0; + while((tmp != NULL)&&(*tmp != 0)&&(*tmp != ',')&& + (*tmp != '\n')&&(*tmp != '/')&&(!isspace(*tmp))) + { + tmp++; + len++; + } + if(len > 0) + { + forecolor = safemalloc(len+1); + strncpy(forecolor,restofline,len); + forecolor[len] = 0; + off_flags |= FORE_COLOR_FLAG; + } + + while(isspace(*tmp))tmp++; + if(*tmp == '/') + { + tmp++; + while(isspace(*tmp))tmp++; + restofline = tmp; + len = 0; + while((tmp != NULL)&&(*tmp != 0)&&(*tmp != ',')&& + (*tmp != '\n')&&(*tmp != '/')&&(!isspace(*tmp))) + { + tmp++; + len++; + } + if(len > 0) + { + backcolor = safemalloc(len+1); + strncpy(backcolor,restofline,len); + backcolor[len] = 0; + off_flags |= BACK_COLOR_FLAG; + } + } + restofline = tmp; + } + if(mystrncasecmp(restofline,"FORECOLOR",9)==0) + { + restofline +=9; + while(isspace(*restofline))restofline++; + tmp = restofline; + len = 0; + while((tmp != NULL)&&(*tmp != 0)&&(*tmp != ',')&& + (*tmp != '\n')&&(*tmp != '/')&&(!isspace(*tmp))) + { + tmp++; + len++; + } + if(len > 0) + { + forecolor = safemalloc(len+1); + strncpy(forecolor,restofline,len); + forecolor[len] = 0; + off_flags |= FORE_COLOR_FLAG; + } + restofline = tmp; + } + + if(mystrncasecmp(restofline,"BACKCOLOR",9)==0) + { + restofline +=9; + while(isspace(*restofline))restofline++; + tmp = restofline; + len = 0; + while((tmp != NULL)&&(*tmp != 0)&&(*tmp != ',')&& + (*tmp != '\n')&&(*tmp != '/')&&(!isspace(*tmp))) + { + tmp++; + len++; + } + if(len > 0) + { + backcolor = safemalloc(len+1); + strncpy(backcolor,restofline,len); + backcolor[len] = 0; + off_flags |= BACK_COLOR_FLAG; + } + restofline = tmp; + } + else if(mystrncasecmp(restofline,"NoIconTitle",11)==0) + { + off_flags |= NOICON_TITLE_FLAG; + restofline +=11; + } + else if(mystrncasecmp(restofline,"IconTitle",9)==0) + { + on_flags |= NOICON_TITLE_FLAG; + restofline +=9; + } + else if(mystrncasecmp(restofline,"NOICON",6)==0) + { + restofline +=6; + off_flags |= SUPPRESSICON_FLAG; + } + else if(mystrncasecmp(restofline,"NOTITLE",7)==0) + { + restofline +=7; + off_flags |= NOTITLE_FLAG; + } + else if(mystrncasecmp(restofline,"TITLE",5)==0) + { + restofline +=5; + on_flags |= NOTITLE_FLAG; + } + else if(mystrncasecmp(restofline,"NOHANDLES",9)==0) + { + restofline +=9; + off_flags |= NOBORDER_FLAG; + } + else if(mystrncasecmp(restofline,"HANDLES",7)==0) + { + restofline +=7; + on_flags |= NOBORDER_FLAG; + } + else if (mystrncasecmp(restofline,"NOBUTTON",8)==0) + { + restofline +=8; + + sscanf(restofline,"%d",&butt); + while(isspace(*restofline))restofline++; + while((!isspace(*restofline))&&(*restofline!= 0)&& + (*restofline != ',')&&(*restofline != '\n')) + restofline++; + while(isspace(*restofline))restofline++; + + off_buttons |= (1<<(butt-1)); + } + else if (mystrncasecmp(restofline,"BUTTON",6)==0) + { + restofline +=6; + + sscanf(restofline,"%d",&butt); + while(isspace(*restofline))restofline++; + while((!isspace(*restofline))&&(*restofline!= 0)&& + (*restofline != ',')&&(*restofline != '\n')) + restofline++; + while(isspace(*restofline))restofline++; + + on_buttons |= (1<<(butt-1)); + } + else if(mystrncasecmp(restofline,"WindowListSkip",14)==0) + { + restofline +=14; + off_flags |= LISTSKIP_FLAG; + } + else if(mystrncasecmp(restofline,"WindowListHit",13)==0) + { + restofline +=13; + on_flags |= LISTSKIP_FLAG; + } + else if(mystrncasecmp(restofline,"CirculateSkip",13)==0) + { + restofline +=13; + off_flags |= CIRCULATESKIP_FLAG; + } + else if(mystrncasecmp(restofline,"CirculateHit",12)==0) + { + restofline +=12; + on_flags |= CIRCULATESKIP_FLAG; + } + else if(mystrncasecmp(restofline,"StartIconic",11)==0) + { + restofline +=11; + off_flags |= START_ICONIC_FLAG; + } + else if(mystrncasecmp(restofline,"StartNormal",11)==0) + { + restofline +=11; + on_flags |= START_ICONIC_FLAG; + } + else if(mystrncasecmp(restofline,"StaysOnTop",10)==0) + { + restofline +=10; + off_flags |= STAYSONTOP_FLAG; + } + else if(mystrncasecmp(restofline,"StaysPut",8)==0) + { + restofline +=8; + on_flags |= STAYSONTOP_FLAG; + } + else if(mystrncasecmp(restofline,"Sticky",6)==0) + { + off_flags |= STICKY_FLAG; + restofline +=6; + } + else if(mystrncasecmp(restofline,"Slippery",8)==0) + { + on_flags |= STICKY_FLAG; + restofline +=8; + } + else if(mystrncasecmp(restofline,"BorderWidth",11)==0) + { + restofline +=11; + off_flags |= BW_FLAG; + sscanf(restofline,"%d",&bw); + while(isspace(*restofline))restofline++; + while((!isspace(*restofline))&&(*restofline!= 0)&& + (*restofline != ',')&&(*restofline != '\n')) + restofline++; + while(isspace(*restofline))restofline++; + } + else if(mystrncasecmp(restofline,"HandleWidth",11)==0) + { + restofline +=11; + off_flags |= NOBW_FLAG; + sscanf(restofline,"%d",&nobw); + while(isspace(*restofline))restofline++; + while((!isspace(*restofline))&&(*restofline!= 0)&& + (*restofline != ',')&&(*restofline != '\n')) + restofline++; + while(isspace(*restofline))restofline++; + } + else if(mystrncasecmp(restofline,"STARTSONDESK",12)==0) + { + restofline +=12; + off_flags |= STAYSONDESK_FLAG; + sscanf(restofline,"%d",&desknumber); + while(isspace(*restofline))restofline++; + while((!isspace(*restofline))&&(*restofline!= 0)&& + (*restofline != ',')&&(*restofline != '\n')) + restofline++; + while(isspace(*restofline))restofline++; + } + else if(mystrncasecmp(restofline,"STARTSANYWHERE",14)==0) + { + restofline +=14; + on_flags |= STAYSONDESK_FLAG; + } + while(isspace(*restofline))restofline++; + if(*restofline == ',') + restofline++; + else if((*restofline != 0)&&(*restofline != '\n')) + { + fvwm_err("bad style command in line %s at %s", + orig_tline,restofline,NULL); + return; + } + } + /* capture default icons */ + if(strcmp(name,"*") == 0) + { + if(off_flags & ICON_FLAG) + Scr.DefaultIcon = icon_name; + off_flags &= ~ICON_FLAG; + icon_name = NULL; + } + + /* capture default colors */ + if(strcmp(name,"*") == 0) + { + extern char *Stdfore, *Stdback; + + if(off_flags & FORE_COLOR_FLAG) + Stdfore = forecolor; + off_flags &= ~FORE_COLOR_FLAG; + forecolor = NULL; + if(off_flags & BACK_COLOR_FLAG) + Stdback = backcolor; + off_flags &= ~BACK_COLOR_FLAG; + backcolor = NULL; + } + free(line); + AddToList(name,icon_name,off_flags,on_flags,desknumber,bw,nobw, + forecolor,backcolor,off_buttons,on_buttons); +} + + +void AddToList(char *name, char *icon_name, unsigned long off_flags, + unsigned long on_flags, int desk, int bw, int nobw, + char *forecolor, char *backcolor, + unsigned long off_buttons, unsigned long on_buttons) +{ + name_list *nptr,*lastptr = NULL; + + if((name == NULL)||((off_flags == 0)&&(on_flags == 0)&&(on_buttons == 0)&& + (off_buttons == 0))) + { + if(name) + free(name); + if(icon_name) + free(icon_name); + return; + } + + /* used to merge duplicate entries, but that is no longer + * appropriate since conficting styles are possible, and the + * last match should win! */ + for (nptr = Scr.TheList; nptr != NULL; nptr = nptr->next) + { + lastptr=nptr; + } + + nptr = (name_list *)safemalloc(sizeof(name_list)); + nptr->next = NULL; + nptr->name = name; + nptr->on_flags = on_flags; + nptr->off_flags = off_flags; + nptr->value = icon_name; + nptr->Desk = desk; + nptr->border_width = bw; + nptr->resize_width = nobw; + nptr->ForeColor = forecolor; + nptr->BackColor = backcolor; + + nptr->off_buttons = off_buttons; + nptr->on_buttons = on_buttons; + + if(lastptr != NULL) + lastptr->next = nptr; + else + Scr.TheList = nptr; +} + diff --git a/fvwm/sun_headers.h b/fvwm/sun_headers.h new file mode 100644 index 0000000..0a43733 --- /dev/null +++ b/fvwm/sun_headers.h @@ -0,0 +1,55 @@ +/**************************************************************************/ +/* Prototypes that don't exist on suns */ +/* If I do ALL this, I can compile OK with -Wall -Wstrict-prototypes on the + * Sun's */ + +#if defined(sun) && !defined(SVR4) +#include +#include +#include + + +extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *); + +extern int system(char *command); +extern int toupper(int); +extern int tolower(int); + +/* stdio things */ +extern int fputc(char, FILE *); +extern int fgetc(FILE *); +extern int fputs(char *, FILE *); +extern char *mktemp(char *); +extern int pclose(FILE *); +extern int sscanf(char *input, char *format, ...); +extern int printf(char *format, ...); +extern int fprintf(FILE *file,char *format, ...); +extern int fseek(FILE *file,long offset,int); +extern int fclose(FILE *file); +extern int fread(char *data, int size, int count, FILE *file); +extern int fflush(FILE *file); +extern void perror(char *s); + +/* string manipulation */ +extern int strncasecmp(char *str1, char *str2, int length); +extern int strcasecmp(char *str1, char *str2); +extern int putenv(char *); + +/* sunOS defines SIG_IGN, but they get it wrong, as far as GCC + * is concerned */ +#ifdef SIG_IGN +#undef SIG_IGN +#endif +#define SIG_IGN (void (*)(int))1 +int wait3(int *, int, struct rusage *); +int sigsetmask(int); +int sigblock(int); + +int setitimer(int, struct itimerval *, struct itimerval *); +int getitimer(int, struct itimerval *); +int bzero(char *, int); + +long time(long *); +int gethostname(char *name, int namelen); +/**************************************************************************/ +#endif diff --git a/fvwm/windows.c b/fvwm/windows.c new file mode 100644 index 0000000..8622c5a --- /dev/null +++ b/fvwm/windows.c @@ -0,0 +1,159 @@ +/**************************************************************************** + * This module is all new + * by Rob Nation + * A little of it is borrowed from ctwm. + * Copyright 1993 Robert Nation. No restrictions are placed on this code, + * as long as the copyright notice is preserved + ****************************************************************************/ +/*********************************************************************** + * + * fvwm window-list popup code + * + ***********************************************************************/ + +#include "../configure.h" + +#include +#include +#include + +#include "fvwm.h" +#include "menus.h" +#include "misc.h" +#include "parse.h" +#include "screen.h" + +/* I tried to include "limits.h" to get these values, but it + * didn't work for some reason */ +/* Minimum and maximum values a `signed int' can hold. */ +#define MY_INT_MIN (- MY_INT_MAX - 1) +#define MY_INT_MAX 2147483647 + +extern XContext MenuContext; +/* + * Change by PRB (pete@tecc.co.uk), 31/10/93. Prepend a hot key + * specifier to each item in the list. This means allocating the + * memory for each item (& freeing it) rather than just using the window + * title directly. */ +void do_windowList(int val1, int val2) +{ +#ifndef NO_WINDOWLIST + MenuRoot *mr; + MenuItem *mi,*tmp; + FvwmWindow *t; + char *tname; + char loc[40],*name=NULL; + int dwidth,dheight; + char tlabel[50]; + int last_desk_done = MY_INT_MIN; + int next_desk; + + char *t_hot; /* Menu label with hotkey added */ + char scut = '0'; /* Current short cut key */ + + sprintf(tlabel,"CurrentDesk: %d",Scr.CurrentDesk); + mr=NewMenuRoot(tlabel); + AddToMenu(mr, tlabel, "Geometry", NULL, F_TITLE,0,0,'s','s'); + + next_desk = 0; + while(next_desk != MY_INT_MAX) + { + /* Sort window list by desktop number */ + if((val1 < 2)&&(val1 > -2)) + { + next_desk = MY_INT_MAX; + for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) + { + if((t->Desk >last_desk_done)&&(t->Desk < next_desk)) + next_desk = t->Desk; + } + } + else if((val1 <4)&&(val1 > -4)) + { + if(last_desk_done == MY_INT_MIN) + next_desk = Scr.CurrentDesk; + else + next_desk = MY_INT_MAX; + } + else + { + if(last_desk_done == MY_INT_MIN) + next_desk = val2; + else + next_desk = MY_INT_MAX; + } + last_desk_done = next_desk; + for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) + { + if((t->Desk == next_desk)&& + (!(t->flags & WINDOWLISTSKIP))) + { + if (++scut == ('9' + 1)) scut = 'A'; /* Next shortcut key */ + if(val1%2 != 0) + name = t->icon_name; + else + name = t->name; + t_hot = safemalloc(strlen(name) + 8); + sprintf(t_hot, "&%c. %s", scut, name); /* Generate label */ + + tname = safemalloc(40); + tname[0]=0; + if(t->flags & ICONIFIED) + strcpy(tname, "("); + sprintf(loc,"%d:",t->Desk); + strcat(tname,loc); + if(t->frame_x >=0) + sprintf(loc,"+%d",t->frame_x); + else + sprintf(loc,"%d",t->frame_x); + strcat(tname, loc); + if(t->frame_y >=0) + sprintf(loc,"+%d",t->frame_y); + else + sprintf(loc,"%d",t->frame_y); + strcat(tname, loc); + dheight = t->frame_height - t->title_height - 2*t->boundary_width; + dwidth = t->frame_width - 2*t->boundary_width; + + dwidth -= t->hints.base_width; + dheight -= t->hints.base_height; + + dwidth /= t->hints.width_inc; + dheight /= t->hints.height_inc; + + sprintf(loc,"x%d",dwidth); + strcat(tname, loc); + sprintf(loc,"x%d",dheight); + strcat(tname, loc); + if(t->flags & ICONIFIED) + strcat(tname, ")"); + + AddToMenu(mr, t_hot, tname, NULL, F_RAISE_IT, + (long)t,(long)(t->w),'s','s'); + } + } + } + MakeMenu(mr); + + do_menu(mr); + + XDestroyWindow(dpy,mr->w); + XDeleteContext(dpy, mr->w, MenuContext); + /* need to free the window list ? */ + mi = mr->first; + while(mi != NULL) + { + tmp = mi->next; + if (mi->func != F_TITLE) + { + if (mi->item != NULL) free(mi->item); + if (mi->item2 != NULL) free(mi->item2); + } + free(mi); + mi = tmp; + } + free(mr); +#endif +} + + diff --git a/fvwm_icons/arrdown2.xpm b/fvwm_icons/arrdown2.xpm new file mode 100644 index 0000000..bbe2a8f --- /dev/null +++ b/fvwm_icons/arrdown2.xpm @@ -0,0 +1,41 @@ +/* XPM */ +static char * arrdown[] = { +/* arrdown pixmap + * width height ncolors chars_per_pixel */ +"32 32 2 2 ", +" s None c None", +". c #000 s s_#000 ", +/* pixels */ +" . . . . . . . . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . . . . . . . . ", +" . . . . ", +" . . . . ", +" . . . . ", +" . . . . ", +" . . . . ", +" . . . . ", +" . . . . ", +" . . . ", +" . " +} ; diff --git a/fvwm_icons/arrows2.xpm b/fvwm_icons/arrows2.xpm new file mode 100644 index 0000000..48122ae --- /dev/null +++ b/fvwm_icons/arrows2.xpm @@ -0,0 +1,51 @@ +/* XPM */ +static char *noname[] = { +/* width height ncolors chars_per_pixel */ +"32 32 12 1", +/* colors */ +"` c #CBFFFF", +"a c #AB0000", +"c c #326565", +"e c red", +"g c green", +"h c #770000", +"i c #99CCCC", +"j c #00AB00", +"l c #007700", +"m c #005500", +"q c #DC0000", +"v c black", +/* pixels */ +"```````````````````````````````i", +"`iiiiiiiiiiiiiiiiiiiiiiiiiiiiiic", +"`iiiiiiiiiiiiiiiiiiiiiiiiiiiiiic", +"`iiiiiiiiiiiiiiiiiiiviiiiiiiiiic", +"`iiiiiiiiiiiiiiiiiivlviiiiiiiiic", +"`iiiiiiiiiiiiiiiiivllmviiiiiiiic", +"`iiiiiiiiiiiiiiiiiivlmmviiiiiiic", +"`iiiiiiiiiiiiiiiiiiivmmmviiiiiic", + "`iiivgvvvgvvvvvvvvvvvvmmmviiiiic", +"`iiiiggggggggjjjjllllmmmmvviiiic", +"`iiiiivgvvvggjjjjllllmmmmvvviiic", +"`iiiiiiggggggjjjjllllmmmmvviiiic", +"`iiiiiiivgvvvjvvvvvvvvmmmviiiiic", +"`iiiiiiiiiiiiiiiiiiivmmmviiiiiic", +"`iiiiiiiiiiviiiiiiivlmmviiiiiiic", +"`iiiiiiiiivqviiiiivllmviiiiiiiic", +"`iiiiiiiivqqqviiiiivlviiiiiiiiic", +"`iiiiiiivqqqviiiiiiiviiiiiiiiiic", +"`iiiiiiveqqviiiiiiiiiiiiiiiiiiic", +"`iiiiiveeqvvvvvvvvvvvvhvvvvviiic", +"`iiiiveeeqqqqaaaahhhhhhhhhviiiic", +"`iiiveeeeqqqqaaaahhhhvvvhviiiiic", +"`iiiiveeeqqqqaaaahhhhhhhhiiiiiic", +"`iiiiiveeqvvvvvvvvhvvvhviiiiiiic", +"`iiiiiiveqqviiiiiiiiiiiiiiiiiiic", +"`iiiiiiivqqqviiiiiiiiiiiiiiiiiic", +"`iiiiiiiivqqqviiiiiiiiiiiiiiiiic", +"`iiiiiiiiivqviiiiiiiiiiiiiiiiiic", +"`iiiiiiiiiiviiiiiiiiiiiiiiiiiiic", +"`iiiiiiiiiiiiiiiiiiiiiiiiiiiiiic", +"`iiiiiiiiiiiiiiiiiiiiiiiiiiiiiic", +"iccccccccccccccccccccccccccccccc" +}; diff --git a/fvwm_icons/arrup2.xpm b/fvwm_icons/arrup2.xpm new file mode 100644 index 0000000..38cba1f --- /dev/null +++ b/fvwm_icons/arrup2.xpm @@ -0,0 +1,41 @@ +/* XPM */ +static char * arrup[] = { +/* arrup pixmap + * width height ncolors chars_per_pixel */ +"32 32 2 2 ", +" s None c None", +". c #000 s s_#000 ", +/* pixels */ +" . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . . . . . . . . . ", +" . . . . . . . . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . ", +" . . . . . . . . . . ", +" . . . . . . . . . " +} ; diff --git a/fvwm_icons/bomb.xpm b/fvwm_icons/bomb.xpm new file mode 100644 index 0000000..a0af515 --- /dev/null +++ b/fvwm_icons/bomb.xpm @@ -0,0 +1,47 @@ +/* XPM */ +static char * icl8_11432_xpm[] = { +/* width height ncolors chars_per_pixel */ +"32 32 9 1", +/* colors */ +" s None c None", +"o c #999999", +"O c black", +"+ c #333333", +"@ c #111111", +"# c #FF6666", +"$ c #FEFE00", +"% c #DDDDDD", +"& c #BBBBBB", +/* pixels */ +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" oOoOo ", +" O Oo ", +" o O ", +" O o ", +" +++++ O ", +" +@@@+ o ", +" +@@O@@+ O ", +" ++@OOO@O@++ o # $", +" +@@OOOOOOO@@+ O $ # ", +" +@OOOOOOOOOOO@+ o $ ", +" +@OOOOOO%&oOO@+ O # $ ", +" +@OOOOOOOO%&oOO@+ o ", +" +@OOOOOOOOOOOOO@+ OoO # $ #", +" +@OOOOOOOOO%&oO@+ ", +" +@OOOOOOOOO%&oO@+ $ $ ", +" +@OOOOOOOOO%&oO@+ # # ", +" +@OOOOOOOO%&oOO@+ # ", +" +@OOOOOOOO%&oOO@+ $ $ $", +" +@OOOOOO%&oOO@+ ", +" +@OOOOOOOOOOO@+ # ", +" +@@OOOOOOO@@+ ", +" ++@@@@@@@++ ", +" +++++++ ", +" "}; diff --git a/fvwm_icons/ccode.icon b/fvwm_icons/ccode.icon new file mode 100644 index 0000000..9c6f4e4 --- /dev/null +++ b/fvwm_icons/ccode.icon @@ -0,0 +1,17 @@ +/* This X bitmap is designed for use with the X Desktop Manager. + * it was designed by Edward Groenendaal, April 1991. + */ +#define ccode_width 32 +#define ccode_height 32 +static char ccode_bits[] = { + 0xf0, 0xff, 0x7f, 0x00, 0x10, 0x00, 0xc0, 0x00, 0x10, 0xe0, 0x41, 0x01, + 0x10, 0xf8, 0x43, 0x02, 0x10, 0x3c, 0x47, 0x04, 0x10, 0x1c, 0xc6, 0x0f, + 0x10, 0x1e, 0x00, 0x08, 0x10, 0x0e, 0x00, 0x08, 0x10, 0x0e, 0x00, 0x08, + 0x10, 0x0e, 0x00, 0x08, 0x10, 0x0e, 0x00, 0x08, 0x10, 0x1e, 0x00, 0x08, + 0x10, 0x1c, 0x06, 0x08, 0x10, 0x3c, 0x07, 0x08, 0x10, 0xf8, 0x03, 0x08, + 0xd0, 0xe0, 0x01, 0x08, 0x10, 0x00, 0x00, 0x08, 0x90, 0x05, 0x00, 0x08, + 0x10, 0x00, 0x00, 0x08, 0x90, 0xdf, 0x0a, 0x08, 0x10, 0x00, 0x00, 0x08, + 0x10, 0xb7, 0x03, 0x08, 0x10, 0x00, 0x00, 0x08, 0x90, 0xbd, 0xb7, 0x08, + 0x10, 0x00, 0x00, 0x08, 0x10, 0x6c, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08, + 0x90, 0xdd, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08, 0xd0, 0x00, 0x00, 0x08, + 0x10, 0x00, 0x00, 0x08, 0xf0, 0xff, 0xff, 0x0f}; diff --git a/fvwm_icons/clamp.xpm b/fvwm_icons/clamp.xpm new file mode 100644 index 0000000..869da60 --- /dev/null +++ b/fvwm_icons/clamp.xpm @@ -0,0 +1,43 @@ +/* XPM */ +static char * icl8_17087_xpm[] = { +/* width height ncolors chars_per_pixel */ +"32 32 5 1", +/* colors */ +" s None c None", +". c black", +"X c wheat", +"o c tan", +"O c #555555", +/* pixels */ +" ................... ", +" .XXXXXXXXXXXXXXXXX.. ", +" .XXXXXX............o. ", +" .XXXXX.OOOOOOOOOOO.oo. ", +" .XXXXX.OOOO........ooo. ", +" .XXXXX.OOO.XXXXXXX.oooo. ", +" .XXXX.......XXXXXX....... ", +" .XXXX.......XXXXXXX....o. ", +" .XXXXXXXXXXXXXXXXXX....o. ", +" .XXXXXXXXXXXXXXXXXX.OO.X. ", +" .XXXXXXXXXXXXXXXXXX.OO.X. ", +" .XXXXXXXXXXXXXXXXXX.OO.X. ", +" .XXXXXXXXXXXXXXXXXX.OO.X. ", +" .XXXXXXXXXXXXXXXXXX.OO.X. ", +" .XXXXXXXXXXXXXXXXXX.OO.X. ", +" .XXXXXXXXXXXXXXXXXX.OO.X. ", +" .XXXXXXXXXXXXXXXXXX.OO.X. ", +" .XXXXXXXXXXXXXXXXXX.OO.X. ", +" .XXXX.......XXXXXXX.OO.X. ", +" .XXXX.......XXXXXXX.OO.X. ", +" .XXXXX.....XXXXXXXX.OO.X. ", +" .XXXXXX.O.XXXXXXXX.OOO.X. ", +" .XXXX..............OOO.X. ", +" .XXXX.OOOOOOOOOOOOOOO.XX. ", +" .XXXX................XXX. ", +" .XXXXXX.O.XXXXXXXXXXXXXX. ", +" .XXXXXX...XXXXXXXXXXXXXX. ", +" .X.XXXX.O.XXXX.XXXXXXXXX. ", +" .X.............XXXXXXXXX. ", +" .X.XXXX...XXXX.XXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXXXXXX. ", +" ......................... "}; diff --git a/fvwm_icons/datebook.xpm b/fvwm_icons/datebook.xpm new file mode 100644 index 0000000..05eda33 --- /dev/null +++ b/fvwm_icons/datebook.xpm @@ -0,0 +1,60 @@ +/* XPM */ +/*****************************************************************************/ +/** This pixmap is kindly offered by Ion Cionca - 1992 - **/ +/** Swiss Federal Institute of Technology **/ +/** Central Computing Service **/ +/*****************************************************************************/ +static char * image_name [] = { +"64 38 13 1", +/**/ +" s None c None", +". c black", +"X c blue", +"o c red", +"O c white", +"+ c lightskyblue", +"@ c navy", +"# c darkslategrey", +"$ c lightyellow", +"% c gray85", +"& c peachpuff4", +"* c gray70", +"= c tan", +" ", +" ", +" ..................... XXXXXXXX ", +" ..ooooooooooooooooooo. XOO+XXXXXXX ", +" .o.ooooooooooooooooooo. XOO+XXXXXXXXX ", +" .o.ooooooooooooooooooo. XXO++XXXXXXXXXXXX ", +" .o.ooooooooooooooooooo. XX++++++++++XXXXXXX ", +" .o.ooooooooooooooooooo. @@@@@@@@@@@@@@@@@@@ ", +" .o..................... ################### ", +" .o.$$$$$$$$$$$$$$$$$$. XXXXXX%%%XXXXXX ", +" ..&.$$$$$$$$$$$$$$$$$. XXX%%***@****%XXX ", +" .&&.$$$$$$$$@@@$$$$$$. XXX%%%%%%@%%***%XXX ", +" .&=.$$$@@$$@@$@@$$$$$. XX%%%%%%%@@@%%***%%XX ", +" .&=.$$$@@$$@@$@@$$$$$. XX%%%%%%%%@@@%%%***%%XX ", +" .&=.$$$@@@$$$$@@@@$$$. #XXX%%%%%%%%@@@%%%%%**%XXX ", +" .&=.$$$@$@$$$@@$$@@$$$. ##XX%%%%%%%%%@@@%%%%%***%XX ", +" .&=.$$$@$@$$$$$$$$@@$$. ##X%%%%%%%%%%@@@%%%%%****%XX ", +" .&=.$$$@$@@$$$$$$$$@$$.##XX%%%%%%%%%%@@@%%%%%%***%XX ", +" .&=.$$$$$$@$$$$$$$$@$$$##XX%%%%%%%%%%%@%%%%%%%%**%XXX ", +" .&=..$$$$$@@$$$$$$$@$$###X%%%%%%%%%%%%@%%%%%%%%***%XX ", +" .&=..$$$$$$@@$$@@$@@$$##XX%%%%%%%%%%%%@%%%%%%%%%**%XX ", +" .&=.=.$$$$$$@@$$@@@$$$##XX%%%%%%%%%%%@%@%%%%%%%%**%XX ", +" .&=.=.$$$$$$$@@$$$$$$$##XX%%%%%%%%%%%%@%%%%%%%%%**%XX ", +" .&=..=.$$$$$$$$$$$$$$$##XX%%%%%%%%%%%%%%@@%%%%%%*%%XX ", +" .&=..=.$$$$$$$$$$$$$$$###XX%%%%%%%%%%%%%@@@%%%%%*%XXX ", +" .&=.=.=.$$$$$$$$$.$$$$###XX%%%%%%%%%%%%%%@@%%%%%%%XXX ", +" .&=.=.==.$$$$$$$..$$$$$##XX%%%%%%%%%%%%%%%%@%%%%%%XX ", +" .&=.=.===..$$$$.$$.$$$$###XX%%%%%%%%%%%%%%%%%%%%%XX ", +" .&==.=.$==*....$$$$.....##XXX%%%%%%%%%%%%%%%%%%%XXX ", +" .&&=..=.$==**.$$$$$$$..$###XX%%%%%%%%%%%%%%%%%%%XX ", +" .&&==.==.$===*.......*$..###XX%%%%%%%%%%%%%%%%%XX ", +" .&&&=..$.$=======$$$.... ###XXX%%%%%%%%%%%%%XXX ", +" .&&&&=..............&. ##XXXX%%%%%%%%%%%XXXX ", +" .&&&&&=============&&. ##XX#XXXXX%%%XXXXXXXX ", +" ...................... #XX#####XXXXXX##X####X ", +" ##X ########### ###XX ", +" #X ##X ", +" "}; diff --git a/fvwm_icons/default.xbm b/fvwm_icons/default.xbm new file mode 100644 index 0000000..8d11fc3 --- /dev/null +++ b/fvwm_icons/default.xbm @@ -0,0 +1,27 @@ +#define default_width 48 +#define default_height 48 +static char default_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xac, 0xaa, 0xaa, 0xab, 0xaa, 0x2a, + 0xa4, 0xaa, 0xaa, 0xa9, 0xaa, 0x2a, 0xfc, 0xff, 0x9f, 0xff, 0xff, 0x27, + 0xa4, 0xaa, 0x8a, 0xa9, 0xaa, 0x22, 0xfc, 0xff, 0x9f, 0xff, 0xff, 0x27, + 0xa4, 0xaa, 0x8a, 0xa9, 0xaa, 0x22, 0xfc, 0xff, 0x9f, 0xff, 0xff, 0x27, + 0xa4, 0xaa, 0x8a, 0xa9, 0xaa, 0x22, 0xfc, 0xff, 0x9f, 0xff, 0xff, 0x27, + 0xa4, 0xaa, 0x8a, 0xa9, 0xaa, 0x22, 0xfc, 0xff, 0x9f, 0xff, 0xff, 0x27, + 0xa4, 0xaa, 0x8a, 0xa9, 0xaa, 0x22, 0xfc, 0xff, 0x9f, 0xff, 0xff, 0x27, + 0xa4, 0xaa, 0x8a, 0xa9, 0xaa, 0x22, 0xfc, 0xff, 0x9f, 0xff, 0xff, 0x27, + 0xa4, 0xaa, 0x8a, 0xa9, 0xaa, 0x22, 0xfc, 0xff, 0x9f, 0xff, 0xff, 0x27, + 0xa4, 0xaa, 0x8a, 0xa9, 0xaa, 0x22, 0x1c, 0x00, 0x80, 0x07, 0x00, 0x20, + 0x04, 0x00, 0x80, 0x01, 0x00, 0x20, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xac, 0xaa, 0xaa, 0xab, 0xaa, 0x2a, + 0xa4, 0xaa, 0xaa, 0xa9, 0xaa, 0x2a, 0xfc, 0xff, 0x9f, 0xff, 0xff, 0x27, + 0xa4, 0xaa, 0x8a, 0xa9, 0xaa, 0x22, 0xfc, 0xff, 0x9f, 0xff, 0xff, 0x27, + 0xa4, 0xaa, 0x8a, 0xa9, 0xaa, 0x22, 0xfc, 0xff, 0x9f, 0xff, 0xff, 0x27, + 0xa4, 0xaa, 0x8a, 0xa9, 0xaa, 0x22, 0xfc, 0xff, 0x9f, 0xff, 0xff, 0x27, + 0xa4, 0xaa, 0x8a, 0xa9, 0xaa, 0x22, 0xfc, 0xff, 0x9f, 0xff, 0xff, 0x27, + 0xa4, 0xaa, 0x8a, 0xa9, 0xaa, 0x22, 0xfc, 0xff, 0x9f, 0xff, 0xff, 0x27, + 0xa4, 0xaa, 0x8a, 0xa9, 0xaa, 0x22, 0xfc, 0xff, 0x9f, 0xff, 0xff, 0x27, + 0xa4, 0xaa, 0x8a, 0xa9, 0xaa, 0x22, 0xfc, 0xff, 0x9f, 0xff, 0xff, 0x27, + 0xa4, 0xaa, 0x8a, 0xa9, 0xaa, 0x22, 0x1c, 0x00, 0x80, 0x07, 0x00, 0x20, + 0x04, 0x00, 0x80, 0x01, 0x00, 0x20, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/fvwm_icons/desk.xpm b/fvwm_icons/desk.xpm new file mode 100644 index 0000000..411830d --- /dev/null +++ b/fvwm_icons/desk.xpm @@ -0,0 +1,46 @@ +/* XPM */ +static char * icl8_30231_xpm[] = { +/* width height ncolors chars_per_pixel */ +"32 32 8 1", +/* colors */ +" s None c None", +". c #660000", +"X c #CD3300", +"o c #33FE00", +"O c #986500", +"+ c #220000", +"@ c #550000", +"# c #983200", +/* pixels */ +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +"......................... ", +".XXXXXXXXXXXXXXXXXXXXXXXX. ", +".XXXXXoooOXoooXOoooXoXXoXX. ", +"+.XXXXoXXoXoXXXoXXXXoXoXXXX. ", +"++.XXXoXXoXooXXOooOXoooXXXXX. ", +"+++.XXoXXoXoXXXXXXoXoXXoXXXXX. ", +"++++.XoooOXoooXoooOXoXXXoXXXXX. ", +"+++++.XXXXXXXXXXXXXXXXXXXXXXXXX.", +"++++++@@@@@@@@@@@@@@@@@@@@@@@@@@", +"++++++@######@ +++++@######@", +"++++++@######@ ++++@######@", +"++++++@@@@@@@@ +++@@@@@@@@", +"++++++@######@ ++@######@", +" +++++@######@ +@######@", +" ++++@@@@@@@@ @@@@@@@@", +" +++@######@ @######@", +" ++@######@ @######@", +" +@######@ @######@", +" @@@@@@@@ @@@@@@@@", +" ", +" ", +" ", +" ", +" "}; diff --git a/fvwm_icons/dialog_box.xpm b/fvwm_icons/dialog_box.xpm new file mode 100644 index 0000000..c9607bd --- /dev/null +++ b/fvwm_icons/dialog_box.xpm @@ -0,0 +1,47 @@ +/* XPM */ +static char * icl8_16322_xpm[] = { +/* width height ncolors chars_per_pixel */ +"32 32 9 1", +/* colors */ +" s None c None", +". c black", +"X c cadet blue", +"o c #555555", +"O c #FF9966", +"+ c white", +"@ c #0000EF", +"# c #99CCCC", +"$ c #00CBFE", +/* pixels */ +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" .............................. ", +" .XXXXXXXXXXXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXXoXXXXXXXX. ", +" .X................XXoXXOOOOXX. ", +" .X.+++++++++++.++.XXoXXOOOOXX. ", +" .X.+@@@@++++++.++.XXoXXXXXXXX. ", +" .X.+++++++++++....XXoXXXXXXXX. ", +" .X.+@@@+@@++++.##.XXoXXOOOOXX. ", +" .X.+++++++++++.##.XXoXXOOOOXX. ", +" .X.+@@+@@@++++.##.XXoXXXXXXXX. ", +" .X.+++++++++++.##.XXoXXXXXXXX. ", +" .X.###########.##.XXoXXXXXXXX. ", +" .X.#$$$$#$$###.##.XXoXXOOOOXX. ", +" .X.###########.##.XXoXXOOOOXX. ", +" .X.+++++++++++....XXoXXXXXXXX. ", +" .X.+@@@+@@@+++.++.XXoXXXXXXXX. ", +" .X.+++++++++++.++.XXoXXOOOOXX. ", +" .X................XXoXXOOOOXX. ", +" .XXXXXXXXXXXXXXXXXXXoXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXXXXXXXXXXX. ", +" .............................. "}; diff --git a/fvwm_icons/editres.xpm b/fvwm_icons/editres.xpm new file mode 100644 index 0000000..6b64fed --- /dev/null +++ b/fvwm_icons/editres.xpm @@ -0,0 +1,47 @@ +/* XPM */ +static char * editres_xpm[] = { +/* width height ncolors chars_per_pixel */ +"32 32 9 1", +/* colors */ +" s None c None", +". c #00FE32", +"X c #006600", +"o c #444444", +"O c #FFCC9A", +"+ c black", +"@ c #3366FF", +"# c #FE0000", +"$ c #CD0000", +/* pixels */ +" .... ", +" ....... ", +" ...X.XXXo oo ", +" .X.X.XXOOO+OO+ ", +" .XXXXXOOo@OOO+ ", +" X XXOOOOOOO+ ", +" XX XOoO#$OOO+ ", +" X oO@O#$O#O+ ", +" +OOOOO#O++ ", +" oOOOO##OO+@+ ", +" oOO+OOOO+@@#+ ", +" ++ ++++@@+#+ ", +" +@+##@+ ", +" +##+@+ ", +" #+@@+ ", +" +@@+#@ ", +" @+#+@ ", +" ###### +###@ ", +" ###### #+@ ### ", +" ###### +@ #### ", +" ###### ### ", +" ###### ### ", +" ###### ### ", +" ###### ### ", +" ###### ### ", +" #### ##### ", +" ### ####### ", +" ### ###### ", +" ### ###### ", +" ### ###### ", +" ### ####### ", +" ### ###### "}; diff --git a/fvwm_icons/eps.xpm b/fvwm_icons/eps.xpm new file mode 100644 index 0000000..6da68cd --- /dev/null +++ b/fvwm_icons/eps.xpm @@ -0,0 +1,53 @@ +/* XPM */ +static char * icl8_6289_xpm[] = { +/* width height ncolors chars_per_pixel */ +"32 32 15 1", +/* colors */ +" s None c None", +". c #444444", +"X c #BDBDC5C5CCCC", +"o c white", +"O c wheat", +"+ c #9AFFFF", +"@ c #00FEFE", +"# c #555555", +"$ c #00CDCD", +"% c #FF33FE", +"& c #888888", +"* c #FF3399", +"= c #CC66FF", +"- c #222222", +"; c #FE9800", +/* pixels */ +" ......................... ", +" .XXXXXXXXoOOOOOOOOOOOOOO. ", +" .XXXXXXoooOOOO++++++++++++++@ ", +" .oXXXXo###oOOO+@@@@@@@@@@@@@$ ", +" .OoXXo###oOOOO+@%%%@%%@@@%@@$ ", +" .OOoXo####oOOO+@%@@@%@%@%@%@$&&", +" .OOOo##o###oOO+@%@@@%@%@%@@@$&&", +" .OOOOooOo##oOO+@%@@@%@%@%@@@$&&", +" .OOOOOOOOoo#oO+@%%@@%@%@@%@@$&&", +" .OOOOOOOOOOO#o+@%@@@%%@@@@%@$&&", +" .oOOOOOOooooOO+@%@@@%@@@@@%@$&&", +" .#oOOOOOo###oo+@%@@@%@@@%@%@$&&", +" .*#oOOOOOo####+@%%%@%@@@@%@@$&&", +" .**#oOOOOOo#==+@@@@@@@@@@@@@$&&", +" .***#oOOOOOo#=@$$$$$$$$$$$$$$&&", +" .****#oOOOOo#===&&&&&&&&-&&&&&&", +" .****##oOOOOo#==&&&&&&&&-&&&&&&", +" .****#X#oOOOOo#====#+#oO.&&&&&&", +" .#**#XXX#oOOOOo#=###++#o.&& ", +" .o##XXXXX#oOOOo#=#@@#++#.&& ", +" .Oo#XXXXXX#oOOOo###@@#++.&& ", +" .OOo#XXXXXX#oOOOo#$#@@#+.&& ", +" .OoOo#XXXXXX#oOOOo#$#@@#.&& ", +" .o#oOo###XXXX#oOOOo#$#@@.&& ", +" .#@#oOooo###XX#oOOOo#$#@.&& ", +" .@@@#oOOOooo##;#oOOOo#$#.&& ", +" .@@#@#oOOOOOoo###oOOOo#$.&& ", +" .@@@@@#oOOOOOOooo#oOOOo#.&& ", +" .@@@@#@#oOOOOOOOOooOOOOo.&& ", +" .@@@@@@@#oOOOOOOOOOOOOOO.&& ", +" .........................&& ", +" &&&&&&&&&&&&&&&&&&&&&&&&& "}; diff --git a/fvwm_icons/flow_chart.xpm b/fvwm_icons/flow_chart.xpm new file mode 100644 index 0000000..a6f9009 --- /dev/null +++ b/fvwm_icons/flow_chart.xpm @@ -0,0 +1,46 @@ +/* XPM */ +static char * icl8_15540_xpm[] = { +/* width height ncolors chars_per_pixel */ +"32 32 8 1", +/* colors */ +" s None c None", +". c #777777", +"X c black", +"o c wheat", +"O c #0066FE", +"+ c #9ACCFF", +"@ c #FF9966", +"# c #FFCC9A", +/* pixels */ +".XXXXXXXXXXXXXXXXXXXXXXXX. ", +"XooooooooooooooooooooooooX ", +"XooooooooooOOOOOoooooooooX ", +"XooooooooooO+++OoooooooooX ", +"XooooooooooO+++OoooooooooX ", +"XooooooooooOOOOOoooooooooX ", +"XooooooooooooOoooooooooooX ", +"XooooooooooooOoooooooooooX ", +"XoooooooooooO+OooooooooooX ", +"XooooooooooO+++OoooooooooX ", +"XooooOOOOOO+++++OOOOOooooX ", +"XooooOoooooO+++OooooOooooX ", +"XooOOOOOooooO+OoooOOOOOooX ", +"XooO+++OoooooOooooO+++OooX ", +"XooO+++OooooooooooO+++OooX ", +"XooOOOOOooooooooooOOOOOooX ", +"XooooOooooooooooooooOooooX ", +"XooooOoooXXXooooooooOooooX ", +"XooooOoooXXXXXXXXXoooooooX ", +"XoooO+OooXX@@@@@@@XoXXXXXX ", +"XooO+++OoXX#######@X@@@@@X ", +"XoO+++++OXX#######X@#####@X ", +"XooO+++OoXX######X@##XX###@X ", +"XoooO+OooXXX#####X##X@@X###@XXXX", +"XooooOooooooX####X##X##X####@@XX", +"XooooOoooooooX###@XX@##X######XX", +"XooOOOOOooooooX###@@##X@######XX", +"XooO+++OoooooooX#####X@#######XX", +"XooO+++OooooooooXXXXXoX#######XX", +"XooOOOOOoooooooooooooooXXXXXXXXX", +"XooooooooooooooooooooooooX XXX", +".XXXXXXXXXXXXXXXXXXXXXXXX. "}; diff --git a/fvwm_icons/folder2.xpm b/fvwm_icons/folder2.xpm new file mode 100644 index 0000000..b3dcc31 --- /dev/null +++ b/fvwm_icons/folder2.xpm @@ -0,0 +1,44 @@ +/* XPM */ +static char *noname[] = { +/* width height ncolors chars_per_pixel */ +"32 32 5 1", +/* colors */ +"` c #000000", +"a c #FFFE9A", +"b c #FFCC9A", +"c c none", +"d c #FFCC66", +/* pixels */ +"cccccccccccccccccccccccccccccccc", +"cccccccccccccccccccccccccccccccc", +"cccccccccccccccccccccccccccccccc", +"cccccccccccccccccccccccccccccccc", +"cccccccccccccccccccccccccccccccc", +"cccccccccccccccccccccccccccccccc", +"cccccccccccccccccccccccccccccccc", +"ccccc```````cccccccccccccccccccc", +"cccc`ddddddd`ccccccccccccccccccc", +"ccc`ddddddddd`cccccccccccccccccc", +"cc`ddddddddddd`ccccccccccccccccc", +"c`````````````````````````````cc", +"`aaaaaaaaaaaaaaaaaaaaaaaaaaaaa`c", +"`aaaaaaaaaaaaaaaaaaaaaaaaaaaaa`c", +"`aaaaaaaaaaaaaaaaaaaaaaaaaaaaa`c", +"`aaaaaaaaaaaaaaaaaaaaaaaaaaaaa`c", +"`aaaaaaaaaaaaaaaaaaaaaaaaaaaaa`c", +"`aaaaaaaaaaaaaaaaaaaaaaaaaaaaa`c", +"`aaaaaaaaaaaaaaaaaaaaaaaaaaaaa`c", +"`aaaaaaaaaaaaaaaaaaaaaaaaaaaaa`c", +"`aaaaaaaaaaaaaaaaaaaaaaaaaaaaa`c", +"`aaaaaaaaaaaaaaaaaaaaaaaaaaaaa`c", +"`aaaaaaaaaaaaaaaaaaaaaaaaaaaaa`c", +"`aaaaaaaaaaaaaaaaaaaaaaaaaaaaa`c", +"`aaaaaaaaaaaaaaaaaaaaaaaaaaaaa`c", +"`aaaaaaaaaaaaaaaaaaaaaaaaaaaaa`c", +"`aaaaaaaaaaaaaaaaaaaaaaaaaaaaa`c", +"`aaaaaaaaaaaaaaaaaaaaaaaaaaaaa`c", +"`aaaaaaaaaaaaaaaaaaaaaaaaaaaaa`c", +"`aaaaaaaaaaaaaaaaaaaaaaaaaaaaa`c", +"`bbbbbbbbbbbbbbbbbbbbbbbbbbbbb`c", +"```````````````````````````````c" +}; diff --git a/fvwm_icons/folders.xpm b/fvwm_icons/folders.xpm new file mode 100644 index 0000000..726f379 --- /dev/null +++ b/fvwm_icons/folders.xpm @@ -0,0 +1,58 @@ +/* XPM */ +static char * icl8_18139_xpm[] = { +/* width height ncolors chars_per_pixel */ +"32 32 20 1", +/* colors */ +" s None c None", +". c black", +"X c tan", +"o c wheat", +"O c #FFCC9A", +"+ c #FF9966", +"@ c #DDDDDD", +"# c #3399FF", +"$ c #9A6633", +"% c white", +"& c #0033FE", +"* c #FE0000", +"= c #663300", +"- c #888888", +"; c #000077", +": c #890000", +"? c #111111", +"> c #444444", +", c #777777", +"< c #BBBBBB", +/* pixels */ +" ", +" ...... ", +" .XXXXXX. ", +"............... ", +".ooooooooooooo. ", +".ooooooooooooo. ", +".ooooooooooooo. ", +".oooooooooooooo ", +".ooooooooooooo. ", +".ooooooooooooOO ", +".ooooooooooOO++++@#@ ", +".......o.oO++$$$$%&%* ", +" +$$$$$=-;-: ", +" +$$$$== ", +" +$$$$= ", +" +$$$= ? ", +" +$$$= > ", +" +$$$= ? , ", +" +$$= ?%> - ", +" +$$= >%, < ", +" @%- , X.X.X. ", +" #&; ?> XXXXXXX. ", +" @%- ,- XX.X.X.........", +" *: +#include + + +/************************************************************************ + * + * Concatentates 3 strings + * + *************************************************************************/ +char CatS[256]; + +char *CatString3(char *a, char *b, char *c) +{ + if (strlen(a)+strlen(b)+strlen(c) > 255) + { + return NULL; + } + strcpy(CatS, a); + strcat(CatS, b); + strcat(CatS, c); + return CatS; +} diff --git a/libs/CopyString.c b/libs/CopyString.c new file mode 100644 index 0000000..b268790 --- /dev/null +++ b/libs/CopyString.c @@ -0,0 +1,38 @@ +#include +#include +#include +#include "fvwmlib.h" +/*************************************************************************** + * + * A simple routine to copy a string, stripping spaces and mallocing + * space for the new string + ***************************************************************************/ +void CopyString(char **dest, char *source) +{ + int len; + char *start; + + while(((isspace(*source))&&(*source != '\n'))&&(*source != 0)) + { + source++; + } + len = 0; + start = source; + while((*source != '\n')&&(*source != 0)) + { + len++; + source++; + } + + source--; + while((isspace(*source))&&(*source != 0)&&(len >0)) + { + len--; + source--; + } + *dest = safemalloc(len+1); + strncpy(*dest,start,len); + (*dest)[len]=0; +} + + diff --git a/libs/GetFdWidth.c b/libs/GetFdWidth.c new file mode 100644 index 0000000..ac7ea3d --- /dev/null +++ b/libs/GetFdWidth.c @@ -0,0 +1,15 @@ +#include +#include +#include + +#include "../configure.h" + + +int GetFdWidth(void) +{ +#ifdef HAVE_SYSCONF + return sysconf(_SC_OPEN_MAX); +#else + return getdtablesize(); +#endif +} diff --git a/libs/Imakefile b/libs/Imakefile new file mode 100644 index 0000000..4580738 --- /dev/null +++ b/libs/Imakefile @@ -0,0 +1,18 @@ +/* Imakefile for fvwm 1.18c */ +/* Thu Aug 5 11:21:36 MET DST 1993, mj@dfv.rwth-aachen.de */ + +/* setup is done entirely in configuration.h now! */ +/* You should need to do much in here, excpt maybe add libraries */ + +/* I need to get the #define XPM from configuration.h if its in there, */ +/* so that I can tell if I should include -lXpm */ +#include <../configure.h> + +COMPILER + +OBJS = CatString3.o SendInfo.o SendText.o wild.o safemalloc.o findIconFile.o \ + mystrcasecmp.o strncmp.o hostname.o ReadPacket.o \ + sleep.o CopyString.o mygetostype.o GetFdWidth.o + +NormalLibraryTarget(fvwmlib, $(OBJS)) + diff --git a/libs/ReadPacket.c b/libs/ReadPacket.c new file mode 100644 index 0000000..6251fe6 --- /dev/null +++ b/libs/ReadPacket.c @@ -0,0 +1,57 @@ +#include +#include +#include "fvwmlib.h" +#include "../fvwm/module.h" + +/************************************************************************ + * + * Reads a single packet of info from fvwm. Prototype is: + * unsigned long header[3]; + * unsigned long *body; + * int fd[2]; + * void DeadPipe(int nonsense); /* Called if the pipe is no longer open + * + * ReadFvwmPacket(fd[1],header, &body); + * + * Returns: + * > 0 everything is OK. + * = 0 invalid packet. + * < 0 pipe is dead. (Should never occur) + * + **************************************************************************/ +int ReadFvwmPacket(int fd, unsigned long *header, unsigned long **body) +{ + int count,total,count2,body_length; + char *cbody; + extern void DeadPipe(int); + + if((count = read(fd,header,3*sizeof(unsigned long))) >0) + { + if(header[0] == START_FLAG) + { + body_length = header[2]-3; + *body = (unsigned long *) + safemalloc(body_length * sizeof(unsigned long)); + cbody = (char *)(*body); + total = 0; + while(total < body_length*sizeof(unsigned long)) + { + if((count2= + read(fd,&cbody[total], + body_length*sizeof(unsigned long)-total)) >0) + { + total += count2; + } + else if(count2 < 0) + { + DeadPipe(1); + } + } + } + else + count = 0; + } + if(count <= 0) + DeadPipe(1); + return count; +} diff --git a/libs/SendInfo.c b/libs/SendInfo.c new file mode 100644 index 0000000..bf9cfe9 --- /dev/null +++ b/libs/SendInfo.c @@ -0,0 +1,26 @@ +#include +#include + +/*********************************************************************** + * + * Procedure: + * SendInfo - send a command back to fvwm + * + ***********************************************************************/ +void SendInfo(int *fd,char *message,unsigned long window) +{ + int w; + + if(message != NULL) + { + write(fd[0],&window, sizeof(unsigned long)); + w=strlen(message); + write(fd[0],&w,sizeof(int)); + write(fd[0],message,w); + + /* keep going */ + w=1; + write(fd[0],&w,sizeof(int)); + } +} + diff --git a/libs/SendText.c b/libs/SendText.c new file mode 100644 index 0000000..6f90633 --- /dev/null +++ b/libs/SendText.c @@ -0,0 +1,24 @@ +#include +#include +/************************************************************************ + * + * Sends arbitrary text to fvwm + * + ***********************************************************************/ +void SendText(int *fd,char *message,unsigned long window) +{ + int w; + + if(message != NULL) + { + write(fd[0],&window, sizeof(unsigned long)); + + w=strlen(message); + write(fd[0],&w,sizeof(int)); + write(fd[0],message,w); + + /* keep going */ + w = 1; + write(fd[0],&w,sizeof(int)); + } +} diff --git a/libs/findIconFile.c b/libs/findIconFile.c new file mode 100644 index 0000000..5eccce1 --- /dev/null +++ b/libs/findIconFile.c @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include + +#include "fvwmlib.h" + +/**************************************************************************** + * + * Find the specified icon file somewhere along the given path. + * + * There is a possible race condition here: We check the file and later + * do something with it. By then, the file might not be accessible. + * Oh well. + * + ****************************************************************************/ +char *findIconFile(char *icon, char *pathlist, int type) +{ + char *path; + char *dir_end; + int l1,l2; + + if(icon != NULL) + l1 = strlen(icon); + else + l1 = 0; + + if(pathlist != NULL) + l2 = strlen(pathlist); + else + l2 = 0; + + path = safemalloc(l1 + l2 + 10); + *path = '\0'; + if (*icon == '/') + { + /* No search if icon begins with a slash */ + strcpy(path, icon); + return path; + } + + if ((pathlist == NULL) || (*pathlist == '\0')) + { + /* No search if pathlist is empty */ + strcpy(path, icon); + return path; + } + + /* Search each element of the pathlist for the icon file */ + while ((pathlist)&&(*pathlist)) + { + dir_end = strchr(pathlist, ':'); + if (dir_end != NULL) + { + strncpy(path, pathlist, dir_end - pathlist); + path[dir_end - pathlist] = 0; + } + else + strcpy(path, pathlist); + + strcat(path, "/"); + strcat(path, icon); + if (access(path, type) == 0) + return path; + strcat(path, ".gz"); + if (access(path, type) == 0) + return path; + + /* Point to next element of the path */ + if(dir_end == NULL) + pathlist = NULL; + else + pathlist = dir_end + 1; + } + /* Hmm, couldn't find the file. Return NULL */ + free(path); + return NULL; +} + + diff --git a/libs/fvwmlib.h b/libs/fvwmlib.h new file mode 100644 index 0000000..dd569b7 --- /dev/null +++ b/libs/fvwmlib.h @@ -0,0 +1,12 @@ +int mystrcasecmp(char *a, char *b); +int mystrncasecmp(char *a, char *b,int n); +char *CatString3(char *a, char *b, char *c); +int mygethostname(char *client, int namelen); +void SendText(int *fd,char *message,unsigned long window); +void SendInfo(int *fd,char *message,unsigned long window); +char *safemalloc(int); +char *findIconFile(char *icon, char *pathlist, int type); +int ReadFvwmPacket(int fd, unsigned long *header, unsigned long **body); +void CopyString(char **dest, char *source); +void sleep_a_little(int n); +int GetFdWidth(void); diff --git a/libs/hostname.c b/libs/hostname.c new file mode 100644 index 0000000..e2a7fbb --- /dev/null +++ b/libs/hostname.c @@ -0,0 +1,29 @@ +#include "../configure.h" + +#if HAVE_UNAME +/* define mygethostname() by using uname() */ + +#include + +int mygethostname(char *client, int length) +{ + struct utsname sysname; + + uname(&sysname); + strncpy(client,sysname.nodename,length); +} +#else +#if HAVE_GETHOSTNAME +/* define mygethostname() by using gethostname() :-) */ + +int mygethostname(char *client, int length) +{ + gethostname(client, length); +} +#else +int mygethostname(char *client, int length) +{ + *client = 0; +} +#endif +#endif diff --git a/libs/mygetostype.c b/libs/mygetostype.c new file mode 100644 index 0000000..37d171c --- /dev/null +++ b/libs/mygetostype.c @@ -0,0 +1,26 @@ +#include +#include "../configure.h" + +#if HAVE_UNAME +#include + +/* return a string indicating the OS type (i.e. "Linux", "SINIX-D", ... ) */ +int mygetostype(char *buf, int max) +{ + struct utsname sysname; + int ret; + + if ((ret = uname(&sysname)) == -1) + strcpy (buf,""); + else + strncat (strcpy(buf,""), sysname.sysname, max); + return ret; +} +#else +int mygetostype(char *buf, int max) +{ + strcpy (buf,""); + return -1; +} +#endif + diff --git a/libs/mystrcasecmp.c b/libs/mystrcasecmp.c new file mode 100644 index 0000000..bf83a31 --- /dev/null +++ b/libs/mystrcasecmp.c @@ -0,0 +1,29 @@ +#include +#include +#include + +int mystrcasecmp(char *s1,char *s2) +{ + int c1,c2; + int n,n2; + + n=strlen(s1); + n2=strlen(s2); + if(n!=n2) + return 1; + + for (;;) + { + c1 = *s1; + c2 = *s2; + if (!c1 || !c2) + return(c1 - c2); + if (isupper(c1)) + c1 = 'a' - 1 + (c1 & 31); + if (isupper(c2)) + c2 = 'a' - 1 + (c2 & 31); + if (c1 != c2) + return(c1 - c2); + n--,s1++,s2++; + } +} diff --git a/libs/safemalloc.c b/libs/safemalloc.c new file mode 100644 index 0000000..2aea3b9 --- /dev/null +++ b/libs/safemalloc.c @@ -0,0 +1,27 @@ +#include +#include + +/*********************************************************************** + * + * Procedure: + * safemalloc - mallocs specified space or exits if there's a + * problem + * + ***********************************************************************/ +char *safemalloc(int length) +{ + char *ptr; + + if(length <= 0) + length = 1; + + ptr = malloc(length); + if(ptr == (char *)0) + { + fprintf(stderr,"malloc of %d bytes failed. Exiting\n",length); + exit(1); + } + return ptr; +} + + diff --git a/libs/sleep.c b/libs/sleep.c new file mode 100644 index 0000000..dfe571e --- /dev/null +++ b/libs/sleep.c @@ -0,0 +1,24 @@ +#include +#if defined ___AIX || defined _AIX || defined __QNX__ || defined ___AIXV3 || defined AIXV3 || defined _SEQUENT_ +#include +#endif + +/************************************************************************** + * + * Sleep for n microseconds + * + *************************************************************************/ +void sleep_a_little(int n) +{ + struct timeval value; + + if (n <= 0) + return; + + value.tv_usec = n % 1000000; + value.tv_sec = n / 1000000; + + (void) select(1, 0, 0, 0, &value); +} + + diff --git a/libs/strncmp.c b/libs/strncmp.c new file mode 100644 index 0000000..c76be38 --- /dev/null +++ b/libs/strncmp.c @@ -0,0 +1,19 @@ +#include +#include +#include + +int mystrncasecmp(char *s1,char *s2,int n) +{ + register int c1,c2; + + for (;;) + { + if (!n) return(0); + c1 = *s1,c2 = *s2; + if (!c1 || !c2) return(c1 - c2); + if (isupper(c1)) c1 = 'a' - 1 + (c1 & 31); + if (isupper(c2)) c2 = 'a' - 1 + (c2 & 31); + if (c1 != c2) return(c1 - c2); + n--,s1++,s2++; + } +} diff --git a/libs/wild.c b/libs/wild.c new file mode 100644 index 0000000..71805cd --- /dev/null +++ b/libs/wild.c @@ -0,0 +1,75 @@ +#include + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +/***************************************************************************** + * Does `string' match `pattern'? '*' in pattern matches any sub-string + * (including the null string) '?' matches any single char. For use + * by filenameforall. Note that '*' matches across directory boundaries + * + * This code donated by Paul Hudson + * It is public domain, no strings attached. No guarantees either. + * + *****************************************************************************/ +int matchWildcards(char *pattern, char *string) +{ + if(string == NULL) + { + if(pattern == NULL) + return TRUE; + else if(strcmp(pattern,"*")==0) + return TRUE; + else + return FALSE; + } + if(pattern == NULL) + return TRUE; + + while (*string && *pattern) + { + if (*pattern == '?') + { + /* match any character */ + pattern += 1; + string += 1; + } + else if (*pattern == '*') + { + /* see if the rest of the pattern matches any trailing substring + of the string. */ + pattern += 1; + if (*pattern == 0) + { + return TRUE; /* trailing * must match rest */ + } + while (*string) + { + if (matchWildcards(pattern,string)) + { + return TRUE; + } + string++; + } + return FALSE; + } + else + { + if (*pattern == '\\') + pattern ++; /* has strange, but harmless effects if the last + character is a '\\' */ + if (*pattern++ != *string++) + { + return FALSE; + } + } + } + if((*pattern == 0)&&(*string == 0)) + return TRUE; + if((*string == 0)&&(strcmp(pattern,"*")==0)) + return TRUE; + return FALSE; +} + diff --git a/modules/FvwmAudio/FvwmAudio.c b/modules/FvwmAudio/FvwmAudio.c new file mode 100644 index 0000000..754b1bc --- /dev/null +++ b/modules/FvwmAudio/FvwmAudio.c @@ -0,0 +1,503 @@ +/* + * Copyright (C) 1994 Mark Boyns (boyns@sdsu.edu) and + * Mark Scott (mscott@mcd.mot.com) + * + * FvwmAudio version 1.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* ChangeLog + + * Fixed FvwmAudio to reflect the changes made to the module protocol. + + * Szijarto Szabolcs provided FvwmSound code that used + $HOSTDISPLAY for the rplay host. The code has been added to FvwmAudio. + + * Fixed bugs reported by beta testers, thanks! + + * Builtin rplay support has been added to FvwmAudio. This support is + enabled when FvwmAudio is compiled with HAVE_RPLAY defined and when + FvwmAudioPlayCmd is set to builtin-rplay. I guess it's safe to say + that FvwmSound is now obsolete. -- Mark Boyns 5/7/94 + + * FvwmAudio is based heavily on an Fvwm module "FvwmSound" by Mark Boyns + and the real credit for this really goes to him for the concept. + I just stripped out the "rplay" library dependencies to allow generic + audio play command support. + + */ + +/* + * This module is based on FvwmModuleDebugger which has the following + * copyright: + * + * This module, and the entire ModuleDebugger program, and the concept for + * interfacing this module to the Window Manager, are all original work + * by Robert Nation + * + * Copyright 1994, Robert Nation. No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. + */ + +/* + * fvwm includes: + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../configure.h" +#include "../../fvwm/module.h" +#include "../../version.h" +#include "../../libs/fvwmlib.h" + +/* + * rplay includes: + */ +#ifdef HAVE_RPLAY +#include +#endif + +#define BUILTIN_STARTUP MAX_MESSAGES +#define BUILTIN_SHUTDOWN MAX_MESSAGES+1 +#define BUILTIN_UNKNOWN MAX_MESSAGES+2 +#define MAX_BUILTIN 3 + +#define BUFSIZE 512 + +/* globals */ +char *MyName; +int fd_width; +int fd[2]; +char audio_play_cmd_line[BUFSIZE], audio_play_dir[BUFSIZE]; +time_t audio_delay = 0; /* seconds */ +#ifdef HAVE_RPLAY +int rplay_fd = -1; +#endif + +/* prototypes */ +void Loop(int *); +void process_message(unsigned long,unsigned long *); +void DeadPipe(int); +void config(char *); +void done(int); +int audio_play(short); + +/* define the message table */ +char *messages[MAX_MESSAGES+MAX_BUILTIN] = +{ + "toggle_paging", + "new_page", + "new_desk", + "add_window", + "raise_window", + "lower_window", + "configure_window", + "focus_change", + "destroy_window", + "iconify", + "deiconify", + "window_name", + "icon_name", + "res_class", + "res_name", + "end_windowlist", + "icon_location", + "map", +/* add builtins here */ + "startup", + "shutdown", + "unknown", +}; + +/* define the sound table */ +char *sound_table[MAX_MESSAGES+MAX_BUILTIN]; + +#ifdef HAVE_RPLAY +/* define the rplay table */ +RPLAY *rplay_table[MAX_MESSAGES+MAX_BUILTIN]; +#endif + +main(int argc, char **argv) +{ + char *temp, *s; + + if ((argc != 6)&&(argc != 7)) + { + fprintf(stderr,"%s Version %s should only be executed by fvwm!\n", + MyName, VERSION); + exit(1); + } + + /* Save our program name - for error messages */ + temp = argv[0]; + s=strrchr(argv[0], '/'); + if (s != NULL) + temp = s + 1; + + MyName = safemalloc(strlen(temp)+2); + strcpy(MyName,"*"); + strcat(MyName, temp); + + /* Dead pipe == Fvwm died */ + signal (SIGPIPE, DeadPipe); + + fd[0] = atoi(argv[1]); + fd[1] = atoi(argv[2]); + + audio_play_dir[0] = '\0'; + audio_play_cmd_line[0] = '\0'; + + /* + * Read the sound configuration. + */ + config(argv[3]); + + /* + * Play the startup sound. + */ + audio_play(BUILTIN_STARTUP); + SendText(fd,"Nop",0); + Loop(fd); +} + +/*********************************************************************** + * + * Procedure: + * config - read the sound configuration file. + * + ***********************************************************************/ +void config(char *config_file) +{ + FILE *fp; + char buf[BUFSIZE]; + char *message; + char *sound; + char *p; + int i, found; +#ifdef HAVE_RPLAY + char host[128]; + int volume = RPLAY_DEFAULT_VOLUME; + int priority = RPLAY_DEFAULT_PRIORITY; +#endif + + fp = fopen(config_file, "r"); + if (fp == NULL) + { + done(1); + } + + /* + * Intialize all the sounds. + */ + for (i = 0; i < MAX_MESSAGES+MAX_BUILTIN; i++) { + sound_table[i] = NULL; +#ifdef HAVE_RPLAY + rplay_table[i] = NULL; +#endif + } + +#ifdef HAVE_RPLAY + strcpy(host, rplay_default_host()); +#endif + + while (fgets(buf, sizeof(buf), fp)) + { + buf[strlen(buf)-1] = '\0'; + if (buf[0] != '*') + { + continue; + } + /* + * Search for *FvwmAudio. + */ + if (mystrncasecmp(buf, MyName, strlen(MyName)) == 0) + { + p = strtok(buf, " \t"); + + if (mystrcasecmp(p, "*FvwmAudioPlayCmd") == 0) { + p = strtok(NULL, "\n"); /* allow parameters */ + if (p && *p) { + strcpy(audio_play_cmd_line, p); + } + } + else if (mystrcasecmp(p, "*FvwmAudioDir") == 0) { + p = strtok(NULL, " \t"); + if (p && *p) { + strcpy(audio_play_dir, p); + } + } + else if (mystrcasecmp(p, "*FvwmAudioDelay") == 0) { + p = strtok(NULL, " \t"); + if (p && *p) { + audio_delay = atoi(p); + } + } + +#ifdef HAVE_RPLAY + /* + * Check for rplay configuration options. + */ + else if (mystrcasecmp(p, "*FvwmAudioRplayHost") == 0) + { + p = strtok(NULL, " \t"); + if (p && *p) + { + /* + * Check for environment variables like $HOSTDISPLAY. + */ + if (*p == '$') + { + char *c1, *c2; + c2 = host; + for (c1 = (char *)getenv(p+1); *c1 && (*c1 != ':'); c1++) + { + *c2++ = *c1; + } + *c2 = '\0'; + } + else + { + strcpy(host, p); + } + } + } + else if (mystrcasecmp(p, "*FvwmAudioRplayVolume") == 0) + { + p = strtok(NULL, " \t"); + if (p && *p) { + volume = atoi(p); + } + } + else if (mystrcasecmp(p, "*FvwmAudioRplayPriority") == 0) + { + p = strtok(NULL, " \t"); + if (p && *p) { + priority = atoi(p); + } + } +#endif + /* + * *FvwmAudio + */ + else { + message = strtok(NULL, " \t"); + sound = strtok(NULL, " \t"); + + if (!message || !*message || !sound || !*sound) + { + continue; + } + + found = 0; + + for (i = 0; !found && i < MAX_MESSAGES+MAX_BUILTIN; i++) + { + if (mystrcasecmp(message, messages[i]) == 0) { +#ifdef HAVE_RPLAY + rplay_table[i] = rplay_create(RPLAY_PLAY); + rplay_set(rplay_table[i], RPLAY_APPEND, + RPLAY_SOUND, sound, + RPLAY_PRIORITY, priority, + RPLAY_VOLUME, volume, + NULL); +#endif + sound_table[i]=safemalloc(strlen(sound)+1); + strcpy(sound_table[i],sound); + found++; + } + } + } + } + } + + fclose(fp); + +#ifdef HAVE_RPLAY + /* + * Builtin rplay support is enabled when FvwmAudioPlayCmd == builtin-rplay. + */ + if (mystrcasecmp(audio_play_cmd_line, "builtin-rplay") == 0) + { + rplay_fd = rplay_open(host); + if (rplay_fd < 0) + { + rplay_perror("rplay_open"); + done(1); + } + } +#endif +} + +/*********************************************************************** + * + * Procedure: + * Loop - wait for data to process + * + ***********************************************************************/ +void Loop(int *fd) +{ + unsigned long header[3], *body; + char *cbody; + int body_length,count,count2=0, total; + time_t now, last_time = 0; + unsigned long code; + + while (1) + { + if ((count = read(fd[1],header,3*sizeof(unsigned long))) > 0) + { + /* + * Ignore messages that occur during the delay + * period. + */ + now = time(0); + if (now < (last_time + audio_delay)) + { + continue; + } + last_time = now; + + if(header[0] == START_FLAG) + { + body_length = header[2]-3; + body = (unsigned long *) + safemalloc(body_length * sizeof(unsigned long)); + cbody = (char *)body; + total = 0; + while(total < body_length*sizeof(unsigned long)) + { + if((count2=read(fd[1],&cbody[total], + body_length*sizeof(unsigned long)-total)) >0) + total += count2; + else if(count2 < 0) + DeadPipe(0); + } + + /* + * code will equal the number of shifts in the + * base-2 header[1] number. Could use log here + * but this should be fast enough. + */ + code = -1; + while (header[1]) + { + code++; + header[1] >>= 1; + } + + /* + * Play the sound. + */ + if (code >= 0 && code < MAX_MESSAGES) + { + audio_play(code); + } + else + { + audio_play(BUILTIN_UNKNOWN); + } + + free(body); + } + } + if(count <= 0) + DeadPipe(1); + } +} + + +/*********************************************************************** + * + * Procedure: + * SIGPIPE handler - SIGPIPE means fvwm is dying + * + ***********************************************************************/ +void DeadPipe(int nonsense) +{ + done(0); +} + +/*********************************************************************** + * + * Procedure: + * done - common exit point for FvwmAudio. + * + ***********************************************************************/ +void done(int n) +{ + audio_play(BUILTIN_SHUTDOWN); + exit(n); +} + +/*********************************************************************** + * + * Procedure: + * + * audio_play - actually plays sound from lookup table + * + **********************************************************************/ +int audio_play(short sound) +{ + static char buf[BUFSIZE]; + +#ifdef HAVE_RPLAY + if (rplay_fd != -1) + { + if (rplay_table[sound]) + { + if (rplay(rplay_fd, rplay_table[sound]) < 0) + { + rplay_perror("rplay"); + } + } + return 0; + } +#endif + + if (sound_table[sound]) + { + memset(buf,NULL,BUFSIZE); + + /* + * Don't use audio_play_dir if it's NULL or if the sound file + * is an absolute pathname. + */ + if (audio_play_dir[0] == '\0' || sound_table[sound][0] == '/') + { + sprintf(buf,"%s %s", audio_play_cmd_line, sound_table[sound]); + } + else + { + sprintf(buf,"%s %s/%s", audio_play_cmd_line, audio_play_dir, + sound_table[sound]); + } + return system(buf); + } + + return 1; +} + + + + diff --git a/modules/FvwmAudio/FvwmAudio.man b/modules/FvwmAudio/FvwmAudio.man new file mode 100644 index 0000000..fa177ca --- /dev/null +++ b/modules/FvwmAudio/FvwmAudio.man @@ -0,0 +1,125 @@ +.\" t +.\" @(#)FvwmAudio.1 3/28/94 +.TH FvwmAudio 1.0 "Mar 28 1994" +.UC +.SH NAME +\fBFvwmAudio\fP \- the FVWM Audio module +.SH SYNOPSIS +\fBFvwmAudio\fP is spawned by \fBfvwm\fP, so no command line invocation will +work. From within the \fI.fvwmrc\fP file, \fBFvwmAudio\fP is spawned as +follows: +.nf +.sp +Module FvwmAudio +.sp +.fi +or from within an fvwm pop-up menu: +.nf +.sp +Popup "Module-Popup" + Title "Modules" + Module "GoodStuff" GoodStuff + Module "NoClutter" FvwmClean + Module "FvwmIdentify" FvwmIdent + Module "Banner" FvwmBanner + Module "Debug" FvwmDebug + Module "Audio" FvwmAudio + Module "Pager" FvwmPager 0 3 +EndPopup +.sp +.fi +.SH DESCRIPTION +The \fBFvwmAudio\fP module communicates with the Fvwm window manager to bind +audio sounds to window manager actions. Different audio queues may be +assigned to any window manager action. \fBFvwmAudio\fP can be used with +any independent audio player, and therefore requires no special audio library +APIs of its own. Simple in its design, it merely binds the audio filenames +to particular actions and forks off the audio player program with the +appropriate filename when that action occurs. + +\fBFvwmAudio\fP can also have builtin support for the rplay library. + +.SH CONFIGURATION OPTIONS +\fBFvwmAudio\fP reads the same \fI.fvwmrc\fP file as \fBfvwm(1)\fP reads when +it starts up, and looks for certain configuration options: + +.IP "*FvwmAudioPlayCmd \fI/usr/bin/X11/demos/auplay\fP" +This determines the independent audio player program that will actually +play the sounds. If the play command is set to \fIbuiltin-rplay\fP +then the builtin rplay support will be used. For example: +.sp +*FvwmAudioPlayCmd \fIbuiltin-rplay\fP + +.IP "*FvwmAudioDir \fI/usr/lib/sounds\fP" +Specifies the directory to look for the audio files. This option +is ignored when rplay is used. + +.IP "*FvwmAudioDelay \fI5\fP" +Specifies that sound events will only be played if they occur +at least 5 seconds after the previous event. Sounds events that +occur during the delay period are ignored. This option is useful if +you don't want several sounds playing at the same time. The default +delay is 0 which disables the audio delay. + +.IP "*FvwmAudioRplayHost \fIhostname\fP" +Specifies what host the sounds will play on. The \fIhostname\fP +can also be an environment variable such as $HOSTDISPLAY. +This option is only valid with builtin rplay support. + +.IP "*FvwmAudioRplayPriority \fI0\fP" +Specifies what priority will be assigned to the sounds when they +are played. This option is only valid with builtin rplay support. + +.IP "*FvwmAudioRplayVolume \fI127\fP" +Specifies what volume will be assigned to the sounds when they +are played. This option is only valid with builtin rplay support. + +.IP "*FvwmAudio \fIwindow-manager_action audio_filename\fP" +Binds particular window manager actions to sound queues. +.nf +.sp +*FvwmAudio startup TaDa.au +*FvwmAudio shutdown Elvis_Left.au +*FvwmAudio unknown doh.au +*FvwmAudio add_window drip.au +*FvwmAudio raise_window swoosh.au +*FvwmAudio lower_window swoosh.au +*FvwmAudio focus_change boing.au +*FvwmAudio destroy_window explosion.au +*FvwmAudio iconify ploop.au +*FvwmAudio deiconify ploop.au +*FvwmAudio toggle_paging fwop.au +*FvwmAudio new_page beam_trek.au +*FvwmAudio new_desk beam_trek.au +*FvwmAudio configure_window huh.au +*FvwmAudio window_name beep.au +*FvwmAudio icon_name beep.au +*FvwmAudio res_class beep.au +*FvwmAudio res_name beep.au +*FvwmAudio end_windowlist twang.au +.sp +.fi +.SH INVOCATION +The invocation method was shown in the synopsis section. No command line +invocation is possible. \fBFvwmAudio\fP must be invoked by the \fBfvwm\fP +window manager. +.sp +.SH BUGS +It's REALLY noisy when fvwm starts and restarts. +.sp +.SH COPYRIGHTS +This module is heavily based on a similar Fvwm module called \fBFvwmSound\fP +by Mark Boyns. \fBFvwmAudio\fP simply takes Mark's original program and extends +it to make it generic enough to work with any audio player. The concept for +interfacing this module to the Window Manager, is original work by Robert +Nation. + +Copyright 1994, Mark Boyns and Mark Scott. No guarantees or warranties or +anything are provided or implied in any way whatsoever. Use this program at +your own risk. Permission to use this program for any purpose is given, +as long as the copyright is kept intact. +.sp +.SH AUTHORS +Mark Boyns (\fIboyns@sdsu.edu\fP) +.sp +Mark Scott (\fImscott@mcd.mot.com\fP) diff --git a/modules/FvwmAudio/Imakefile b/modules/FvwmAudio/Imakefile new file mode 100644 index 0000000..ef63b76 --- /dev/null +++ b/modules/FvwmAudio/Imakefile @@ -0,0 +1,45 @@ +/* + * Imakefile for FvwmAudio. + */ + +#include "../../configure.h" +COMPILER +/* + * Uncomment the line below to add builtin support for the + * rplay library. Also make sure that the AUDIO_* settings + * are correct for your rplay installation. + */ + +/* #define HAVE_RPLAY */ + + +#ifdef HAVE_RPLAY +AUDIO_DEFINES = -DHAVE_RPLAY +AUDIO_INCLUDES = -I/usr/local/include +AUDIO_LIBRARIES = -L/usr/local/lib -lrplay +#else +AUDIO_DEFINES = +AUDIO_INCLUDES = +AUDIO_LIBRARIES = +#endif + +EXTRA_DEFINES = $(AUDIO_DEFINES) +EXTRA_INCLUDES = $(AUDIO_INCLUDES) +EXTRA_LIBRARIES = $(AUDIO_LIBRARIES) + +DEPLIBS = $(DEPXLIB) ../../libs/libfvwmlib.a + +#ifdef AlphaArchitecture +LOCAL_LIBRARIES = -ldnet_stub -L../../libs -lfvwmlib +#else +LOCAL_LIBRARIES = -L../../libs -lfvwmlib +#endif + +LINTLIBS = $(LINTXLIB) + +SRCS = FvwmAudio.c +OBJS = FvwmAudio.o +TARGET_DIR + +ComplexProgramTarget(FvwmAudio) + diff --git a/modules/FvwmAudio/README b/modules/FvwmAudio/README new file mode 100644 index 0000000..cb5a712 --- /dev/null +++ b/modules/FvwmAudio/README @@ -0,0 +1,37 @@ +This is the first version of the FvwmAudio module. This program must +be compiled in the fvwm/modules/FvwmAudio directory. + +This module can play different sounds depending on message types. + +The following can be specified in your .fvwmrc: + +Here's a sample: +*FvwmAudioPlayCmd /usr/bin/X11/demos/auplay +*FvwmAudioDir /usr/lib/sounds +*FvwmAudio startup Cheers.au +*FvwmAudio shutdown Goodbye.au +*FvwmAudio unknown doh.au +*FvwmAudio add_window drip.au +*FvwmAudio raise_window beep_pure_saw.au +*FvwmAudio lower_window beep_pure_saw.au +*FvwmAudio focus_change tap2.au +*FvwmAudio destroy_window beep_drop_of_water.au +*FvwmAudio iconify ploop.au +*FvwmAudio deiconify beep_kind_warning.au + +Note that startup, shutdown, and unknown are builtin sound events that are +played when the module begins, ends, and when an unknown message is received. + +Sounds can be played using any independent audio player that can accept +filenames a command line argument. + +This version of FvwmAudio has builtin rplay support which does not need to +invoke an external audio player to play sounds. The rplay support is +enabled when FvwmAudio is compiled with HAVE_RPLAY defined (see the Imakefile) +and when FvwmAudioPlayCmd is set to builtin-rplay. rplay can be obtained +via anonymous ftp at ftp.sdsu.edu in the /pub/rplay directory and at +ftp.x.org in the /contrib/audio/rplay directory. + +Send questions and comments to Mark Boyns and + Mark Scott + diff --git a/modules/FvwmAuto/FvwmAuto.c b/modules/FvwmAuto/FvwmAuto.c new file mode 100644 index 0000000..b95906b --- /dev/null +++ b/modules/FvwmAuto/FvwmAuto.c @@ -0,0 +1,170 @@ +/* This module, and the entire FvwmAuto program, and the concept for + * interfacing this module to the Window Manager, are all original work + * by Robert Nation + * + * Copyright 1994, Robert Nation. No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. */ + +#define TRUE 1 +#define FALSE + +#include "../../configure.h" +#ifdef ISC +#include /* Saul */ +#endif + +#include +#include +#include +#include +#include +#include +#if defined ___AIX || defined _AIX || defined __QNX__ || defined ___AIXV3 || defined AIXV3 || defined _SEQUENT_ +#include +#endif +#include +#include +#include +#include "../../fvwm/module.h" +#include "../../libs/fvwmlib.h" +#include "../../version.h" + +int fd_width; +int fd[2]; +int timeout, t_secs, t_usecs; + +/************************************************************************* + * + * Subroutine Prototypes + * + *************************************************************************/ +void Loop(int *fd); +void DeadPipe(int nonsense); + +#ifdef BROKEN_SUN_HEADERS +#include "../../fvwm/sun_headers.h" +#endif + +#ifdef NEEDS_ALPHA_HEADER +#include "../../fvwm/alpha_header.h" +#endif /* NEEDS_ALPHA_HEADER */ + +/*********************************************************************** + * + * Procedure: + * main - start of module + * + ***********************************************************************/ +void main(int argc, char **argv) +{ + FILE *file; + char mask_mesg[80]; + + if(argc != 7) + { + fprintf(stderr,"FvwmAuto requires one argument.\n"); + exit(1); + } + + /* Dead pipes mean fvwm died */ + signal (SIGPIPE, DeadPipe); + + fd[0] = atoi(argv[1]); + fd[1] = atoi(argv[2]); + + timeout = atoi(argv[6]); + t_secs = timeout/1000; + t_usecs = (timeout - t_secs*1000)*1000; + + fd_width = GetFdWidth(); + sprintf(mask_mesg,"SET_MASK %lu\n",(unsigned long)(M_FOCUS_CHANGE)); + SendInfo(fd,mask_mesg,0); + Loop(fd); +} + + +/*********************************************************************** + * + * Procedure: + * Loop - wait for data to process + * + ***********************************************************************/ +unsigned long focus_win = 0; + +void Loop(int *fd) +{ + unsigned long header[3], *body; + fd_set in_fdset; + struct itimerval value; + int retval; + int Raised = 0; + + while(1) + { + FD_ZERO(&in_fdset); + FD_SET(fd[1],&in_fdset); + + /* set up a time-out, in case no packets arrive before we have to + * iconify something */ + value.it_value.tv_usec = t_usecs; + value.it_value.tv_sec = t_secs; + +#ifdef __hpux + if((timeout > 0)&&(Raised == 0)) + retval=select(fd_width,(int *)&in_fdset, 0, 0, &value.it_value); + else + retval=select(fd_width,(int *)&in_fdset, 0, 0, NULL); +#else + if((timeout > 0)&&(Raised == 0)) + retval=select(fd_width,&in_fdset, 0, 0, &value.it_value); + else + retval=select(fd_width,&in_fdset, 0, 0, NULL); +#endif + + if(FD_ISSET(fd[1], &in_fdset)) + { + /* read a packet */ + if(ReadFvwmPacket(fd[1],header, &body) > 0) + { + if(header[1] == M_FOCUS_CHANGE) + { + focus_win = body[0]; + if(focus_win != 0) + Raised = 0; + if(timeout == 0) + { + if(focus_win != 0) + SendInfo(fd,"Raise",focus_win); + Raised = 1; + } + } + free(body); + } + } + else + { + /* Raise the current focus window */ + Raised = 1; + if(focus_win != 0) + { + SendInfo(fd,"Raise",focus_win); + } + } + } +} + + + +/*********************************************************************** + * + * Procedure: + * SIGPIPE handler - SIGPIPE means fvwm is dying + * + ***********************************************************************/ +void DeadPipe(int nonsense) +{ + exit(0); +} + diff --git a/modules/FvwmAuto/FvwmAuto.man b/modules/FvwmAuto/FvwmAuto.man new file mode 100644 index 0000000..51bc2e1 --- /dev/null +++ b/modules/FvwmAuto/FvwmAuto.man @@ -0,0 +1,35 @@ +.\" t +.\" @(#)FvwmAuto.1 12/1/94 +.TH FvwmAuto 2.0 "Dec 1, 1994" +.UC +.SH NAME +FvwmAuto \- the FVWM auto-raise module +.SH SYNOPSIS +FvwmAuto is spawned by fvwm, so no command line invocation will work. +An appropriate invocation from fvwm looks like: +.nf +.sp +Module FvwmAuto 200 +.sp +.fi +or, from a menu: +Popup "Module-Popup" + Title "Modules" + Module "GoodStuff" GoodStuff + Module "NoClutter" FvwmClean + Module "FvwmIdentify" FvwmIdent + Module "Banner" FvwmBanner + Module "Debug" FvwmDebug + Module "SaveDesktop" FvwmSave + Module "AutoRaise" FvwmAuto 200 +EndPopup +.sp +.fi + +The numeric argument is required. It specified how long a window +must retain the keyboard input focus before it is raised. The delay +is measured in milliseconds, and any integer 0 or greater is acceptable. + +.SH AUTHOR +FvwmAuto just appeared one day, nobody knows how. + diff --git a/modules/FvwmAuto/Imakefile b/modules/FvwmAuto/Imakefile new file mode 100644 index 0000000..f3d2602 --- /dev/null +++ b/modules/FvwmAuto/Imakefile @@ -0,0 +1,30 @@ +/* Imakefile for FvwmAuto */ +/* Thu Aug 5 11:21:36 MET DST 1993, mj@dfv.rwth-aachen.de */ + +/* setup is done entirely in configuration.h now! */ +/* You should need to do much in here, excpt maybe add libraries */ + +/* I need to get the #define XPM from configuration.h if its in there,*/ +/* so that I can tell if I should include -lXpm */ +#include <../../configure.h> + +COMPILER + + +DEPLIBS = $(DEPXLIB) ../../libs/libfvwmlib.a + +#ifdef AlphaArchitecture +LOCAL_LIBRARIES = -ldnet_stub -L../../libs -lfvwmlib +#else +LOCAL_LIBRARIES = -L../../libs -lfvwmlib +#endif + +LINTLIBS = $(LINTXLIB) + +SRCS = FvwmAuto.c +OBJS = FvwmAuto.o + +TARGET_DIR + +ComplexProgramTarget(FvwmAuto) + diff --git a/modules/FvwmBacker/FvwmBacker.README b/modules/FvwmBacker/FvwmBacker.README new file mode 100644 index 0000000..197ca04 --- /dev/null +++ b/modules/FvwmBacker/FvwmBacker.README @@ -0,0 +1,36 @@ +This is version 0.1 of the FvwmBacker module. + +Description: This is a pretty simple module. When the desktop number changes, + it will execute the user specified command to change the + background. Like I said, pretty simple. This was a quickly + written module, so please let me know of any bugs. + +To do: +----- + - Change the system call to be fork/exec calls. + + +I am open to, actually I am trolling for, suggestions/improvments/ideas/rags +on this. + +Here is a list of files included in the tar file: + +FvwmBacker.README +FvwmBacker.c +FvwmBacker.h +FvwmBacker.man +Imakefile +Mallocs.c +Mallocs.h +xsetroot_bits.c + +You can unpack it by: + +cd /foo/fvwm/modules +gzip -dc FvwmBacker-0.1.tar.gz | tar xf - + +That will unpack the source into /foo/fvwm/modules/FvwmBacker. + +Enjoy, +Mike +mfinger@mermaid.micro.umn.edu or Mike_Finger@atk.com diff --git a/modules/FvwmBacker/FvwmBacker.c b/modules/FvwmBacker/FvwmBacker.c new file mode 100644 index 0000000..d991f47 --- /dev/null +++ b/modules/FvwmBacker/FvwmBacker.c @@ -0,0 +1,384 @@ +/* FvwmBacker Module for Fvwm. + * + * Copyright 1994, Mike Finger (mfinger@mermaid.micro.umn.edu or + * Mike_Finger@atk.com) + * + * The author makes not guarantees or warantees, either express or + * implied. Feel free to use any contained here for any purpose, as long + * and this and any other applicible copyrights are kept intact. + + * The functions in this source file that are based on part of the FvwmIdent + * module for Fvwm are noted by a small copyright atop that function, all others + * are copyrighted by Mike Finger. For those functions modified/used, here is + * the full, origonal copyright: + * + * Copyright 1994, Robert Nation and Nobutaka Suzuki. + * No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. */ + +/* Modified to directly manipulate the X server if a solid color + * background is requested. To use this, usr "-solid " + * as the command to be executed. + * + * A. Davison + * Septmber 1994. + */ +#include "../../configure.h" + +#include +#include +#include +#include +#include +#include +#if defined ___AIX || defined _AIX || defined __QNX__ || defined ___AIXV3 || defined AIXV3 || defined _SEQUENT_ +#include +#endif +#include +#include +#ifdef ISC /* Saul */ +#include /* Saul */ +#endif /* Saul */ +#include + +#include "../../fvwm/module.h" +#include "../../version.h" +#include "FvwmBacker.h" +#include "Mallocs.h" + +#include + +unsigned long NameToPixel(char*, unsigned long); + +typedef struct +{ + int type; /* The command type. */ + /* -1 = no command. */ + /* 0 = command to be spawned */ + /* 1 = a solid color to be set */ + char* cmdStr; /* The command string (Type 0) */ + unsigned long solidColor; + /* A solid color after X parsing (Type 1) */ +} Command; + +Command *commands; +int DeskCount=0; + +int Fvwm_fd[2]; +int fd_width; + +char *Module; + +/* X Display information. */ + +Display* dpy; +Window root; +int screen; + +FILE* logFile; + +/* Comment this out if you don't want a logfile. */ + +/* #define LOGFILE "/tmp/FvwmBacker.log"*/ + + +void main(int argc, char **argv) +{ +char *temp, *s; + char* displayName = NULL; + + commands=NULL; + + /* Save the program name for error messages and config parsing */ + temp = argv[0]; + s=strrchr(argv[0], '/'); + if (s != NULL) + temp = s + 1; + + Module=temp; + + if((argc != 6)&&(argc != 7)) { + fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",Module, + VERSION); + exit(1); + } + + Fvwm_fd[0] = atoi(argv[1]); + Fvwm_fd[1] = atoi(argv[2]); + + /* Grab the X display information now. */ + + dpy = XOpenDisplay(displayName); + if (!dpy) + { + fprintf(stderr, "%s: unable to open display '%s'\n", + Module, XDisplayName (displayName)); + exit (2); + } + screen = DefaultScreen(dpy); + root = RootWindow(dpy, screen); + + /* Open a log file if necessary */ +# ifdef LOGFILE + logFile = fopen(LOGFILE,"a"); + fprintf(logFile,"Initialising FvwmBacker\n"); +# endif + + signal (SIGPIPE, DeadPipe); + + /* Parse the config file */ + ParseConfig(argv[3]); + + fd_width = GetFdWidth(); + + /* Request a list of all windows, + * wait for ConfigureWindow packets */ + SendFvwmPipe("Send_WindowList",0); + + /* Recieve all messages from Fvwm */ + EndLessLoop(); +} + +/****************************************************************************** + EndLessLoop - Read until we get killed, blocking when can't read +******************************************************************************/ +void EndLessLoop() +{ +fd_set readset; +struct timeval tv; + + while(1) { + FD_ZERO(&readset); + FD_SET(Fvwm_fd[1],&readset); + tv.tv_sec=0; + tv.tv_usec=0; +#ifdef __hpux + if (!select(fd_width,(int *)&readset,NULL,NULL,&tv)) { + FD_ZERO(&readset); + FD_SET(Fvwm_fd[1],&readset); + select(fd_width,(int *)&readset,NULL,NULL,NULL); + } +#else + if (!select(fd_width,&readset,NULL,NULL,&tv)) { + FD_ZERO(&readset); + FD_SET(Fvwm_fd[1],&readset); + select(fd_width,&readset,NULL,NULL,NULL); + } +#endif + + if (!FD_ISSET(Fvwm_fd[1],&readset)) continue; + ReadFvwmPipe(); + } +} + +/****************************************************************************** + ReadFvwmPipe - Read a single message from the pipe from Fvwm + Originally Loop() from FvwmIdent: + Copyright 1994, Robert Nation and Nobutaka Suzuki. +******************************************************************************/ +void ReadFvwmPipe() +{ + int count,total,count2=0,body_length; + unsigned long header[3],*body; + char *cbody; + + body = NULL; + if(count = ReadFvwmPacket(Fvwm_fd[1],header,&body) > 0) + { + ProcessMessage(header[1],body); + free(body); + } +} + + +/****************************************************************************** + ProcessMessage - Process the message coming from Fvwm + Skeleton based on processmessage() from FvwmIdent: + Copyright 1994, Robert Nation and Nobutaka Suzuki. +******************************************************************************/ +void ProcessMessage(unsigned long type,unsigned long *body) +{ + char* color; + char* tmp; + + if (type==M_NEW_DESK) + { + if (body[0]>DeskCount || commands[body[0]].type == -1) + { + return; + } +#ifdef LOGFILE + fprintf(logFile,"Desk: %d\n",body[0]); + fprintf(logFile,"Command type: %d\n",commands[body[0]].type); + if (commands[body[0]].type == 0) + fprintf(logFile,"Command String: %s\n",commands[body[0]].cmdStr); + else if (commands[body[0]].type == 1) + fprintf(logFile,"Color Number: %d\n",commands[body[0]].solidColor); + else if (commands[body[0]].type == -1) + fprintf(logFile,"No Command\n"); + else + { + fprintf(logFile,"Illegal command type !\n"); + exit(1); + } + fflush(logFile); +# endif + + + if (commands[body[0]].type == 1) + { + /* Process a solid color request */ + + XSetWindowBackground(dpy, root, commands[body[0]].solidColor); + XClearWindow(dpy, root); + XFlush(dpy); + /* XSetWindowBackground(dpy, root, commands[body[0]].solidColor); + */ + +# ifdef LOGFILE + fprintf(logFile,"Color set.\n"); + fflush(logFile); +# endif + } + else if(commands[body[0]].cmdStr != NULL) + { + system(commands[body[0]].cmdStr); + } + } +} + +/****************************************************************************** + SendFvwmPipe - Send a message back to fvwm + Based on SendInfo() from FvwmIdent: + Copyright 1994, Robert Nation and Nobutaka Suzuki. +******************************************************************************/ +void SendFvwmPipe(char *message,unsigned long window) +{ +int w; +char *hold,*temp,*temp_msg; + hold=message; + + while(1) { + temp=strchr(hold,','); + if (temp!=NULL) { + temp_msg=malloc(temp-hold+1); + strncpy(temp_msg,hold,(temp-hold)); + temp_msg[(temp-hold)]='\0'; + hold=temp+1; + } else temp_msg=hold; + + write(Fvwm_fd[0],&window, sizeof(unsigned long)); + + w=strlen(temp_msg); + write(Fvwm_fd[0],&w,sizeof(int)); + write(Fvwm_fd[0],temp_msg,w); + + /* keep going */ + w=1; + write(Fvwm_fd[0],&w,sizeof(int)); + + if(temp_msg!=hold) free(temp_msg); + else break; + } +} + +/*********************************************************************** + Detected a broken pipe - time to exit + Based on DeadPipe() from FvwmIdent: + Copyright 1994, Robert Nation and Nobutaka Suzuki. + **********************************************************************/ +void DeadPipe(int nonsense) +{ + exit(1); +} + +/****************************************************************************** + ParseConfig - Parse the configuration file fvwm to us to use + Based on part of main() from FvwmIdent: + Copyright 1994, Robert Nation and Nobutaka Suzuki. +******************************************************************************/ +void ParseConfig(char *file) +{ +char line[256]; +char line2[40]; +char *tline; +FILE *ptr; + sprintf(line2,"*%sDesk",Module); + ptr=fopen(file,"r"); + if(ptr != (FILE *)NULL) { + + tline = fgets(line,(sizeof line)-1,ptr); + while(tline != (char *)0) { + while(isspace(*tline))tline++; + if(strlen(tline)>1) { + if(mystrncasecmp(tline,line2,strlen(line2))==0) + AddCommand(&tline[strlen(line2)]); + } + tline = fgets(line,(sizeof line)-1,ptr); + } + } +} + +/****************************************************************************** +AddCommand - Add a command to the correct spot on the dynamic array. +******************************************************************************/ +void AddCommand(char *string) +{ +char *temp; +int num; + temp=string; + while(isspace(*temp)) temp++; + num=atoi(temp); + while(!isspace(*temp)) temp++; + while(isspace(*temp)) temp++; + if (DeskCount<1) { + commands=(Command*)safemalloc((num+1)*sizeof(Command)); + while(DeskCountDeskCount) { + commands=(Command*)realloc(commands,(num+1)*sizeof(Command)); + while(DeskCount + +COMPILER + +DEPLIBS = $(DEPXLIB) ../../libs/libfvwmlib.a + +#ifdef AlphaArchitecture +LOCAL_LIBRARIES = $(XLIB) -ldnet_stub -L../../libs -lfvwmlib +#else +LOCAL_LIBRARIES = $(XLIB) -L../../libs -lfvwmlib +#endif + +LINTLIBS = $(LINTXLIB) + +SRCS = FvwmBacker.c Mallocs.c root_bits.c +OBJS = FvwmBacker.o Mallocs.o root_bits.o + +TARGET_DIR + +ComplexProgramTarget(FvwmBacker) + diff --git a/modules/FvwmBacker/Mallocs.c b/modules/FvwmBacker/Mallocs.c new file mode 100644 index 0000000..926c201 --- /dev/null +++ b/modules/FvwmBacker/Mallocs.c @@ -0,0 +1,62 @@ +/* FvwmWinList Module for Fvwm. + * + * Copyright 1994, Mike Finger (mfinger@mermaid.micro.umn.edu or + * Mike_Finger@atk.com) + * + * The author makes not guarantees or warantees, either express or + * implied. Feel free to use any contained here for any purpose, as long + * and this and any other applicible copyrights are kept intact. + + * The functions in this source file that are based on part of the FvwmIdent + * module for Fvwm are noted by a small copyright atop that function, all others + * are copyrighted by Mike Finger. For those functions modified/used, here is + * the full, original copyright: + * + * Copyright 1994, Robert Nation and Nobutaka Suzuki. + * No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. */ + +#include "../../configure.h" +#include +#include +#include +#include +#include + +#ifdef BROKEN_SUN_HEADERS +#include "../../fvwm/sun_headers.h" +#endif + +#ifdef NEEDS_ALPHA_HEADER +#include "../../fvwm/alpha_header.h" +#endif /* NEEDS_ALPHA_HEADER */ + +extern char *Module; + +/****************************************************************************** + saferealloc - safely reallocate memory or exit if fails. (Doesn't work right) +******************************************************************************/ +char *saferealloc(char *ptr, int length) +{ +char *newptr; + + if(length <=0) length=1; + + newptr=realloc(ptr,length); + if (ptr == (char *)0) { + fprintf(stderr,"%s:realloc failed",Module); + exit(1); + } + return ptr; +} + +void UpdateString(char **string,char *value) +{ + if (value==NULL) return; + if (*string==NULL) *string=(char *)safemalloc(strlen(value)+1); + else *string=(char *)realloc(*string,strlen(value)+1); + strcpy(*string,value); +} + diff --git a/modules/FvwmBacker/Mallocs.h b/modules/FvwmBacker/Mallocs.h new file mode 100644 index 0000000..a40fd91 --- /dev/null +++ b/modules/FvwmBacker/Mallocs.h @@ -0,0 +1,25 @@ +/* FvwmBacker Module for Fvwm. + * + * Copyright 1994, Mike Finger (mfinger@mermaid.micro.umn.edu or + * Mike_Finger@atk.com) + * + * The author makes not guarantees or warantees, either express or + * implied. Feel free to use any contained here for any purpose, as long + * and this and any other applicible copyrights are kept intact. + + * The functions in this source file that are based on part of the FvwmIdent + * module for Fvwm are noted by a small copyright atop that function, all others + * are copyrighted by Mike Finger. For those functions modified/used, here is + * the full, original copyright: + * + * Copyright 1994, Robert Nation and Nobutaka Suzuki. + * No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. */ + +/* Function Prototypes */ +char *safemalloc(int length); +char *saferealloc(char *ptr, int length); +void sleep_a_little(int n); +void UpdateString(char **string,char *value); diff --git a/modules/FvwmBacker/root_bits.c b/modules/FvwmBacker/root_bits.c new file mode 100644 index 0000000..6781d41 --- /dev/null +++ b/modules/FvwmBacker/root_bits.c @@ -0,0 +1,73 @@ +/* This file has been derived from the original file xsetroot.c + * by Andrew Davison, September 1994 for use with the Fvwm Backer + * module. + */ +/* + * $XConsortium: xsetroot.c,v 1.21 91/04/24 08:22:41 gildea Exp $ + * + * Copyright 1987, Massachusetts Institute of Technology + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * xsetroot.c MIT Project Athena, X Window System root window + * parameter setting utility. This program will set + * various parameters of the X root window. + * + * Author: Mark Lillibridge, MIT Project Athena + * 11-Jun-87 + */ + +#include +#include +#include +#include +#include "X11/bitmaps/gray" + +char *index(); + +#define Dynamic 1 + +extern Display *dpy; +extern int screen; +extern Window root; +extern char* Module; + +unsigned long NameToPixel(char* name, unsigned long pixel) +{ + XColor ecolor; + + if (!name || !*name) + return pixel; + if (!XParseColor(dpy,DefaultColormap(dpy,screen),name,&ecolor)) { + fprintf(stderr,"%s: unknown color \"%s\"\n",Module,name); + exit(1); + /*NOTREACHED*/ + } + if (!XAllocColor(dpy, DefaultColormap(dpy, screen),&ecolor)) { + fprintf(stderr, "%s: unable to allocate color for \"%s\"\n", + Module, name); + exit(1); + /*NOTREACHED*/ + } + if ((ecolor.pixel != BlackPixel(dpy, screen)) && + (ecolor.pixel != WhitePixel(dpy, screen)) && + (DefaultVisual(dpy, screen)->class & Dynamic)) + return(ecolor.pixel); +} diff --git a/modules/FvwmBanner/FvwmBanner.c b/modules/FvwmBanner/FvwmBanner.c new file mode 100644 index 0000000..3808d53 --- /dev/null +++ b/modules/FvwmBanner/FvwmBanner.c @@ -0,0 +1,319 @@ +/*************************************************************************** + * FvwmBanner + * + * Show Fvwm Banner + * + ***************************************************************************/ + +#include "../../configure.h" + +#ifdef ISC +#include /* Saul */ +#endif + +#include +#include +#include +#include +#include +#include +#if defined ___AIX || defined _AIX || defined __QNX__ || defined ___AIXV3 || defined AIXV3 || defined _SEQUENT_ +#include +#endif + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "fvwm3.xpm" + +#ifdef BROKEN_SUN_HEADERS +#include "../../fvwm/sun_headers.h" +#endif + +#include "../../libs/fvwmlib.h" + +#ifdef NEEDS_ALPHA_HEADER +#include "../../fvwm/alpha_header.h" +#endif /* NEEDS_ALPHA_HEADER */ + +typedef struct _XpmIcon { + Pixmap pixmap; + Pixmap mask; + XpmAttributes attributes; +} XpmIcon; + +/************************************************************************** + * A few function prototypes + **************************************************************************/ +void RedrawWindow(void); +void GetXPM(void); +Pixel GetColor(char *name); +void change_window_name(char *str); +int flush_expose (Window w); + +time_t t0 = -1; + +XpmIcon view; +Window win; + +Display *dpy; /* which display are we talking to */ +Window Root; +int screen; +int x_fd; +int d_depth; +int ScreenWidth, ScreenHeight; +XSizeHints mysizehints; +Pixel back_pix, fore_pix; +GC NormalGC; +static Atom wm_del_win; + +#define MW_EVENTS (ExposureMask | ButtonReleaseMask) + +/**************************************************************************** + * + * Creates an icon window as needed + * + ****************************************************************************/ +int main(int argc, char **argv) +{ + char *display_name = NULL; + int retval; + XGCValues gcv; + unsigned long gcm; + XEvent Event; + fd_set in_fdset; + int fd_width ; + time_t t; + struct itimerval value; + int fd[2]; + + fd_width = GetFdWidth(); + + if(argc>=3) + { + /* sever our connection with fvwm, if we have one. */ + fd[0] = atoi(argv[1]); + fd[1] = atoi(argv[2]); + + if(fd[0]>0)close(fd[0]); + if(fd[1]>0)close(fd[1]); + } + /* Open the display */ + if (!(dpy = XOpenDisplay(display_name))) + { + fprintf(stderr,"FvwmBanner: can't open display %s", + XDisplayName(display_name)); + exit (1); + } + screen= DefaultScreen(dpy); + Root = RootWindow(dpy, screen); + d_depth = DefaultDepth(dpy, screen); + x_fd = XConnectionNumber(dpy); + + ScreenHeight = DisplayHeight(dpy,screen); + ScreenWidth = DisplayWidth(dpy,screen); + + /* Get the xpm banner */ + GetXPM(); + + /* Create a window to hold the banner */ + mysizehints.flags= + USSize|USPosition|PWinGravity|PResizeInc|PBaseSize|PMinSize|PMaxSize; + /* subtract one for the right/bottom border */ + mysizehints.width = view.attributes.width; + mysizehints.height=view.attributes.height; + mysizehints.width_inc = 1; + mysizehints.height_inc = 1; + mysizehints.base_height = mysizehints.height; + mysizehints.base_width = mysizehints.width; + mysizehints.min_height = mysizehints.height; + mysizehints.min_width = mysizehints.width; + mysizehints.max_height = mysizehints.height; + mysizehints.max_width = mysizehints.width; + mysizehints.win_gravity = NorthWestGravity; + + mysizehints.x = (ScreenWidth - view.attributes.width)/2; + mysizehints.y = (ScreenHeight - view.attributes.height)/2; + + back_pix = GetColor("white"); + fore_pix = GetColor("black"); + + win = XCreateSimpleWindow(dpy,Root,mysizehints.x,mysizehints.y, + mysizehints.width,mysizehints.height, + 1,fore_pix,back_pix); + + /* Set assorted info for the window */ + XSetTransientForHint(dpy,win,Root); + wm_del_win = XInternAtom(dpy,"WM_DELETE_WINDOW",False); + XSetWMProtocols(dpy,win,&wm_del_win,1); + + XSetWMNormalHints(dpy,win,&mysizehints); + XSelectInput(dpy,win,MW_EVENTS); + change_window_name("FvwmBanner"); + + /* Create a GC for drawing */ + gcm = GCForeground|GCBackground; + gcv.foreground = fore_pix; + gcv.background = back_pix; + NormalGC = XCreateGC(dpy, Root, gcm, &gcv); + +#ifdef SHAPE + if(view.mask != None) + XShapeCombineMask(dpy, win, ShapeBounding,0,0,view.mask, ShapeSet); +#endif + + XMapWindow(dpy,win); + + /* Display the window */ + while(1) + { + FD_ZERO(&in_fdset); + + FD_SET(x_fd,&in_fdset); + + t=time(0); + if((t0>0)&&(t-t0) >= 5) + { + XDestroyWindow(dpy,win); + XSync(dpy,0); + exit(0); + } + + value.it_value.tv_usec = 0; + if(t0>0) + value.it_value.tv_sec = t-t0; + else + value.it_value.tv_sec = 1; + + if(!XPending(dpy)) +#ifdef __hpux + retval=select(fd_width,(int *)&in_fdset, 0, 0, &value.it_value); +#else + retval=select(fd_width,&in_fdset, 0, 0, &value.it_value); +#endif + if(FD_ISSET(x_fd, &in_fdset)) + { + /* read a packet */ + XNextEvent(dpy,&Event); + switch(Event.type) + { + case Expose: + if(Event.xexpose.count == 0) + RedrawWindow(); + break; + + case ButtonRelease: + exit(0); + case ClientMessage: + if (Event.xclient.format==32 && Event.xclient.data.l[0]==wm_del_win) + exit(0); + default: + break; + } + } + } + return 0; +} + +/**************************************************************************** + * + * Draws the icon window + * + ****************************************************************************/ +void RedrawWindow(void) +{ + flush_expose (win); + if(t0==-1) + t0 = time(0); + XCopyArea(dpy,view.pixmap,win,NormalGC, + 0,0,view.attributes.width, view.attributes.height,0,0); + +} + + +/**************************************************************************** + * + * Looks for a color XPM icon file + * + ****************************************************************************/ +void GetXPM(void) +{ + view.attributes.valuemask |= XpmReturnPixels; + view.attributes.valuemask |= XpmReturnExtensions; + + if(XpmCreatePixmapFromData(dpy, Root, fvwm2_xpm, + &view.pixmap, &view.mask, + &view.attributes)!=XpmSuccess) + exit(1); +} + +void nocolor(char *a, char *b) +{ + fprintf(stderr,"FvwmBanner: can't %s %s\n", a,b); +} + + +/**************************************************************************** + * + * Loads a single color + * + ****************************************************************************/ +Pixel GetColor(char *name) +{ + XColor color; + XWindowAttributes attributes; + + XGetWindowAttributes(dpy,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; +} + + +/************************************************************************** + * Change the window name displayed in the title bar. + **************************************************************************/ +void change_window_name(char *str) +{ + XTextProperty name; + + if (XStringListToTextProperty(&str,1,&name) == 0) + { + fprintf(stderr,"FvwmBanner: cannot allocate window name"); + return; + } + XSetWMName(dpy,win,&name); + XSetWMIconName(dpy,win,&name); + XFree(name.value); +} + +/************************************************************************** + * + * Removes expose events for a specific window from the queue + * + *************************************************************************/ +int flush_expose (Window w) +{ + XEvent dummy; + int i=0; + + while (XCheckTypedWindowEvent (dpy, w, Expose, &dummy))i++; + return i; +} + + diff --git a/modules/FvwmBanner/FvwmBanner.man b/modules/FvwmBanner/FvwmBanner.man new file mode 100644 index 0000000..ce8bdf8 --- /dev/null +++ b/modules/FvwmBanner/FvwmBanner.man @@ -0,0 +1,34 @@ +.\" t +.\" @(#)FvwmBanner.1 1/12/94 +.TH FvwmBanner 1.20 "Jan 28, 1994" +.UC +.SH NAME +FvwmBanner \- the FVWM Banner +.SH SYNOPSIS +FvwmBanner is intended to be spawned by fvwm, but it will work if +run from the command line. + +.SH DESCRIPTION +The FvwmInitBanner displays an Fvwm Logo in the center of the screen +for 5 seconds. + +.SH COPYRIGHTS +None. + +.SH INITIALIZATION +Nothing interesting. + +.SH INVOCATION +FvwmBanner can be invoked by binding the action 'Module +FvwmBanner' to a menu or key-stroke in the .fvwmrc file. +Fvwm will search +directory specified in the ModulePath configuration option to attempt +to locate FvwmBanner. Although nothing keeps you from launching +FvwmBanner at start-up time, you probably don't want to. + +.SH CONFIGURATION OPTIONS +There are no configuration options. + +.SH AUTHOR +Robert Nation + diff --git a/modules/FvwmBanner/Imakefile b/modules/FvwmBanner/Imakefile new file mode 100644 index 0000000..f0627a3 --- /dev/null +++ b/modules/FvwmBanner/Imakefile @@ -0,0 +1,39 @@ +/* Imakefile for FvwmInitBanner */ +/* Thu Aug 5 11:21:36 MET DST 1993, mj@dfv.rwth-aachen.de */ + +/* setup is done entirely in configuration.h now! */ +/* You should need to do much in here, excpt maybe add libraries */ + +/* I need to get the #define XPM from configuration.h if its in there,*/ +/* so that I can tell if I should include -lXpm */ +#include <../../configure.h> + +COMPILER + +#ifdef XPM +XPMLIB = XPMLIBRARY + +DEPLIBS = $(DEPXLIB) + +#ifdef AlphaArchitecture +LOCAL_LIBRARIES = $(XPMLIB) $(XLIB) -ldnet_stub -L../../libs -lfvwmlib +#else +LOCAL_LIBRARIES = $(XPMLIB) $(XLIB) -L../../libs -lfvwmlib +#endif + +LINTLIBS = $(LINTXLIB) + +SRCS = FvwmBanner.c +OBJS = FvwmBanner.o + +TARGET_DIR + +ComplexProgramTarget(FvwmBanner) + + +#endif + + + + + diff --git a/modules/FvwmBanner/fvwm3.xpm b/modules/FvwmBanner/fvwm3.xpm new file mode 100644 index 0000000..3852f31 --- /dev/null +++ b/modules/FvwmBanner/fvwm3.xpm @@ -0,0 +1,265 @@ +/* XPM */ +static char * fvwm2_xpm[] = { +/* width height ncolors cpp [x_hot y_hot] */ +"528 256 5 1 0 0", +" s none m none c none", +". c #FEFE00000000", +"X c #777700000000", +"o c #FFFF00000000", +"O c #CBCB00000000", +" ", +" ", +" ", +" ", +" ............................................................................................................................ ........................................ ........................................ ........................................ ........................................ .................................... .................................... ", +" ...........................................................................................................................X .......................................X .......................................X .......................................X .......................................X ...................................X ...................................X ", +" ..........................................................................................................................XX ......................................XX ......................................XX ......................................XX ......................................XX ..................................XXX ...................................XX ", +" .........................................................................................................................XXX .....................................XXX .....................................XXX .....................................XXX .....................................XXX .................................XXXX ..................................XXX ", +" ........................................................................................................................XXXX ....................................XXXX ....................................XXXX ....................................XXXX ....................................XXXX ................................XXXXXX ..................................XXXX ", +" .......................................................................................................................XXXXX ...................................XXXXX ...................................XXXXX ...................................XXXXX ...................................XXXXX ...............................XXXXXXX .................................XXXXX ", +" ......................................................................................................................XXXXXX .................................oXXXXXX ..................................XXXXXX ..................................XXXXXX ..................................XXXXXX ..............................XXXXXXXXX .................................XXXXXX ", +" .....................................................................................................................XXXXXXX .................................XXXXXXX .................................XXXXXXX .................................XXXXXXX .................................XXXXXXX .............................XXXXXXXXXX ................................XXXXXXX ", +" ....................................................................................................................XXXXXXXX ................................XXXXXXXX ................................XXXXXXXX ................................XXXXXXXX ................................XXXXXXXX ............................XXXXXXXXXXXX ................................XXXXXXXX ", +" ...................................................................................................................XXXXXXXXX ...............................XXXXXXXXX ...............................XXXXXXXXX ...............................XXXXXXXXX ...............................XXXXXXXXX ...........................XXXXXXXXXXXXX ...............................XXXXXXXXX ", +" ..................................................................................................................XXXXXXXXXX ..............................XXXXXXXXXX ..............................XXXXXXXXXX ..............................XXXXXXXXXX ..............................XXXXXXXXXX ..........................XXXXXXXXXXXXXXX ...............................XXXXXXXXXX ", +" .................................................................................................................XXXXXXXXXXX .............................XXXXXXXXXXX .............................XXXXXXXXXXX .............................XXXXXXXXXXX .............................XXXXXXXXXXX ..........................XXXXXXXXXXXXXXX ..............................XXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXX.OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXX.OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXX.OOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXX..OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXX.OOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXX..OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXX.OOOOOOOOOOOOOXXXXXXXXXXXXXX.............OOOOOOOOOOOOOOXXXXXX..OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXX.OOOOOOOOOOOOOXXXXXXXXXXXXXX.............OOOOOOOOOOOOOOXXXXXX..OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXX.OOOOOOOOOOOOOOXXXXXXXXXXXXX............OOOOOOOOOOOOOOXXXXXX...OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXX.OOOOOOOOOOOOOOXXXXXXXXXXXXX............OOOOOOOOOOOOOOXXXXXX...OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXX.OOOOOOOOOOOOOOXXXXXXXXXXXX...........OOOOOOOOOOOOOOXXXXXXX...OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXX.OOOOOOOOOOOOOOXXXXXXXXXXXX...........OOOOOOOOOOOOOOXXXXXXX...OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXX..OOOOOOOOOOOOOOXXXXXXXXXXX..........OOOOOOOOOOOOOOXXXXXXX....OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXX..OOOOOOOOOOOOOOXXXXXXXXXXX..........OOOOOOOOOOOOOOXXXXXXX....OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXX..OOOOOOOOOOOOOOXXXXXXXXXX.........OOOOOOOOOOOOOOXXXXXXXX....OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXX..OOOOOOOOOOOOOOXXXXXXXXXX.........OOOOOOOOOOOOOOXXXXXXXX....OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXX...OOOOOOOOOOOOOOXXXXXXXXX........OOOOOOOOOOOOOOXXXXXXXX.....OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXX...OOOOOOOOOOOOOOXXXXXXXXX........OOOOOOOOOOOOOOXXXXXXXX.....OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXX...OOOOOOOOOOOOOOXXXXXXXX.......OOOOOOOOOOOOOOXXXXXXXXX.....OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXX...OOOOOOOOOOOOOOXXXXXXXX.......OOOOOOOOOOOOOOXXXXXXXXX.....OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXX....OOOOOOOOOOOOOOXXXXXXX......OOOOOOOOOOOOOOXXXXXXXXX......OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXX....OOOOOOOOOOOOOOXXXXXXX......OOOOOOOOOOOOOOXXXXXXXXX......OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXX....OOOOOOOOOOOOOOXXXXXX.....OOOOOOOOOOOOOOXXXXXXXXXX......OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXX....OOOOOOOOOOOOOOXXXXXX.....OOOOOOOOOOOOOOXXXXXXXXXX......OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXX.....OOOOOOOOOOOOOOXXXXX....OOOOOOOOOOOOOOXXXXXXXXXX.......OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXX.....OOOOOOOOOOOOOOXXXXX....OOOOOOOOOOOOOOXXXXXXXXXX.......OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXX.....OOOOOOOOOOOOOOXXXX...OOOOOOOOOOOOOOXXXXXXXXXXX.......OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXX.....OOOOOOOOOOOOOOXXXX...OOOOOOOOOOOOOOXXXXXXXXXXX.......OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXX......OOOOOOOOOOOOOOXXX..OOOOOOOOOOOOOOXXXXXXXXXXX........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXX......OOOOOOOOOOOOOOXXX..OOOOOOOOOOOOOOXXXXXXXXXXX........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXX......OOOOOOOOOOOOOOXX.OOOOOOOOOOOOOOXXXXXXXXXXXX........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXX......OOOOOOOOOOOOOOXX.OOOOOOOOOOOOOOXXXXXXXXXXXX........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXX.......OOOOOOOOOOOOOOXOOOOOOOOOOOOOOXXXXXXXXXXXX.........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXX.......OOOOOOOOOOOOOOXOOOOOOOOOOOOOOXXXXXXXXXXXX.........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX................................................................ ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX.......OOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXX.........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXX................................................................X ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX.......OOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXX.........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXX................................................................XX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX........OOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXX..........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXX................................................................XXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX........OOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXX..........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXX................................................................XXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..XX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX.........OOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXX..........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXX................................................................XXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..XX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX.........OOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXX..........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXX................................................................XXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ...XXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX..........OOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXX...........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXX................................................................XXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ...XXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX..........OOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXX...........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXX................................................................XXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ....XXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX...........OOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX...........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXX................................................................XXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ....XXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX...........OOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX...........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXX................................................................XXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX .....XXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX............OOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOX................................................................XXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX .....XXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX............OOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ......XXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ......XXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX .......XXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX .......XXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ........XXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX .............OOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ........XXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX .............OOOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX .........XXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX .........XXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..........XXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..........XXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ...........XXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ...........XXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............XXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............XXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX .............XXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX .............XXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..............XXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..............XXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..............OOXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............XXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..............OOXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............XXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..............OOOOXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ...........XXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..............OOOOXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ...........XXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..............OOOOOOXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..........XXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..............OOOOOOXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..........XXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..............OOOOOOOOXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX .........XXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..............OOOOOOOOXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX .........XXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..............OOOOOOOOOOXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ........XXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..............OOOOOOOOOOXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ........XXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..............OOOOOOOOOOOOXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX .......XXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..............OOOOOOOOOOOOXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX .......XXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..............OOOOOOOOOOOOOOXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ......XXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..............OOOOOOOOOOOOOOXXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ......XXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXX...............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXX............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX .....XXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXX...............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXX............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX .....XXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXX..............OOOOOOOOOOOOOOOOOOXXXXXXXXXXXXX............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ....XXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXX..............OOOOOOOOOOOOOOOOOOXXXXXXXXXXXXX............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ....XXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXX..............OOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXX...........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ...XXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXX..............OOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXX...........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ...XXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXX.............OOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX...........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..XX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXX.............OOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX...........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..XX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXX.............OOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX..........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXX.............OOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX..........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXX............OOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXX..........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXX............OOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXX..........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXX............OOOOOOOOOOOOXX..OOOOOOOOOOOOXXXXXXXXXXX.........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXX............OOOOOOOOOOOOXX..OOOOOOOOOOOOXXXXXXXXXXX.........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXX............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXX...........OOOOOOOOOOOOXXX...OOOOOOOOOOOOXXXXXXXXXX.........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXXX............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXX............OOOOOOOOOOOOXXX...OOOOOOOOOOOOXXXXXXXXXX.........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXX...........OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXX...........OOOOOOOOOOOOXXXX....OOOOOOOOOOOOXXXXXXXXXX........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXXX...........OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXX...........OOOOOOOOOOOOXXXX....OOOOOOOOOOOOXXXXXXXXXX........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXX..........OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXX..........OOOOOOOOOOOOXXXXX.....OOOOOOOOOOOOXXXXXXXXX........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXXX..........OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXX..........OOOOOOOOOOOOXXXXX.....OOOOOOOOOOOOXXXXXXXXX........OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXX.........OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXX..........OOOOOOOOOOOOXXXXXX......OOOOOOOOOOOOXXXXXXXXX.......OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXXX.........OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXX..........OOOOOOOOOOOOXXXXXX......OOOOOOOOOOOOXXXXXXXXX.......OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXX........OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXX.........OOOOOOOOOOOOXXXXXXX.......OOOOOOOOOOOOXXXXXXXX.......OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXXX........OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXX.........OOOOOOOOOOOOXXXXXXX.......OOOOOOOOOOOOXXXXXXXX.......OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXX.......OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXX.........OOOOOOOOOOOOXXXXXXXX........OOOOOOOOOOOOXXXXXXXX......OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXXX.......OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXX.........OOOOOOOOOOOOXXXXXXXX........OOOOOOOOOOOOXXXXXXXX......OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXX......OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXX........OOOOOOOOOOOOXXXXXXXXX.........OOOOOOOOOOOOXXXXXXX......OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXXX......OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXX........OOOOOOOOOOOOXXXXXXXXX.........OOOOOOOOOOOOXXXXXXX......OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXX.....OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXX........OOOOOOOOOOOOXXXXXXXXXX..........OOOOOOOOOOOOXXXXXXX.....OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXXX.....OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXX........OOOOOOOOOOOOXXXXXXXXXX..........OOOOOOOOOOOOXXXXXXX.....OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXX....OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXX.......OOOOOOOOOOOOXXXXXXXXXXX...........OOOOOOOOOOOOXXXXXX.....OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXXX....OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXX.......OOOOOOOOOOOOXXXXXXXXXXX...........OOOOOOOOOOOOXXXXXX.....OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXX...OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXX.......OOOOOOOOOOOOXXXXXXXXXXXX............OOOOOOOOOOOOXXXXXX....OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXXX...OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXX.......OOOOOOOOOOOOXXXXXXXXXXXX............OOOOOOOOOOOOXXXXXX....OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXX..OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXX......OOOOOOOOOOOOXXXXXXXXXXXXX.............OOOOOOOOOOOOXXXXX....OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOXX..OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXX......OOOOOOOOOOOOXXXXXXXXXXXXX.............OOOOOOOOOOOOXXXXX....OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOX.OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXX......OOOOOOOOOOOOXXXXXXXXXXXXXX..............OOOOOOOOOOOOXXXXX...OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOX.OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXX......OOOOOOOOOOOOXXXXXXXXXXXXXX..............OOOOOOOOOOOOXXXXX...OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXX.....OOOOOOOOOOOOXXXXXXXXXXXXXXX...............OOOOOOOOOOOOXXXX...OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXX.....OOOOOOOOOOOOXXXXXXXXXXXXXXX...............OOOOOOOOOOOOXXXX...OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOX.....OOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOXXXX..OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOX.....OOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOXXXX..OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOX....OOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOXXX..OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOX....OOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOXXX..OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ...........OOOOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ...........OOOXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OXXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............XXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............XXXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ...........XXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ...........XXXXXXXXXXX ............OOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..........XXXXXXXXXX ............OOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ..........XXXXXXXXXX ............OOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX .........XXXXXXXXX ............OOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX .........XXXXXXXXX ............OOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ........XXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ........XXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX .......XXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX .......XXXXXXX ............OOOOOOOOOOOOOOOXXXXXXXXXXXXXXX ...............OOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ............OOOOOOOOOOOOOOOOXXXXXXXXXXXX ", +" ............XXXXXXXXXXXXXXXXXXXXXXXXXXXX ......XXXXXX ............XXXXXXXXXXXXXXXXXXXXXXXXXXXXX ...............XXXXXXXXXXXXXXXXXXXXXXXXXX ............XXXXXXXXXXXXXXXXXXXXXXXXXXXX ............XXXXXXXXXXXXXXXXXXXXXXXXXXXX ", +" ...........XXXXXXXXXXXXXXXXXXXXXXXXXXXXX ......XXXXXX ...........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ..............XXXXXXXXXXXXXXXXXXXXXXXXXXX ...........XXXXXXXXXXXXXXXXXXXXXXXXXXXXX ...........XXXXXXXXXXXXXXXXXXXXXXXXXXXXX ", +" ..........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX .....XXXXX ..........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ............XXXXXXXXXXXXXXXXXXXXXXXXXXXX ..........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ..........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ", +" .........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX .....XXXXX .........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ...........XXXXXXXXXXXXXXXXXXXXXXXXXXXXX .........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX .........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ", +" ........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ....XXXX ........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX .........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ", +" .......XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ....XXXX .......XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX .......XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX .......XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ", +" ......XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ...XXX ......XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ......XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ......XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ......XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ", +" .....XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ...XXX .....XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX .....XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX .....XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX .....XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ", +" ....XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ..XX ....XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ...XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ....XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ....XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ", +" ...XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ..XX ...XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ..XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ...XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ...XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ", +" ..XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX .X ..XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ..XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ..XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ", +" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX .X .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/modules/FvwmClean/FvwmClean.c b/modules/FvwmClean/FvwmClean.c new file mode 100644 index 0000000..84b50ed --- /dev/null +++ b/modules/FvwmClean/FvwmClean.c @@ -0,0 +1,430 @@ +/* This module, and the entire NoClutter program, and the concept for + * interfacing this module to the Window Manager, are all original work + * by Robert Nation + * + * Copyright 1994, Robert Nation. No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. */ + +#define TRUE 1 +#define FALSE + +#include "../../configure.h" +#ifdef ISC +#include /* Saul */ +#endif + +#include +#include +#include +#include +#include +#include +#if defined ___AIX || defined _AIX || defined __QNX__ || defined ___AIXV3 || defined AIXV3 || defined _SEQUENT_ +#include +#endif +#include +#include +#include +#include "../../fvwm/module.h" + +#include "FvwmClean.h" +#include "../../version.h" + +char *MyName; +int fd_width; +int fd[2]; +struct list *list_root = NULL; +unsigned long current_focus = 0; + +long period[3] = {-1,-1,-1}; +long maxperiod = -1; +char command[3][256]; +int num_commands = 0; + +unsigned long next_event_time = 0; +unsigned long t0; + +/*********************************************************************** + * + * Procedure: + * main - start of module + * + ***********************************************************************/ +void main(int argc, char **argv) +{ + char *temp, *s; + FILE *file; + + /* Save the program name - its used for error messages and option parsing */ + temp = argv[0]; + + s=strrchr(argv[0], '/'); + if (s != NULL) + temp = s + 1; + + MyName = safemalloc(strlen(temp)+2); + strcpy(MyName,"*"); + strcat(MyName, temp); + + if((argc != 6)&&(argc != 7)) + { + fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",MyName, + VERSION); + exit(1); + } + + /* Save the program name - its used for error messages and option parsing */ + temp = argv[0]; + + s=strrchr(argv[0], '/'); + if (s != NULL) + temp = s + 1; + + MyName = safemalloc(strlen(temp)+2); + strcpy(MyName,"*"); + strcat(MyName, temp); + + /* Dead pipes mean fvwm died */ + signal (SIGPIPE, DeadPipe); + + fd[0] = atoi(argv[1]); + fd[1] = atoi(argv[2]); + + /* scan config file for set-up parameters */ + file = fopen(argv[3],"r"); + if(file != (FILE *)NULL) + { + char line[256]; + char *tline; + + tline = fgets(line,(sizeof line)-1,file); + while((tline != (char *)0)&&(num_commands < 3)) + { + while(isspace(*tline))tline++; + if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline, MyName,strlen(MyName))==0)) + { + sscanf(&tline[strlen(MyName)],"%ld",&period[num_commands]); + if(period[num_commands]>maxperiod) + maxperiod = period[num_commands]; + while(!isspace(*tline))tline++; + while(isspace(*tline))tline++; /* points to "time" field */ + while(!isspace(*tline))tline++; + while(isspace(*tline))tline++; /* points to "command" field */ + strcpy(command[num_commands],tline); + num_commands++; + } + tline = fgets(line,(sizeof line)-1,file); + } + } + + if(num_commands == 0) + { + fprintf(stderr,"%s: Nothing to do!\n",MyName); + exit(0); + } + + fd_width = GetFdWidth(); + + /* Create a list of all windows */ + /* Request a list of all windows, + * wait for ConfigureWindow packets */ + SendInfo(fd,"Send_WindowList",0); + + Loop(fd); +} + + +/*********************************************************************** + * + * Procedure: + * Loop - wait for data to process + * + ***********************************************************************/ +void Loop(int *fd) +{ + unsigned long header[3], *body; + fd_set in_fdset; + struct itimerval value; + int retval, count; + + while(1) + { + FD_ZERO(&in_fdset); + FD_SET(fd[1],&in_fdset); + + /* Find out when we have to iconify or whatever a window */ + find_next_event_time(); + + /* set up a time-out, in case no packets arrive before we have to + * iconify something */ + value.it_value.tv_usec = 0; + value.it_value.tv_sec = next_event_time - t0; + +#ifdef __hpux + if(value.it_value.tv_sec > 0) + retval=select(fd_width,(int *)&in_fdset, 0, 0, &value.it_value); + else + retval=select(fd_width,(int *)&in_fdset, 0, 0, NULL); +#else + if(value.it_value.tv_sec > 0) + retval=select(fd_width,&in_fdset, 0, 0, &value.it_value); + else + retval=select(fd_width,&in_fdset, 0, 0, NULL); +#endif + if(FD_ISSET(fd[1], &in_fdset)) + { + /* read a packet */ + if(ReadFvwmPacket(fd[1],header, &body) > 0) + { + /* dispense with the new packet */ + process_message(header[1],body); + free(body); + } + } + } +} + + +/*********************************************************************** + * + * Procedure: + * Process message - examines packet types, and takes appropriate action + * + ***********************************************************************/ +void process_message(unsigned long type,unsigned long *body) +{ + struct list *l; + + switch(type) + { + case M_ADD_WINDOW: + if(!find_window(body[0])) + add_window(body[0]); + break; + case M_CONFIGURE_WINDOW: + if(!find_window(body[0])) + add_window(body[0]); + break; + case M_DESTROY_WINDOW: + remove_window(body[0]); + break; + case M_FOCUS_CHANGE: + l = find_window(body[0]); + if(l == 0) + { + add_window(body[0]); + l = find_window(body[0]); + update_focus(l,body[0]); + } + else + update_focus(l,body[0]); + break; + default: + break; + } +} + + + + +/*********************************************************************** + * + * Procedure: + * safemalloc - mallocs specified space or exits if there's a + * problem + * + ***********************************************************************/ +char *safemalloc(int length) +{ + char *ptr; + + if(length <=0) + length = 1; + + ptr = malloc(length); + if(ptr == (char *)0) + { + fprintf(stderr,"%s:malloc failed",MyName); + exit(1); + } + return ptr; +} + +/*********************************************************************** + * + * Procedure: + * find_window - find a window in the current window list + * + ***********************************************************************/ +struct list *find_window(unsigned long id) +{ + struct list *l; + + if(list_root == NULL) + return NULL; + + for(l = list_root; l!= NULL; l= l->next) + { + if(l->id == id) + return l; + } + return NULL; +} + + +/*********************************************************************** + * + * Procedure: + * remove_window - remove a window in the current window list + * + ***********************************************************************/ +void remove_window(unsigned long id) +{ + struct list *l, *prev; + + if(list_root == NULL) + return; + + prev = NULL; + for(l = list_root; l!= NULL; l= l->next) + { + if(l->id == id) + { + if(prev != NULL) + prev->next = l->next; + else + list_root = l->next; + free(l); + return; + } + prev = l; + } +} + + +/*********************************************************************** + * + * Procedure: + * add_window - add a new window in the current window list + * + ***********************************************************************/ +void add_window(unsigned long new_win) +{ + struct list *t; + + if(new_win == 0) + return; + + t = (struct list *)safemalloc(sizeof(struct list)); + t->id = new_win; + t->last_focus_time = time(0); + t->actions = 0; + t->next = list_root; + list_root = t; +} + + +/*********************************************************************** + * + * Procedure: + * mark the window which currently has focus, so we don't iconify it + * + ***********************************************************************/ +void update_focus(struct list *l, unsigned long win) +{ + struct list *t; + + t=find_window(current_focus); + if(t!= NULL) + { + t->last_focus_time = time(0); + t->actions = 0; + } + + if(l != NULL) + { + l->last_focus_time = time(0); + l->actions = 0; + } +current_focus = win; +} + +/*********************************************************************** + * + * Procedure: + * SIGPIPE handler - SIGPIPE means fvwm is dying + * + ***********************************************************************/ +void DeadPipe(int nonsense) +{ + exit(0); +} + +/*********************************************************************** + * + * Procedure: + * checks to see if we are supposed to take some action now, + * finds time for next action to be performed. + * + ***********************************************************************/ +void find_next_event_time(void) +{ + struct list *t; + + t0 = time(0); + next_event_time = t0; + + if(list_root == NULL) + return; + + next_event_time = t0 + maxperiod; + + for(t = list_root; t!= NULL; t= t->next) + { + if(t->id != current_focus) + { + if((period[2] >0)&&(t->last_focus_time + period[2] <= t0)) + { + if(!(t->actions & ACTION1)) + { + SendInfo(fd,command[2],t->id); + t->actions |= ACTION1; + } + } + else if((period[1]>0)&&(t->last_focus_time + period[1] <= t0)) + { + if(!(t->actions & ACTION2)) + { + SendInfo(fd,command[1],t->id); + t->actions |= ACTION2; + } + } + else if((period[0]>0)&&(t->last_focus_time + period[0] <= t0)) + { + if(!(t->actions & ACTION3)) + { + SendInfo(fd,command[0],t->id); + t->actions |= ACTION3; + } + } + + } + else + t->last_focus_time = t0; + + if((period[0] > 0)&&(t->last_focus_time + period[0] > t0)&& + (t->last_focus_time + period[0] last_focus_time + period[0]; + else if((period[1]>0)&&(t->last_focus_time + period[1] > t0)& + (t->last_focus_time + period[1] last_focus_time + period[1]; + else if((period[2]>0)&&(t->last_focus_time + period[2] > t0)&& + (t->last_focus_time + period[2] last_focus_time + period[2]; + } +} + + diff --git a/modules/FvwmClean/FvwmClean.h b/modules/FvwmClean/FvwmClean.h new file mode 100644 index 0000000..7e74e62 --- /dev/null +++ b/modules/FvwmClean/FvwmClean.h @@ -0,0 +1,37 @@ +#include "../../libs/fvwmlib.h" +#define ACTION1 1 +#define ACTION2 2 +#define ACTION3 4 + +struct list +{ + unsigned long id; + unsigned long last_focus_time; + unsigned long actions; + struct list *next; +}; + +/************************************************************************* + * + * Subroutine Prototypes + * + *************************************************************************/ +void Loop(int *fd); +void SendInfo(int *fd,char *message,unsigned long window); +char *safemalloc(int length); +struct list *find_window(unsigned long id); +void remove_window(unsigned long id); +void add_window(unsigned long new_win); +void update_focus(struct list *l, unsigned long); +void DeadPipe(int nonsense); +void find_next_event_time(void); +void process_message(unsigned long type,unsigned long *body); + +#ifdef BROKEN_SUN_HEADERS +#include "../../fvwm/sun_headers.h" +#endif + +#ifdef NEEDS_ALPHA_HEADER +#include "../../fvwm/alpha_header.h" +#endif /* NEEDS_ALPHA_HEADER */ + diff --git a/modules/FvwmClean/FvwmClean.man b/modules/FvwmClean/FvwmClean.man new file mode 100644 index 0000000..128fb75 --- /dev/null +++ b/modules/FvwmClean/FvwmClean.man @@ -0,0 +1,60 @@ +.\" t +.\" @(#)FvwmClean.1 1/12/94 +.TH FvwmClean 1.20 "Jan 28 1994" +.UC +.SH NAME +FvwmClean \- the FVWM desktop clutter reduction module +.SH SYNOPSIS +FvwmClean is spawned by fvwm, so no command line invocation will work. + +.SH DESCRIPTION +The FvwmClean module performs actions on windows which have not had +the keyboard focus for a specific length of time. This is intended to +help alleviate the problem of leaving programs running in unused +portions of your desktop. + +FvwmClean reads the same .fvwmrc file as fvwm reads when it starts up, +and looks for lines similar to "*FvwmNoClutter 3600 Iconify". + +.SH COPYRIGHTS +The FvwmClean program, and the concept for +interfacing this module to the Window Manager, are all original work +by Robert Nation + +Copyright 1994, Robert Nation. No guarantees or warranties or anything +are provided or implied in any way whatsoever. Use this program at your +own risk. Permission to use this program for any purpose is given, +as long as the copyright is kept intact. + + +.SH INITIALIZATION +During initialization, \fIFvwmClean\fP will eventually search a +configuration file which describes the time-outs and actions to take. +The configuration file is the same file that fvwm used during initialization. + +If the FvwmClean executable is linked to another name, ie ln -s +FvwmClean OtherClutter, then another module called OtherClutter can be +started, with a completely different configuration than FvwmClean, +simply by changing the keyword FvwmClean to OtherClutter. This way multiple +clutter-reduction programs can be used. + +.SH INVOCATION +FvwmClean can be invoked by inserting the line 'Module FvwmClean' in +the .fvwmrc file. This can be placed on a line by itself, if FvwmClean +is to be spawned during fvwm's initialization, or can be bound to a +menu or mouse button or keystroke to invoke it later. Fvwm will search +directory specified in the ModulePath configuration option to attempt +to locate FvwmClean. + +.SH CONFIGURATION OPTIONS +FvwmClean reads the same .fvwmrc file as fvwm reads when it starts up, +and looks for lines similar to "*FvwmClean 3600 Iconify". The format +of these lines is "*FvwmClean [time] [command]", where command is any +fvwm built-in command, and time is the time in seconds between when a +window looses focus and when the command is executed. At most 3 +actions can be specified. + + +.SH AUTHOR +Robert Nation + diff --git a/modules/FvwmClean/Imakefile b/modules/FvwmClean/Imakefile new file mode 100644 index 0000000..3c32dba --- /dev/null +++ b/modules/FvwmClean/Imakefile @@ -0,0 +1,30 @@ +/* Imakefile for FvwmClean */ +/* Thu Aug 5 11:21:36 MET DST 1993, mj@dfv.rwth-aachen.de */ + +/* setup is done entirely in configuration.h now! */ +/* You should need to do much in here, excpt maybe add libraries */ + +/* I need to get the #define XPM from configuration.h if its in there,*/ +/* so that I can tell if I should include -lXpm */ +#include <../../configure.h> + +COMPILER + + +DEPLIBS = $(DEPXLIB) ../../libs/libfvwmlib.a + +#ifdef AlphaArchitecture +LOCAL_LIBRARIES = -ldnet_stub -L../../libs -lfvwmlib +#else +LOCAL_LIBRARIES = -L../../libs -lfvwmlib +#endif + +LINTLIBS = $(LINTXLIB) + +SRCS = FvwmClean.c +OBJS = FvwmClean.o + +TARGET_DIR + +ComplexProgramTarget(FvwmClean) + diff --git a/modules/FvwmDebug/FvwmDebug.c b/modules/FvwmDebug/FvwmDebug.c new file mode 100644 index 0000000..c03dc14 --- /dev/null +++ b/modules/FvwmDebug/FvwmDebug.c @@ -0,0 +1,505 @@ +/* This module, and the entire FvwmDebug program, and the concept for + * interfacing this module to the Window Manager, are all original work + * by Robert Nation + * + * Copyright 1994, Robert Nation. No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. */ + +#define TRUE 1 +#define FALSE + +#include "../../configure.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../fvwm/module.h" + +#include "FvwmDebug.h" +#include "../../version.h" + +char *MyName; +int fd_width; +int fd[2]; + +/*********************************************************************** + * + * Procedure: + * main - start of module + * + ***********************************************************************/ +void main(int argc, char **argv) +{ + char *temp, *s; + + /* Save our program name - for error messages */ + temp = argv[0]; + s=strrchr(argv[0], '/'); + if (s != NULL) + temp = s + 1; + + MyName = safemalloc(strlen(temp)+2); + strcpy(MyName,"*"); + strcat(MyName, temp); + + if((argc != 6)&&(argc != 7)) + { + fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",MyName, + VERSION); + exit(1); + } + + /* Dead pipe == Fvwm died */ + signal (SIGPIPE, DeadPipe); + + fd[0] = atoi(argv[1]); + fd[1] = atoi(argv[2]); + + /* Data passed in command line */ + fprintf(stderr,"Application Window 0x%s\n",argv[4]); + fprintf(stderr,"Application Context %s\n",argv[5]); + + fd_width = GetFdWidth(); + + /* Create a list of all windows */ + /* Request a list of all windows, + * wait for ConfigureWindow packets */ + SendInfo(fd,"Send_WindowList",0); + + Loop(fd); +} + +/*********************************************************************** + * + * Procedure: + * Loop - wait for data to process + * + ***********************************************************************/ +void Loop(int *fd) +{ + unsigned long header[3], *body; + char *cbody; + int body_length,count,count2=0, total; + + while(1) + { + if(count = ReadFvwmPacket(fd[1],header,&body) > 0) + { + process_message(header[1],body); + free(body); + } + } +} + + +/*********************************************************************** + * + * Procedure: + * Process message - examines packet types, and takes appropriate action + * + ***********************************************************************/ +void process_message(unsigned long type,unsigned long *body) +{ + switch(type) + { + case M_ADD_WINDOW: + list_add(body); + case M_CONFIGURE_WINDOW: + list_configure(body); + break; + case M_DESTROY_WINDOW: + list_destroy(body); + break; + case M_FOCUS_CHANGE: + list_focus(body); + break; + case M_TOGGLE_PAGING: + list_toggle(body); + break; + case M_NEW_PAGE: + list_new_page(body); + break; + case M_NEW_DESK: + list_new_desk(body); + break; + case M_RAISE_WINDOW: + list_raise(body); + break; + case M_LOWER_WINDOW: + list_lower(body); + break; + case M_ICONIFY: + list_iconify(body); + break; + case M_MAP: + list_map(body); + break; + case M_ICON_LOCATION: + list_icon_loc(body); + break; + case M_DEICONIFY: + list_deiconify(body); + break; + case M_WINDOW_NAME: + list_window_name(body); + break; + case M_ICON_NAME: + list_icon_name(body); + break; + case M_RES_CLASS: + list_class(body); + break; + case M_RES_NAME: + list_res_name(body); + break; + case M_END_WINDOWLIST: + list_end(); + break; + default: + list_unknown(body); + break; + } +} + + + +/*********************************************************************** + * + * Procedure: + * SIGPIPE handler - SIGPIPE means fvwm is dying + * + ***********************************************************************/ +void DeadPipe(int nonsense) +{ + exit(0); +} + +/*********************************************************************** + * + * Procedure: + * list_add - displays packet contents to stderr + * + ***********************************************************************/ +void list_add(unsigned long *body) +{ + fprintf(stderr,"Add Window\n"); + fprintf(stderr,"\t ID %lx\n",body[0]); + fprintf(stderr,"\t frame ID %lx\n",body[1]); + fprintf(stderr,"\t fvwm ptr %lx\n",body[2]); + fprintf(stderr,"\t frame x %ld\n",(long)body[3]); + fprintf(stderr,"\t frame y %ld\n",(long)body[4]); + fprintf(stderr,"\t frame w %ld\n",(long)body[5]); + fprintf(stderr,"\t frame h %ld\n",(long)body[6]); + fprintf(stderr,"\t desk %ld\n",(long)body[7]); + fprintf(stderr,"\t flags %lx\n",body[8]); + fprintf(stderr,"\t title height %ld\n",(long)body[9]); + fprintf(stderr,"\t border width %ld\n",(long)body[10]); + fprintf(stderr,"\t window base width %ld\n",(long)body[11]); + fprintf(stderr,"\t window base height %ld\n",(long)body[12]); + fprintf(stderr,"\t window resize width increment %ld\n",(long)body[13]); + fprintf(stderr,"\t window resize height increment %ld\n",(long)body[14]); + fprintf(stderr,"\t window min width %ld\n",(long)body[15]); + fprintf(stderr,"\t window min height %ld\n",(long)body[16]); + fprintf(stderr,"\t window max %ld\n",(long)body[17]); + fprintf(stderr,"\t window max %ld\n",(long)body[18]); + fprintf(stderr,"\t icon label window %lx\n",body[19]); + fprintf(stderr,"\t icon pixmap window %lx\n",body[20]); + fprintf(stderr,"\t window gravity %lx\n",body[21]); +} + +/*********************************************************************** + * + * Procedure: + * list_configure - displays packet contents to stderr + * + ***********************************************************************/ +void list_configure(unsigned long *body) +{ + fprintf(stderr,"Configure Window\n"); + fprintf(stderr,"\t ID %lx\n",body[0]); + fprintf(stderr,"\t frame ID %lx\n",body[1]); + fprintf(stderr,"\t fvwm ptr %lx\n",body[2]); + fprintf(stderr,"\t frame x %ld\n",(long)body[3]); + fprintf(stderr,"\t frame y %ld\n",(long)body[4]); + fprintf(stderr,"\t frame w %ld\n",(long)body[5]); + fprintf(stderr,"\t frame h %ld\n",(long)body[6]); + fprintf(stderr,"\t desk %ld\n",(long)body[7]); + fprintf(stderr,"\t flags %lx\n",body[8]); + fprintf(stderr,"\t title height %ld\n",(long)body[9]); + fprintf(stderr,"\t border width %ld\n",(long)body[10]); + fprintf(stderr,"\t window base width %ld\n",(long)body[11]); + fprintf(stderr,"\t window base height %ld\n",(long)body[12]); + fprintf(stderr,"\t window resize width increment %ld\n",(long)body[13]); + fprintf(stderr,"\t window resize height increment %ld\n",(long)body[14]); + fprintf(stderr,"\t window min width %ld\n",(long)body[15]); + fprintf(stderr,"\t window min height %ld\n",(long)body[16]); + fprintf(stderr,"\t window max %ld\n",(long)body[17]); + fprintf(stderr,"\t window max %ld\n",(long)body[18]); + fprintf(stderr,"\t icon label window %lx\n",body[19]); + fprintf(stderr,"\t icon pixmap window %lx\n",body[20]); + fprintf(stderr,"\t window gravity %lx\n",body[21]); +} + +/*********************************************************************** + * + * Procedure: + * list_destroy - displays packet contents to stderr + * + ***********************************************************************/ +void list_destroy(unsigned long *body) +{ + fprintf(stderr,"destroy\n"); + fprintf(stderr,"\t ID %lx\n",body[0]); + fprintf(stderr,"\t frame ID %lx\n",body[1]); + fprintf(stderr,"\t fvwm ptr %lx\n",body[2]); +} + +/*********************************************************************** + * + * Procedure: + * list_focus - displays packet contents to stderr + * + ***********************************************************************/ +void list_focus(unsigned long *body) +{ + fprintf(stderr,"focus\n"); + fprintf(stderr,"\t ID %lx\n",body[0]); + fprintf(stderr,"\t frame ID %lx\n",body[1]); + fprintf(stderr,"\t fvwm ptr %lx\n",body[2]); + +} + +/*********************************************************************** + * + * Procedure: + * list_toggle - displays packet contents to stderr + * + ***********************************************************************/ +void list_toggle(unsigned long *body) +{ + fprintf(stderr,"toggle\n"); + fprintf(stderr,"\t value %ld\n",body[0]); + +} + +/*********************************************************************** + * + * Procedure: + * list_new_page - displays packet contents to stderr + * + ***********************************************************************/ +void list_new_page(unsigned long *body) +{ + fprintf(stderr,"new page\n"); + fprintf(stderr,"\t x %ld\n",(long)body[0]); + fprintf(stderr,"\t y %ld\n",(long)body[1]); + fprintf(stderr,"\t desk %ld\n",(long)body[2]); +} + +/*********************************************************************** + * + * Procedure: + * list_new_desk - displays packet contents to stderr + * + ***********************************************************************/ +void list_new_desk(unsigned long *body) +{ + fprintf(stderr,"new desk\n"); + fprintf(stderr,"\t desk %ld\n",(long)body[0]); +} + +/*********************************************************************** + * + * Procedure: + * list_raise - displays packet contents to stderr + * + ***********************************************************************/ +void list_raise(unsigned long *body) +{ + fprintf(stderr,"raise\n"); + fprintf(stderr,"\t ID %lx\n",body[0]); + fprintf(stderr,"\t frame ID %lx\n",body[1]); + fprintf(stderr,"\t fvwm ptr %lx\n",body[2]); +} + + +/*********************************************************************** + * + * Procedure: + * list_lower - displays packet contents to stderr + * + ***********************************************************************/ +void list_lower(unsigned long *body) +{ + fprintf(stderr,"lower\n"); + fprintf(stderr,"\t ID %lx\n",body[0]); + fprintf(stderr,"\t frame ID %lx\n",body[1]); + fprintf(stderr,"\t fvwm ptr %lx\n",body[2]); +} + + +/*********************************************************************** + * + * Procedure: + * list_unknow - handles an unrecognized packet. + * + ***********************************************************************/ +void list_unknown(unsigned long *body) +{ + fprintf(stderr,"Unknown packet type\n"); +} + +/*********************************************************************** + * + * Procedure: + * list_iconify - displays packet contents to stderr + * + ***********************************************************************/ +void list_iconify(unsigned long *body) +{ + fprintf(stderr,"iconify\n"); + fprintf(stderr,"\t ID %lx\n",body[0]); + fprintf(stderr,"\t frame ID %lx\n",body[1]); + fprintf(stderr,"\t fvwm ptr %lx\n",body[2]); + fprintf(stderr,"\t icon x %ld\n",(long)body[3]); + fprintf(stderr,"\t icon y %ld\n",(long)body[4]); + fprintf(stderr,"\t icon w %ld\n",(long)body[5]); + fprintf(stderr,"\t icon h %ld\n",(long)body[6]); +} + + +/*********************************************************************** + * + * Procedure: + * list_map - displays packet contents to stderr + * + ***********************************************************************/ +void list_map(unsigned long *body) +{ + fprintf(stderr,"map\n"); + fprintf(stderr,"\t ID %lx\n",body[0]); + fprintf(stderr,"\t frame ID %lx\n",body[1]); + fprintf(stderr,"\t fvwm ptr %lx\n",body[2]); +} + + +/*********************************************************************** + * + * Procedure: + * list_icon_loc - displays packet contents to stderr + * + ***********************************************************************/ +void list_icon_loc(unsigned long *body) +{ + fprintf(stderr,"icon location\n"); + fprintf(stderr,"\t ID %lx\n",body[0]); + fprintf(stderr,"\t frame ID %lx\n",body[1]); + fprintf(stderr,"\t fvwm ptr %lx\n",body[2]); + fprintf(stderr,"\t icon x %ld\n",(long)body[3]); + fprintf(stderr,"\t icon y %ld\n",(long)body[4]); + fprintf(stderr,"\t icon w %ld\n",(long)body[5]); + fprintf(stderr,"\t icon h %ld\n",(long)body[6]); +} + + + +/*********************************************************************** + * + * Procedure: + * list_deiconify - displays packet contents to stderr + * + ***********************************************************************/ + +void list_deiconify(unsigned long *body) +{ + fprintf(stderr,"de-iconify\n"); + fprintf(stderr,"\t ID %lx\n",body[0]); + fprintf(stderr,"\t frame ID %lx\n",body[1]); + fprintf(stderr,"\t fvwm ptr %lx\n",body[2]); +} + +/*********************************************************************** + * + * Procedure: + * list_window_name - displays packet contents to stderr + * + ***********************************************************************/ + +void list_window_name(unsigned long *body) +{ + fprintf(stderr,"window name\n"); + fprintf(stderr,"\t ID %lx\n",body[0]); + fprintf(stderr,"\t frame ID %lx\n",body[1]); + fprintf(stderr,"\t fvwm ptr %lx\n",body[2]); + fprintf(stderr,"\t window name %s\n",(char *)(&body[3])); + +} + + +/*********************************************************************** + * + * Procedure: + * list_icon_name - displays packet contents to stderr + * + ***********************************************************************/ +void list_icon_name(unsigned long *body) +{ + fprintf(stderr,"icon name\n"); + fprintf(stderr,"\t ID %lx\n",body[0]); + fprintf(stderr,"\t frame ID %lx\n",body[1]); + fprintf(stderr,"\t fvwm ptr %lx\n",body[2]); + fprintf(stderr,"\t icon name %s\n",(char *)(&body[3])); +} + + + +/*********************************************************************** + * + * Procedure: + * list_class - displays packet contents to stderr + * + ***********************************************************************/ +void list_class(unsigned long *body) +{ + fprintf(stderr,"window class\n"); + fprintf(stderr,"\t ID %lx\n",body[0]); + fprintf(stderr,"\t frame ID %lx\n",body[1]); + fprintf(stderr,"\t fvwm ptr %lx\n",body[2]); + fprintf(stderr,"\t window class %s\n",(char *)(&body[3])); +} + + +/*********************************************************************** + * + * Procedure: + * list_res_name - displays packet contents to stderr + * + ***********************************************************************/ +void list_res_name(unsigned long *body) +{ + fprintf(stderr,"class resource name\n"); + fprintf(stderr,"\t ID %lx\n",body[0]); + fprintf(stderr,"\t frame ID %lx\n",body[1]); + fprintf(stderr,"\t fvwm ptr %lx\n",body[2]); + fprintf(stderr,"\t resource name %s\n",(char *)(&body[3])); +} + +/*********************************************************************** + * + * Procedure: + * list_end - displays packet contents to stderr + * + ***********************************************************************/ +void list_end(void) +{ + fprintf(stderr,"Send_WindowList End\n"); +} + diff --git a/modules/FvwmDebug/FvwmDebug.h b/modules/FvwmDebug/FvwmDebug.h new file mode 100644 index 0000000..1f69987 --- /dev/null +++ b/modules/FvwmDebug/FvwmDebug.h @@ -0,0 +1,38 @@ +#include "../../libs/fvwmlib.h" +/************************************************************************* + * + * Subroutine Prototypes + * + *************************************************************************/ +void Loop(int *fd); +void SendInfo(int *fd,char *message,unsigned long window); +char *safemalloc(int length); +void DeadPipe(int nonsense); +void process_message(unsigned long type,unsigned long *body); + +void list_add(unsigned long *body); +void list_configure(unsigned long *body); +void list_destroy(unsigned long *body); +void list_focus(unsigned long *body); +void list_toggle(unsigned long *body); +void list_new_page(unsigned long *body); +void list_new_desk(unsigned long *body); +void list_raise(unsigned long *body); +void list_lower(unsigned long *body); +void list_unknown(unsigned long *body); +void list_iconify(unsigned long *body); +void list_icon_loc(unsigned long *body); +void list_deiconify(unsigned long *body); +void list_map(unsigned long *body); +void list_window_name(unsigned long *body); +void list_icon_name(unsigned long *body); +void list_class(unsigned long *body); +void list_res_name(unsigned long *body); +void list_end(void); + + + +#ifdef BROKEN_SUN_HEADERS +#include "../../fvwm/sun_headers.h" +#endif + diff --git a/modules/FvwmDebug/FvwmDebug.man b/modules/FvwmDebug/FvwmDebug.man new file mode 100644 index 0000000..f92a09e --- /dev/null +++ b/modules/FvwmDebug/FvwmDebug.man @@ -0,0 +1,44 @@ +.\" t +.\" @(#)FvwmDebug.1 1/28/94 +.TH FvwmDebug 1.20 "Jan 28 1994" +.UC +.SH NAME +FvwmDebug \- the FVWM module debugger +.SH SYNOPSIS +FvwmDebug is spawned by fvwm, so no command line invocation will work. + +.SH DESCRIPTION +The FvwmDebug captures the stream of module packets coming from +fvwm, and displays them on stderr. + +.SH COPYRIGHTS +The FvwmDebug program, and the concept for +interfacing this module to the Window Manager, are all original work +by Robert Nation + +Copyright 1994, Robert Nation. No guarantees or warranties or anything +are provided or implied in any way whatsoever. Use this program at your +own risk. Permission to use this program for any purpose is given, +as long as the copyright is kept intact. + + +.SH INITIALIZATION +During initialization, the FvwmDebug requests that fvwm dump a +complete window list into its pipe. These packets are terminated with +and "end Send_WindowList" message. + +.SH INVOCATION +FvwmDebug can be invoked by inserting the line 'Module FvwmDebug' in +the .fvwmrc file. This can be placed on a line by itself, if FvwmDebug +is to be spawned during fvwm's initialization, or can be bound to a +menu or mouse button or keystroke to invoke it later. Fvwm will search +directory specified in the ModulePath configuration option to attempt +to locate FvwmDebug. + +.SH CONFIGURATION OPTIONS +There are no configuration options. + + +.SH AUTHOR +Robert Nation + diff --git a/modules/FvwmDebug/Imakefile b/modules/FvwmDebug/Imakefile new file mode 100644 index 0000000..3593f49 --- /dev/null +++ b/modules/FvwmDebug/Imakefile @@ -0,0 +1,27 @@ +/* Imakefile for FvwmDebug */ +/* Thu Aug 5 11:21:36 MET DST 1993, mj@dfv.rwth-aachen.de */ + +/* setup is done entirely in configuration.h now! */ +/* You should need to do much in here, excpt maybe add libraries */ + +/* I need to get the #define XPM from configuration.h if its in there,*/ +/* so that I can tell if I should include -lXpm */ +#include <../../configure.h> + +COMPILER + +DEPLIBS = $(DEPXLIB) ../../libs/libfvwmlib.a + +#ifdef AlphaArchitecture +LOCAL_LIBRARIES = -ldnet_stub -L../../libs -lfvwmlib +#else +LOCAL_LIBRARIES = -L../../libs -lfvwmlib +#endif +LINTLIBS = $(LINTXLIB) + +SRCS = FvwmDebug.c +OBJS = FvwmDebug.o + +TARGET_DIR + +ComplexProgramTarget(FvwmDebug) diff --git a/modules/FvwmIconBox/COPYRIGHT b/modules/FvwmIconBox/COPYRIGHT new file mode 100644 index 0000000..47bae99 --- /dev/null +++ b/modules/FvwmIconBox/COPYRIGHT @@ -0,0 +1,62 @@ +FvwmIconBox Module --- Copyright 1994, Nobutaka Suzuki. + +No guarantees or warantees or anything are provided or implied in +any way whatsoever. Use this program at your own risk. Permission +to use this program for any purpose is given, as long as the +copyright is kept intact. + + +Here is original copyright for functions based on GoodStuff. + + Copyright 1994, Robert Nation. No guarantees or warranties + or anything are provided or implied in any way whatsoever. + Use this program at your own risk. Permission to use this + program for any purpose is given, as long as the copyright + is kept intact. + + +Here is original copyright for functions based on FvwmScroll. + + Copyright 1994, Robert Nation. No guarantees or warranties + or anything are provided or implied in any way whatsoever. + Use this program at your own risk. Permission to use this + program for any purpose is given, as long as the copyright + is kept intact. + + +Here is original copyright for functions based on FvwmWinList. + + Copyright 1994, Mike Finger. The author makes no guaran- + tees or warranties of any kind about the use of this mod- + ule. Use this modules at your own risk. You may freely + use this module or any portion of it for any purpose as + long as the copyright is kept intact. + + +Here is original copyright for functions based on fvwm. + + fvwm is copyright 1988 by Evans and Sutherland Computer + Corporation, Salt Lake City, Utah, and 1989 by the Mas- + sachusetts Institute of Technology, Cambridge, Mas- + sachusetts, All rights reserved. It is also copyright 1993 + and 1994 by Robert Nation. + + Permission to use, copy, modify, and distribute this soft- + ware and its documentation for any purpose and with- + out fee is hereby granted, provided that the above copy- + right notice appear in all copies and that both that + copyright notice and this permission notice appear in + supporting documentation, and that the names of Evans + & Sutherland and M.I.T. not be used in advertising in pub- + licity pertaining to distribution of the software with- + out specific, written prior permission. + + ROBERT NATION, EVANS & SUTHERLAND, AND M.I.T. DISCLAIM ALL + WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + IMPLIED WARRANTIES OF MERCHANT- ABILITY AND FITNESS, + IN NO EVENT SHALL EVANS & SUTHERLAND OR M.I.T. BE LIABLE + FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- AGES OR + ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA + OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + OR OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION + WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/modules/FvwmIconBox/FvwmIconBox.c b/modules/FvwmIconBox/FvwmIconBox.c new file mode 100644 index 0000000..f444a99 --- /dev/null +++ b/modules/FvwmIconBox/FvwmIconBox.c @@ -0,0 +1,2451 @@ +/* FvwmIconBox Module --- Copyright 1994, Nobutaka Suzuki. + * + * No guarantees or warantees or anything are provided or implied in + * any way whatsoever. Use this program at your own risk. Permission + * to use this program for any purpose is given, as long as the + * copyright is kept intact. + * + * The functions based on part of GoodStuff, FvwmScroll, FvwmWinList + * and Fvwm are noted by a small copyright atop that function. + * Full original copyright is described in COPYRIGHT. + */ + +#define TRUE 1 +#define FALSE 0 + +#define MARGIN1 8 +#define MARGIN2 6 +#define BAR_WIDTH 9 + +#define NONE 0 +#define VERTICAL 1 +#define HORIZONTAL 2 + +#define DEAD 0 +#define DELETE 1 + +#include "../../configure.h" + +#ifdef ISC +#include /* Saul */ +#endif + +#include +#include +#include +#include +#include +#include +#if defined ___AIX || defined _AIX || defined __QNX__ || defined ___AIXV3 || defined AIXV3 || defined _SEQUENT_ +#include +#endif +#include +#include +#include +#include "../../fvwm/module.h" + +#include +#include +#include +#include +#include +#ifdef SHAPE +#include +#endif /* SHAPE */ + +/* just as same as wild.c */ +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#include "FvwmIconBox.h" +#include "../../version.h" + +char *MyName; + +XFontStruct *font; + +Display *dpy; /* which display are we talking to */ +int x_fd,fd_width; + +Window Root; +int screen; +int d_depth; + +char *Back = "#5f9ea0"; +char *Fore = "#82dfe3"; +char *IconBack = "#cfcfcf"; +char *IconFore = "black"; +char *ActIconBack = "white"; +char *ActIconFore = "black"; +char *font_string = "fixed"; + +Pixel fore_pix, hilite_pix, back_pix, shadow_pix; +Pixel icon_fore_pix, icon_back_pix, icon_hilite_pix, icon_shadow_pix; +Pixel act_icon_fore_pix, act_icon_back_pix, act_icon_hilite_pix, act_icon_shadow_pix; + +GC NormalGC,ShadowGC,ReliefGC,IconShadowGC,IconReliefGC; +Window main_win; +Window holder_win; +Window icon_win; +Window h_scroll_bar; +Window v_scroll_bar; +Window l_button, r_button, t_button, b_button; +Window Pressed = None; + +int Width, Height; +int UWidth, UHeight; + +#define MW_EVENTS (KeyPressMask| ExposureMask | StructureNotifyMask|\ + ButtonReleaseMask | ButtonPressMask ) +#define SCROLL_EVENTS (ExposureMask | StructureNotifyMask|\ + ButtonReleaseMask |ButtonPressMask | PointerMotionMask) +#define BUTTON_EVENTS (ExposureMask | StructureNotifyMask|\ + ButtonReleaseMask | ButtonPressMask |\ + LeaveWindowMask | PointerMotionMask) + +struct icon_info *Hilite; +int main_width, main_height; +int num_icons = 0; +int num_rows = 1; +int num_columns = 6; +int Lines = 6; +int max_icon_width = 48,max_icon_height = 48; +int ButtonWidth,ButtonHeight; +int x= -100000,y= -100000,w= -1,h= -1,gravity = NorthWestGravity; +int icon_win_x = 0, icon_win_y = 0, icon_win_width = 100, +icon_win_height = 100; +int ready = 0; +int sorticons = 0; +int interval = 8; +int motion = NONE; +int primary = LEFT, secondary = BOTTOM; +int xneg = 0, yneg = 0; +int ClickTime = 150; +int hidesc = NONE; + +Pixmap IconwinPixmap = None; +char *IconwinPixmapFile = NULL; + +int h_margin = MARGIN1*2 + BAR_WIDTH + MARGIN2 + 8; +int v_margin = MARGIN1*2 + BAR_WIDTH + MARGIN2 + 8; + +int fd[2]; + +struct icon_info *Head = NULL; +struct icon_info *Tail = NULL; +struct iconfile *IconListHead = NULL; +struct iconfile *IconListTail = NULL; +struct iconfile *DefaultIcon = NULL; +struct mousefunc *MouseActions = NULL; +struct keyfunc *KeyActions = NULL; +char *iconPath = NULL; +char *pixmapPath = NULL; + +static Atom wm_del_win; +Atom _XA_WM_PROTOCOLS; +Atom _XA_WM_NAME; + +int UP = 0; +int isendlist = 0; + +/************************************************************************ + Main + Based on main() from GoodStuff: + Copyright 1993, Robert Nation. +************************************************************************/ +void main(int argc, char **argv) +{ + char *display_name = NULL; + char *temp, *s; + char set_mask_mesg[50]; + + temp = argv[0]; + + s=strrchr(argv[0], '/'); + if (s != NULL) + temp = s + 1; + + + MyName = safemalloc(strlen(temp)+1); + strcpy(MyName, temp); + + signal (SIGPIPE, DeadPipe); + + if((argc != 6)&&(argc != 7)) + { + fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",MyName, + VERSION); + exit(1); + } + + fd[0] = atoi(argv[1]); + fd[1] = atoi(argv[2]); + + if (!(dpy = XOpenDisplay(display_name))) + { + fprintf(stderr,"%s: can't open display %s", MyName, + XDisplayName(display_name)); + exit (1); + } + x_fd = XConnectionNumber(dpy); + + fd_width = GetFdWidth(); + + screen= DefaultScreen(dpy); + Root = RootWindow(dpy, screen); + if(Root == None) + { + fprintf(stderr,"%s: Screen %d is not valid ", MyName, screen); + exit(1); + } + d_depth = DefaultDepth(dpy, screen); + + sprintf(set_mask_mesg,"SET_MASK %lu\n", + (unsigned long)(M_CONFIGURE_WINDOW| + M_ADD_WINDOW| + M_DESTROY_WINDOW| + M_END_WINDOWLIST| + M_ICONIFY| + M_DEICONIFY| + M_ICON_NAME| + M_RES_NAME| + M_RES_CLASS| + M_WINDOW_NAME)); + + SendFvwmPipe(fd,set_mask_mesg,0); + + ParseOptions(argv[3]); + + CreateWindow(); + + SendFvwmPipe(fd,"Send_WindowList",0); + + Loop(); +} + +/************************************************************************ + Loop + Based on Loop() from GoodStuff: + Copyright 1993, Robert Nation. +************************************************************************/ +void Loop(void) +{ + Window root; + struct icon_info *tmp, *exhilite; + int x,y,border_width,depth; + int i, hr = ICON_RELIEF/2; + XEvent Event; + int tw,th; + int diffx, diffy; + int oldw, oldh; + + while(1) + { + if(My_XNextEvent(dpy,&Event)) + { + switch(Event.type) + { + case Expose: + if(Event.xexpose.count == 0){ + if (Event.xany.window == main_win){ + if(ready < 1) + ready ++; + RedrawWindow(-1); + }else{ + tmp = Head; + while(tmp != NULL){ + if (Event.xany.window == tmp->icon_pixmap_w){ + RedrawIcon(tmp, 1); + break; + }else if(Event.xany.window == tmp->IconWin){ + RedrawIcon(tmp, 2); + break; + } + tmp = tmp->next; + } + } + } + break; + + case ConfigureNotify: + XGetGeometry(dpy,main_win,&root,&x,&y, + (unsigned int *)&tw,(unsigned int *)&th, + (unsigned int *)&border_width, + (unsigned int *)&depth); + if (UP && (tw != main_width || th != main_height)){ + main_width = tw; + main_height= th; + oldw = Width; + oldh = Height; + num_columns = (tw - h_margin - interval + 1) / UWidth; + num_rows = (th - v_margin - interval + 1) / UHeight; + Width = UWidth * num_columns + interval - 1; + Height = UHeight * num_rows + interval -1; + XMoveResizeWindow(dpy, holder_win, MARGIN1+2, + MARGIN1+2, + tw - h_margin, th - v_margin); + if (hidesc != HORIZONTAL) + XResizeWindow(dpy, h_scroll_bar, + Width - BAR_WIDTH*2, BAR_WIDTH); + if (hidesc != VERTICAL) + XResizeWindow(dpy ,v_scroll_bar, + BAR_WIDTH, Height - BAR_WIDTH*2); + GetIconwinSize(&diffx, &diffy); + i = 0; + tmp = Head; + while(tmp != NULL){ + AdjustIconWindow(tmp, i++); + tmp = tmp->next; + } + if (primary == BOTTOM || secondary == BOTTOM) + icon_win_y -= Height - oldh; + if (primary == RIGHT || secondary == RIGHT) + icon_win_x -= Width - oldw; + if (icon_win_x < 0) + icon_win_x = 0; + if (icon_win_y < 0) + icon_win_y = 0; + if (icon_win_x + Width > icon_win_width) + icon_win_x = icon_win_width - Width; + if (icon_win_y + Height > icon_win_height) + icon_win_y = icon_win_height - Height; + XMoveResizeWindow(dpy, icon_win, -icon_win_x, + -icon_win_y, icon_win_width, + icon_win_height); + XClearWindow(dpy,main_win); + RedrawWindow(-1); + } + break; + case KeyPress: + ExecuteKey(Event); + break; + case ButtonPress: + if (hidesc != HORIZONTAL){ + if (Event.xbutton.window == h_scroll_bar) + motion = HORIZONTAL; + else if (Event.xbutton.window == l_button){ + Pressed = l_button; + RedrawLeftButton(ShadowGC, ReliefGC); + } + else if (Event.xbutton.window == r_button){ + Pressed = r_button; + RedrawRightButton(ShadowGC, ReliefGC); + } + } + if (hidesc != VERTICAL){ + if (Event.xbutton.window == v_scroll_bar) + motion = VERTICAL; + else if (Event.xbutton.window == t_button){ + Pressed = t_button; + RedrawTopButton(ShadowGC, ReliefGC); + } + else if (Event.xbutton.window == b_button){ + Pressed = b_button; + RedrawBottomButton(ShadowGC, ReliefGC); + } + } + if ((tmp = Search(Event.xbutton.window)) != NULL) + ExecuteAction(Event.xbutton.x, Event.xbutton.y, tmp); + break; + + case ButtonRelease: + if (hidesc != HORIZONTAL){ + if (Event.xbutton.window == h_scroll_bar && motion == + HORIZONTAL) + HScroll(Event.xbutton.x * icon_win_width / Width); + else if (Event.xbutton.window == l_button && Pressed == + l_button){ + Pressed = None; + RedrawLeftButton(ReliefGC, ShadowGC); + HScroll(icon_win_x - UWidth); + } + else if (Event.xbutton.window == r_button && Pressed == + r_button){ + Pressed = None; + RedrawRightButton(ReliefGC, ShadowGC); + HScroll(icon_win_x + UWidth); + } + } + if (hidesc != VERTICAL){ + if (Event.xbutton.window == v_scroll_bar && motion + == VERTICAL) + VScroll(Event.xbutton.y * icon_win_height / Height); + else if (Event.xbutton.window == t_button && Pressed == + t_button){ + Pressed = None; + RedrawTopButton(ReliefGC, ShadowGC); + VScroll(icon_win_y - UHeight); + } + else if (Event.xbutton.window == b_button && Pressed == + b_button){ + Pressed = None; + RedrawBottomButton(ReliefGC, ShadowGC); + VScroll(icon_win_y + UHeight); + } + } + motion = NONE; + break; + + case MotionNotify: + if (motion == VERTICAL){ + VScroll(Event.xbutton.y * icon_win_height / Height); + }else if (motion == HORIZONTAL){ + HScroll(Event.xbutton.x * icon_win_width / Width); + } + break; + case EnterNotify: + if ((tmp = Search(Event.xcrossing.window)) != NULL) + if ((exhilite = Hilite) != tmp){ + Hilite = tmp; + if (exhilite != NULL) + RedrawIcon(exhilite, 3); + RedrawIcon(tmp, 3); + } + break; + + case LeaveNotify: + if ((tmp = Search(Event.xcrossing.window)) != NULL && + tmp == Hilite){ + Hilite = NULL; + RedrawIcon(tmp, 3); + } + if (hidesc != HORIZONTAL && Event.xbutton.window == + l_button && Pressed == l_button){ + Pressed = None; + RedrawLeftButton(ReliefGC, ShadowGC); + } + else if (hidesc != HORIZONTAL && Event.xbutton.window == + r_button && Pressed == r_button){ + Pressed = None; + RedrawRightButton(ReliefGC, ShadowGC); + } + else if (hidesc != VERTICAL && Event.xbutton.window == + t_button && Pressed == t_button){ + Pressed = None; + RedrawTopButton(ReliefGC, ShadowGC); + } + else if (hidesc != VERTICAL && Event.xbutton.window == + b_button && Pressed == b_button){ + Pressed = None; + RedrawBottomButton(ReliefGC, ShadowGC); + } + break; + case ClientMessage: + if ((Event.xclient.format==32) && + (Event.xclient.data.l[0]==wm_del_win)) + DeadPipe(1); + break; + case PropertyNotify: + switch (Event.xproperty.atom){ + case XA_WM_HINTS: + if (Event.xproperty.state == PropertyDelete) + break; + tmp = Head; + i=0; + while(tmp != NULL){ + if (Event.xproperty.window == tmp->id) + break; + tmp = tmp->next; + ++i; + } + if (tmp == NULL || tmp->wmhints == NULL || !tmp->defaulticon) + break; +#ifdef SHAPE + /* turn off "old" shape mask */ + if (tmp->icon_maskPixmap != None) + XShapeCombineMask(dpy, tmp->icon_pixmap_w, + ShapeBounding, 0, 0, None, ShapeSet); +#endif + if (tmp->wmhints) + XFree (tmp->wmhints); + tmp->wmhints = XGetWMHints(dpy, tmp->id); + if (tmp->wmhints && (tmp->wmhints->flags & IconPixmapHint)){ + if (tmp->iconPixmap != None) + XFreePixmap(dpy, tmp->iconPixmap); + GetIconBitmap(tmp); +#ifdef SHAPE + if (tmp->icon_maskPixmap != None) + XShapeCombineMask(dpy, tmp->icon_pixmap_w, + ShapeBounding, hr, hr, + tmp->icon_maskPixmap, ShapeSet); +#endif + AdjustIconWindow(tmp, i); + RedrawIcon(tmp, 1); + } + break; + } + break; + default: + break; + } + } + } + return; +} + +void HScroll(int x) +{ + int oldx = icon_win_x; + + if (x + Width > icon_win_width) + x = icon_win_width - Width; + if (x < 0) + x = 0; + if (oldx != x){ + icon_win_x = x; + XMoveWindow(dpy,icon_win, -icon_win_x, -icon_win_y); + if (hidesc != HORIZONTAL) + RedrawHScrollbar(); + } +} + +void VScroll(int y) +{ + int oldy = icon_win_y; + + if (y + Height > icon_win_height) + y = icon_win_height - Height; + if (y < 0) + y = 0; + if (oldy != y){ + icon_win_y = y; + XMoveWindow(dpy,icon_win, -icon_win_x, -icon_win_y); + if (hidesc != VERTICAL) + RedrawVScrollbar(); + } +} + +struct icon_info *Search(Window w) +{ + struct icon_info *tmp; + + tmp = Head; + while (tmp != NULL){ + if (tmp->IconWin == w || tmp->icon_pixmap_w == w) + return tmp; + tmp = tmp->next; + } + return NULL; +} + +/************************************************************************ + * + * Draw the window + * + ***********************************************************************/ +void RedrawWindow(int newbutton) +{ + XEvent dummy; + + if(ready < 1) + return; + + while (XCheckTypedWindowEvent (dpy, main_win, Expose, &dummy)); + + + RelieveWindow(main_win, MARGIN1, MARGIN1, Width + 4, + Height + 4, ShadowGC,ReliefGC); + if (hidesc != HORIZONTAL) + RelieveWindow(main_win, MARGIN1, MARGIN1 + 4 + Height + MARGIN2, + Width + 4, BAR_WIDTH+4, ShadowGC,ReliefGC); + if (hidesc != VERTICAL) + RelieveWindow(main_win, MARGIN1 + 4 + Width + MARGIN2, MARGIN1, + BAR_WIDTH+4, Height + 4, ShadowGC,ReliefGC); + RelieveWindow(main_win, 0, 0, Width + h_margin, Height + v_margin, + ReliefGC, ShadowGC); + + /* scroll bar */ + if (hidesc != HORIZONTAL) + RedrawHScrollbar(); + if (hidesc != VERTICAL) + RedrawVScrollbar(); + + /* buttons */ + if (hidesc != HORIZONTAL){ + RedrawLeftButton(ReliefGC, ShadowGC); + RedrawRightButton(ReliefGC, ShadowGC); + } + if (hidesc != VERTICAL){ + RedrawTopButton(ReliefGC, ShadowGC); + RedrawBottomButton(ReliefGC, ShadowGC); + } + + /* icons */ + RedrawIcons(); +} + +void RedrawIcons(void) +{ + struct icon_info *tmp; + + tmp = Head; + while(tmp != NULL){ + RedrawIcon(tmp, 3); + tmp = tmp->next; + } +} + +void RedrawIcon(struct icon_info *item, int f) +{ + unsigned long plane = 1; + int hr, len; + int diff, lm ,w, h, tw; + char label[256]; + + hr = ICON_RELIEF/2; + + if (Hilite == item){ + XSetForeground(dpy, NormalGC, act_icon_fore_pix); + XSetBackground(dpy, NormalGC, act_icon_back_pix); + XSetForeground(dpy, IconReliefGC, act_icon_hilite_pix); + XSetForeground(dpy, IconShadowGC, act_icon_shadow_pix); + + XSetWindowBackground(dpy, item->icon_pixmap_w, act_icon_back_pix); + XSetWindowBackground(dpy, item->IconWin, act_icon_back_pix); + } + + /* icon pixmap */ + if ((f & 1) && (item->flags & ICON_OURS)){ + if (item->iconPixmap != None && item->icon_pixmap_w != None){ + if (item->icon_depth != d_depth) + XCopyPlane(dpy, item->iconPixmap, item->icon_pixmap_w, NormalGC, + 0, 0, item->icon_w, item->icon_h, + hr, hr, plane); + else + XCopyArea(dpy, item->iconPixmap, item->icon_pixmap_w, NormalGC, + 0, 0, item->icon_w, item->icon_h, hr, hr); + +/* if (item->flags & ICONIFIED){ + if (Hilite == item) + XSetForeground(dpy, NormalGC, act_icon_back_pix); + else + XSetForeground(dpy, NormalGC, icon_back_pix); + + XSetFillStyle(dpy, NormalGC, FillStippled); + XFillRectangle(dpy, item->icon_pixmap_w, NormalGC, hr, hr, + item->icon_w, item->icon_h); + XSetFillStyle(dpy, NormalGC, FillSolid); + + if (Hilite == item) + XSetForeground(dpy, NormalGC, act_icon_fore_pix); + else + XSetForeground(dpy, NormalGC, icon_fore_pix); + } + */ } + if (!(item->flags & SHAPED_ICON)){ + if (item->icon_w > 0 && item->icon_h > 0) + RelieveWindow(item->icon_pixmap_w, 0, 0, item->icon_w + +ICON_RELIEF, + item->icon_h + ICON_RELIEF, IconReliefGC, + IconShadowGC); + else + RelieveWindow(item->icon_pixmap_w, 0, 0, max_icon_width + +ICON_RELIEF, + max_icon_height + ICON_RELIEF, IconReliefGC, + IconShadowGC); + } + } + else if (f & 1) + XMapWindow(dpy, item->icon_pixmap_w); + + /* label */ + if (f & 2){ + w = max_icon_width + ICON_RELIEF; + h = max_icon_height + ICON_RELIEF; + + if (item->flags & ICONIFIED){ + sprintf(label, "(%s)", item->name); + }else + strcpy(label, item->name); + + len = strlen(label); + tw = XTextWidth(font, label, len); + diff = max_icon_width + ICON_RELIEF - tw; + lm = diff/2; + lm = lm > 4 ? lm : 4; + + if (Hilite == item){ + XRaiseWindow(dpy, item->IconWin); + XMoveResizeWindow(dpy, item->IconWin, + item->x + min(0, (diff - 8))/2, + item->y + h, + max(tw + 8, w), 6 + font->ascent + + font->descent); + XClearWindow(dpy, item->IconWin); + XDrawString(dpy, item->IconWin, NormalGC, lm, 3 + font->ascent, + label, len); + RelieveWindow(item->IconWin, 0, 0, + max(tw + 8, w), 6 + font->ascent + + font->descent, IconReliefGC, IconShadowGC); + }else{ + XMoveResizeWindow(dpy, item->IconWin, item->x, item->y + h, + w, 6 + font->ascent + font->descent); + XClearWindow(dpy, item->IconWin); + XDrawString(dpy, item->IconWin, NormalGC, lm, 3 + font->ascent, + label, len); + RelieveWindow(item->IconWin, 0, 0, + w, 6 + font->ascent + font->descent, + IconReliefGC, IconShadowGC); + } + } + + if (Hilite == item){ + XSetForeground(dpy, NormalGC, icon_fore_pix); + XSetBackground(dpy, NormalGC, icon_back_pix); + XSetForeground(dpy, IconReliefGC, icon_hilite_pix); + XSetForeground(dpy, IconShadowGC, icon_shadow_pix); + + XSetWindowBackground(dpy, item->icon_pixmap_w, icon_back_pix); + XSetWindowBackground(dpy, item->IconWin, icon_back_pix); + } +} + +/*********************************************************************** + * RedrawHScrollbar + * Based on part of Loop() of GrabWindow.c in FvwmScroll: + * Copyright 1994, Robert Nation. + ***********************************************************************/ +void RedrawHScrollbar(void) +{ + int x,width; + + x = (Width - BAR_WIDTH*2) * icon_win_x / icon_win_width; + width = (Width - BAR_WIDTH*2) * Width / icon_win_width; + XClearArea(dpy, h_scroll_bar, 0, 0, Width, BAR_WIDTH,False); + RelieveWindow(h_scroll_bar, x, 0, width, BAR_WIDTH, ReliefGC, ShadowGC); +} + +/*********************************************************************** + * RedrawVScrollbar + * Based on part of Loop() of GrabWindow.c in FvwmScroll: + * Copyright 1994, Robert Nation. + ***********************************************************************/ +void RedrawVScrollbar(void) +{ + int y, height; + + y = (Height - BAR_WIDTH*2) * icon_win_y / icon_win_height; + height = (Height - BAR_WIDTH*2)* Height / icon_win_height; + XClearArea(dpy, v_scroll_bar, 0, 0, BAR_WIDTH, Height,False); + RelieveWindow(v_scroll_bar, 0, y, BAR_WIDTH, height, ReliefGC, ShadowGC); +} + +void RedrawLeftButton(GC rgc, GC sgc) +{ + XSegment seg[4]; + int i=0; + + seg[i].x1 = 1; seg[i].y1 = BAR_WIDTH/2; + seg[i].x2 = BAR_WIDTH - 2; seg[i++].y2 = 1; + + seg[i].x1 = 0; seg[i].y1 = BAR_WIDTH/2; + seg[i].x2 = BAR_WIDTH - 1; seg[i++].y2 = 0; + XDrawSegments(dpy, l_button, rgc, seg, i); + + i = 0; + seg[i].x1 = 1; seg[i].y1 = BAR_WIDTH/2; + seg[i].x2 = BAR_WIDTH - 2; seg[i++].y2 = BAR_WIDTH - 2; + + seg[i].x1 = 0; seg[i].y1 = BAR_WIDTH/2; + seg[i].x2 = BAR_WIDTH - 1; seg[i++].y2 = BAR_WIDTH - 1; + + seg[i].x1 = BAR_WIDTH - 2; seg[i].y1 = 1; + seg[i].x2 = BAR_WIDTH - 2; seg[i++].y2 = BAR_WIDTH - 2; + + seg[i].x1 = BAR_WIDTH - 1; seg[i].y1 = 0; + seg[i].x2 = BAR_WIDTH - 1; seg[i++].y2 = BAR_WIDTH - 1; + XDrawSegments(dpy, l_button, sgc, seg, i); +} + +void RedrawRightButton(GC rgc, GC sgc) +{ + XSegment seg[4]; + int i=0; + + seg[i].x1 = 1; seg[i].y1 = 1; + seg[i].x2 = 1; seg[i++].y2 = BAR_WIDTH - 2; + + seg[i].x1 = 0; seg[i].y1 = 0; + seg[i].x2 = 0; seg[i++].y2 = BAR_WIDTH - 1; + + seg[i].x1 = 1; seg[i].y1 = 1; + seg[i].x2 = BAR_WIDTH - 2; seg[i++].y2 = BAR_WIDTH/2; + + seg[i].x1 = 0; seg[i].y1 = 0; + seg[i].x2 = BAR_WIDTH - 1; seg[i++].y2 = BAR_WIDTH/2; + + XDrawSegments(dpy, r_button, rgc, seg, i); + + i = 0; + seg[i].x1 = 1; seg[i].y1 = BAR_WIDTH - 2; + seg[i].x2 = BAR_WIDTH - 2; seg[i++].y2 = BAR_WIDTH/2; + + seg[i].x1 = 0; seg[i].y1 = BAR_WIDTH - 1; + seg[i].x2 = BAR_WIDTH - 1; seg[i++].y2 = BAR_WIDTH/2; + XDrawSegments(dpy, r_button, sgc, seg, i); +} + +void RedrawTopButton(GC rgc, GC sgc) +{ + XSegment seg[4]; + int i=0; + + seg[i].x1 = BAR_WIDTH/2; seg[i].y1 = 1; + seg[i].x2 = 1; seg[i++].y2 = BAR_WIDTH - 2; + + seg[i].x1 = BAR_WIDTH/2; seg[i].y1 = 0; + seg[i].x2 = 0; seg[i++].y2 = BAR_WIDTH - 1; + XDrawSegments(dpy, t_button, rgc, seg, i); + + i = 0; + seg[i].x1 = BAR_WIDTH/2; seg[i].y1 = 1; + seg[i].x2 = BAR_WIDTH - 2; seg[i++].y2 = BAR_WIDTH - 2; + + seg[i].x1 = BAR_WIDTH/2; seg[i].y1 = 0; + seg[i].x2 = BAR_WIDTH - 1; seg[i++].y2 = BAR_WIDTH - 1; + + seg[i].x1 = 1; seg[i].y1 = BAR_WIDTH - 2; + seg[i].x2 = BAR_WIDTH - 2; seg[i++].y2 = BAR_WIDTH - 2; + + seg[i].x1 = 0; seg[i].y1 = BAR_WIDTH - 1; + seg[i].x2 = BAR_WIDTH - 1; seg[i++].y2 = BAR_WIDTH - 1; + XDrawSegments(dpy, t_button, sgc, seg, i); +} + +void RedrawBottomButton(GC rgc, GC sgc) +{ + XSegment seg[4]; + int i=0; + + seg[i].x1 = 1; seg[i].y1 = 1; + seg[i].x2 = BAR_WIDTH/2; seg[i++].y2 = BAR_WIDTH - 2; + + seg[i].x1 = 0; seg[i].y1 = 0; + seg[i].x2 = BAR_WIDTH/2; seg[i++].y2 = BAR_WIDTH - 1; + + seg[i].x1 = 1; seg[i].y1 = 1; + seg[i].x2 = BAR_WIDTH - 2; seg[i++].y2 = 1; + + seg[i].x1 = 0; seg[i].y1 = 0; + seg[i].x2 = BAR_WIDTH - 1; seg[i++].y2 = 0; + XDrawSegments(dpy, b_button, rgc, seg, i); + + i = 0; + seg[i].x1 = BAR_WIDTH - 2; seg[i].y1 = 1; + seg[i].x2 = BAR_WIDTH/2; seg[i++].y2 = BAR_WIDTH - 2; + + seg[i].x1 = BAR_WIDTH - 1; seg[i].y1 = 0; + seg[i].x2 = BAR_WIDTH/2; seg[i++].y2 = BAR_WIDTH - 1; + XDrawSegments(dpy, b_button, sgc, seg, i); +} + +/************************************************************************ + RelieveWindow + Original work from GoodStuff: + Copyright 1993, Robert Nation. +************************************************************************/ +FVWM_INLINE void RelieveWindow(Window win,int x,int y,int w,int h, + GC rgc,GC sgc) +{ + XSegment seg[4]; + int i; + + i=0; + seg[i].x1 = x; seg[i].y1 = y; + seg[i].x2 = w+x-1; seg[i++].y2 = y; + + seg[i].x1 = x; seg[i].y1 = y; + seg[i].x2 = x; seg[i++].y2 = h+y-1; + + seg[i].x1 = x+1; seg[i].y1 = y+1; + seg[i].x2 = x+w-2; seg[i++].y2 = y+1; + + seg[i].x1 = x+1; seg[i].y1 = y+1; + seg[i].x2 = x+1; seg[i++].y2 = y+h-2; + XDrawSegments(dpy, win, rgc, seg, i); + + i=0; + seg[i].x1 = x; seg[i].y1 = y+h-1; + seg[i].x2 = w+x-1; seg[i++].y2 = y+h-1; + + seg[i].x1 = x+w-1; seg[i].y1 = y; + seg[i].x2 = x+w-1; seg[i++].y2 = y+h-1; + if(d_depth<2) + XDrawSegments(dpy, win, ShadowGC, seg, i); + else + XDrawSegments(dpy, win, sgc, seg, i); + + i=0; + seg[i].x1 = x+1; seg[i].y1 = y+h-2; + seg[i].x2 = x+w-2; seg[i++].y2 = y+h-2; + + seg[i].x1 = x+w-2; seg[i].y1 = y+1; + seg[i].x2 = x+w-2; seg[i++].y2 = y+h-2; + + XDrawSegments(dpy, win, sgc, seg, i); +} + +/************************************************************************ + * CreateWindow --Sizes and creates the window + * Based on CreateWindow() from GoodStuff: + * Copyright 1993, Robert Nation. + ***********************************************************************/ +XSizeHints mysizehints; +XSetWindowAttributes attributes; +void CreateWindow(void) +{ + XGCValues gcv; + unsigned long gcm; + unsigned long mask; + + wm_del_win = XInternAtom(dpy,"WM_DELETE_WINDOW",False); + _XA_WM_PROTOCOLS = XInternAtom (dpy, "WM_PROTOCOLS", False); + + /* load the font */ + if ((font = XLoadQueryFont(dpy, font_string)) == NULL) + { + if ((font = XLoadQueryFont(dpy, "fixed")) == NULL) + { + fprintf(stderr,"%s: No fonts available\n",MyName); + exit(1); + } + }; + + if (hidesc == HORIZONTAL) + v_margin -= BAR_WIDTH + MARGIN2 + 4; + if (hidesc == VERTICAL) + h_margin -= BAR_WIDTH + MARGIN2 + 4; + + UWidth = max_icon_width + ICON_RELIEF + interval; + UHeight = font->ascent + font->descent + max_icon_height + + ICON_RELIEF + 6 + interval; + Width = UWidth * num_columns + interval -1; + Height = UHeight * num_rows + interval -1; + + mysizehints.flags = PWinGravity| PResizeInc | PMinSize; + + /* subtract one for the right/bottom border */ + mysizehints.min_width = UWidth + interval - 1 + h_margin; + main_width = mysizehints.width = Width + h_margin; + mysizehints.min_height = UHeight + interval - 1 + v_margin; + main_height = mysizehints.height = Height + v_margin; + mysizehints.width_inc = UWidth; + mysizehints.height_inc = UHeight; + + if(x > -100000) + { + if (xneg) + { + mysizehints.x = DisplayWidth(dpy,screen) + x - mysizehints.width-2; + gravity = NorthEastGravity; + } + else + mysizehints.x = x; + if (yneg) + { + mysizehints.y = DisplayHeight(dpy,screen) + y - mysizehints.height-2; + gravity = SouthWestGravity; + } + else + mysizehints.y = y; + + if((xneg) && (yneg)) + gravity = SouthEastGravity; + + mysizehints.flags |= USPosition; + } + + mysizehints.win_gravity = gravity; +#define BW 1 + if(d_depth < 2) + { + back_pix = icon_back_pix = act_icon_fore_pix = GetColor("white"); + fore_pix = icon_fore_pix = act_icon_back_pix = GetColor("black"); + hilite_pix = icon_hilite_pix = act_icon_shadow_pix = icon_back_pix; + shadow_pix = icon_shadow_pix = act_icon_hilite_pix = icon_fore_pix; + } + else + { + fore_pix = GetColor(Fore); + back_pix = GetColor(Back); + icon_back_pix = GetColor(IconBack); + icon_fore_pix = GetColor(IconFore); + icon_hilite_pix = GetHilite(icon_back_pix); + icon_shadow_pix = GetShadow(icon_back_pix); + act_icon_back_pix = GetColor(ActIconBack); + act_icon_fore_pix = GetColor(ActIconFore); + act_icon_hilite_pix = GetHilite(act_icon_back_pix); + act_icon_shadow_pix = GetShadow(act_icon_back_pix); + hilite_pix = GetHilite(back_pix); + shadow_pix = GetShadow(back_pix); + } + + main_win = XCreateSimpleWindow(dpy,Root,mysizehints.x,mysizehints.y, + mysizehints.width,mysizehints.height, + BW,fore_pix,back_pix); + XSetWMProtocols(dpy,main_win,&wm_del_win,1); + XSetWMNormalHints(dpy,main_win,&mysizehints); + XSelectInput(dpy,main_win,MW_EVENTS); + change_window_name(MyName); + + mysizehints.flags = PWinGravity| PResizeInc | PSize; + mysizehints.width -= h_margin; + mysizehints.height -= v_margin; + holder_win = XCreateSimpleWindow(dpy,main_win,MARGIN1+2, + MARGIN1+2, + mysizehints.width, + mysizehints.height, + 0,fore_pix,back_pix); + + icon_win = XCreateSimpleWindow(dpy,holder_win,-icon_win_x,-icon_win_y, + icon_win_width, + icon_win_height, + 0,fore_pix,back_pix); + + gcm = GCForeground|GCBackground; + gcv.foreground = hilite_pix; + gcv.background = back_pix; + ReliefGC = XCreateGC(dpy, Root, gcm, &gcv); + + gcm = GCForeground|GCBackground; + gcv.foreground = shadow_pix; + gcv.background = back_pix; + ShadowGC = XCreateGC(dpy, Root, gcm, &gcv); + + gcm = GCForeground|GCBackground; + gcv.foreground = icon_hilite_pix; + gcv.background = icon_back_pix; + IconReliefGC = XCreateGC(dpy, Root, gcm, &gcv); + + gcm = GCForeground|GCBackground; + gcv.foreground = icon_shadow_pix; + gcv.background = icon_back_pix; + IconShadowGC = XCreateGC(dpy, Root, gcm, &gcv); + + gcm = GCForeground|GCBackground|GCFont; + gcv.foreground = fore_pix; + gcv.background = back_pix; + gcv.font = font->fid; + NormalGC = XCreateGC(dpy, Root, gcm, &gcv); + + + /* icon_win's background */ + if (GetBackPixmap() == True){ + XSetWindowBackgroundPixmap(dpy, icon_win, IconwinPixmap); + /* special thanks to Dave Goldberg + for his helpful information */ + XFreePixmap(dpy, IconwinPixmap); + } + + XSetForeground(dpy, NormalGC, icon_fore_pix); + XSetBackground(dpy, NormalGC, icon_back_pix); + + /* scroll bars */ + mask = CWWinGravity | CWBackPixel; + attributes.background_pixel = back_pix; + if (hidesc != HORIZONTAL){ + attributes.win_gravity = SouthWestGravity; + h_scroll_bar = XCreateWindow(dpy ,main_win, MARGIN1 + 2 + + BAR_WIDTH, + MARGIN1 + 6 + Height + MARGIN2, + Width - BAR_WIDTH*2, BAR_WIDTH, + 0, CopyFromParent, + InputOutput, CopyFromParent, + mask, &attributes); + XSelectInput(dpy,h_scroll_bar,SCROLL_EVENTS); + } + if (hidesc != VERTICAL){ + attributes.win_gravity = NorthEastGravity; + v_scroll_bar = XCreateWindow(dpy ,main_win, MARGIN1 + 6 + + Width + MARGIN2, + MARGIN1 + 2 + BAR_WIDTH, + BAR_WIDTH, Height - BAR_WIDTH*2, + 0, CopyFromParent, + InputOutput, CopyFromParent, + mask, &attributes); + XSelectInput(dpy,v_scroll_bar,SCROLL_EVENTS); + } + + /* buttons */ + if (hidesc != HORIZONTAL){ + attributes.win_gravity = SouthWestGravity; + l_button = XCreateWindow(dpy, main_win, MARGIN1 + 2, + MARGIN1 + 6 + Height + MARGIN2, + BAR_WIDTH, BAR_WIDTH, + 0, CopyFromParent, + InputOutput, CopyFromParent, + mask, &attributes); + attributes.win_gravity = SouthEastGravity; + r_button = XCreateWindow(dpy, main_win, MARGIN1 + 2 + Width - + BAR_WIDTH, + MARGIN1 + 6 + Height + MARGIN2, + BAR_WIDTH, BAR_WIDTH, + 0, CopyFromParent, + InputOutput, CopyFromParent, + mask, &attributes); + XSelectInput(dpy,l_button,BUTTON_EVENTS); + XSelectInput(dpy,r_button,BUTTON_EVENTS); + } + if (hidesc != VERTICAL){ + attributes.win_gravity = NorthEastGravity; + t_button = XCreateWindow(dpy, main_win, MARGIN1 + 6 + + Width + MARGIN2, MARGIN1 + 2, + BAR_WIDTH, BAR_WIDTH, + 0, CopyFromParent, + InputOutput, CopyFromParent, + mask, &attributes); + attributes.win_gravity = SouthEastGravity; + b_button = XCreateWindow(dpy, main_win, MARGIN1 + 6 + + Width + MARGIN2, + MARGIN1 + 2 + Height - BAR_WIDTH, + BAR_WIDTH, BAR_WIDTH, + 0, CopyFromParent, + InputOutput, CopyFromParent, + mask, &attributes); + XSelectInput(dpy,t_button,BUTTON_EVENTS); + XSelectInput(dpy,b_button,BUTTON_EVENTS); + } +} + +void GetIconwinSize(int *dx, int *dy) +{ + *dx = icon_win_width; + *dy = icon_win_height; + + if (primary == LEFT || primary == RIGHT){ + icon_win_width = max(Width, UWidth * Lines + interval - 1); + icon_win_height = max(Height, UHeight * (max(0, + (num_icons-1))/Lines + + 1) - 1 + interval); + }else{ + icon_win_width = max(Width, UWidth * (max(0,num_icons-1) / Lines + + 1) + interval - 1); + icon_win_height = max(Height, UHeight * Lines - 1 + interval); + } + *dx = icon_win_width - *dx; + *dy = icon_win_height - *dy; +} + +/************************************************************************ + * GetShadow + * Original work from GoodStuff: + * Copyright 1993, Robert Nation. + ***********************************************************************/ +Pixel GetShadow(Pixel background) +{ + XColor bg_color; + XWindowAttributes attributes; + + XGetWindowAttributes(dpy,Root,&attributes); + + bg_color.pixel = background; + XQueryColor(dpy,attributes.colormap,&bg_color); + + bg_color.red = (unsigned short)((bg_color.red*50)/100); + bg_color.green = (unsigned short)((bg_color.green*50)/100); + bg_color.blue = (unsigned short)((bg_color.blue*50)/100); + + if(!XAllocColor(dpy,attributes.colormap,&bg_color)) + nocolor("alloc shadow",""); + + return bg_color.pixel; +} + +/************************************************************************ + * GetHilite + * Original work from GoodStuff: + * Copyright 1993, Robert Nation. + ***********************************************************************/ +Pixel GetHilite(Pixel background) +{ + XColor bg_color, white_p; + XWindowAttributes attributes; + + XGetWindowAttributes(dpy,Root,&attributes); + + bg_color.pixel = background; + XQueryColor(dpy,attributes.colormap,&bg_color); + + white_p.pixel = GetColor("white"); + XQueryColor(dpy,attributes.colormap,&white_p); + + + 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); + + if(!XAllocColor(dpy,attributes.colormap,&bg_color)) + nocolor("alloc hilight",""); + + return bg_color.pixel; +} + + +/************************************************************************ + * nocolor + * Original work from GoodStuff: + * Copyright 1993, Robert Nation. + ***********************************************************************/ +void nocolor(char *a, char *b) +{ + fprintf(stderr,"%s: can't %s %s\n", MyName, a,b); +} + + +/************************************************************************ + * GetColor + * Original work from GoodStuff: + * Copyright 1993, Robert Nation. + ***********************************************************************/ +Pixel GetColor(char *name) +{ + XColor color; + XWindowAttributes attributes; + + XGetWindowAttributes(dpy,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; +} + +/************************************************************************ + SendFvwmPipe - Send a message back to fvwm + Original work from FvwmWinList: + Copyright 1994, Mike Finger. +************************************************************************/ +void SendFvwmPipe(int *fd, char *message,unsigned long window) +{ + int w; + char *hold,*temp,*temp_msg; + hold=message; + + while(1) { + temp=strchr(hold,','); + if (temp!=NULL) { + temp_msg=malloc(temp-hold+1); + strncpy(temp_msg,hold,(temp-hold)); + temp_msg[(temp-hold)]='\0'; + hold=temp+1; + } else temp_msg=hold; + + if (!ExecIconBoxFunction(temp_msg)){ + write(fd[0],&window, sizeof(unsigned long)); + + w=strlen(temp_msg); + write(fd[0],&w,sizeof(int)); + write(fd[0],temp_msg,w); + + /* keep going */ + w=1; + write(fd[0],&w,sizeof(int)); + + } + if(temp_msg!=hold) free(temp_msg); + else break; + } +} + +Bool ExecIconBoxFunction(char *msg) +{ + if (mystrncasecmp(msg, "Next", 4) == 0){ + Next(); + return True; + }else if (mystrncasecmp(msg, "Prev", 4) == 0){ + Prev(); + return True; + }else if (mystrncasecmp(msg, "Left", 4) == 0){ + HScroll(icon_win_x - UWidth); + return True; + }else if (mystrncasecmp(msg, "Right", 5) == 0){ + HScroll(icon_win_x + UWidth); + return True; + }else if (mystrncasecmp(msg, "Up", 2) == 0){ + VScroll(icon_win_y - UHeight); + return True; + }else if (mystrncasecmp(msg, "Down", 4) == 0){ + VScroll(icon_win_y + UHeight); + return True; + } + return False; +} + +void Next(void) +{ + struct icon_info *new, *old; + int i; + + old = new = Hilite; + + if (new != NULL) + new = new->next; + + if (new != NULL) + Hilite = new; + else + new = Hilite = Head; + + if (new == NULL) + return; + + if (old != NULL) + RedrawIcon(old, 3); + if (new != NULL) + RedrawIcon(new, 3); + + i=0; + if (new->x < icon_win_x){ + while (new->x + UWidth * ++i < icon_win_x) + ; + HScroll(icon_win_x - UWidth*i); + }else if (new->x > icon_win_x + Width){ + while (new->x - UWidth * ++i > icon_win_x + Width) + ; + HScroll(icon_win_x + UWidth*i); + } + + i=0; + if (new->y < icon_win_y){ + while (new->y + UHeight * ++i < icon_win_y) + ; + VScroll(icon_win_y - UHeight*i); + }else if (new->y > icon_win_y + Height){ + while (new->y - UHeight * ++i > icon_win_y + Height) + ; + VScroll(icon_win_y + UHeight*i); + } +} + +void Prev(void) +{ + struct icon_info *new, *old; + int i; + + old = new = Hilite; + + if (new != NULL) + new = new->prev; + + if (new != NULL) + Hilite = new; + else + new = Hilite = Tail; + + if (new == NULL) + return; + + if (old != NULL) + RedrawIcon(old, 3); + if (new != NULL) + RedrawIcon(new, 3); + + i=0; + if (new->x < icon_win_x){ + while (new->x + UWidth * ++i < icon_win_x) + ; + HScroll(icon_win_x - UWidth*i); + }else if (new->x > icon_win_x + Width){ + while (new->x - UWidth * ++i > icon_win_x + Width) + ; + HScroll(icon_win_x + UWidth*i); + } + + i=0; + if (new->y < icon_win_y){ + while (new->y + UHeight * ++i < icon_win_y) + ; + VScroll(icon_win_y - UHeight*i); + }else if (new->y > icon_win_y + Height){ + while (new->y - UHeight * ++i > icon_win_y + Height) + ; + VScroll(icon_win_y + UHeight*i); + } +} + +/************************************************************************ + * DeadPipe --Dead pipe handler + * Based on DeadPipe() from GoodStuff: + * Copyright 1993, Robert Nation. + ***********************************************************************/ +void DeadPipe(int nonsense) +{ + struct icon_info *tmpi, *tmpi2; + struct mousefunc *tmpm, *tmpm2; + struct keyfunc *tmpk, *tmpk2; + struct iconfile *tmpf, *tmpf2; + + tmpm = MouseActions; + while(tmpm != NULL){ + tmpm2 = tmpm; + tmpm = tmpm->next; + free(tmpm2->action); + free(tmpm2); + } + + tmpk = KeyActions; + while(tmpk != NULL){ + tmpk2 = tmpk; + tmpk = tmpk->next; + free(tmpk2->action); + free(tmpk2->name); + free(tmpk2); + } + + tmpf = IconListHead; + while(tmpf != NULL){ + tmpf2 = tmpf; + tmpf = tmpf->next; + free(tmpf2->name); + free(tmpf2->iconfile); + free(tmpf2); + } + + tmpi = Head; + while(tmpi != NULL){ + tmpi2 = tmpi; + tmpi = tmpi->next; + freeitem(tmpi2, DEAD); + } + XSync(dpy,0); + exit(0); +} + + +/************************************************************************ + * ParseOptions + * Based on ParseConfig() from FvwmWinList: + * Copyright 1994, Mike Finger. + ***********************************************************************/ +void ParseOptions(char *filename) +{ + FILE *fd = (FILE *)0; + char line[256]; + char *tline,*orig_tline,*tmp; + int Clength; + + fd = fopen(filename,"r"); + if(fd == (FILE *)0) + { + fprintf(stderr,"%s: can't open config file %s",MyName,filename); + exit(1); + } + + tline = fgets(line,(sizeof line)-1,fd); + orig_tline = tline; + Clength = strlen(MyName); + while(tline != (char *)0) + { + int g_x, g_y, flags; + unsigned width,height; + + while(isspace(*tline))tline++; + + if(strlen(&tline[0])>1){ + if (mystrncasecmp(tline,CatString3("*", MyName, + "Geometry"),Clength+9)==0){ + tmp = &tline[Clength+9]; + while(((isspace(*tmp))&&(*tmp != '\n'))&&(*tmp != 0)) + tmp++; + tmp[strlen(tmp)-1] = 0; + flags = XParseGeometry(tmp,&g_x,&g_y,&width,&height); + if (flags & WidthValue) + num_columns = width; + if (flags & HeightValue) + num_rows = height; + if (flags & XValue) + x = g_x; + if (flags & YValue) + y = g_y; + if (flags & XNegative) + xneg = 1; + if (flags & YNegative) + yneg = 1; + } else if (mystrncasecmp(tline,CatString3("*", MyName, + "MaxIconSize"),Clength+12)==0){ + tmp = &tline[Clength+12]; + while(((isspace(*tmp))&&(*tmp != '\n'))&&(*tmp != 0)) + tmp++; + tmp[strlen(tmp)-1] = 0; + + flags = XParseGeometry(tmp,&g_x,&g_y,&width,&height); + if (flags & WidthValue) + max_icon_width = width; + if (flags & HeightValue) + max_icon_height = height; + }else if + (mystrncasecmp(tline,CatString3("*",MyName,"Font"),Clength+5)==0) + CopyString(&font_string,&tline[Clength+5]); + else if + (mystrncasecmp(tline,CatString3("*",MyName,"IconFore"),Clength+9)==0) + CopyString(&IconFore,&tline[Clength+9]); + else if + (mystrncasecmp(tline,CatString3("*",MyName,"IconBack"),Clength+9)==0) + CopyString(&IconBack,&tline[Clength+9]); + else if + (mystrncasecmp(tline,CatString3("*",MyName,"IconHiFore"),Clength+11)==0) + CopyString(&ActIconFore,&tline[Clength+11]); + else if + (mystrncasecmp(tline,CatString3("*",MyName,"IconHiBack"),Clength+11)==0) + CopyString(&ActIconBack,&tline[Clength+11]); + else if (mystrncasecmp(tline,CatString3("*",MyName, + "Fore"),Clength+5)==0) + CopyString(&Fore,&tline[Clength+5]); + else if (mystrncasecmp(tline,CatString3("*",MyName, + "Back"),Clength+5)==0) + CopyString(&Back,&tline[Clength+5]); + else if (mystrncasecmp(tline,CatString3("*",MyName, + "Pixmap"),Clength+7)==0) + CopyString(&IconwinPixmapFile,&tline[Clength+7]); + else if (mystrncasecmp(tline,CatString3("*",MyName, + "Padding"),Clength+8)==0) + interval = max(0,atoi(&tline[Clength+8])); + else if (mystrncasecmp(tline,CatString3("*",MyName, + "Lines"),Clength+6)==0) + Lines = max(1,atoi(&tline[Clength+6])); + else if (mystrncasecmp(tline,CatString3("*",MyName, + "Placement"),Clength+10)==0) + parseplacement(&tline[Clength+10]); + else if (mystrncasecmp(tline,CatString3("*",MyName, + "SortIcons"),Clength+10)==0) + sorticons = 1; + else if (mystrncasecmp(tline,CatString3("*",MyName, + "Mouse"),Clength+6)==0) + parsemouse(&tline[Clength + 6]); + else if (mystrncasecmp(tline,CatString3("*",MyName, + "Key"),Clength+4)==0) + parsekey(&tline[Clength + 4]); + else if (mystrncasecmp(tline,CatString3("*",MyName, + "HideSC"),Clength+7)==0){ + tmp = &tline[Clength+7]; + while(((isspace(*tmp))&&(*tmp != '\n'))&&(*tmp != 0)) + tmp++; + if (mystrncasecmp(tmp, "Horizontal", 10) == 0) + hidesc = HORIZONTAL; + else if (mystrncasecmp(tmp, "Vertical", 8) == 0) + hidesc = VERTICAL; + }else if (mystrncasecmp(tline,CatString3("*",MyName, + ""),Clength+1)==0) + parseicon(&tline[Clength + 1]); + else if (mystrncasecmp(tline,"IconPath",8)==0) + CopyString(&iconPath,&tline[8]); + else if (mystrncasecmp(tline,"PixmapPath",10)==0) + CopyString(&pixmapPath,&tline[10]); + else if (mystrncasecmp(tline,"ClickTime",9)==0) + ClickTime = atoi(&tline[9]); + } + tline = fgets(line,(sizeof line)-1,fd); + orig_tline = tline; + } + return; +} + +void parseicon(char *tline) +{ + int len; + struct iconfile *tmp; + char *ptr, *start, *end; + + tmp = (struct iconfile *)safemalloc(sizeof(struct iconfile)); + + + /* windowname */ + tmp->name = stripcpy(tline); + if(tmp->name == NULL){ + free(tmp); + return; + } + + /* skip windowname, based on strpcpy3 of configure.c */ + while((*tline != '"')&&(tline != NULL)) + tline++; + if(*tline != 0) + tline++; + while((*tline != '"')&&(tline != NULL)) + tline++; + if(*tline == 0){ + free(tmp); + return; + } + tline++; + + /* file */ + /* skip spaces */ + while(isspace(*tline)&&(*tline != '\n')&&(*tline != 0)) + tline++; + start = tline; + end = tline; + while(!isspace(*end)&&(*end != '\n')&&(*end != 0)) + end++; + len = end - start; + ptr = safemalloc(len+1); + strncpy(ptr, start, len); + ptr[len] = 0; + tmp->iconfile = ptr; + + if (strcmp(tmp->name, "*") == 0) + DefaultIcon = tmp; + + tmp->next = NULL; + + if (IconListHead == NULL) + IconListHead = IconListTail = tmp; + else{ + IconListTail->next = tmp; + IconListTail = tmp; + } +} + +void parseplacement(char *tline) +{ + char p[240], s[240]; + + sscanf(tline, "%s %s", p, s); + + if (mystrncasecmp(p, "Left", 4) == 0) + primary = LEFT; + else if (mystrncasecmp(p, "Right", 5) == 0) + primary = RIGHT; + else if (mystrncasecmp(p, "Top", 3) == 0) + primary = TOP; + else if (mystrncasecmp(p, "Bottom", 6) == 0) + primary = BOTTOM; + + if (mystrncasecmp(s, "Left", 4) == 0) + secondary = LEFT; + else if (mystrncasecmp(s, "Right", 5) == 0) + secondary = RIGHT; + else if (mystrncasecmp(s, "Top", 3) == 0) + secondary = TOP; + else if (mystrncasecmp(s, "Bottom", 6) == 0) + secondary = BOTTOM; +} + +void parsemouse(char *tline) +{ + struct mousefunc *f = NULL; + int len; + char *ptr,*start,*end,*tmp; + + f = (struct mousefunc *)safemalloc(sizeof(struct mousefunc)); + f->next = NULL; + f->mouse = 0; + + /* skip spaces */ + while(isspace(*tline)&&(*tline != '\n')&&(*tline != 0)) + tline++; + start = tline; + end = tline; + while((!isspace(*end))&&(*end!='\n')&&(*end!=0)) + end++; + if (mystrncasecmp(start, "1", 1) == 0) + f->mouse = Button1; + else if (mystrncasecmp(start, "2", 1) == 0) + f->mouse = Button2; + else if (mystrncasecmp(start, "3", 1) == 0) + f->mouse = Button3; + /* click or doubleclick */ + tline = end; + /* skip spaces */ + while(isspace(*tline)&&(*tline != '\n')&&(*tline != 0)) + tline++; + start = tline; + end = tline; + while((!isspace(*end))&&(*end!='\n')&&(*end!=0)) + end++; + if (mystrncasecmp(start, "Click", 5) == 0) + f->type = CLICK; + else if (mystrncasecmp(start, "DoubleClick", 11) == 0) + f->type = DOUBLE_CLICK; + + /* actions */ + tline = end; + /* skip spaces */ + while(isspace(*tline)&&(*tline != '\n')&&(*tline != 0)) + tline++; + start = tline; + end = tline; + tmp = tline; + while((*tmp!='\n')&&(*tmp!=0)){ + if (!isspace(*tmp)) + end = tmp; + tmp++; + } + end++; + len = end - start; + ptr = safemalloc(len+1); + strncpy(ptr, start, len); + ptr[len] = 0; + f->action = ptr; + f->next = MouseActions; + MouseActions = f; +} + +/*********************************************************************** + parsekey + Based on part of AddFunckey() of configure.c in Fvwm. + Copyright 1988, Evans and Sutherland Computer Corporation, + Copyright 1989, Massachusetts Institute of Technology, + Copyright 1993, Robert Nation. + ***********************************************************************/ +void parsekey(char *tline) +{ + struct keyfunc *k; + int nlen, alen; + char *nptr, *aptr, *start, *end, *tmp; + int i, kmin, kmax; + KeySym keysym; + + /* skip spaces */ + while(isspace(*tline)&&(*tline != '\n')&&(*tline != 0)) + tline++; + start = tline; + end = tline; + while((!isspace(*end))&&(*end!='\n')&&(*end!=0)) + end++; + nlen = end - start; + nptr = safemalloc(nlen+1); + strncpy(nptr, start, nlen); + nptr[nlen] = 0; + + /* actions */ + tline = end; + /* skip spaces */ + while(isspace(*tline)&&(*tline != '\n')&&(*tline != 0)) + tline++; + start = tline; + end = tline; + tmp = tline; + while((*tmp!='\n')&&(*tmp!=0)){ + if (!isspace(*tmp)) + end = tmp; + tmp++; + } + end++; + alen = end - start; + aptr = safemalloc(alen+1); + strncpy(aptr, start, alen); + aptr[alen] = 0; + + if ((keysym = XStringToKeysym(nptr)) == NoSymbol || + XKeysymToKeycode(dpy, keysym) == 0){ + free(nptr); + free(aptr); + return; + } + + XDisplayKeycodes(dpy, &kmin, &kmax); + for (i=kmin; i<=kmax; i++) + if (XKeycodeToKeysym(dpy, i, 0) == keysym) + { + k = (struct keyfunc *)safemalloc(sizeof(struct keyfunc)); + k->name = nptr; + k->keycode = i; + k->action = aptr; + k->next = KeyActions; + KeyActions = k; + } +} + +/*********************************************************************** + * change_window_name + * Original work from GoodStuff: + * Copyright 1993, Robert Nation. + ***********************************************************************/ +void change_window_name(char *str) +{ + XTextProperty name; + + if (XStringListToTextProperty(&str,1,&name) == 0) + { + fprintf(stderr,"%s: cannot allocate window name",MyName); + return; + } + XSetWMName(dpy,main_win,&name); + XSetWMIconName(dpy,main_win,&name); + XFree(name.value); +} + +/*********************************************************************** + * My_XNextEvent + * Original work from GoodStuff: + * Copyright 1993, Robert Nation. + ***********************************************************************/ +int My_XNextEvent(Display *dpy, XEvent *event) +{ + fd_set in_fdset; + unsigned long header[3]; + int body_length; + int count,count2 = 0; + static int miss_counter = 0; + unsigned long *body; + int total; + char *cbody; + + if(XPending(dpy)) + { + XNextEvent(dpy,event); + return 1; + } + + FD_ZERO(&in_fdset); + FD_SET(x_fd,&in_fdset); + FD_SET(fd[1],&in_fdset); + +#ifdef __hpux + select(fd_width,(int *)&in_fdset, 0, 0, NULL); +#else + select(fd_width,&in_fdset, 0, 0, NULL); +#endif + + + if(FD_ISSET(x_fd, &in_fdset)) + { + if(XPending(dpy)) + { + XNextEvent(dpy,event); + miss_counter = 0; + return 1; + } + else + miss_counter++; + if(miss_counter > 100) + DeadPipe(0); + } + + if(FD_ISSET(fd[1], &in_fdset)) + { + if(count = ReadFvwmPacket(fd[1],header,&body) > 0) + { + process_message(header[1],body); + free(body); + } + } + return 0; +} + +/************************************************************************** + * process_message + * Based on ProcessMassage() from FvwmWinList: + * Copyright 1994, Mike Finger. + *************************************************************************/ +int diffx, diffy; +void process_message(unsigned long type, unsigned long *body) +{ + struct icon_info *tmp; + int isndeleted=0, i=0; + Window iw; + + switch(type){ + case M_CONFIGURE_WINDOW: + if (isendlist) + break; + case M_ADD_WINDOW: + if (AddItem(body[0], body[1], body[8]) == True && UP){ + GetIconwinSize(&diffx, &diffy); + if (diffy && (primary == BOTTOM || secondary == BOTTOM)) + icon_win_y += diffy; + if (diffx && (primary == RIGHT || secondary == RIGHT)) + icon_win_x += diffx; + XMoveResizeWindow(dpy, icon_win, -icon_win_x, -icon_win_y, + icon_win_width, icon_win_height); + } + break; + case M_DESTROY_WINDOW: + if (DeleteItem(body[0]) && UP){ + GetIconwinSize(&diffx, &diffy); + if (diffy && (primary == BOTTOM || secondary == BOTTOM)) + icon_win_y += diffy; + if (diffx && (primary == RIGHT || secondary == RIGHT)) + icon_win_x += diffx; + if (icon_win_y < 0) + icon_win_y = 0; + if (icon_win_x < 0) + icon_win_x = 0; + if (icon_win_x + Width > icon_win_width) + icon_win_x = icon_win_width - Width; + if (icon_win_y + Height > icon_win_height) + icon_win_y = icon_win_height - Height; + XMoveResizeWindow(dpy, icon_win, -icon_win_x, -icon_win_y, + icon_win_width, icon_win_height); + tmp = Head; + i = 0; + while(tmp != NULL){ + AdjustIconWindow(tmp, i++); + tmp = tmp->next; + } + RedrawIcons(); + if (hidesc != HORIZONTAL && diffx) + RedrawHScrollbar(); + if (hidesc != VERTICAL && diffy) + RedrawVScrollbar(); + } + break; + case M_WINDOW_NAME: + UpdateItem(type, body[0], (char *)&body[3]); + break; + case M_RES_CLASS: + UpdateItem(type, body[0], (char *)&body[3]); + break; + case M_RES_NAME: + if ((tmp = UpdateItem(type, body[0], (char *)&body[3])) != NULL) + isndeleted = LookInList(tmp); + if (UP && isndeleted && tmp != NULL){ + CreateIconWindow(tmp); + ConfigureIconWindow(tmp); + XMapWindow(dpy, tmp->icon_pixmap_w); + XMapWindow(dpy, tmp->IconWin); + tmp = Head; + while(tmp != NULL){ + AdjustIconWindow(tmp, i++); + tmp = tmp->next; + } + RedrawIcons(); + if (hidesc != HORIZONTAL) + RedrawHScrollbar(); + if (hidesc != VERTICAL) + RedrawVScrollbar(); + } + break; + case M_ICON_NAME: + tmp = UpdateItem(type, body[0], (char *)&body[3]); + iw = tmp == NULL ? None : tmp->IconWin; + if (UP && tmp != NULL && sorticons){ /* SortIcon is specified */ + if (SortItem(tmp) == True && iw != None){ + tmp = Head; + while(tmp != NULL){ + AdjustIconWindow(tmp, i++); + tmp = tmp->next; + } + RedrawIcons(); + }else if (iw != None) + RedrawIcon(tmp, 2); + } + else if (UP && iw != None) /* SortIcon is not specified */ + RedrawIcon(tmp, 2); + break; + case M_ICONIFY: + case M_DEICONIFY: + if (UP && (tmp = SetFlag(body[0], type)) != NULL) + RedrawIcon(tmp, 2); + break; + case M_END_WINDOWLIST: + GetIconwinSize(&diffx, &diffy); + tmp = Head; + while(tmp != NULL){ + CreateIconWindow(tmp); + ConfigureIconWindow(tmp); + tmp = tmp->next; + } + if (sorticons) + SortItem(NULL); + tmp = Head; i=0; + while(tmp != NULL){ + AdjustIconWindow(tmp, i++); + tmp = tmp->next; + } + if (primary == BOTTOM || secondary == BOTTOM) + icon_win_y = icon_win_height - Height; + if (primary == RIGHT || secondary == RIGHT) + icon_win_x = icon_win_width - Width; + XMoveResizeWindow(dpy, icon_win, -icon_win_x, -icon_win_y, + icon_win_width, icon_win_height); + XMapWindow(dpy,main_win); + XMapSubwindows(dpy, main_win); + XMapWindow(dpy, icon_win); + XMapSubwindows(dpy, icon_win); + UP = 1; + isendlist = 1; + break; + default: + break; + } +} + +struct icon_info *SetFlag(unsigned long id, int t) +{ + struct icon_info *tmp; + tmp = Head; + + while(tmp != NULL){ + if (tmp->id == id){ + if (t == M_ICONIFY) + tmp->flags |= ICONIFIED; + else + tmp->flags ^= ICONIFIED; + return tmp; + } + tmp = tmp->next; + } + return NULL; +} + + +/************************************************************************ + * send_clientmessage + * Original work from GoodStuff: + * Copyright 1993, Robert Nation. + ***********************************************************************/ +void send_clientmessage (Window w, Atom a, Time timestamp) +{ + XClientMessageEvent ev; + + ev.type = ClientMessage; + ev.window = w; + ev.message_type = _XA_WM_PROTOCOLS; + ev.format = 32; + ev.data.l[0] = a; + ev.data.l[1] = timestamp; + XSendEvent (dpy, w, False, 0L, (XEvent *) &ev); +} + + +/************************************************************************ + * AddItem + * Skeleton based on AddItem() from FvwmWinList: + * Copyright 1994, Mike Finger. + ***********************************************************************/ +Bool AddItem(unsigned long id, unsigned long fid, unsigned long flags) +{ + struct icon_info *new, *tmp; + tmp = Head; + + if (id == main_win || (flags & TRANSIENT)) + return False; + + while (tmp != NULL){ + if (tmp->id == id || + (tmp->wmhints && (tmp->wmhints->flags & IconWindowHint) && + tmp->wmhints->icon_window == id)) + return False; + tmp = tmp->next; + } + + new = (struct icon_info *)safemalloc(sizeof(struct icon_info)); + new->name = NULL; + new->window_name = NULL; + new->res_class = NULL; + new->res_name = NULL; + new->action = NULL; + new->icon_file = NULL; + new->icon_w = 0; + new->icon_h = 0; + new->IconWin = None; + new->iconPixmap = None; + new->icon_maskPixmap = None; + new->icon_pixmap_w = None; + new->icon_depth = 0; + new->id = id; + new->fid = fid; + new->defaulticon = 1; + new->flags = flags | ICON_OURS; + new->wmhints = NULL; + new->prev = NULL; + + new->next = Head; + if (Head != NULL) + Head->prev = new; + else + Tail = new; + Head = new; + + num_icons++; + + return True; +} + +/************************************************************************ + * Deletetem + * Skeleton based on DeleteItem() from FvwmWinList: + * Copyright 1994, Mike Finger. + ***********************************************************************/ +Bool DeleteItem(unsigned long id) +{ + struct icon_info *tmp; + + tmp = Head; + if (tmp == NULL) + return False; + + if (tmp->id == id){ + if (Hilite == tmp) + Hilite = NULL; + if ((tmp->icon_pixmap_w != None) && (tmp->flags & ICON_OURS)) + XDestroyWindow(dpy, tmp->icon_pixmap_w); + if (tmp->IconWin != None) + XDestroyWindow(dpy, tmp->IconWin); + Head = tmp->next; + if (Head != NULL) + Head->prev = NULL; + else + Tail = NULL; + freeitem(tmp, DELETE); + num_icons--; + return True; + } + + tmp = tmp->next; + while(tmp != NULL){ + if (tmp->id == id){ + if (Hilite == tmp) + Hilite = NULL; + if (Tail == tmp) + Tail = tmp->prev; + if ((tmp->icon_pixmap_w != None) && (tmp->flags & ICON_OURS)) + XDestroyWindow(dpy, tmp->icon_pixmap_w); + if (tmp->IconWin != None) + XDestroyWindow(dpy, tmp->IconWin); + tmp->prev->next = tmp->next; + if (tmp->next != NULL) + tmp->next->prev = tmp->prev; + freeitem(tmp, DELETE); + num_icons--; + return True; + } + tmp = tmp->next; + } + return False; +} + +/************************************************************************ + * UpdateItem + * Skeleton based on UpdateItem() from FvwmWinList: + * Copyright 1994, Mike Finger. + ***********************************************************************/ +struct icon_info *UpdateItem(unsigned long type, unsigned long id, char *item) +{ + struct icon_info *tmp; + char *str; + + tmp = Head; + while (tmp != NULL){ + if (tmp->id == id){ + str = (char *)safemalloc(strlen(item)+1); + strcpy(str, item); + + switch (type){ + case M_ICON_NAME: + if (tmp->name != NULL) + free(tmp->name); + tmp->name = str; + return tmp; + case M_WINDOW_NAME: + if (tmp->window_name != NULL) + free(tmp->window_name); + tmp->window_name = str; + return tmp; + case M_RES_CLASS: + tmp->res_class = str; + return tmp; + case M_RES_NAME: + tmp->res_name = str; + return tmp; + } + } + tmp = tmp->next; + } + return NULL; +} + +Bool SortItem(struct icon_info *item) +{ + struct icon_info *tmp, *i_min, *next, *prev, tmp2; + + if (item != NULL && + (item->prev==NULL || strcmp(item->prev->name, item->name) <= 0) && + (item->next==NULL || strcmp(item->next->name, item->name) >= 0)) + return False; + + tmp = Head; + while (tmp != NULL){ + i_min = MinItem(tmp); + tmp2 = *i_min; + *i_min = *tmp; + next = tmp->next; + prev = tmp->prev; + i_min->next = tmp2.next; + i_min->prev = tmp2.prev; + *tmp = tmp2; + tmp->next = next; + tmp->prev = prev; + tmp = tmp->next; + } + return True; +} + +struct icon_info *MinItem(struct icon_info *head) +{ + struct icon_info *tmp, *i_min; + + if (head == NULL) + return NULL; + + i_min = head; + tmp = head->next; + while (tmp != NULL){ + if (strcmp(i_min->name, tmp->name) > 0) + i_min = tmp; + tmp = tmp->next; + } + return i_min; +} + +/* +void ShowItem(struct icon_info *head) +{ + struct icon_info *tmp; + + fprintf(stderr, "The contents of item are as follows:\n"); + tmp = head; + while (tmp != NULL){ + fprintf(stderr, "id:%x name:%s resname:%s class%s iconfile:%s\n", + tmp->id, + tmp->name == NULL ? "NULL" : tmp->name, tmp->res_name, + tmp->res_class, tmp->icon_file); + tmp = tmp->next; + } +} + +void ShowAction(void) +{ + struct mousefunc *tmp; + + tmp = MouseActions; + while (tmp != NULL){ + fprintf(stderr, "mouse:%d type %d action:%s\n", tmp->mouse, + tmp->type, tmp->action); + tmp = tmp->next; + } +} + +void ShowKAction(void) +{ + struct keyfunc *tmp; + + tmp = KeyActions; + while (tmp != NULL){ + fprintf(stderr, "key:%s keycode:%d action:%s\n", tmp->name, + tmp->keycode, tmp->action); + tmp = tmp->next; + } +} +*/ + +void freeitem(struct icon_info *item, int s) +{ + if (item == NULL) + return; + + if (!(item->flags & ICON_OURS) && s == DEAD){ + XUnmapWindow(dpy, item->icon_pixmap_w); + XReparentWindow(dpy, item->icon_pixmap_w, Root, 0, 0); + } + + if (item->name != NULL) + free(item->name); + if (item->window_name != NULL) + free(item->window_name); + if (item->res_name != NULL) + free(item->res_name); + if (item->res_class != NULL) + free(item->res_class); + if (item->wmhints != NULL) + XFree(item->wmhints); + if (item->iconPixmap != None) + XFreePixmap(dpy, item->iconPixmap); + free(item); +} + + +/************************************************************************ + IsClick + Based on functions.c from Fvwm: + Copyright 1988, Evans and Sutherland Computer Corporation, + Copyright 1989, Massachusetts Institute of Technology, + Copyright 1993, Robert Nation. + ***********************************************************************/ +Bool IsClick(int x,int y,unsigned EndMask, XEvent *d) +{ + int xcurrent,ycurrent,total = 0; + + xcurrent = x; + ycurrent = y; + while((total < ClickTime)&& + (x - xcurrent < 5)&&(x - xcurrent > -5)&& + (y - ycurrent < 5)&&(y - ycurrent > -5)) + { + sleep_a_little(10000); + total+=10; + if(XCheckMaskEvent (dpy,EndMask, d)) + return True; + if(XCheckMaskEvent (dpy,ButtonMotionMask|PointerMotionMask, d)) + { + xcurrent = d->xmotion.x_root; + ycurrent = d->xmotion.y_root; + } + } + return False; +} + +/************************************************************************ + * ExecuteAction +* Based on part of ComplexFunction() of functions.c from fvwm: + Copyright 1988, Evans and Sutherland Computer Corporation, + Copyright 1989, Massachusetts Institute of Technology, + Copyright 1993, Robert Nation. + ***********************************************************************/ +void ExecuteAction(int x, int y, struct icon_info *item) +{ + int type = NO_CLICK; + XEvent *ev; + XEvent d; + struct mousefunc *tmp; + + /* Wait and see if we have a click, or a move */ + /* wait 100 msec, see if the used releases the button */ + if(IsClick(x,y,ButtonReleaseMask,&d)) + { + type = CLICK; + ev = &d; + } + + /* If it was a click, wait to see if its a double click */ + if((type == CLICK) && (IsClick(x,y,ButtonPressMask, &d))) + { + type = ONE_AND_A_HALF_CLICKS; + ev = &d; + } + if((type == ONE_AND_A_HALF_CLICKS) && + (IsClick(x,y,ButtonReleaseMask, &d))) + { + type = DOUBLE_CLICK; + ev = &d; + } + tmp = MouseActions; + + while (tmp != NULL){ + if (tmp->mouse == d.xbutton.button && tmp->type == type){ + SendFvwmPipe(fd, tmp->action, item->id); + return; + } + tmp = tmp->next; + } +} + +void ExecuteKey(XEvent event) +{ + struct icon_info *item; + struct keyfunc *tmp; + + if ((item = Hilite) == NULL) + if ((item = Head) == NULL) + return; + + tmp = KeyActions; + event.xkey.keycode = + XKeysymToKeycode(dpy,XKeycodeToKeysym(dpy,event.xkey.keycode,0)); + while (tmp != NULL){ + if (tmp->keycode == event.xkey.keycode){ + SendFvwmPipe(fd, tmp->action, item->id); + return; + } + tmp = tmp->next; + } +} + +void ShowList(void) +{ + struct iconfile *nptr; + + for (nptr = IconListHead; nptr != NULL; nptr = nptr->next) + fprintf(stderr, "%s, %s,\n", nptr->name, nptr->iconfile); +} + +/*********************************************************************** + LookInList + Based on part of LookInList() of add_window.c from fvwm: + Copyright 1988, Evans and Sutherland Computer Corporation, + Copyright 1989, Massachusetts Institute of Technology, + Copyright 1993, Robert Nation. + ***********************************************************************/ +int LookInList(struct icon_info *item) +{ + int isdefault=0; + char *value=NULL; + struct iconfile *nptr; + + for (nptr = IconListHead; nptr != NULL; nptr = nptr->next){ + if (nptr == DefaultIcon) + isdefault = 1; + + if (matchWildcards(nptr->name, item->res_class) == TRUE){ + value = nptr->iconfile; + if (nptr != DefaultIcon) + isdefault = 0; + } + + if (matchWildcards(nptr->name, item->res_name) == TRUE){ + value = nptr->iconfile; + if (nptr != DefaultIcon) + isdefault = 0; + } + + if (matchWildcards(nptr->name, item->window_name) == TRUE){ + value = nptr->iconfile; + if (nptr != DefaultIcon) + isdefault = 0; + } + } + + if (!isdefault){ + item->icon_file = value; + item->defaulticon = 0; + }else + item->icon_file = DefaultIcon->iconfile; + + /* Icon is not shown if "-" is specified */ + if (item->icon_file != NULL && (strcmp(item->icon_file, "-") == 0)){ + DeleteItem(item->id); + return 0; + } + return 1; +} + +/*********************************************************************** + strcpy + Based on stripcpy2() of configure.c from Fvwm: + Copyright 1988, Evans and Sutherland Computer Corporation, + Copyright 1989, Massachusetts Institute of Technology, + Copyright 1993, Robert Nation. + ***********************************************************************/ +char *stripcpy(char *source) +{ + char *ptr; + int count = 0; + while((*source != '"')&&(*source != 0)) + source++; + if(*source == 0) + return 0; + + source++; + ptr = source; + while((*ptr!='"')&&(*ptr != 0)){ + ptr++; + count++; + } + ptr = safemalloc(count+1); + strncpy(ptr,source,count); + ptr[count]=0; + return ptr; +} diff --git a/modules/FvwmIconBox/FvwmIconBox.h b/modules/FvwmIconBox/FvwmIconBox.h new file mode 100644 index 0000000..d725bbd --- /dev/null +++ b/modules/FvwmIconBox/FvwmIconBox.h @@ -0,0 +1,181 @@ +/************************************************************************* + * + * Subroutine Prototypes + * + *************************************************************************/ +#include "../../libs/fvwmlib.h" +struct icon_info; +Bool ExecIconBoxFunction(char *msg); +extern void CreateWindow(void); +extern Pixel GetColor(char *name); +extern Pixel GetHilite(Pixel background); +extern Pixel GetShadow(Pixel background); +extern void nocolor(char *a, char *b); +extern void RedrawWindow(int); +extern void match_string(char *tline); +extern void Loop(void); +extern void ParseOptions(char *); +extern char *safemalloc(int length); +extern void change_window_name(char *str); +extern int My_XNextEvent(Display *dpy, XEvent *event); +extern void CopyString(char **dest, char *source); +extern FVWM_INLINE void RelieveWindow(Window win,int x,int y,int w,int h,GC rGC,GC sGC); +extern void SendFvwmPipe(int *,char *text, unsigned long window); +extern void DeadPipe(int nonsense); +extern void CreateIconWindow(struct icon_info *item); +extern void ConfigureIconWindow(struct icon_info *item); +extern void DrawIconWindow(struct icon_info *item); +extern void GetBitmapFile(struct icon_info *item); +extern void GetXPMFile(struct icon_info *item); +extern void GetIconWindow(struct icon_info *item); +extern void GetIconBitmap(struct icon_info *item); +extern void process_message(unsigned long type,unsigned long *body); +extern void send_clientmessage (Window w, Atom a, Time timestamp); +extern Bool AddItem(unsigned long id, unsigned long fid, unsigned long flags); +extern Bool DeleteItem(unsigned long id); +extern struct icon_info *UpdateItem(unsigned long type, unsigned long id, char *item); +extern void freeitem(struct icon_info *item, int s); +extern void RedrawHScrollbar(void); +extern void RedrawVScrollbar(void); +extern void RedrawIcons(void); +extern void GetIconwinSize(int *dx, int *dy); +extern void RedrawLeftButton(GC rgc, GC sgc); +extern void RedrawRightButton(GC rgc, GC sgc); +extern void RedrawTopButton(GC rgc, GC sgc); +extern void RedrawBottomButton(GC rgc, GC sgc); +extern struct icon_info *Search(Window w); +extern void ExecuteAction(int x, int y, struct icon_info *item); +extern void HScroll(int x); +extern void VScroll(int y); +extern void RedrawLabel(struct icon_info *item); +extern void parseplacement(char *tline); +extern void parseaction(char *tline); +extern void AdjustIconWindow(struct icon_info *item, int n); +extern struct icon_info *SetFlag(unsigned long id, int t); +extern void sleep_a_little(int n); +extern void RedrawIcon(struct icon_info *item, int f); +extern void Next(void); +extern void Prev(void); +extern void GetDefaultPixmap(struct icon_info *item); +extern void parsemouse(char *tline); +extern void parsekey(char *tline); +extern void parseicon(char *tline); +extern Bool SortItem(struct icon_info *item); +extern struct icon_info *MinItem(struct icon_info *head); +extern void ExecuteKey(XEvent event); +extern int matchWildcards(char *pattern, char *string); +extern Bool GetBackPixmap(void); +extern int LookInList(struct icon_info *item); +extern char *stripcpy(char *source); + + +extern Display *dpy; /* which display are we talking to */ +extern Window Root; +extern Window main_win; +extern Window holder_win; +extern Window icon_win; +extern int screen; +extern int d_depth; +extern Pixel fore_pix, back_pix, icon_fore_pix, icon_back_pix; +extern GC NormalGC; +extern GC ReliefGC; +extern int ButtonWidth,ButtonHeight; +extern XFontStruct *font; +extern int num_rows; +extern int num_columns; +extern int Lines; +extern int interval; +extern int max_icon_width; +extern int max_icon_height; +extern int primary, secondary; +extern int icon_win_width, icon_win_height; +extern Pixmap IconwinPixmap; +extern char *IconwinPixmapFile; + +struct icon_info +{ + char *action; + char *name; + char *window_name; + char *res_class; + char *res_name; + char *icon_file; + int x; + int y; + int icon_w; + int icon_h; + Pixmap iconPixmap; /* pixmap for the icon */ + Pixmap icon_maskPixmap; + Window IconWin; + Window icon_pixmap_w; + XWMHints *wmhints; + int icon_depth; + long id; + long fid; + long flags; + int defaulticon; + struct icon_info *next; + struct icon_info *prev; +}; + +struct iconfile +{ + char *name; + char *iconfile; + struct iconfile *next; +}; + +struct mousefunc +{ + int mouse; + int type; + char *action; + struct mousefunc *next; +}; + +struct keyfunc +{ + char *name; + KeyCode keycode; + char *action; + struct keyfunc *next; +}; + +extern struct icon_info *Head; +extern struct icon_info *Tail; +extern struct func *Actions; +extern struct iconfile *IconListHead; +extern struct iconfile *IconListTail; + +extern char *iconPath; +extern char *pixmapPath; + +#ifdef BROKEN_SUN_HEADERS +#include "../../fvwm/sun_headers.h" +#endif + +#ifdef NEEDS_ALPHA_HEADER +#include "../../fvwm/alpha_header.h" +#endif /* NEEDS_ALPHA_HEADER */ + + +#define NOPLACE -1 +#define LEFT 0 +#define RIGHT 1 +#define TOP 2 +#define BOTTOM 3 + +#define ICON_RELIEF 4 + +#include "../../fvwm/fvwm.h" + +#define NO_CLICK 0 +#define CLICK 1 +#define ONE_AND_A_HALF_CLICKS 3 +#define DOUBLE_CLICK 2 + +#ifndef min +#define min(a,b) (((a)<(b)) ? (a) : (b)) +#define max(a,b) (((a)>(b)) ? (a) : (b)) +#endif + diff --git a/modules/FvwmIconBox/FvwmIconBox.man b/modules/FvwmIconBox/FvwmIconBox.man new file mode 100644 index 0000000..844d332 --- /dev/null +++ b/modules/FvwmIconBox/FvwmIconBox.man @@ -0,0 +1,254 @@ +.\" t +.\" @(#)FvwmIconBox.1 6/20/94 +.TH FvwmIconBox 0.56b "Jun 24 1994" +.UC +.SH NAME +FvwmIconBox \- the FVWM iconbox module +.SH SYNOPSIS +FvwmIconBox is spawned by fvwm, so no command line invocation will work. + +.SH DESCRIPTION +The FvwmIconBox module provides an icon manager. The user can do +operations, like iconify and deiconify, for each icon shown in the +module via mouse and keyboard. + +FvwmIconBox reads the same .fvwmrc file as fvwm reads when it starts up, +and looks for lines similar to "*FvwmIconBoxFore green". + +.SH COPYRIGHTS +The FvwmIconBox program is original work of Nobutaka Suzuki. + +Copyright 1994, Nobutaka Suzuki. No guarantees or warranties or anything +are provided or implied in any way whatsoever. Use this program at your +own risk. Permission to use this program for any purpose is given, +as long as the copyright is kept intact. + + +.SH INITIALIZATION +During initialization, \fIFvwmIconBox\fP will eventually search a +configuration file. The configuration file is the same file that fvwm +used during initialization. + +If the FvwmIconBox executable is linked to another name, ie ln -s +FvwmIconBox MoreIconBox, then another module called MoreIconBox can be +started, with a completely different configuration than FvwmIconBox, +simply by changing the keyword FvwmIconBox to MoreIconBox. This way +multiple clutter-reduction programs can be used. + +.SH INVOCATION +FvwmIconBox can be invoked by binding the action 'Module +FvwmIconBox' to a menu or key-stroke in the .fvwmrc file. +Fvwm will search directory specified in the ModulePath configuration +option to attempt +to locate FvwmIconBox. + +.SH CONFIGURATION OPTIONS +FvwmIconBox reads the same .fvwmrc file as fvwm reads when it starts up, +and looks for lines as listed below: + +.IP "*FvwmIconBoxFore \fIcolor\fP" +Tells the module to use \fIcolor\fP instead of white for the window +foreground. This option affects only the foreground color of +background_bitmap specifed in *FvwmIconBoxPixmap option described +below. + +.IP "*FvwmIconBoxBack \fIcolor\fP" +Tells the module to use \fIcolor\fP instead of black for the window +background. + +.IP "*FvwmIconBoxIconFore \fIcolor\fP" +Tells the module to use \fIcolor\fP instead of black for non-selected +icon text. + +.IP "*FvwmIconBoxIconBack \fIcolor\fP" +Tells the module to use \fIcolor\fP instead of white for the +non-selected icon background. + +.IP "*FvwmIconBoxIconHiFore \fIcolor\fP" +Tells the module to use \fIcolor\fP instead of black for selected icon +text. + +.IP "*FvwmIconBoxIconHiBack \fIcolor\fP" +Tells the module to use \fIcolor\fP instead of white for the selected +icon background. + +.IP "*FvwmIconBoxPixmap \fIpixmap\fP" +Tells the module to use \fIpixmap\fP for the window background_pixmap. + +.IP "*FvwmIconBoxFont \fIfontname\fP" +Tells the module to use \fIfontname\fP instead of fixed for text. + +.IP "*FvwmIconBoxSortIcons" +Tells the module to sort all icons in iconbox in alphabetical order. + +.IP "*FvwmIconBoxPadding \fInumber\fP" +Specifies the number of pixels between icons. The default value is 5. + +.IP "*FvwmIconBoxPlacement \fIprimary\fP \fIsecondary\fP" +Specifies icon placement policy. \fIprimary\fP and \fIsecondary\fP can +be \fITop\fP, \fIBottom\fP, \fILeft\fP and \fIRight\fP. The following +eight combinations are available: +.nf +.sp +\fIprimary\fP \fIsecondary\fP + + Left Top + Left Bottom + Right Top + Right Bottom + Top Left + Top Right + Bottom Left + Bottom Right +.sp +.fi +.B "\fITop\fP:" +Icons are placed from top to bottom. + +.B "\fIBottom\fP:" +Icons are placed from bottom to top. + +.B "\fILeft\fP:" +Icons are placed from left to right. + +.B "\fIRight\fP:" +Icons are placed from right to left. + +For example, when the placement is "Left Top", icons are placed from +left to right, and new rows are added from top to bottom. The default +vale is "Left Bottom". + +.IP "*FvwmIconBoxLines" +Specifies the number of icons placed in a line. If \fIprimary\fP is +Left or Right, this value specifies the number of columns. +If \fIprimary\fP is Top or Bottom, this value specifies the number of +rows. For example, seven icons are placed in a row if +*FvwmIconBoxLines is 7 and *FvwmIconBoxPlacement is "Left Top". +The default value is 6. + +.IP "*FvwmIconBoxHideSC \fIdirection\fP" +Specifies the undisplayed scroll bar . \fIDirection\fP can be +either \fIHorizontal\fP or \fIVertical\fP. + +.IP "*FvwmIconBoxGeometry \fIx{+-}{+-}\fP" +Specifies the location and/or size of FvwmIconBox. +\fIwidth\fP and \fIheight\fP are measured in icons, not pixels. +The default value is 6x1+0+0. + +.IP "*FvwmIconBoxMaxIconSize \fIx\fP" +Specifies the maximum size of icon bitmap. A bitmap larger than +this size is clipped to this size. The default value is 48x48. + +.IP "*FvwmIconBoxMouse \fIButton\fP \fIAction\fP \fIResponse[, Response]\fP" +Tells the module to do \fIResponce\fP when \fIAction\fP is done on +button \fIButton\fP. Available \fIResponse\fPes are built-in commands +in Fvwm (e.g. Iconify, Delete, Focus) and available \fIAction\fPs +are Click and DoubleClick. + +.IP "*FvwmIconBoxKey \fIKey\fP \fIResponse[, Response]\fP" +Tells the module to do \fIResponse\fP when \fIKey\fP is pressed. +Available \fIResponce\fPes are, besides Fvwm built-in commands, the +following six FvwmIconBox built-in commands: \fINext\fP, \fIPrev\fP, +\fILeft\fP, \fIRight\fP, \fIUp\fP, and \fIDown\fP. + +.B "\fINext\fP:" +Change the hilited-icon to the next. + +.B "\fIPrev\fP:" +Change the hilited-icon to the previous. + +.B "\fILeft\fP:" +Move the slider of the horizontal scrollbar to left. Icons move +to right accordingly. + +.B "\fIRight\fP:" +Move the slider of the horizontal scrollbar to right. Icons move +to left accordingly. + +.B "\fIUp\fP:" +Move the slider of the vertical scrollbar to up. Icons move to +down accordingly. + +.B "\fIDown\fP:" +Move the slider of the vertical scrollbar to down. Icons move to +up accordingly. + +.IP "*FvwmIconBox \fIwindowname\fP \fIbitmap-file\fP" +Specifies the bitmap to be displayed in iconbox for \fIwindowname\fP. +\fIWindowname\fP can be window name, class name, or resource name. +\fIWindowname\fP can contain "*" and "?" like Fvwm configuration +file. The \fIbitmap-file\fP is either the full path name to a bitmap +file, or a file in the IconPath or PixmapPath. If \fIbitmap-file\fP is +specefied to be "-", the icon for a window corresponding to +\fIwindowname\fP is not shown in the iconbox. + +.SH SAMPLE CONFIGURATION +The following are excepts from a .fvwmrc file which describe +FvwmIconBox initialization commands: +.nf +.sp +############################################################ +# Make no icon to be shown in root window +# by spcifying in your .fvwmrc +# (1) "SuppressIcons" if PRUNE is defined in configure.h, or +# (2) "Style "*" NoIcon" if PRUNE is defined. +#SuppressIcons +Style "*" NoIcon + +############################################################ +*FvwmIconBoxIconBack #cfcfcf +*FvwmIconBoxIconHiFore black +*FvwmIconBoxIconHiBack LightSkyBlue +*FvwmIconBoxBack #5f9ea0 +#*FvwmIconBoxFore blue +*FvwmIconBoxGeometry 5x1+0+0 +*FvwmIconBoxMaxIconSize 64x38 +*FvwmIconBoxFont -adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-* +*FvwmIconBoxSortIcons +*FvwmIconBoxPadding 4 +*FvwmIconBoxLines 10 +*FvwmIconBoxPlacement Left Top +*FvwmIconBoxPixmap fvwm.xpm +#*FvwmIconBoxHideSC Horizontal +# +# mouse bindings +# +*FvwmIconBoxMouse 1 Click RaiseLower +*FvwmIconBoxMouse 1 DoubleClick Iconify +*FvwmIconBoxMouse 2 Click Iconify -1, Focus +*FvwmIconBoxMouse 3 Click Module "FvwmIdent" FvwmIdent +# +# Key bindings +# +*FvwmIconBoxKey r RaiseLower +*FvwmIconBoxKey space Iconify +*FvwmIconBoxKey d Close +# +# FvwmIconBox built-in functions +# +*FvwmIconBoxKey n Next +*FvwmIconBoxKey p Prev +*FvwmIconBoxKey h Left +*FvwmIconBoxKey j Down +*FvwmIconBoxKey k Up +*FvwmIconBoxKey l Right +# +# Icon file spcifications +# +*FvwmIconBox "*" unknown1.xpm +*FvwmIconBox "Fvwm*" - +*FvwmIconBox "FvwmFileMgr" folder2.xpm +*FvwmIconBox "rxvt" term.xpm +*FvwmIconBox "xterm" xterm.xpm +*FvwmIconBox "editres" editres.xpm +*FvwmIconBox "xman" xman.xpm +*FvwmIconBox "xbiff" mail1.xpm +*FvwmIconBox "xmh" mail1.xpm +*FvwmIconBox "xcalc" xcalc.xpm +*FvwmIconBox "GoodStuff" toolbox.xpm +.sp +.fi + +.SH AUTHOR +Nobutaka Suzuki (nobuta-s@is.aist-nara.ac.jp). + diff --git a/modules/FvwmIconBox/Imakefile b/modules/FvwmIconBox/Imakefile new file mode 100644 index 0000000..21edbe7 --- /dev/null +++ b/modules/FvwmIconBox/Imakefile @@ -0,0 +1,33 @@ +/* Imakefile for GoodStuff */ +/* Thu Aug 5 11:21:36 MET DST 1993, mj@dfv.rwth-aachen.de */ + +/* setup is done entirely in configuration.h now! */ +/* You should need to do much in here, excpt maybe add libraries */ + +/* I need to get the #define XPM from configuration.h if its in there,*/ +/* so that I can tell if I should include -lXpm */ +#include <../../configure.h> + +COMPILER + +#ifdef XPM +XPMLIB = XPMLIBRARY +#endif + +DEPLIBS = $(DEPXLIB) ../../libs/libfvwmlib.a + +#ifdef AlphaArchitecture +LOCAL_LIBRARIES = $(XPMLIB) $(XLIB) -ldnet_stub -L../../libs -lfvwmlib +#else +LOCAL_LIBRARIES = $(XPMLIB) $(XLIB) -L../../libs -lfvwmlib +#endif + +LINTLIBS = $(LINTXLIB) + +SRCS = FvwmIconBox.c icons.c +OBJS = FvwmIconBox.o icons.o + +TARGET_DIR + +ComplexProgramTarget(FvwmIconBox) + diff --git a/modules/FvwmIconBox/icons.c b/modules/FvwmIconBox/icons.c new file mode 100644 index 0000000..4f24559 --- /dev/null +++ b/modules/FvwmIconBox/icons.c @@ -0,0 +1,387 @@ +/*********************************************************************** + * icons.c + * Based on icons.c of GoodStuff: + * Copyright 1993, Robert Nation. + ***********************************************************************/ + +/* Copyright 1993, Robert Nation. No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. */ + + +/*********************************************************************** + * + * Derived from fvwm icon code + * + ***********************************************************************/ + +#include "../../configure.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "../../fvwm/module.h" + +#ifdef NeXT +#include +#endif + +#include "FvwmIconBox.h" + +#ifdef XPM +#include +#endif /* XPM */ +#ifdef SHAPE +#include +#endif /* SHAPE */ + +#define ICON_EVENTS (ExposureMask | StructureNotifyMask|\ +ButtonReleaseMask | ButtonPressMask | EnterWindowMask | LeaveWindowMask) + +/**************************************************************************** + * + * Creates an Icon Window + * + ****************************************************************************/ +void CreateIconWindow(struct icon_info *item) +{ + unsigned long valuemask; /* mask for create windows */ + XSetWindowAttributes attributes; /* attributes for create windows */ + + attributes.background_pixel = icon_back_pix; + attributes.event_mask = ExposureMask; + valuemask = CWEventMask | CWBackPixel; + + /* pixmap */ + item->icon_pixmap_w = + XCreateWindow(dpy, icon_win, 0, 0, + max(max_icon_width,item->icon_w), + max(max_icon_height,item->icon_h), + 0,CopyFromParent,CopyFromParent, + CopyFromParent,valuemask,&attributes); + XSelectInput(dpy, item->icon_pixmap_w, ICON_EVENTS); + + /* label */ + item->IconWin = + XCreateWindow(dpy, icon_win, 0, 0, + max_icon_width, + max_icon_height, + 0,CopyFromParent,CopyFromParent, + CopyFromParent,valuemask,&attributes); + XSelectInput(dpy, item->IconWin, ICON_EVENTS); +} + +/**************************************************************************** + * + * Loads an icon file and combines icon shape masks after a resize + * + ****************************************************************************/ +void ConfigureIconWindow(struct icon_info *item) +{ + Pixmap temp; + unsigned int nchildren; + int i, hr = ICON_RELIEF/2; + Window Junkroot, Junkparent; + Window *wlist; + + XQueryTree(dpy, Root, &Junkroot, &Junkparent, &wlist, &nchildren); + for (i=nchildren-1; i>=0; --i) + if (item->fid == wlist[i]){ + XSelectInput(dpy, item->id, PropertyChangeMask); + item->wmhints = XGetWMHints(dpy, item->id); + break; + } + XFree(wlist); + + if (item->icon_file != NULL && (item->defaulticon == 0 || !(item->wmhints && + item->wmhints->flags & + (IconPixmapHint|IconWindowHint)))){ + /* monochrome bitmap */ + GetBitmapFile(item); + + /* color pixmap */ + if((item->icon_w == 0)&&(item->icon_h == 0)) + GetXPMFile(item); + } + + if((item->icon_h == 0)&&(item->icon_w == 0)&& + (item->wmhints) && (item->wmhints->flags & IconWindowHint)) + GetIconWindow(item); + + /* icon bitmap from the application */ + if((item->icon_h == 0)&&(item->icon_w == 0)&& + (item->wmhints)&&(item->wmhints->flags & IconPixmapHint)) + GetIconBitmap(item); + +#ifdef XPM +#ifdef SHAPE + if (item->icon_maskPixmap != None) + { + XShapeCombineMask(dpy, item->icon_pixmap_w, ShapeBounding, + hr, hr, item->icon_maskPixmap, ShapeSet); + } +#endif +#endif + + if(item->icon_depth == -1) + { + temp = item->iconPixmap; + item->iconPixmap = + XCreatePixmap(dpy, Root, item->icon_w, + item->icon_h,d_depth); + XCopyPlane(dpy,temp,item->iconPixmap,NormalGC, + 0,0,item->icon_w,item->icon_h,0,0,1); + } +} + +void AdjustIconWindow(struct icon_info *item, int n) +{ + int x=0,y=0,w,h,h2,h3,w3; + + w3 = w = max_icon_width + ICON_RELIEF; + h3 = h2 = max_icon_height + ICON_RELIEF; + h = h2 + 6 + font->ascent + font->descent; + + switch (primary){ + case LEFT: + case RIGHT: + if (secondary == BOTTOM) + y = icon_win_height - (n / Lines + 1)*(h + interval); + else if (secondary == TOP) + y = (n / Lines)*(h + interval) + interval; + + if (primary == LEFT) + x = (n % Lines)*(w + interval) + interval; + else + x = icon_win_width - (n % Lines + 1)*(w + interval); + break; + case TOP: + case BOTTOM: + if (secondary == RIGHT) + x = icon_win_width - (n / Lines + 1)*(w + interval); + else if (secondary == LEFT) + x = (n / Lines)*(w + interval) + interval; + + if (primary == TOP) + y = (n % Lines)*(h + interval) + interval; + else + y = icon_win_height - (n % Lines + 1)*(h + interval); + break; + default: + break; + } + + item->x = x; + item->y = y; + + if (item->icon_w > 0 && item->icon_h > 0){ + w3 = min(max_icon_width, item->icon_w) + ICON_RELIEF; + h3 = min(max_icon_height, item->icon_h) + ICON_RELIEF; + } + XMoveResizeWindow(dpy, item->icon_pixmap_w, x + (w - w3)/2, + y + (h2 - h3)/2,w3,h3); + XMoveResizeWindow(dpy, item->IconWin, x,y + h2,w,h - h2); +} + +/*************************************************************************** + * + * Looks for a monochrome icon bitmap file + * + **************************************************************************/ +void GetBitmapFile(struct icon_info *item) +{ + char *path = NULL; + int HotX,HotY; + + path = findIconFile(item->icon_file, iconPath,R_OK); + if(path == NULL)return; + + if(XReadBitmapFile (dpy, Root,path,(unsigned int *)&item->icon_w, + (unsigned int *)&item->icon_h, + &item->iconPixmap, + (int *)&HotX, + (int *)&HotY) != BitmapSuccess) + { + item->icon_w = 0; + item->icon_h = 0; + } + else + item->icon_depth = 1; + + item->icon_w = min(max_icon_width, item->icon_w); + item->icon_h = min(max_icon_height, item->icon_h); + item->icon_maskPixmap = None; + free(path); +} + + +/**************************************************************************** + * + * Looks for a color XPM icon file + * + ****************************************************************************/ +void GetXPMFile(struct icon_info *item) +{ +#ifdef XPM + XWindowAttributes root_attr; + XpmAttributes xpm_attributes; + char *path = NULL; + + path = findIconFile(item->icon_file, pixmapPath,R_OK); + if(path == NULL)return; + + XGetWindowAttributes(dpy,Root,&root_attr); + xpm_attributes.colormap = root_attr.colormap; + xpm_attributes.valuemask = XpmSize | XpmReturnPixels|XpmColormap; + if(XpmReadFileToPixmap(dpy, Root, path, + &item->iconPixmap, + &item->icon_maskPixmap, + &xpm_attributes) == XpmSuccess) + { + item->icon_w = min(max_icon_width, xpm_attributes.width); + item->icon_h = min(max_icon_height, xpm_attributes.height); + item->icon_depth = d_depth; + } + free(path); +#endif /* XPM */ +} + +/*************************************************************************** +* + * + * Looks for an application supplied icon window + * + *************************************************************************** +*/ +void GetIconWindow(struct icon_info *item) +{ + int x, y; + unsigned int bw; + Window Junkroot; + + if(!XGetGeometry(dpy, item->wmhints->icon_window, &Junkroot, + &x, &y, (unsigned int *)&item->icon_w, + (unsigned int *)&item->icon_h, + &bw, (unsigned int *)&item->icon_depth)){ + fprintf(stderr,"Help! Bad Icon Window!\n"); + exit(1); + } + + item->icon_pixmap_w = item->wmhints->icon_window; + +#ifdef SHAPE + if (item->wmhints->flags & IconMaskHint) + { + item->flags |= SHAPED_ICON; + item->icon_maskPixmap = item->wmhints->icon_mask; + } +#endif + + item->icon_w = min(max_icon_width, item->icon_w); + item->icon_h = min(max_icon_height, item->icon_h); + + XReparentWindow(dpy, item->icon_pixmap_w, icon_win, 0, 0); + XSetWindowBorderWidth(dpy, item->icon_pixmap_w, 0); + item->flags &= ~ICON_OURS; +} + +/*************************************************************************** +* + * + * Looks for an application supplied bitmap or pixmap + * + *************************************************************************** +*/ +void GetIconBitmap(struct icon_info *item) +{ + int x, y; + unsigned int bw, depth; + Window Junkroot; + GC gc; + + if (!XGetGeometry(dpy, item->wmhints->icon_pixmap, &Junkroot, &x, &y, + (unsigned int *)&item->icon_w, + (unsigned int *)&item->icon_h, &bw, &depth)){ + fprintf(stderr, "invalid icon pixmap.\n"); + exit(1); + } + + item->icon_depth = depth; + item->icon_file = NULL; + item->icon_maskPixmap = None; +#ifdef SHAPE + if (item->wmhints->flags & IconMaskHint) + { + item->flags |= SHAPED_ICON; + item->icon_maskPixmap = item->wmhints->icon_mask; + } +#endif + + item->icon_w = min(max_icon_width, item->icon_w); + item->icon_h = min(max_icon_height, item->icon_h); + + item->iconPixmap = XCreatePixmap(dpy, Root, item->icon_w, + item->icon_h, depth); + gc = XCreateGC(dpy, item->iconPixmap, 0, NULL); + XCopyArea(dpy, item->wmhints->icon_pixmap, item->iconPixmap, + gc, 0, 0, item->icon_w, item->icon_h, 0, 0); + XFreeGC(dpy, gc); +} + +Bool GetBackPixmap(void) +{ + XWindowAttributes root_attr; +#ifdef XPM + XpmAttributes xpm_attributes; +#endif + char *path = NULL; + Pixmap tmp_bitmap, maskPixmap; + int x, y, w=0, h=0; + + if (IconwinPixmapFile == NULL) + return False; + + if ((path = findIconFile(IconwinPixmapFile, iconPath,R_OK)) != NULL){ + if (XReadBitmapFile(dpy, Root,path,(unsigned int *)&w, + (unsigned int *)&h, &tmp_bitmap, + (int *)&x, (int *)&y)!= BitmapSuccess) + w = h = 0; + else{ + IconwinPixmap = XCreatePixmap(dpy, Root, w, h, d_depth); + XCopyPlane(dpy, tmp_bitmap, IconwinPixmap, NormalGC, 0, 0, w, h, + 0, 0, 1); + XFreePixmap(dpy, tmp_bitmap); + } + free(path); + } + +#ifdef XPM + if ( w == 0 && h == 0 && (path = findIconFile(IconwinPixmapFile, + pixmapPath,R_OK)) != NULL) + { + XGetWindowAttributes(dpy,Root,&root_attr); + xpm_attributes.colormap = root_attr.colormap; + xpm_attributes.valuemask = XpmSize|XpmReturnPixels|XpmColormap; + if (XpmReadFileToPixmap(dpy, Root, path, &IconwinPixmap, + &maskPixmap, &xpm_attributes) == + XpmSuccess){ + w = xpm_attributes.width; + h = xpm_attributes.height; + } + free(path); + } +#endif + if (w != 0 && h != 0) + return True; + return False; +} diff --git a/modules/FvwmIconBox/stipple b/modules/FvwmIconBox/stipple new file mode 100644 index 0000000..8e9e77f --- /dev/null +++ b/modules/FvwmIconBox/stipple @@ -0,0 +1,6 @@ +#define stipple_width 16 +#define stipple_height 16 +static char stipple_bits[] = { + 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, + 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, + 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00}; diff --git a/modules/FvwmIdent/FvwmIdent.c b/modules/FvwmIdent/FvwmIdent.c new file mode 100644 index 0000000..ee405c7 --- /dev/null +++ b/modules/FvwmIdent/FvwmIdent.c @@ -0,0 +1,727 @@ +/* This module, and the entire NoClutter program, and the concept for + * interfacing this module to the Window Manager, are all original work + * by Robert Nation and Nobutaka Suzuki + * + * Copyright 1994, Robert Nation and Nobutaka Suzuki. + * No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. */ + +#define TRUE 1 +#define FALSE + +#define YES "Yes" +#define NO "No" + +#include "../../configure.h" + +#include +#include +#include +#include +#include +#include +#if defined ___AIX || defined _AIX || defined __QNX__ || defined ___AIXV3 || defined AIXV3 || defined _SEQUENT_ +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../fvwm/module.h" +#include "FvwmIdent.h" +#include "../../version.h" + +char *MyName; +int fd_width; +int fd[2]; + +Display *dpy; /* which display are we talking to */ +Window Root; +int screen; +int x_fd; +int d_depth; +int ScreenWidth, ScreenHeight; + +char *BackColor = "white"; +char *ForeColor = "black"; +char *font_string = "fixed"; + +Pixel back_pix, fore_pix; +GC NormalGC; +Window main_win; +Window app_win; +XFontStruct *font; + +int Width, Height,win_x,win_y; + +#define MW_EVENTS (ExposureMask | ButtonReleaseMask | KeyReleaseMask) + +static Atom wm_del_win; + +struct target_struct target; +int found=0; + + +struct Item* itemlistRoot = NULL; +int max_col1, max_col2; +char id[15], desktop[10], swidth[10], sheight[10], borderw[10], geometry[30]; + +/*********************************************************************** + * + * Procedure: + * main - start of module + * + ***********************************************************************/ +void main(int argc, char **argv) +{ + char *temp, *s; + FILE *file; + char *display_name = NULL; + int Clength; + + /* Save the program name for error messages and config parsing */ + temp = argv[0]; + s=strrchr(argv[0], '/'); + if (s != NULL) + temp = s + 1; + + MyName = safemalloc(strlen(temp)+2); + strcpy(MyName,"*"); + strcat(MyName, temp); + Clength = strlen(MyName); + + if((argc != 6)&&(argc != 7)) + { + fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",MyName, + VERSION); + exit(1); + } + + /* Dead pipe == dead fvwm */ + signal (SIGPIPE, DeadPipe); + + fd[0] = atoi(argv[1]); + fd[1] = atoi(argv[2]); + + /* An application window may have already been selected - look for it */ + sscanf(argv[4],"%x",(unsigned int *)&app_win); + + /* Open the Display */ + if (!(dpy = XOpenDisplay(display_name))) + { + fprintf(stderr,"%s: can't open display %s", MyName, + XDisplayName(display_name)); + exit (1); + } + x_fd = XConnectionNumber(dpy); + screen= DefaultScreen(dpy); + Root = RootWindow(dpy, screen); + d_depth = DefaultDepth(dpy, screen); + + ScreenHeight = DisplayHeight(dpy,screen); + ScreenWidth = DisplayWidth(dpy,screen); + + /* scan config file for set-up parameters */ + /* Colors and fonts */ + file = fopen(argv[3],"r"); + if(file != (FILE *)NULL) + { + char line[256]; + char *tline; + + tline = fgets(line,(sizeof line)-1,file); + while(tline != (char *)0) + { + while(isspace(*tline))tline++; + if(strlen(tline)>1) + { + if(mystrncasecmp(tline, CatString3(MyName,"Font",""),Clength+4)==0) + { + CopyString(&font_string,&tline[Clength+4]); + } + else if(mystrncasecmp(tline,CatString3(MyName,"Fore",""), + Clength+4)==0) + { + CopyString(&ForeColor,&tline[Clength+4]); + } + else if(mystrncasecmp(tline,CatString3(MyName, "Back",""), + Clength+4)==0) + { + CopyString(&BackColor,&tline[Clength+4]); + } + } + tline = fgets(line,(sizeof line)-1,file); + } + } + + if(app_win == 0) + GetTargetWindow(&app_win); + + fd_width = GetFdWidth(); + + /* Create a list of all windows */ + /* Request a list of all windows, + * wait for ConfigureWindow packets */ + SendInfo(fd,"Send_WindowList",0); + + Loop(fd); +} + +/************************************************************************** + * + * Read the entire window list from fvwm + * + *************************************************************************/ +void Loop(int *fd) +{ + unsigned long header[3], *body; + char *cbody; + int body_length,count,count2=0,total; + + while(1) + { + if(count = ReadFvwmPacket(fd[1],header,&body) > 0) + { + process_message(header[1],body); + free(body); + } + } +} + + +/************************************************************************** + * + * Process window list messages + * + *************************************************************************/ +void process_message(unsigned long type,unsigned long *body) +{ + switch(type) + { + case M_CONFIGURE_WINDOW: + list_configure(body); + break; + case M_WINDOW_NAME: + list_window_name(body); + break; + case M_ICON_NAME: + list_icon_name(body); + break; + case M_RES_CLASS: + list_class(body); + break; + case M_RES_NAME: + list_res_name(body); + break; + case M_END_WINDOWLIST: + list_end(); + break; + default: + break; + + } +} + + + + +/*********************************************************************** + * + * Detected a broken pipe - time to exit + * + **********************************************************************/ +void DeadPipe(int nonsense) +{ + freelist(); + exit(0); +} + +/*********************************************************************** + * + * Got window configuration info - if its our window, safe data + * + ***********************************************************************/ +void list_configure(unsigned long *body) +{ + if((app_win == (Window)body[1])||(app_win == (Window)body[0]) + ||((body[19] != 0)&&(app_win == (Window)body[19])) + ||((body[19] != 0)&&(app_win == (Window)body[20]))) + { + app_win = body[1]; + target.id = body[0]; + target.frame = body[1]; + target.frame_x = body[3]; + target.frame_y = body[4]; + target.frame_w = body[5]; + target.frame_h = body[6]; + target.desktop = body[7]; + target.flags = body[8]; + target.title_h = body[9]; + target.border_w = body[10]; + target.base_w = body[11]; + target.base_h = body[12]; + target.width_inc = body[13]; + target.height_inc = body[14]; + target.gravity = body[21]; + found = 1; + } + +} + +/************************************************************************* + * + * Capture Window name info + * + ************************************************************************/ +void list_window_name(unsigned long *body) +{ + if((app_win == (Window)body[1])||(app_win == (Window)body[0])) + { + strncpy(target.name,(char *)&body[3],255); + } +} + +/************************************************************************* + * + * Capture Window Icon name info + * + ************************************************************************/ +void list_icon_name(unsigned long *body) +{ + if((app_win == (Window)body[1])||(app_win == (Window)body[0])) + { + strncat(target.icon_name,(char *)&body[3],255); + } +} + + +/************************************************************************* + * + * Capture Window class name info + * + ************************************************************************/ +void list_class(unsigned long *body) +{ + if((app_win == (Window)body[1])||(app_win == (Window)body[0])) + { + strncat(target.class,(char *)&body[3],255); + } +} + + +/************************************************************************* + * + * Capture Window resource info + * + ************************************************************************/ +void list_res_name(unsigned long *body) +{ + if((app_win == (Window)body[1])||(app_win == (Window)body[0])) + { + strncat(target.res,(char *)&body[3],255); + } +} + + +/************************************************************************* + * + * End of window list, open an x window and display data in it + * + ************************************************************************/ +XSizeHints mysizehints; +void list_end(void) +{ + XGCValues gcv; + unsigned long gcm; + int lmax,height; + XEvent Event; + Window JunkRoot, JunkChild; + int JunkX, JunkY; + unsigned int JunkMask; + int x,y; + + if(!found) + { +/* fprintf(stderr,"%s: Couldn't find app window\n",MyName); */ + exit(0); + } + + close(fd[0]); + close(fd[1]); + + /* load the font */ + if ((font = XLoadQueryFont(dpy, font_string)) == NULL) + { + if ((font = XLoadQueryFont(dpy, "fixed")) == NULL) + exit(1); + }; + + /* make window infomation list */ + MakeList(); + + /* size and create the window */ + lmax = max_col1 + max_col2 + 15; + + height = 15*(font->ascent+font->descent); + + mysizehints.flags= + USSize|USPosition|PWinGravity|PResizeInc|PBaseSize|PMinSize|PMaxSize; + /* subtract one for the right/bottom border */ + mysizehints.width = lmax+10; + mysizehints.height=height+10; + mysizehints.width_inc = 1; + mysizehints.height_inc = 1; + mysizehints.base_height = mysizehints.height; + mysizehints.base_width = mysizehints.width; + mysizehints.min_height = mysizehints.height; + mysizehints.min_width = mysizehints.width; + mysizehints.max_height = mysizehints.height; + mysizehints.max_width = mysizehints.width; + XQueryPointer( dpy, Root, &JunkRoot, &JunkChild, + &x, &y, &JunkX, &JunkY, &JunkMask); + mysizehints.win_gravity = NorthWestGravity; + + if((y+height+100)>ScreenHeight) + { + y = ScreenHeight- 2 - height - 10; + mysizehints.win_gravity = SouthWestGravity; + } + + if((x+lmax+100)>ScreenWidth) + { + x = ScreenWidth - 2 - lmax - 10; + if((y+height+100)>ScreenHeight) + mysizehints.win_gravity = SouthEastGravity; + else + mysizehints.win_gravity = NorthEastGravity; + } + mysizehints.x = x; + mysizehints.y = y; + + +#define BW 1 + if(d_depth < 2) + { + back_pix = GetColor("white"); + fore_pix = GetColor("black"); + } + else + { + back_pix = GetColor(BackColor); + fore_pix = GetColor(ForeColor); + + } + + main_win = XCreateSimpleWindow(dpy,Root,mysizehints.x,mysizehints.y, + mysizehints.width,mysizehints.height, + BW,fore_pix,back_pix); + XSetTransientForHint(dpy,main_win,app_win); + wm_del_win = XInternAtom(dpy,"WM_DELETE_WINDOW",False); + XSetWMProtocols(dpy,main_win,&wm_del_win,1); + + XSetWMNormalHints(dpy,main_win,&mysizehints); + XSelectInput(dpy,main_win,MW_EVENTS); + change_window_name(&MyName[1]); + + gcm = GCForeground|GCBackground|GCFont; + gcv.foreground = fore_pix; + gcv.background = back_pix; + gcv.font = font->fid; + NormalGC = XCreateGC(dpy, Root, gcm, &gcv); + XMapWindow(dpy,main_win); + + /* Window is created. Display it until the user clicks or deletes it. */ + while(1) + { + XNextEvent(dpy,&Event); + switch(Event.type) + { + case Expose: + if(Event.xexpose.count == 0) + RedrawWindow(); + break; + case KeyRelease: + case ButtonRelease: + freelist(); + exit(0); + case ClientMessage: + if (Event.xclient.format==32 && Event.xclient.data.l[0]==wm_del_win) + { + freelist(); + exit(0); + } + default: + break; + } + } + +} + + + +/********************************************************************** + * + * If no application window was indicated on the command line, prompt + * the user to select one + * + *********************************************************************/ +void GetTargetWindow(Window *app_win) +{ + XEvent eventp; + int val = -10,trials; + + trials = 0; + while((trials <100)&&(val != GrabSuccess)) + { + val=XGrabPointer(dpy, Root, True, + ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, Root, + XCreateFontCursor(dpy,XC_crosshair), + CurrentTime); + if(val != GrabSuccess) + { + sleep_a_little(1000); + } + trials++; + } + if(val != GrabSuccess) + { + fprintf(stderr,"%s: Couldn't grab the cursor!\n",MyName); + exit(1); + } + XMaskEvent(dpy, ButtonReleaseMask,&eventp); + XUngrabPointer(dpy,CurrentTime); + XSync(dpy,0); + *app_win = eventp.xany.window; + if(eventp.xbutton.subwindow != None) + *app_win = eventp.xbutton.subwindow; +} + +/************************************************************************ + * + * Draw the window + * + ***********************************************************************/ +void RedrawWindow(void) +{ + int fontheight,i=0; + struct Item *cur = itemlistRoot; + + fontheight = font->ascent + font->descent; + + while(cur != NULL) + { + /* first column */ + XDrawString(dpy,main_win,NormalGC,5,5+font->ascent+i*fontheight, + cur->col1,strlen(cur->col1)); + /* second column */ + XDrawString(dpy,main_win,NormalGC,10+max_col1,5+font->ascent+i*fontheight, + cur->col2,strlen(cur->col2)); + ++i; + cur = cur->next; + } +} + +/************************************************************************** + * Change the window name displayed in the title bar. + **************************************************************************/ +void change_window_name(char *str) +{ + XTextProperty name; + + if (XStringListToTextProperty(&str,1,&name) == 0) + { + fprintf(stderr,"%s: cannot allocate window name",MyName); + return; + } + XSetWMName(dpy,main_win,&name); + XSetWMIconName(dpy,main_win,&name); + XFree(name.value); +} + + +/************************************************************************** +* +* Add s1(string at first column) and s2(string at second column) to itemlist +* + *************************************************************************/ +void AddToList(char *s1, char* s2) +{ + int tw1, tw2; + struct Item* item, *cur = itemlistRoot; + + tw1 = XTextWidth(font, s1, strlen(s1)); + tw2 = XTextWidth(font, s2, strlen(s2)); + max_col1 = max_col1 > tw1 ? max_col1 : tw1; + max_col2 = max_col2 > tw2 ? max_col2 : tw2; + + item = (struct Item*)safemalloc(sizeof(struct Item)); + + item->col1 = s1; + item->col2 = s2; + item->next = NULL; + + if (cur == NULL) + itemlistRoot = item; + else { + while(cur->next != NULL) + cur = cur->next; + cur->next = item; + } +} + +void MakeList(void) +{ + int bw,width,height,x1,y1,x2,y2; + char loc[20]; + + bw = 2*target.border_w; + width = target.frame_w - bw; + height = target.frame_h - target.title_h - bw; + + sprintf(desktop, "%ld", target.desktop); + sprintf(id, "0x%x", (unsigned int)target.id); + sprintf(swidth, "%d", width); + sprintf(sheight, "%d", height); + sprintf(borderw, "%ld", target.border_w); + + AddToList("Name:", target.name); + AddToList("Icon Name:", target.icon_name); + AddToList("Class:", target.class); + AddToList("Resource:", target.res); + AddToList("Window ID:", id); + AddToList("Desk:", desktop); + AddToList("Width:", swidth); + AddToList("Height:", sheight); + AddToList("BoundaryWidth:", borderw); + AddToList("Sticky:", (target.flags & STICKY ? YES : NO)); + AddToList("Ontop:", (target.flags & ONTOP ? YES : NO)); + AddToList("NoTitle:", (target.flags & TITLE ? NO : YES)); + AddToList("Iconified:", (target.flags & ICONIFIED ? YES : NO)); + + switch(target.gravity) + { + case ForgetGravity: + AddToList("Gravity:", "Forget"); + break; + case NorthWestGravity: + AddToList("Gravity:", "NorthWest"); + break; + case NorthGravity: + AddToList("Gravity:", "North"); + break; + case NorthEastGravity: + AddToList("Gravity:", "NorthEast"); + break; + case WestGravity: + AddToList("Gravity:", "West"); + break; + case CenterGravity: + AddToList("Gravity:", "Center"); + break; + case EastGravity: + AddToList("Gravity:", "East"); + break; + case SouthWestGravity: + AddToList("Gravity:", "SouthWest"); + break; + case SouthGravity: + AddToList("Gravity:", "South"); + break; + case SouthEastGravity: + AddToList("Gravity:", "SouthEast"); + break; + case StaticGravity: + AddToList("Gravity:", "Static"); + break; + default: + AddToList("Gravity:", "Unknown"); + break; + } + x1 = target.frame_x; + if(x1 < 0) + x1 = 0; + x2 = ScreenWidth - x1 - target.frame_w; + if(x2 < 0) + x2 = 0; + y1 = target.frame_y; + if(y1 < 0) + y1 = 0; + y2 = ScreenHeight - y1 - target.frame_h; + if(y2 < 0) + y2 = 0; + width = (width - target.base_w)/target.width_inc; + height = (height - target.base_h)/target.height_inc; + + sprintf(loc,"%dx%d",width,height); + strcpy(geometry, loc); + + if ((target.gravity == EastGravity) ||(target.gravity == NorthEastGravity)|| + (target.gravity == SouthEastGravity)) + sprintf(loc,"-%d",x2); + else + sprintf(loc,"+%d",x1); + strcat(geometry, loc); + + if((target.gravity == SouthGravity)||(target.gravity == SouthEastGravity)|| + (target.gravity == SouthWestGravity)) + sprintf(loc,"-%d",y2); + else + sprintf(loc,"+%d",y1); + strcat(geometry, loc); + AddToList("Geometry:", geometry); +} + +void freelist(void) +{ + struct Item* cur = itemlistRoot, *cur2; + + while(cur != NULL) + { + cur2 = cur; + cur = cur->next; + free(cur2); + } +} + + +void nocolor(char *a, char *b) +{ + fprintf(stderr,"FvwmInitBanner: can't %s %s\n", a,b); +} + +/**************************************************************************** + * + * Loads a single color + * + ****************************************************************************/ +Pixel GetColor(char *name) +{ + XColor color; + XWindowAttributes attributes; + + XGetWindowAttributes(dpy,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; +} + + + + + diff --git a/modules/FvwmIdent/FvwmIdent.h b/modules/FvwmIdent/FvwmIdent.h new file mode 100644 index 0000000..ef81aa4 --- /dev/null +++ b/modules/FvwmIdent/FvwmIdent.h @@ -0,0 +1,73 @@ +#include "../../libs/fvwmlib.h" +#define STICKY 1 /* Does window stick to glass? */ +#define ONTOP 2 /* does window stay on top */ +#define BORDER 4 /* Is this decorated with border*/ +#define TITLE 8 /* Is this decorated with title */ +#define ICONIFIED 32 /* is it an icon now? */ +#define TRANSIENT 64 /* is it a transient window? */ +struct target_struct +{ + char res[256]; + char class[256]; + char name[256]; + char icon_name[256]; + unsigned long id; + unsigned long frame; + long frame_x; + long frame_y; + long frame_w; + long frame_h; + long base_w; + long base_h; + long width_inc; + long height_inc; + long desktop; + unsigned long gravity; + unsigned long flags; + long title_h; + long border_w; +}; + +struct Item +{ + char* col1; + char* col2; + struct Item* next; +}; + +/************************************************************************* + * + * Subroutine Prototypes + * + *************************************************************************/ +void Loop(int *fd); +void SendInfo(int *fd,char *message,unsigned long window); +char *safemalloc(int length); +void DeadPipe(int nonsense); +void process_message(unsigned long type,unsigned long *body); +void GetTargetWindow(Window *app_win); +void sleep_a_little(int n); +void RedrawWindow(void); +void change_window_name(char *str); +Pixel GetColor(char *name); +void nocolor(char *a, char *b); +void CopyString(char **dest, char *source); +char *CatString2(char *a, char *b); +void AddToList(char *, char *); +void MakeList(void); +void freelist(void); + +void list_configure(unsigned long *body); +void list_window_name(unsigned long *body); +void list_icon_name(unsigned long *body); +void list_class(unsigned long *body); +void list_res_name(unsigned long *body); +void list_end(void); + +#ifdef BROKEN_SUN_HEADERS +#include "../../fvwm/sun_headers.h" +#endif + +#ifdef NEEDS_ALPHA_HEADER +#include "../../fvwm/alpha_header.h" +#endif /* NEEDS_ALPHA_HEADER */ diff --git a/modules/FvwmIdent/FvwmIdent.man b/modules/FvwmIdent/FvwmIdent.man new file mode 100644 index 0000000..0f5198d --- /dev/null +++ b/modules/FvwmIdent/FvwmIdent.man @@ -0,0 +1,68 @@ +.\" t +.\" @(#)FvwmIdent.1 1/12/94 +.TH FvwmIdent 1.20 "Jan 28 1994" +.UC +.SH NAME +FvwmIdent \- the FVWM identify-window module +.SH SYNOPSIS +FvwmIdent is spawned by fvwm, so no command line invocation will work. + +.SH DESCRIPTION +The FvwmIdent module prompts the user to select a target window, if +the module was not launched from within a window context in Fvwm. +After that, it pops up a window with information about the window +which was selected. + +FvwmIdent reads the same .fvwmrc file as fvwm reads when it starts up, +and looks for lines similar to "*FvwmIdentFore green". + +.SH COPYRIGHTS +The FvwmIdent program, and the concept for +interfacing this module to the Window Manager, are all original work +by Robert Nation and Nobutaka Suzuki. + +Copyright 1994, Robert Nation and Nobutaka Suzuki. No guarantees or +warranties or anything +are provided or implied in any way whatsoever. Use this program at your +own risk. Permission to use this program for any purpose is given, +as long as the copyright is kept intact. + + +.SH INITIALIZATION +During initialization, \fIFvwmIdent\fP will eventually search a +configuration file which describes the colors and font to use. +The configuration file is the same file that fvwm used during initialization. + +If the FvwmIdent executable is linked to another name, ie ln -s +FvwmIdent MoreIdentify, then another module called MoreIdentify can be +started, with a completely different configuration than FvwmIdent, +simply by changing the keyword FvwmIdent to MoreIdentify. This way multiple +clutter-reduction programs can be used. + +.SH INVOCATION +FvwmIdent can be invoked by binding the action 'Module +FvwmIdent' to a menu or key-stroke in the .fvwmrc file. +Fvwm will search +directory specified in the ModulePath configuration option to attempt +to locate FvwmIdent. Although nothing keeps you from launching +FvwmIdent at start-up time, you probably don't want to. + +.SH CONFIGURATION OPTIONS +FvwmIdent reads the same .fvwmrc file as fvwm reads when it starts up, +and looks for lines as listed below: + +.IP "*FvwmIdentFore \fIcolor\fP" +Tells the module to use \fIcolor\fP instead of black for text. + +.IP "*FvwmIdentBack \fIcolor\fP" +Tells the module to use \fIcolor\fP instead of black for the window +background. + +.IP "*FvwmIdentFont \fIfontname\fP" +Tells the module to use \fIfontname\fP instead of fixed for text. + + +.SH AUTHOR +Robert Nation and and Nobutaka +Suzuki (nobuta-s@is.aist-nara.ac.jp). + diff --git a/modules/FvwmIdent/Imakefile b/modules/FvwmIdent/Imakefile new file mode 100644 index 0000000..aea7f72 --- /dev/null +++ b/modules/FvwmIdent/Imakefile @@ -0,0 +1,30 @@ +/* Imakefile for FvwmIdent */ +/* Thu Aug 5 11:21:36 MET DST 1993, mj@dfv.rwth-aachen.de */ + +/* setup is done entirely in configuration.h now! */ +/* You should need to do much in here, excpt maybe add libraries */ + +/* I need to get the #define XPM from configuration.h if its in there,*/ +/* so that I can tell if I should include -lXpm */ +#include <../../configure.h> + +COMPILER + +DEPLIBS = $(DEPXLIB) ../../libs/libfvwmlib.a + +#ifdef AlphaArchitecture +LOCAL_LIBRARIES = $(XLIB) -ldnet_stub -L../../libs -lfvwmlib +#else +LOCAL_LIBRARIES = $(XLIB) -L../../libs -lfvwmlib +#endif + +LINTLIBS = $(LINTXLIB) + +SRCS = FvwmIdent.c +OBJS = FvwmIdent.o + +TARGET_DIR + +ComplexProgramTarget(FvwmIdent) + + diff --git a/modules/FvwmPager/FvwmPager.c b/modules/FvwmPager/FvwmPager.c new file mode 100644 index 0000000..70fff6c --- /dev/null +++ b/modules/FvwmPager/FvwmPager.c @@ -0,0 +1,956 @@ +/* This module, and the entire ModuleDebugger program, and the concept for + * interfacing this module to the Window Manager, are all original work + * by Robert Nation + * + * Copyright 1994, Robert Nation. No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. */ + +#define TRUE 1 +#define FALSE + +#include "../../configure.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef ISC /* Saul */ +#include /* Saul */ +#endif /* Saul */ + +#include +#if defined ___AIX || defined _AIX || defined __QNX__ || defined ___AIXV3 || defined AIXV3 || defined _SEQUENT_ +#include +#endif + +#include +#include +#include +#include +#include + +#include "../../fvwm/module.h" + +#include "../../libs/fvwmlib.h" +#include "FvwmPager.h" +#include "../../version.h" +#include "../../fvwm/fvwm.h" + +char *MyName; +int fd_width; +int fd[2]; + +/************************************************************************* + * + * Screen, font, etc info + * + **************************************************************************/ +ScreenInfo Scr; +PagerWindow *Start = NULL; +PagerWindow *FocusWin = NULL; + +Display *dpy; /* which display are we talking to */ +int x_fd,fd_width; + +char *PagerFore = "black"; +char *PagerBack="white"; +char *font_string = "fixed"; +char *smallFont = NULL; +char *HilightC = "black"; + +char *HiBack = "white"; +char *HiFore = "black"; + +int window_w=0, window_h=0, window_x=0, window_y=0; +int icon_x=-10000, icon_y=-10000, icon_w=0, icon_h=0; +int usposition = 0,uselabel = 1; +extern DeskInfo *Desks; +int StartIconic = 0; +int Rows = -1, Columns = -1; +int desk1=0, desk2 =0; +int ndesks = 0; +int StickyIcons = 0; +/*********************************************************************** + * + * Procedure: + * main - start of module + * + ***********************************************************************/ +void main(int argc, char **argv) +{ + char *temp, *s, *cptr; + char *display_name = NULL; + int itemp,i; + char line[100]; + char mask_mesg[50]; + + /* Save our program name - for error messages */ + temp = argv[0]; + s=strrchr(argv[0], '/'); + if (s != NULL) + temp = s + 1; + + MyName = safemalloc(strlen(temp)+2); + strcpy(MyName, temp); + + if((argc != 7)&&(argc != 6)) + { + fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",MyName, + VERSION); + exit(1); + } + if(argc != 7) + { + fprintf(stderr,"%s Version %s requires an argument: %s n m\n", + MyName,VERSION,MyName); + fprintf(stderr," where desktops n through m are displayed\n"); + exit(1); + } + + /* Dead pipe == Fvwm died */ + signal (SIGPIPE, DeadPipe); + + fd[0] = atoi(argv[1]); + fd[1] = atoi(argv[2]); + + fd_width = GetFdWidth(); + + cptr = argv[6]; + while((isspace(*cptr))&&(*cptr != 0))cptr++; + desk1 = atoi(cptr); + while(!(isspace(*cptr))&&(*cptr != 0))cptr++; + while((isspace(*cptr))&&(*cptr != 0))cptr++; + desk2 = atoi(cptr); + if(desk2 < desk1) + { + itemp = desk1; + desk1 = desk2; + desk2 = itemp; + } + ndesks = desk2 - desk1 + 1; + + Desks = (DeskInfo *)malloc(ndesks*sizeof(DeskInfo)); + for(i=0;inext); + t = t->next; + i++; + } + *prev = (PagerWindow *)safemalloc(sizeof(PagerWindow)); + (*prev)->w = body[0]; + (*prev)->t = (char *)body[2]; + (*prev)->frame = body[1]; + (*prev)->x = body[3]; + (*prev)->y = body[4]; + (*prev)->width = body[5]; + (*prev)->height = body[6]; + (*prev)->desk = body[7]; + (*prev)->next = NULL; + (*prev)->flags = body[8]; + (*prev)->icon_name = NULL; + (*prev)->title_height = body[9]; + (*prev)->border_width = body[10]; + (*prev)->icon_w = body[19]; + (*prev)->icon_pixmap_w = body[20]; + (*prev)->text = body[22]; + (*prev)->back = body[23]; + AddNewWindow(*prev); +} + +/*********************************************************************** + * + * Procedure: + * list_configure - displays packet contents to stderr + * + ***********************************************************************/ +void list_configure(unsigned long *body) +{ + PagerWindow *t; + Window target_w; + + target_w = body[0]; + t = Start; + while((t!= NULL)&&(t->w != target_w)) + { + t = t->next; + } + if(t== NULL) + { + list_add(body); + + } + else + { + t->t = (char *)body[2]; + t->frame = body[1]; + t->frame_x = body[3]; + t->frame_y = body[4]; + t->frame_width = body[5]; + t->frame_height = body[6]; + t->title_height = body[9]; + t->border_width = body[10]; + t->flags = body[8]; + t->icon_w = body[19]; + t->icon_pixmap_w = body[20]; + t->text = body[22]; + t->back = body[23]; + if(t->flags & ICONIFIED) + { + t->x = t->icon_x; + t->y = t->icon_y; + t->width = t->icon_width; + t->height = t->icon_height; + if(t->flags & SUPPRESSICON) + { + t->x = -10000; + t->y = -10000; + } + } + else + { + t->x = t->frame_x; + t->y = t->frame_y; + t->width = t->frame_width; + t->height = t->frame_height; + } + if(t->desk != body[7]) + { + ChangeDeskForWindow(t,body[7]); + } + + else + MoveResizePagerView(t); + if(FocusWin == t) + Hilight(t,ON); + else + Hilight(t,OFF); + } +} + +/*********************************************************************** + * + * Procedure: + * list_destroy - displays packet contents to stderr + * + ***********************************************************************/ +void list_destroy(unsigned long *body) +{ + PagerWindow *t,**prev; + Window target_w; + + target_w = body[0]; + t = Start; + prev = &Start; + while((t!= NULL)&&(t->w != target_w)) + { + prev = &(t->next); + t = t->next; + } + if(t!= NULL) + { + if(prev != NULL) + *prev = t->next; + /* remove window from the chain */ + if(t->PagerView != None) + XDestroyWindow(dpy,t->PagerView); + XDestroyWindow(dpy,t->IconView); + if(FocusWin == t) + FocusWin = NULL; + + free(t); + } +} + +/*********************************************************************** + * + * Procedure: + * list_focus - displays packet contents to stderr + * + ***********************************************************************/ +void list_focus(unsigned long *body) +{ + PagerWindow *t,*temp; + Window target_w; + + target_w = body[0]; + + t = Start; + while((t!= NULL)&&(t->w != target_w)) + { + t = t->next; + } + if(t != FocusWin) + { + temp = FocusWin; + FocusWin = t; + + if(temp != NULL) + Hilight(temp,OFF); + if(FocusWin != NULL) + Hilight(FocusWin,ON); + } +} + +/*********************************************************************** + * + * Procedure: + * list_new_page - displays packet contents to stderr + * + ***********************************************************************/ +void list_new_page(unsigned long *body) +{ + Scr.Vx = (long)body[0]; + Scr.Vy = (long)body[1]; + Scr.CurrentDesk = (long)body[2]; + MovePage(); + MoveStickyWindows(); + Hilight(FocusWin,OFF); + Hilight(FocusWin,ON); +} + +/*********************************************************************** + * + * Procedure: + * list_new_desk - displays packet contents to stderr + * + ***********************************************************************/ +void list_new_desk(unsigned long *body) +{ + int oldDesk; + + oldDesk = Scr.CurrentDesk; + Scr.CurrentDesk = (long)body[0]; + + MovePage(); + + DrawGrid(oldDesk - desk1,1); + DrawGrid(Scr.CurrentDesk - desk1,1); + MoveStickyWindows(); + Hilight(FocusWin,OFF); + Hilight(FocusWin,ON); +} + +/*********************************************************************** + * + * Procedure: + * list_raise - displays packet contents to stderr + * + ***********************************************************************/ +void list_raise(unsigned long *body) +{ + PagerWindow *t; + Window target_w; + + target_w = body[0]; + t = Start; + while((t!= NULL)&&(t->w != target_w)) + { + t = t->next; + } + if(t!= NULL) + { + if(t->PagerView != None) + XRaiseWindow(dpy,t->PagerView); + XRaiseWindow(dpy,t->IconView); + } +} + + +/*********************************************************************** + * + * Procedure: + * list_lower - displays packet contents to stderr + * + ***********************************************************************/ +void list_lower(unsigned long *body) +{ + PagerWindow *t; + Window target_w; + + target_w = body[0]; + t = Start; + while((t!= NULL)&&(t->w != target_w)) + { + t = t->next; + } + if(t!= NULL) + { + if(t->PagerView != None) + XLowerWindow(dpy,t->PagerView); + if((t->desk - desk1>=0)&&(t->desk - desk1desk - desk1].CPagerWin); + XLowerWindow(dpy,t->IconView); + } +} + + +/*********************************************************************** + * + * Procedure: + * list_unknow - handles an unrecognized packet. + * + ***********************************************************************/ +void list_unknown(unsigned long *body) +{ + /* fprintf(stderr,"Unknown packet type\n");*/ +} + +/*********************************************************************** + * + * Procedure: + * list_iconify - displays packet contents to stderr + * + ***********************************************************************/ +void list_iconify(unsigned long *body) +{ + PagerWindow *t; + Window target_w; + + target_w = body[0]; + t = Start; + while((t!= NULL)&&(t->w != target_w)) + { + t = t->next; + } + if(t== NULL) + { + return; + } + else + { + t->t = (char *)body[2]; + t->frame = body[1]; + t->icon_x = body[3]; + t->icon_y = body[4]; + t->icon_width = body[5]; + t->icon_height = body[6]; + t->flags |= ICONIFIED; + t->x = t->icon_x; + t->y = t->icon_y; + if(t->flags & SUPPRESSICON) + { + t->x = -10000; + t->y = -10000; + } + t->width = t->icon_width; + t->height = t->icon_height; + MoveResizePagerView(t); + } +} + + +/*********************************************************************** + * + * Procedure: + * list_deiconify - displays packet contents to stderr + * + ***********************************************************************/ + +void list_deiconify(unsigned long *body) +{ + PagerWindow *t; + Window target_w; + + target_w = body[0]; + t = Start; + while((t!= NULL)&&(t->w != target_w)) + { + t = t->next; + } + if(t== NULL) + { + return; + } + else + { + t->flags &= ~ICONIFIED; + t->x = t->frame_x; + t->y = t->frame_y; + t->width = t->frame_width; + t->height = t->frame_height; + MoveResizePagerView(t); + if(FocusWin == t) + Hilight(t,ON); + else + Hilight(t,OFF); + } +} + + +/*********************************************************************** + * + * Procedure: + * list_icon_name - displays packet contents to stderr + * + ***********************************************************************/ +void list_icon_name(unsigned long *body) +{ + PagerWindow *t; + Window target_w; + + target_w = body[0]; + t = Start; + while((t!= NULL)&&(t->w != target_w)) + { + t = t->next; + } + if(t!= NULL) + { + if(t->icon_name != NULL) + free(t->icon_name); + CopyString(&t->icon_name,(char *)(&body[3])); + LabelWindow(t); + LabelIconWindow(t); + } +} + + + + +/*********************************************************************** + * + * Procedure: + * list_end - displays packet contents to stderr + * + ***********************************************************************/ +void list_end(void) +{ + unsigned int nchildren,i; + Window root, parent, *children; + PagerWindow *ptr; + + if(!XQueryTree(dpy, Scr.Root, &root, &parent, &children, &nchildren)) + return; + + for(i=0; iframe == children[i])||(ptr->icon_w == children[i])|| + (ptr->icon_pixmap_w == children[i])) + { + if(ptr->PagerView != None) + XRaiseWindow(dpy,ptr->PagerView); + XRaiseWindow(dpy,ptr->IconView); + } + ptr = ptr->next; + } + } + + + if(nchildren > 0) + XFree((char *)children); +} + + + + +/*************************************************************************** + * + * Waits for next X event, or for an auto-raise timeout. + * + ****************************************************************************/ +int My_XNextEvent(Display *dpy, XEvent *event) +{ + fd_set in_fdset; + unsigned long header[3]; + int body_length; + int count,count2 = 0; + static int miss_counter = 0; + unsigned long *body; + int total; + char *cbody; + + if(XPending(dpy)) + { + XNextEvent(dpy,event); + return 1; + } + + FD_ZERO(&in_fdset); + FD_SET(x_fd,&in_fdset); + FD_SET(fd[1],&in_fdset); + +#ifdef __hpux + select(fd_width,(int *)&in_fdset, 0, 0, NULL); +#else + select(fd_width,&in_fdset, 0, 0, NULL); +#endif + + if(FD_ISSET(x_fd, &in_fdset)) + { + if(XPending(dpy)) + { + XNextEvent(dpy,event); + miss_counter = 0; + return 1; + } + else + miss_counter++; + if(miss_counter > 100) + DeadPipe(0); + } + + if(FD_ISSET(fd[1], &in_fdset)) + { + if(count = ReadFvwmPacket(fd[1],header,&body) > 0) + { + process_message(header[1],body); + free(body); + } + } + return 0; +} + + + +/***************************************************************************** + * + * This routine is responsible for reading and parsing the config file + * + ****************************************************************************/ +void ParseOptions(char *filename) +{ + FILE *fd = (FILE *)0; + char line[256]; + char *tline,*orig_tline,*tmp; + int Clength,n,desk; + + Scr.FvwmRoot = NULL; + Scr.Hilite = NULL; + Scr.VScale = 32; + + Scr.MyDisplayWidth = DisplayWidth(dpy, Scr.screen); + Scr.MyDisplayHeight = DisplayHeight(dpy, Scr.screen); + + Scr.VxMax = 3*Scr.MyDisplayWidth - Scr.MyDisplayWidth; + Scr.VyMax = 3*Scr.MyDisplayHeight - Scr.MyDisplayHeight; + if(Scr.VxMax <0) + Scr.VxMax = 0; + if(Scr.VyMax <0) + Scr.VyMax = 0; + Scr.Vx = 0; + Scr.Vy = 0; + + fd = fopen(filename,"r"); + if(fd == (FILE *)0) + { + fprintf(stderr,"%s: can't open config file %s",MyName,filename); + exit(1); + } + + tline = fgets(line,(sizeof line)-1,fd); + orig_tline = tline; + Clength = strlen(MyName); + while(tline != (char *)0) + { + int g_x, g_y, flags; + unsigned width,height; + + while(isspace(*tline))tline++; + + if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline, CatString3("*", MyName, "Geometry"),Clength+9)==0)) + { + tmp = &tline[Clength+9]; + while(((isspace(*tmp))&&(*tmp != '\n'))&&(*tmp != 0)) + { + tmp++; + } + tmp[strlen(tmp)-1] = 0; + + flags = XParseGeometry(tmp,&g_x,&g_y,&width,&height); + if (flags & WidthValue) + window_w = width; + if (flags & HeightValue) + window_h = height; + if (flags & XValue) + { + window_x = g_x; + usposition = 1; + } + if (flags & YValue) + { + window_y = g_y; + usposition = 1; + } + } + else if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline, CatString3("*", MyName, "IconGeometry"), + Clength+13)==0)) + { + tmp = &tline[Clength+13]; + while(((isspace(*tmp))&&(*tmp != '\n'))&&(*tmp != 0)) + { + tmp++; + } + tmp[strlen(tmp)-1] = 0; + + flags = XParseGeometry(tmp,&g_x,&g_y,&width,&height); + if (flags & WidthValue) + icon_w = width; + if (flags & HeightValue) + icon_h = height; + if (flags & XValue) + { + icon_x = g_x; + } + if (flags & YValue) + { + icon_y = g_y; + } + } + else if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline,CatString3("*",MyName,"Label"),Clength+6)==0)) + { + desk = desk1; + sscanf(&tline[Clength+6],"%d",&desk); + if((desk >= desk1)&&(desk <=desk2)) + { + n = 0; + while(isspace(tline[Clength+6+n]))n++; + while(!isspace(tline[Clength+6+n]))n++; + free(Desks[desk - desk1].label); + CopyString(&Desks[desk - desk1].label,&tline[Clength+6+n]); + } + } + else if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline, CatString3("*", MyName, "Font"),Clength+5)==0)) + { + CopyString(&font_string,&tline[Clength+5]); + if(mystrncasecmp(font_string,"none",4) == 0) + uselabel = 0; + + } + else if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline, CatString3("*", MyName, "Fore"),Clength+5)==0)) + { + CopyString(&PagerFore,&tline[Clength+5]); + } + else if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline,CatString3("*", MyName, "Back"),Clength+5)==0)) + { + CopyString(&PagerBack,&tline[Clength+5]); + } + else if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline,CatString3("*",MyName,"Hilight"),Clength+8)==0)) + { + if(Scr.d_depth > 1) + CopyString(&HilightC,&tline[Clength+8]); + } + else if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline,CatString3("*",MyName,"SmallFont"), + Clength+10)==0)) + { + CopyString(&smallFont,&tline[Clength+10]); + } + else if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline,CatString3("*",MyName,"StartIconic"), + Clength+12)==0)) + { + StartIconic = 1; + } + else if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline,CatString3("*",MyName,"Rows"), + Clength+5)==0)) + { + sscanf(&tline[Clength+5],"%d",&Rows); + } + else if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline,CatString3("*",MyName,"Columns"), + Clength+8)==0)) + { + sscanf(&tline[Clength+8],"%d",&Columns); + } + else if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline,"HiBackColor",11)==0)) + { + if(Scr.d_depth > 1) + CopyString(&HiBack,&tline[11]); + } + else if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline,"HiForeColor",11)==0)) + { + if(Scr.d_depth > 1) + CopyString(&HiFore,&tline[11]); + } + else if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline,"StickyIcons",11)==0)) + { + StickyIcons = 1; + } + else if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline,"DeskTopSize",11)==0)) + { + sscanf(&tline[11],"%dx%d",&Scr.VxMax,&Scr.VyMax); + Scr.VxMax = Scr.VxMax*Scr.MyDisplayWidth - Scr.MyDisplayWidth; + Scr.VyMax = Scr.VyMax*Scr.MyDisplayHeight - Scr.MyDisplayHeight; + } + else if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline,"DeskTopScale",12)==0)) + { + sscanf(&tline[12],"%d",&Scr.VScale); + } + tline = fgets(line,(sizeof line)-1,fd); + orig_tline = tline; + } + return; +} + + + diff --git a/modules/FvwmPager/FvwmPager.h b/modules/FvwmPager/FvwmPager.h new file mode 100644 index 0000000..12c47ce --- /dev/null +++ b/modules/FvwmPager/FvwmPager.h @@ -0,0 +1,141 @@ +typedef struct ScreenInfo +{ + unsigned long screen; + int d_depth; /* copy of DefaultDepth(dpy, screen) */ + int MyDisplayWidth; /* my copy of DisplayWidth(dpy, screen) */ + int MyDisplayHeight; /* my copy of DisplayHeight(dpy, screen) */ + + char *FvwmRoot; /* the head of the fvwm window list */ + Window Root; /* the root window */ + + Window Pager_w; + + Font PagerFont; /* font struct for window labels in pager (optional)*/ + + GC NormalGC; /* normal GC for menus, pager, resize window */ + + char *Hilite; /* the fvwm window that is highlighted + * except for networking delays, this is the + * window which REALLY has the focus */ + unsigned VScale; /* Panner scale factor */ + int VxMax; /* Max location for top left of virt desk*/ + int VyMax; + int Vx; /* Current loc for top left of virt desk */ + int Vy; + int CurrentDesk; + Pixmap sticky_gray_pixmap; + Pixmap light_gray_pixmap; + Pixmap gray_pixmap; + +} ScreenInfo; + +typedef struct pager_window +{ + char *t; + Window w; + Window frame; + int x; + int y; + int width; + int height; + int desk; + int frame_x; + int frame_y; + int frame_width; + int frame_height; + int title_height; + int border_width; + int icon_x; + int icon_y; + int icon_width; + int icon_height; + Pixel text; + Pixel back; + unsigned long flags; + Window icon_w; + Window icon_pixmap_w; + char *icon_name; + + Window PagerView; + Window IconView; + + struct pager_window *next; +} PagerWindow; + + +typedef struct desk_info +{ + Window w; + Window title_w; + Window CPagerWin; + int x; + int y; + char *label; +} DeskInfo; + +#define ON 1 +#define OFF 0 + +/************************************************************************* + * + * Subroutine Prototypes + * + *************************************************************************/ +void Loop(int *fd); +void SendInfo(int *fd,char *message,unsigned long window); +char *safemalloc(int length); +void DeadPipe(int nonsense); +void process_message(unsigned long type,unsigned long *body); +void ParseOptions(char *filename); + +void list_add(unsigned long *body); +void list_configure(unsigned long *body); +void list_destroy(unsigned long *body); +void list_focus(unsigned long *body); +void list_toggle(unsigned long *body); +void list_new_page(unsigned long *body); +void list_new_desk(unsigned long *body); +void list_raise(unsigned long *body); +void list_lower(unsigned long *body); +void list_unknown(unsigned long *body); +void list_iconify(unsigned long *body); +void list_deiconify(unsigned long *body); +void list_window_name(unsigned long *body); +void list_icon_name(unsigned long *body); +void list_class(unsigned long *body); +void list_res_name(unsigned long *body); +void list_end(void); +int My_XNextEvent(Display *dpy, XEvent *event); + +/* Stuff in x_pager.c */ +void initialize_pager(void); +Pixel GetColor(char *name); +void nocolor(char *a, char *b); +void DispatchEvent(XEvent *Event); +void ReConfigure(void); +void ReConfigureAll(void); +void MovePage(void); +void DrawGrid(int i,int erase); +void DrawIconGrid(int erase); +void SwitchToDesk(int Desk); +void SwitchToDeskAndPage(int Desk, XEvent *Event); +void AddNewWindow(PagerWindow *prev); +void MoveResizePagerView(PagerWindow *t); +void ChangeDeskForWindow(PagerWindow *t,long newdesk); +void MoveStickyWindow(void); +void Hilight(PagerWindow *, int); +void Scroll(int Desk, int x, int y); +void MoveWindow(XEvent *Event); +void LabelWindow(PagerWindow *t); +void LabelIconWindow(PagerWindow *t); +void ReConfigureIcons(void); +void IconSwitchPage(XEvent *Event); +void IconScroll(int x, int y); +void IconMoveWindow(XEvent *Event,PagerWindow *t); +void HandleExpose(XEvent *Event); +void MoveStickyWindows(void); +#ifdef BROKEN_SUN_HEADERS +#include "../../fvwm/sun_headers.h" +#endif + + diff --git a/modules/FvwmPager/FvwmPager.man b/modules/FvwmPager/FvwmPager.man new file mode 100644 index 0000000..3859322 --- /dev/null +++ b/modules/FvwmPager/FvwmPager.man @@ -0,0 +1,171 @@ +.\" t +.\" @(#)FvwmPager.1 1/12/94 +.TH FvwmPager 1.20 "Mar 16 1994" +.UC +.SH NAME +FvwmPager \- the FVWM Pager module +.SH SYNOPSIS +FvwmPager is spawned by fvwm, so no command line invocation will work. +From within the .fvwmrc file, FvwmPager is spawned as follows: +.nf +.sp +Module FvwmPager 0 3 +.sp +.fi +or from within an fvwm pop-up menu: +.nf +.sp +Popup "Module-Popup" + Title "Modules" + Module "GoodStuff" GoodStuff + Module "NoClutter" FvwmClean + Module "FvwmIdentify" FvwmIdent + Module "Banner" FvwmBanner + Module "Debug" FvwmDebug + Module "SaveDesktop" FvwmSave + Module "Pager" FvwmPager 0 3 +EndPopup +.sp +.fi +where "0" is the first desktop to show, and "3" is the last. + +.SH DESCRIPTION +The FvwmPager module shows a miniature view of the Fvwm desktops which +are specified in the command line. This is a useful reminder of where +your active windows are. Windows in the pager are shown in the same +color as their fvwm decorations. + +The pager can be used to change your viewport into the current +desktop, to change desktops, or to move windows around. + +Pressing mouse button 1 in the pager will cause you viewport to +change to the selected page of the selected desk. If you click with +button 1 in the desk-label area, you will switch desks but not +pages within the desk. + +Dragging mouse button 2 on a miniature view of a window will cause +that window to be move to the location where you release the mouse +button, but your viewport will not change. If you drag the window +out of the pager and onto your desktop, a full size image of +the window will appear for you to place. There is no way to +pick up a full size image of the window and move it into the pager, +however. Since some mice do not have button 2, I have made provisions to drag +windows in the pager by using pressing modifier-1 (usually Alt) and dragging +with button 3. + +Clicking mouse button 3 on a location within the current desktop will +cause the viewport to move to the selected location, but will not +align the viewport to a page boundary. Dragging button 3 will +cause the viewport to move as you drag. Button 3 operations are +limited to the current desktop only. + +When iconified, the pager will work as a fully functional current page +only pager. Windows and viewports can be moved within the icon of the +pager. Users will want to make sure that they have no lines similar to +.nf +.sp +Icon "Fvwm Pager" whatever +.sp +.fi +in their .fvwmrc files. + + +.SH COPYRIGHTS +The FvwmClean program, and the concept for +interfacing this module to the Window Manager, are all original work +by Robert Nation. + +Copyright 1994, Robert Nation. No guarantees or warranties or anything +are provided or implied in any way whatsoever. Use this program at your +own risk. Permission to use this program for any purpose is given, +as long as the copyright is kept intact. + + +.SH INITIALIZATION +During initialization, \fIFvwmPager\fP will eventually search a +configuration file which describes the time-outs and actions to take. +The configuration file is the same file that fvwm used during initialization. + +If the FvwmPager executable is linked to another name, ie ln -s +FvwmPager OtherPager, then another module called OtherPager can be +started, with a completely different configuration than FvwmPager, +simply by changing the keyword FvwmPager to OtherPager. This way multiple +pager programs can be used. + +.SH KEYBOARD FOCUS CONTROL +You can direct the keyboard focus to any window on the current desktop +by clicking with button 2 on its image in the pager. The window does +not need to be visible, but it does need to be on the current page. + +.SH INVOCATION +The invocation method was shown in the synopsis section + +.SH CONFIGURATION OPTIONS +FvwmPager reads the same .fvwmrc file as fvwm reads when it starts up, +and looks for certain configuration options: + +.IP "*FvwmPagerGeometry \fIgeometry\fP" +Completely or partially specifies the pager windows location and +geometry, in standard X11 notation. +In order to maintain an undistorted aspect ratio, you might +want to leave out either the width or height dimension of the +geometry specification + +.IP "*FvwmPagerRows \fIrows\fP" +Tells fvwm how many rows of desks to use when laying out the pager +window. + +.IP "*FvwmPagerColumns \fIcolumns\fP" +Tells fvwm how many columnss of desks to use when laying out the pager +window. + +.IP "*FvwmPagerIconGeometry \fIgeometry\fP" +Specifies a size (optional) and location (optional) for the pager's icon +window. Since there is no easy way for FvwmPager to determine the height of the +icon's label, you will have to make an allowance for the icon label height +when using negative y-coordinates in the icon location specification (used to +specify a location relative to the bottom instead of the top of the screen). + +.IP "*FvwmPagerStartIconic" +Causes the pager to start iconified. + +.IP "*FvwmPagerFont \fIfont-name\fP" +Specified a font to use to label the desktops. If \fIfont_name\fP is +"none" then no desktop labels will be displayed. + +.IP "*FvwmPagerSmallFont \fIfont-name\fP" +Specified a font to use to label the window names in the pager. If not +specified, the window labels will be omitted. Window labels seem to +be fairly useless for desktop scales of 32 or greater. + +.IP "*FvwmPagerFore \fIcolor\fP" +Specifies the color to use to write the desktop labels, and +to draw the page-grid lines. + +.IP "*FvwmPagerBack \fIcolor\fP" +Specifies the background color for the window. + +.IP "*FvwmPagerHilight \fIcolor\fP" +The active page and desk label will be highlighted by using this +background pattern instead of the normal background. + +.IP "*FvwmPagerLabel \fIdesk label\fP" +Assigns the text \fIlabel\fP to desk \fIdesk\fP in the pager window. +Useful for assigning symbolic names to desktops, ie +.nf +.sp +*FvwmPagerLabel 1 Mail +*FvwmPagerLabel 2 Maker +*FvwmPagerLabel 2 Matlab +.sp +.fi + +.IP "DeskTopScale \fInumber\fP" +If the geometry is not specified, then a desktop reduction factor is +used to calculate the pager's size. Things in the pager window +are shown at 1/\fInumber\fP of the actual size. + + +.SH AUTHOR +Robert Nation + diff --git a/modules/FvwmPager/Imakefile b/modules/FvwmPager/Imakefile new file mode 100644 index 0000000..3490954 --- /dev/null +++ b/modules/FvwmPager/Imakefile @@ -0,0 +1,31 @@ +/* Imakefile for FvwmPager */ +/* Thu Aug 5 11:21:36 MET DST 1993, mj@dfv.rwth-aachen.de */ + +/* setup is done entirely in configuration.h now! */ +/* You should need to do much in here, excpt maybe add libraries */ + +/* I need to get the #define XPM from configuration.h if its in there,*/ +/* so that I can tell if I should include -lXpm */ + +#include <../../configure.h> + +COMPILER + +DEPLIBS = $(DEPXLIB) ../../libs/libfvwmlib.a + +#ifdef AlphaArchitecture +LOCAL_LIBRARIES = $(XLIB) -ldnet_stub -L../../libs -lfvwmlib +#else +LOCAL_LIBRARIES = $(XLIB) -L../../libs -lfvwmlib +#endif + +LINTLIBS = $(LINTXLIB) + +SRCS = FvwmPager.c x_pager.c +OBJS = FvwmPager.o x_pager.o + +TARGET_DIR + +ComplexProgramTarget(FvwmPager) + + diff --git a/modules/FvwmPager/x_pager.c b/modules/FvwmPager/x_pager.c new file mode 100644 index 0000000..cb9fe6a --- /dev/null +++ b/modules/FvwmPager/x_pager.c @@ -0,0 +1,1626 @@ +/**************************************************************************** + * This module is all new + * by Rob Nation + ****************************************************************************/ +/*********************************************************************** + * + * fvwm pager handling code + * + ***********************************************************************/ + +#include "../../configure.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "../../fvwm/fvwm.h" +#include "FvwmPager.h" +extern ScreenInfo Scr; +extern Display *dpy; + +Pixel back_pix, fore_pix, hi_pix; +Pixel focus_pix; +Pixel focus_fore_pix; +extern int window_w, window_h,window_x,window_y,usposition,uselabel; +extern int StartIconic; +extern int icon_w, icon_h, icon_x, icon_y; +XFontStruct *font, *windowFont; + +GC NormalGC,HiliteGC,rvGC; +GC StdGC, FocusGC; + +extern int StickyIcons; +extern PagerWindow *Start; +extern PagerWindow *FocusWin; +static Atom wm_del_win; + +extern char *MyName; + +extern int desk1, desk2, ndesks; +extern int Rows,Columns; +extern int fd[2]; + +int desk_w = 0; +int desk_h = 0; +int label_h = 0; + +DeskInfo *Desks; +int Wait = 0; +XErrorHandler FvwmErrorHandler(Display *, XErrorEvent *); + + +/* assorted gray bitmaps for decorative borders */ +#define g_width 2 +#define g_height 2 +static char g_bits[] = {0x02, 0x01}; + +#define l_g_width 4 +#define l_g_height 2 +static char l_g_bits[] = {0x08, 0x02}; + +#define s_g_width 4 +#define s_g_height 4 +static char s_g_bits[] = {0x01, 0x02, 0x04, 0x08}; + + +Window icon_win; /* icon window */ + +/*********************************************************************** + * + * Procedure: + * Initialize_pager - creates the pager window, if needed + * + * Inputs: + * x,y location of the window + * + ***********************************************************************/ +char *pager_name = "Fvwm Pager"; +XSizeHints sizehints = +{ + (PMinSize | PResizeInc | PBaseSize | PWinGravity), + 0, 0, 100, 100, /* x, y, width and height */ + 1, 1, /* Min width and height */ + 0, 0, /* Max width and height */ + 1, 1, /* Width and height increments */ + {0, 0}, {0, 0}, /* Aspect ratio - not used */ + 1, 1, /* base size */ + (NorthWestGravity) /* gravity */ +}; + +void initialize_pager(void) +{ + XTextProperty name; + unsigned long valuemask; + XSetWindowAttributes attributes; + XWMHints wmhints; + extern char *PagerFore, *PagerBack, *HilightC; + extern char *font_string, *smallFont; + extern char *HiBack; + extern char *HiFore; + int n,m,w,h,i,x,y; + XGCValues gcv; + unsigned long gcm; + XClassHint class1; + + XSetErrorHandler((XErrorHandler)FvwmErrorHandler); + wm_del_win = XInternAtom(dpy,"WM_DELETE_WINDOW",False); + + n = Scr.VxMax/Scr.MyDisplayWidth; + m = Scr.VyMax/Scr.MyDisplayHeight; + + /* load the font */ + if ((font = XLoadQueryFont(dpy, font_string)) == NULL) + { + if ((font = XLoadQueryFont(dpy, "fixed")) == NULL) + { + fprintf(stderr,"%s: No fonts available\n",MyName); + exit(1); + } + }; + if(uselabel) + label_h = font->ascent + font->descent+2; + else + label_h = 0; + + + if(smallFont!= NULL) + { + windowFont= XLoadQueryFont(dpy, smallFont); + } + else + windowFont= NULL; + + /* Load the colors */ + fore_pix = GetColor(PagerFore); + back_pix = GetColor(PagerBack); + focus_pix = GetColor(HiBack); + + focus_fore_pix = GetColor(HiFore); + hi_pix = GetColor(HilightC); + + /* Load pixmaps for mono use */ + if(Scr.d_depth<2) + { + Scr.gray_pixmap = + XCreatePixmapFromBitmapData(dpy,Scr.Root,g_bits, g_width,g_height, + fore_pix,back_pix,Scr.d_depth); + Scr.light_gray_pixmap = + XCreatePixmapFromBitmapData(dpy,Scr.Root,l_g_bits,l_g_width,l_g_height, + fore_pix,back_pix,Scr.d_depth); + Scr.sticky_gray_pixmap = + XCreatePixmapFromBitmapData(dpy,Scr.Root,s_g_bits,s_g_width,s_g_height, + fore_pix,back_pix,Scr.d_depth); + } + + + /* Size the window */ + if(Rows < 0) + { + if(Columns < 0) + { + Columns = ndesks; + Rows = 1; + } + else + { + Rows = ndesks/Columns; + if(Rows*Columns < ndesks) + Rows++; + } + } + if(Columns < 0) + { + Columns = ndesks/Rows; + if(Rows*Columns < ndesks) + Columns++; + } + + if(Rows*Columns < ndesks) + Rows = ndesks/Columns; + if(window_w > 0) + { + window_w = ((window_w - n)/(n+1))*(n+1)+n; + Scr.VScale = (Scr.VxMax + Scr.MyDisplayWidth)/window_w; + } + if(window_h > 0) + { + window_h = ((window_h - m)/(m+1))*(m+1)+m; + Scr.VScale = (Scr.VyMax + Scr.MyDisplayHeight)/(window_h- label_h); + } + if(window_w <= 0) + window_w = Columns*((Scr.VxMax + Scr.MyDisplayWidth)/Scr.VScale + n) + + Columns-1; + if(window_h <= 0) + window_h = Rows*((Scr.VyMax + Scr.MyDisplayHeight)/Scr.VScale + + m + label_h + 1)-2; + + if(window_x < 0) + { + sizehints.win_gravity = NorthEastGravity; + window_x = Scr.MyDisplayWidth - window_w + window_x -2; + } + + if(window_y < 0) + { + window_y = Scr.MyDisplayHeight - window_h + window_y -2; + if(sizehints.win_gravity == NorthEastGravity) + sizehints.win_gravity = SouthEastGravity; + else + sizehints.win_gravity = SouthWestGravity; + } + + if(usposition) + sizehints.flags |= USPosition; + + valuemask = (CWBackPixel | CWBorderPixel | CWEventMask); + attributes.background_pixel = back_pix; + attributes.border_pixel = fore_pix; + attributes.event_mask = (StructureNotifyMask); + sizehints.width = window_w; + sizehints.height = window_h; + sizehints.x = window_x; + sizehints.y = window_y; + sizehints.width_inc = Columns*(n+1); + sizehints.height_inc = Rows*(m+1); + sizehints.base_width = Columns * n + Columns - 1; + sizehints.base_height = Rows*(m + label_h+1) -2; + sizehints.min_width = Columns * n + Columns - 1; + sizehints.min_height = Rows*(m + label_h+1) -2; + + Scr.Pager_w = XCreateWindow (dpy, Scr.Root, window_x, window_y, window_w, + window_h, (unsigned int) 1, + CopyFromParent, InputOutput, + (Visual *) CopyFromParent, + valuemask, &attributes); + XSetWMProtocols(dpy,Scr.Pager_w,&wm_del_win,1); + XSetWMNormalHints(dpy,Scr.Pager_w,&sizehints); + + if((desk1==desk2)&&(Desks[0].label != NULL)) + XStringListToTextProperty(&Desks[0].label,1,&name); + else + XStringListToTextProperty(&pager_name,1,&name); + + attributes.event_mask = (StructureNotifyMask| ExposureMask); + if(icon_w < 1) + icon_w = (window_w - Columns+1)/Columns; + if(icon_h < 1) + icon_h = (window_h - Rows* label_h - Rows + 1)/Rows; + + icon_w = (icon_w / (n+1)) *(n+1)+n; + icon_h = (icon_h / (m+1)) *(m+1)+m; + icon_win = XCreateWindow (dpy, Scr.Root, window_x, window_y, + icon_w,icon_h, + (unsigned int) 1, + CopyFromParent, InputOutput, + (Visual *) CopyFromParent, + valuemask, &attributes); + XGrabButton(dpy, 1, AnyModifier, icon_win, + True, ButtonPressMask | ButtonReleaseMask|ButtonMotionMask, + GrabModeAsync, GrabModeAsync, None, + None); + XGrabButton(dpy, 2, AnyModifier, icon_win, + True, ButtonPressMask | ButtonReleaseMask|ButtonMotionMask, + GrabModeAsync, GrabModeAsync, None, + None); + XGrabButton(dpy, 3, AnyModifier, icon_win, + True, ButtonPressMask | ButtonReleaseMask|ButtonMotionMask, + GrabModeAsync, GrabModeAsync, None, + None); + if(!StartIconic) + wmhints.initial_state = NormalState; + else + wmhints.initial_state = IconicState; + wmhints.flags = 0; + if(icon_x > -10000) + { + if(icon_x < 0) + icon_x = Scr.MyDisplayWidth + icon_x - icon_w; + if(icon_y > -10000) + { + if(icon_y < 0) + icon_y = Scr.MyDisplayHeight + icon_y - icon_h; + } + else + icon_y = 0; + wmhints.icon_x = icon_x; + wmhints.icon_y = icon_y; + wmhints.flags = IconPositionHint; + } + wmhints.icon_window = icon_win; + wmhints.input = False; + + wmhints.flags |= InputHint | StateHint | IconWindowHint; + + class1.res_name = MyName; + class1.res_class = "FvwmModule"; + + XSetWMProperties(dpy,Scr.Pager_w,&name,&name,NULL,0, + &sizehints,&wmhints,&class1); + XFree((char *)name.value); + + for(i=0;ifid; + NormalGC = XCreateGC(dpy, Scr.Root, gcm, &gcv); + + gcv.foreground = hi_pix; + if(Scr.d_depth < 2) + { + gcv.foreground = fore_pix; + gcv.background = back_pix; + } + HiliteGC = XCreateGC(dpy, Scr.Root, gcm, &gcv); + + if((Scr.d_depth < 2)||(fore_pix == hi_pix)) + gcv.foreground = back_pix; + else + gcv.foreground = fore_pix; + rvGC = XCreateGC(dpy, Scr.Root, gcm, &gcv); + + if(windowFont != NULL) + { + /* Create GC's for doing window labels */ + gcv.foreground = focus_fore_pix; + gcv.background = focus_pix; + gcv.font = windowFont->fid; + StdGC = XCreateGC(dpy, Scr.Root, gcm, &gcv); + + gcv.foreground = focus_fore_pix; + gcv.background = focus_pix; + FocusGC = XCreateGC(dpy, Scr.Root, gcm, &gcv); + } +} + + + +/**************************************************************************** + * + * 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 *a, char *b) +{ + fprintf(stderr,"%s: can't %s %s\n", MyName, a,b); +} + +/**************************************************************************** + * + * Decide what to do about received X events + * + ****************************************************************************/ +void DispatchEvent(XEvent *Event) +{ + int i,x,y; + Window JunkRoot, JunkChild; + int JunkX, JunkY; + unsigned JunkMask; + + switch(Event->xany.type) + { + case ConfigureNotify: + ReConfigure(); + break; + case Expose: + HandleExpose(Event); + break; + case ButtonRelease: + if((Event->xbutton.button == 1)|| + (Event->xbutton.button == 2)) + { + for(i=0;ixany.window == Desks[i].w) + SwitchToDeskAndPage(i,Event); + if(Event->xany.window == Desks[i].title_w) + SwitchToDesk(i); + } + if(Event->xany.window == icon_win) + { + IconSwitchPage(Event); + } + } + else if (Event->xbutton.button == 3) + { + for(i=0;ixany.window == Desks[i].w) + { + XQueryPointer(dpy, Desks[i].w, &JunkRoot, &JunkChild, + &JunkX, &JunkY,&x, &y, &JunkMask); + Scroll(i,x,y); + } + } + if(Event->xany.window == icon_win) + { + XQueryPointer(dpy, icon_win, &JunkRoot, &JunkChild, + &JunkX, &JunkY,&x, &y, &JunkMask); + IconScroll(x,y); + } + } + break; + case ButtonPress: + if (((Event->xbutton.button == 2)|| + ((Event->xbutton.button == 3)&& + (Event->xbutton.state & Mod1Mask)))&& + (Event->xbutton.subwindow != None)) + { + MoveWindow(Event); + } + else if (Event->xbutton.button == 3) + { + for(i=0;ixany.window == Desks[i].w) + { + XQueryPointer(dpy, Desks[i].w, &JunkRoot, &JunkChild, + &JunkX, &JunkY,&x, &y, &JunkMask); + Scroll(i,x,y); + } + } + if(Event->xany.window == icon_win) + { + XQueryPointer(dpy, icon_win, &JunkRoot, &JunkChild, + &JunkX, &JunkY,&x, &y, &JunkMask); + IconScroll(x,y); + } + } + break; + case MotionNotify: + while(XCheckMaskEvent(dpy, PointerMotionMask | ButtonMotionMask,Event)); + + if(Event->xmotion.state == Button3MotionMask) + { + for(i=0;ixany.window == Desks[i].w) + { + XQueryPointer(dpy, Desks[i].w, &JunkRoot, &JunkChild, + &JunkX, &JunkY,&x, &y, &JunkMask); + Scroll(i,x,y); + } + } + if(Event->xany.window == icon_win) + { + XQueryPointer(dpy, icon_win, &JunkRoot, &JunkChild, + &JunkX, &JunkY,&x, &y, &JunkMask); + IconScroll(x,y); + } + + } + break; + + case ClientMessage: + if ((Event->xclient.format==32) && + (Event->xclient.data.l[0]==wm_del_win)) + { + exit(0); + } + break; + } +} + +void HandleExpose(XEvent *Event) +{ + int i; + PagerWindow *t; + + for(i=0;ixany.window == Desks[i].w) + ||(Event->xany.window == Desks[i].title_w)) + DrawGrid(i,0); + } + if(Event->xany.window == icon_win) + DrawIconGrid(0); + + t = Start; + while(t!= NULL) + { + if(t->PagerView == Event->xany.window) + { + LabelWindow(t); + } + else if(t->IconView == Event->xany.window) + { + LabelIconWindow(t); + } + + t = t->next; + } +} + + +/**************************************************************************** + * + * Respond to a change in window geometry. + * + ****************************************************************************/ +void ReConfigure(void) +{ + Window root; + unsigned border_width, depth; + int n,m,w,h,n1,m1,x,y,i,j,k; + + + XGetGeometry(dpy,Scr.Pager_w,&root,&x,&y, + (unsigned *)&window_w,(unsigned *)&window_h, + &border_width,&depth); + + n1 = Scr.Vx/Scr.MyDisplayWidth; + m1 = Scr.Vy/Scr.MyDisplayHeight; + n = (Scr.VxMax)/Scr.MyDisplayWidth; + m = (Scr.VyMax)/Scr.MyDisplayHeight; + desk_w = (window_w - Columns + 1)/Columns; + desk_h = (window_h - Rows*label_h - Rows + 2)/Rows; + w = (desk_w - n)/(n+1); + h = (desk_h - m)/(m+1); + + x = (desk_w-n)* Scr.Vx/(Scr.VxMax+Scr.MyDisplayWidth) +n1; + y = (desk_h-m)*Scr.Vy/(Scr.VyMax+Scr.MyDisplayHeight) +m1; + + for(k=0;k= desk1)&&(Scr.CurrentDesk <=desk2)) + sptr = Desks[Scr.CurrentDesk -desk1].label; + else + { + sprintf(str,"Desk %d",Scr.CurrentDesk); + sptr = &str[0]; + } + if (XStringListToTextProperty(&sptr,1,&name) == 0) + { + fprintf(stderr,"%s: cannot allocate window name",MyName); + return; + } + XSetWMIconName(dpy,Scr.Pager_w,&name); + } +} + +void ReConfigureAll(void) +{ + PagerWindow *t; + + t = Start; + while(t!= NULL) + { + MoveResizePagerView(t); + t = t->next; + } +} + +void ReConfigureIcons(void) +{ + PagerWindow *t; + int x,y,w,h,n,m,n1,m1; + + n = (Scr.VxMax)/Scr.MyDisplayWidth; + m = (Scr.VyMax)/Scr.MyDisplayHeight; + + t = Start; + while(t!= NULL) + { + n1 = (Scr.Vx+t->x)/Scr.MyDisplayWidth; + m1 = (Scr.Vy+t->y)/Scr.MyDisplayHeight; + x = (Scr.Vx + t->x)*(icon_w-n)/(Scr.VxMax + Scr.MyDisplayWidth) +n1; + y = (Scr.Vy + t->y)*(icon_h-m)/(Scr.VyMax + Scr.MyDisplayHeight)+m1; + w = (Scr.Vx + t->x + t->width+2)*(icon_w-n)/ + (Scr.VxMax + Scr.MyDisplayWidth) - 2 - x + n1; + h = (Scr.Vy + t->y + t->height+2)*(icon_h-m)/ + (Scr.VyMax + Scr.MyDisplayHeight) -2 - y +m1; + + if (w < 1) + w = 1; + if (h < 1) + h = 1; + + if(Scr.CurrentDesk == t->desk) + XMoveResizeWindow(dpy,t->IconView,x,y,w,h); + else + XMoveResizeWindow(dpy,t->IconView,-1000,-1000,w,h); + t = t->next; + } +} + +/**************************************************************************** + * + * Draw grid lines for desk #i + * + ****************************************************************************/ +void DrawGrid(int i, int erase) +{ + int y, y1, y2, x, x1, x2,d,hor_off,w; + int MaxW,MaxH; + char str[15], *ptr; + + if((i < 0 ) ||(i >= ndesks)) + return; + + MaxW = (Scr.VxMax + Scr.MyDisplayWidth); + MaxH = Scr.VyMax + Scr.MyDisplayHeight; + + x = Scr.MyDisplayWidth; + y1 = 0; + y2 = desk_h; + while(x < MaxW) + { + x1 = x*desk_w/MaxW; + XDrawLine(dpy,Desks[i].w,NormalGC,x1,y1,x1,y2); + x += Scr.MyDisplayWidth; + } + + y = Scr.MyDisplayHeight; + x1 = 0; + x2 = desk_w; + while(y < MaxH) + { + y1 = y*(desk_h)/MaxH; + XDrawLine(dpy,Desks[i].w,NormalGC,x1,y1,x2,y1); + y += Scr.MyDisplayHeight; + } + if((Scr.CurrentDesk - desk1) == i) + { + if(uselabel) + XFillRectangle(dpy,Desks[i].title_w,HiliteGC, + 0,0,desk_w,label_h -1); + } + else + { + if(uselabel && erase) + XClearArea(dpy,Desks[i].title_w, + 0,0,desk_w,label_h - 1,False); + } + + d = desk1+i; + ptr = Desks[i].label; + w=XTextWidth(font,ptr,strlen(ptr)); + if( w > desk_w) + { + sprintf(str,"%d",d); + ptr = str; + w=XTextWidth(font,ptr,strlen(ptr)); + } + if((w<= desk_w)&&(uselabel)) + { + hor_off = (desk_w -w)/2; + if(i == (Scr.CurrentDesk - desk1)) + XDrawString (dpy, Desks[i].title_w,rvGC,hor_off,font->ascent +1 , + ptr, strlen(ptr)); + else + XDrawString (dpy, Desks[i].title_w,NormalGC,hor_off,font->ascent+1 , + ptr, strlen(ptr)); + } +} + + +void DrawIconGrid(int erase) +{ + int y, y1, y2, x, x1, x2,w,h,n,m,n1,m1; + int MaxW,MaxH; + + MaxW = (Scr.VxMax + Scr.MyDisplayWidth); + MaxH = Scr.VyMax + Scr.MyDisplayHeight; + + if(erase) + XClearWindow(dpy,icon_win); + x = Scr.MyDisplayWidth; + y1 = 0; + y2 = icon_h; + while(x < MaxW) + { + x1 = x*icon_w/MaxW; + XDrawLine(dpy,icon_win,NormalGC,x1,y1,x1,y2); + x += Scr.MyDisplayWidth; + } + + y = Scr.MyDisplayHeight; + x1 = 0; + x2 = icon_w; + while(y < MaxH) + { + y1 = y*(icon_h)/MaxH; + XDrawLine(dpy,icon_win,NormalGC,x1,y1,x2,y1); + y += Scr.MyDisplayHeight; + } + n1 = Scr.Vx/Scr.MyDisplayWidth; + m1 = Scr.Vy/Scr.MyDisplayHeight; + n = (Scr.VxMax)/Scr.MyDisplayWidth; + m = (Scr.VyMax)/Scr.MyDisplayHeight; + w = (icon_w - n)/(n+1); + h = (icon_h - m)/(m+1); + + x = (icon_w-n)* Scr.Vx/(Scr.VxMax+Scr.MyDisplayWidth) +n1; + y = (icon_h-m)*Scr.Vy/(Scr.VyMax+Scr.MyDisplayHeight) +m1; + + XFillRectangle(dpy,icon_win,HiliteGC, + x,y,w,h); + +} + + +void SwitchToDesk(int Desk) +{ + char command[256]; + + sprintf(command,"Desk 0 %d\n",Desk+desk1); + + SendInfo(fd,command,0); +} + + +void SwitchToDeskAndPage(int Desk, XEvent *Event) +{ + char command[256]; + + SendInfo(fd,"Desk 0 10000\n",0); +#ifndef NON_VIRTUAL + sprintf(command,"GotoPage %d %d\n", + Event->xbutton.x*(Scr.VxMax+Scr.MyDisplayWidth)/ + (desk_w*Scr.MyDisplayWidth), + Event->xbutton.y*(Scr.VyMax+Scr.MyDisplayHeight)/ + (desk_h*Scr.MyDisplayHeight)); + SendInfo(fd,command,0); + + sprintf(command,"Desk 0 %d\n",Desk+desk1); + SendInfo(fd,command,0); + +#endif + Wait = 1; +} + +void IconSwitchPage(XEvent *Event) +{ + char command[256]; + +#ifndef NON_VIRTUAL + sprintf(command,"GotoPage %d %d\n", + Event->xbutton.x*(Scr.VxMax+Scr.MyDisplayWidth)/ + (icon_w*Scr.MyDisplayWidth), + Event->xbutton.y*(Scr.VyMax+Scr.MyDisplayHeight)/ + (icon_h*Scr.MyDisplayHeight)); + SendInfo(fd,command,0); +#endif + Wait = 1; +} + + +void AddNewWindow(PagerWindow *t) +{ + unsigned long valuemask; + XSetWindowAttributes attributes; + int i,x,y,w,h,n,m,n1,m1; + + i = t->desk - desk1; + n = (Scr.VxMax)/Scr.MyDisplayWidth; + m = (Scr.VyMax)/Scr.MyDisplayHeight; + n1 = (Scr.Vx+t->x)/Scr.MyDisplayWidth; + m1 = (Scr.Vy+t->y)/Scr.MyDisplayHeight; + x = (Scr.Vx + t->x)*(desk_w-n)/(Scr.VxMax + Scr.MyDisplayWidth) +n1; + y = (Scr.Vy + t->y)*(desk_h-m)/(Scr.VyMax + Scr.MyDisplayHeight)+m1; + w = (Scr.Vx + t->x + t->width+2)*(desk_w-n)/ + (Scr.VxMax + Scr.MyDisplayWidth) - 2 - x + n1; + h = (Scr.Vy + t->y + t->height+2)*(desk_h-m)/ + (Scr.VyMax + Scr.MyDisplayHeight) -2 - y +m1; + if(w<1) + w = 1; + if(h<1) + h = 1; + + valuemask = (CWBackPixel | CWBorderPixel | CWEventMask); + attributes.background_pixel = t->back; + attributes.border_pixel = fore_pix; + attributes.event_mask = (ExposureMask); + + if((i >= 0)&& (i PagerView = XCreateWindow(dpy,Desks[i].w, x, y, w, h,1, + CopyFromParent, + InputOutput,CopyFromParent, + valuemask,&attributes); + + XMapRaised(dpy,t->PagerView); + } + else + t->PagerView = None; + + + x = (Scr.Vx + t->x)*(icon_w-n)/(Scr.VxMax + Scr.MyDisplayWidth) +n1; + y = (Scr.Vy + t->y)*(icon_h-m)/(Scr.VyMax + Scr.MyDisplayHeight)+m1; + w = (Scr.Vx + t->x + t->width+2)*(icon_w-n)/ + (Scr.VxMax + Scr.MyDisplayWidth) - 2 - x + n1; + h = (Scr.Vy + t->y + t->height+2)*(icon_h-m)/ + (Scr.VyMax + Scr.MyDisplayHeight) -2 - y +m1; + if(w<1) + w = 1; + if(h<1) + h = 1; + + if(Scr.CurrentDesk == t->desk) + { + t->IconView = XCreateWindow(dpy,icon_win, x, y, w, h,1, + CopyFromParent, + InputOutput,CopyFromParent, + valuemask,&attributes); + XGrabButton(dpy, 2, AnyModifier, t->IconView, + True, ButtonPressMask | ButtonReleaseMask|ButtonMotionMask, + GrabModeAsync, GrabModeAsync, None, + None); + XMapRaised(dpy,t->IconView); + } + else + { + t->IconView = XCreateWindow(dpy,icon_win, -1000, -1000, w, h,1, + CopyFromParent, + InputOutput,CopyFromParent, + valuemask,&attributes); + XMapRaised(dpy,t->IconView); + } + Hilight(t,OFF); +} + + + +void ChangeDeskForWindow(PagerWindow *t,long newdesk) +{ + int i,x,y,w,h,n,m,n1,m1; + + i = newdesk - desk1; + + if(t->PagerView == None) + { + t->desk = newdesk; + XDestroyWindow(dpy,t->IconView); + AddNewWindow( t); + return; + } + + n = (Scr.VxMax)/Scr.MyDisplayWidth; + m = (Scr.VyMax)/Scr.MyDisplayHeight; + n1 = (Scr.Vx+t->x)/Scr.MyDisplayWidth; + m1 = (Scr.Vy+t->y)/Scr.MyDisplayHeight; + x = (Scr.Vx + t->x)*(desk_w-n)/(Scr.VxMax + Scr.MyDisplayWidth) +n1; + y = (Scr.Vy + t->y)*(desk_h-m)/(Scr.VyMax + Scr.MyDisplayHeight)+m1; + w = (Scr.Vx + t->x + t->width+2)*(desk_w-n)/(Scr.VxMax + Scr.MyDisplayWidth) - 2 - x + n1; + h = (Scr.Vy + t->y + t->height+2)*(desk_h-m)/(Scr.VyMax + Scr.MyDisplayHeight) -2 - y +m1; + if (w < 1) + w = 1; + if (h < 1) + h = 1; + if((i >= 0)&&(i < ndesks)) + { + XReparentWindow(dpy, t->PagerView, Desks[i].w, x,y); + XResizeWindow(dpy,t->PagerView,w,h); + } + else + { + XDestroyWindow(dpy,t->PagerView); + t->PagerView = None; + } + t->desk = i+desk1; + + x = (Scr.Vx + t->x)*(icon_w-n)/(Scr.VxMax + Scr.MyDisplayWidth) +n1; + y = (Scr.Vy + t->y)*(icon_h-m)/(Scr.VyMax + Scr.MyDisplayHeight)+m1; + w = (Scr.Vx + t->x + t->width+2)*(icon_w-n)/(Scr.VxMax + Scr.MyDisplayWidth) - 2 - x + n1; + h = (Scr.Vy + t->y + t->height+2)*(icon_h-m)/(Scr.VyMax + Scr.MyDisplayHeight) -2 - y +m1; + if (w < 1) + w = 1; + if (h < 1) + h = 1; + if(Scr.CurrentDesk == t->desk) + XMoveResizeWindow(dpy,t->IconView,x,y,w,h); + else + XMoveResizeWindow(dpy,t->IconView,-1000,-1000,w,h); +} + +void MoveResizePagerView(PagerWindow *t) +{ + int x,y,w,h,n,m,n1,m1; + + n = (Scr.VxMax)/Scr.MyDisplayWidth; + m = (Scr.VyMax)/Scr.MyDisplayHeight; + n1 = (Scr.Vx+t->x)/Scr.MyDisplayWidth; + m1 = (Scr.Vy+t->y)/Scr.MyDisplayHeight; + x = (Scr.Vx + t->x)*(desk_w-n)/(Scr.VxMax + Scr.MyDisplayWidth) +n1; + y = (Scr.Vy + t->y)*(desk_h-m)/(Scr.VyMax + Scr.MyDisplayHeight)+m1; + w = (Scr.Vx + t->x + t->width+2)*(desk_w-n)/ + (Scr.VxMax + Scr.MyDisplayWidth) - 2 - x + n1; + h = (Scr.Vy + t->y + t->height+2)*(desk_h-m)/ + (Scr.VyMax + Scr.MyDisplayHeight) -2 - y +m1; + + if (w < 1) + w = 1; + if (h < 1) + h = 1; + if(t->PagerView != None) + XMoveResizeWindow(dpy,t->PagerView,x,y,w,h); + else if((t->desk >= desk1)&&(t->desk <= desk2)) + { + XDestroyWindow(dpy,t->IconView); + AddNewWindow(t); + return; + } + + x = (Scr.Vx + t->x)*(icon_w-n)/(Scr.VxMax + Scr.MyDisplayWidth) +n1; + y = (Scr.Vy + t->y)*(icon_h-m)/(Scr.VyMax + Scr.MyDisplayHeight)+m1; + w = (Scr.Vx + t->x + t->width+2)*(icon_w-n)/ + (Scr.VxMax + Scr.MyDisplayWidth) - 2 - x + n1; + h = (Scr.Vy + t->y + t->height+2)*(icon_h-m)/ + (Scr.VyMax + Scr.MyDisplayHeight) -2 - y +m1; + + if (w < 1) + w = 1; + if (h < 1) + h = 1; + if(Scr.CurrentDesk == t->desk) + XMoveResizeWindow(dpy,t->IconView,x,y,w,h); + else + XMoveResizeWindow(dpy,t->IconView,-1000,-1000,w,h); +} + + +void MoveStickyWindows(void) +{ + PagerWindow *t; + + t = Start; + while(t!= NULL) + { + if(((t->flags & ICONIFIED)&&(StickyIcons))|| + (t->flags & STICKY)) + { + if(t->desk != Scr.CurrentDesk) + { + ChangeDeskForWindow(t,Scr.CurrentDesk); + } + else + { + MoveResizePagerView(t); + + } + } + t = t->next; + } +} + +void Hilight(PagerWindow *t, int on) +{ + + if(!t)return; + + if(Scr.d_depth < 2) + { + if(on) + { + if(t->PagerView != None) + XSetWindowBackgroundPixmap(dpy,t->PagerView,Scr.gray_pixmap); + XSetWindowBackgroundPixmap(dpy,t->IconView,Scr.gray_pixmap); + } + else + { + if(t->flags & STICKY) + { + if(t->PagerView != None) + XSetWindowBackgroundPixmap(dpy,t->PagerView, + Scr.sticky_gray_pixmap); + XSetWindowBackgroundPixmap(dpy,t->IconView, + Scr.sticky_gray_pixmap); + } + else + { + if(t->PagerView != None) + XSetWindowBackgroundPixmap(dpy,t->PagerView, + Scr.light_gray_pixmap); + XSetWindowBackgroundPixmap(dpy,t->IconView, + Scr.light_gray_pixmap); + } + } + } + else + { + if(on) + { + if(t->PagerView != None) + XSetWindowBackground(dpy,t->PagerView,focus_pix); + XSetWindowBackground(dpy,t->IconView,focus_pix); + } + else + { + if(t->PagerView != None) + XSetWindowBackground(dpy,t->PagerView,t->back); + XSetWindowBackground(dpy,t->IconView,t->back); + } + } + if(t->PagerView != None) + XClearWindow(dpy,t->PagerView); + XClearWindow(dpy,t->IconView); + LabelWindow(t); + LabelIconWindow(t); +} + +void Scroll(int Desk, int x, int y) +{ +#ifndef NON_VIRTUAL + char command[256]; + int sx, sy; + if(Wait == 0) + { + if(Desk != Scr.CurrentDesk) + { + return; + } + + if(x < 0) + x = 0; + if(y < 0) + y = 0; + + if(x > desk_w) + x = desk_w; + if(y > desk_h) + y = desk_h; + + sx = (100*(x*(Scr.VxMax+Scr.MyDisplayWidth)/desk_w- Scr.Vx))/Scr.MyDisplayWidth; + sy = (100*(y*(Scr.VyMax+Scr.MyDisplayHeight)/ + desk_h - Scr.Vy))/Scr.MyDisplayHeight; + if(sx > 100)sx = 100; + if(sx < -100)sx = -100; + if(sy < -100)sy = -100; + if(sy > 100)sy = 100; + + sprintf(command,"Scroll %d %d\n",sx,sy); + SendInfo(fd,command,0); + Wait = 1; + } +#endif +} + + +void IconScroll(int x, int y) +{ +#ifndef NON_VIRTUAL + char command[256]; + int sx, sy; + if(Wait == 0) + { + if(x < 0) + x = 0; + if(y < 0) + y = 0; + + if(x > icon_w) + x = icon_w; + if(y > icon_h) + y = icon_h; + + sx = (100*(x*(Scr.VxMax+Scr.MyDisplayWidth)/icon_w- Scr.Vx))/Scr.MyDisplayWidth; + sy = (100*(y*(Scr.VyMax+Scr.MyDisplayHeight)/ + icon_h - Scr.Vy))/Scr.MyDisplayHeight; + if(sx > 100)sx = 100; + if(sx < -100)sx = -100; + if(sy < -100)sy = -100; + if(sy > 100)sy = 100; + + sprintf(command,"Scroll %d %d\n",sx,sy); + SendInfo(fd,command,0); + Wait = 1; + } +#endif +} + + +void MoveWindow(XEvent *Event) +{ + char command[100]; + int x1,y1,finished = 0,wx,wy,n,x,y,xi=0,yi=0,wx1,wy1,x2,y2; + Window dumwin; + PagerWindow *t; + int m,n1,m1; + int NewDesk,KeepMoving = 0; + int moved = 0; + int row,column; + + t = Start; + while ((t != NULL)&&(t->PagerView != Event->xbutton.subwindow)) + t= t->next; + + if(t==NULL) + { + t = Start; + while ((t != NULL)&&(t->IconView != Event->xbutton.subwindow)) + t= t->next; + if(t!=NULL) + { + IconMoveWindow(Event,t); + return; + } + } + + if(t == NULL) + return; + + NewDesk = t->desk - desk1; + if((NewDesk < 0)||(NewDesk >= ndesks)) + return; + + n = (Scr.VxMax)/Scr.MyDisplayWidth; + m = (Scr.VyMax)/Scr.MyDisplayHeight; + n1 = (Scr.Vx+t->x)/Scr.MyDisplayWidth; + m1 = (Scr.Vy+t->y)/Scr.MyDisplayHeight; + wx = (Scr.Vx + t->x)*(desk_w-n)/(Scr.VxMax + Scr.MyDisplayWidth) +n1; + wy = (Scr.Vy + t->y)*(desk_h-m)/(Scr.VyMax + Scr.MyDisplayHeight)+m1; + wx1 = wx+(desk_w+1)*(NewDesk%Columns); + wy1 = wy + label_h + (desk_h+label_h+1)*(NewDesk/Columns); + + XReparentWindow(dpy, t->PagerView, Scr.Pager_w,wx1,wy1); + XRaiseWindow(dpy,t->PagerView); + + XTranslateCoordinates(dpy, Event->xany.window, t->PagerView, + Event->xbutton.x, Event->xbutton.y, &x1, &y1, &dumwin); + xi = x1; + yi = y1; + while(!finished) + { + XMaskEvent(dpy,ButtonReleaseMask | ButtonMotionMask|ExposureMask,Event); + + if(Event->type == MotionNotify) + { + XTranslateCoordinates(dpy, Event->xany.window, Scr.Pager_w, + Event->xmotion.x, Event->xmotion.y, &x, &y, + &dumwin); + if(moved == 0) + { + xi = x; + yi = y; + moved = 1; + } + if((x < -5)||(y<-5)||(x>window_w+5)||(y>window_h+5)) + { + KeepMoving = 1; + finished = 1; + } + XMoveWindow(dpy,t->PagerView, x - (x1), + y - (y1)); + } + else if(Event->type == ButtonRelease) + { + XTranslateCoordinates(dpy, Event->xany.window, Scr.Pager_w, + Event->xbutton.x, Event->xbutton.y, &x, &y, + &dumwin); + XMoveWindow(dpy,t->PagerView, x - (x1), + y - (y1)); + finished = 1; + } + else if (Event->type == Expose) + { + HandleExpose(Event); + } + } + + if(moved) + { + if((x - xi < 3)&&(y - yi < 3)&& + (x - xi > -3)&&(y -yi > -3)) + moved = 0; + } + if(KeepMoving) + { + NewDesk = Scr.CurrentDesk; + if(NewDesk != t->desk) + { + XMoveWindow(dpy,t->w,Scr.MyDisplayWidth+Scr.VxMax, + Scr.MyDisplayHeight+Scr.VyMax); + XSync(dpy,0); + sprintf(command,"WindowsDesk %d", NewDesk); + SendInfo(fd,command,t->w); + t->desk = NewDesk; + } + if((NewDesk>=desk1)&&(NewDesk<=desk2)) + XReparentWindow(dpy, t->PagerView, Desks[NewDesk-desk1].w,0,0); + else + { + XDestroyWindow(dpy,t->PagerView); + t->PagerView = None; + } + XTranslateCoordinates(dpy, Scr.Pager_w, Scr.Root, + x, y, &x1, &y1, &dumwin); + if(t->flags & ICONIFIED) + { + XUngrabPointer(dpy,CurrentTime); + XSync(dpy,0); + SendInfo(fd,"Move",t->icon_w); + } + else + { + XUngrabPointer(dpy,CurrentTime); + XSync(dpy,0); + SendInfo(fd,"Move",t->w); + } + return; + } + else + { + column = (x/(desk_w+1)); + row = (y/(desk_h+ label_h+1)); + NewDesk = column + (row)*Columns; + if((NewDesk <0)||(NewDesk >=ndesks)) + { + NewDesk = Scr.CurrentDesk - desk1; + x = xi; + y = yi; + moved = 0; + } + XTranslateCoordinates(dpy, Scr.Pager_w,Desks[NewDesk].w, + x-x1, y-y1, &x2,&y2,&dumwin); + + n1 = x2*(Scr.VxMax + Scr.MyDisplayWidth)/(desk_w * Scr.MyDisplayWidth); + m1 = y2*(Scr.VyMax + Scr.MyDisplayHeight)/(desk_h * Scr.MyDisplayHeight); + x = (x2-n1)* + (Scr.VxMax + Scr.MyDisplayWidth)/(desk_w-n) - Scr.Vx; + y = (y2-m1)* + (Scr.VyMax + Scr.MyDisplayHeight)/(desk_h-m) - Scr.Vy; + if(x + t->frame_width + Scr.Vx < 0 ) + x = -Scr.Vx; + if(y+t->frame_height + Scr.Vy< 0) + y = -Scr.Vy; + if(x + Scr.Vx > Scr.MyDisplayWidth+Scr.VxMax) + x = Scr.MyDisplayWidth + Scr.VxMax - t->frame_width - Scr.Vx; + if(y +Scr.Vy> Scr.MyDisplayHeight+Scr.VyMax) + y = Scr.MyDisplayHeight+ Scr.VyMax - t->frame_height - Scr.Vy; + if(((t->flags & ICONIFIED)&&(StickyIcons))|| + (t->flags & STICKY)) + { + NewDesk = Scr.CurrentDesk - desk1; + if(x > Scr.MyDisplayWidth -16) + x = Scr.MyDisplayWidth - 16; + if(y > Scr.MyDisplayHeight-16) + y = Scr.MyDisplayHeight - 16; + if(x + t->width < 16) + x = 16 - t->width; + if(y + t->height < 16) + y = 16 - t->height; + } + if(NewDesk +desk1 != t->desk) + { + if(((t->flags & ICONIFIED)&&(StickyIcons))|| + (t->flags & STICKY)) + { + NewDesk = Scr.CurrentDesk - desk1; + if(t->desk != Scr.CurrentDesk) + ChangeDeskForWindow(t,Scr.CurrentDesk); + } + else + { + sprintf(command,"WindowsDesk %d", NewDesk + desk1); + SendInfo(fd,command,t->w); + t->desk = NewDesk + desk1; + } + } + + if((NewDesk >= 0)&&(NewDesk < ndesks)) + { + XReparentWindow(dpy, t->PagerView, Desks[NewDesk].w,x,y); + if(moved) + { + if(t->flags & ICONIFIED) + XMoveWindow(dpy,t->icon_w,x,y); + else + XMoveWindow(dpy,t->w,x+t->border_width, + y+t->title_height+t->border_width); + XSync(dpy,0); + } + else + MoveResizePagerView(t); + SendInfo(fd,"Raise",t->w); + } + if(Scr.CurrentDesk == t->desk) + { + if(t->flags & ICONIFIED) + XSetInputFocus (dpy, t->icon_w, RevertToParent, Event->xbutton.time); + else + XSetInputFocus (dpy, t->w, RevertToParent, Event->xbutton.time); + } + } +} + + + + + + +/*********************************************************************** + * + * Procedure: + * FvwmErrorHandler - displays info on internal errors + * + ************************************************************************/ +XErrorHandler FvwmErrorHandler(Display *dpy, XErrorEvent *event) +{ + return 0; +} + + +void LabelWindow(PagerWindow *t) +{ + XGCValues Globalgcv; + unsigned long Globalgcm; + GC tgc; + + if(windowFont == NULL) + { + return; + } + if(t->icon_name == NULL) + { + return; + } + if(t == FocusWin) + { + tgc = FocusGC; + } + else + { + tgc = StdGC; + Globalgcv.foreground = t->text; + Globalgcv.background = t->back; + Globalgcm = GCForeground|GCBackground; + XChangeGC(dpy, StdGC,Globalgcm,&Globalgcv); + } + if(t->PagerView != None) + { + XClearWindow(dpy, t->PagerView); + XDrawImageString (dpy, t->PagerView,tgc,2,windowFont->ascent+2 , + t->icon_name, strlen(t->icon_name)); + } +} + + +void LabelIconWindow(PagerWindow *t) +{ + XGCValues Globalgcv; + unsigned long Globalgcm; + GC tgc; + + if(windowFont == NULL) + { + return; + } + if(t->icon_name == NULL) + { + return; + } + + if(t == FocusWin) + { + tgc = FocusGC; + } + else + { + tgc = StdGC; + Globalgcv.foreground = t->text; + Globalgcv.background = t->back; + Globalgcm = GCForeground|GCBackground; + XChangeGC(dpy,StdGC,Globalgcm,&Globalgcv); + + } + XClearWindow(dpy, t->IconView); + XDrawImageString (dpy, t->IconView,tgc,2,windowFont->ascent+2 , + t->icon_name, strlen(t->icon_name)); + +} + +void IconMoveWindow(XEvent *Event,PagerWindow *t) +{ + int x1,y1,finished = 0,wx,wy,n,x=0,y=0,xi=0,yi=0; + Window dumwin; + int m,n1,m1; + int moved = 0; + int KeepMoving = 0; + + if(t==NULL) + return; + + n = (Scr.VxMax)/Scr.MyDisplayWidth; + m = (Scr.VyMax)/Scr.MyDisplayHeight; + n1 = (Scr.Vx+t->x)/Scr.MyDisplayWidth; + m1 = (Scr.Vy+t->y)/Scr.MyDisplayHeight; + wx = (Scr.Vx + t->x)*(icon_w-n)/(Scr.VxMax + Scr.MyDisplayWidth) +n1; + wy = (Scr.Vy + t->y)*(icon_h-m)/(Scr.VyMax + Scr.MyDisplayHeight)+m1; + + XRaiseWindow(dpy,t->IconView); + + XTranslateCoordinates(dpy, Event->xany.window, t->IconView, + Event->xbutton.x, Event->xbutton.y, &x1, &y1, &dumwin); + while(!finished) + { + XMaskEvent(dpy,ButtonReleaseMask | ButtonMotionMask|ExposureMask,Event); + + if(Event->type == MotionNotify) + { + x = Event->xbutton.x; + y = Event->xbutton.y; + if(moved == 0) + { + xi = x; + yi = y; + moved = 1; + } + + XMoveWindow(dpy,t->IconView, x - (x1), + y - (y1)); + if((x < -5)||(y < -5)||(x>icon_w+5)||(y>icon_h+5)) + { + finished = 1; + KeepMoving = 1; + } + } + else if(Event->type == ButtonRelease) + { + x = Event->xbutton.x; + y = Event->xbutton.y; + XMoveWindow(dpy,t->PagerView, x - (x1),y - (y1)); + finished = 1; + } + else if (Event->type == Expose) + { + HandleExpose(Event); + } + } + + if(moved) + { + if((x - xi < 3)&&(y - yi < 3)&& + (x - xi > -3)&&(y -yi > -3)) + moved = 0; + } + + if(KeepMoving) + { + XTranslateCoordinates(dpy, t->IconView, Scr.Root, + x, y, &x1, &y1, &dumwin); + if(t->flags & ICONIFIED) + { + XUngrabPointer(dpy,CurrentTime); + XSync(dpy,0); + SendInfo(fd,"Move",t->icon_w); + } + else + { + XUngrabPointer(dpy,CurrentTime); + XSync(dpy,0); + SendInfo(fd,"Move",t->w); + } + } + else + { + x = x - x1; + y = y - y1; + n1 = x*(Scr.VxMax + Scr.MyDisplayWidth)/(icon_w * Scr.MyDisplayWidth); + m1 = y*(Scr.VyMax + Scr.MyDisplayHeight)/(icon_h * Scr.MyDisplayHeight); + x = (x-n1)* + (Scr.VxMax + Scr.MyDisplayWidth)/(icon_w-n) - Scr.Vx; + y = (y-m1)* + (Scr.VyMax + Scr.MyDisplayHeight)/(icon_h-m) - Scr.Vy; + + if(((t->flags & ICONIFIED)&&(StickyIcons))|| + (t->flags & STICKY)) + { + if(x > Scr.MyDisplayWidth -16) + x = Scr.MyDisplayWidth - 16; + if(y > Scr.MyDisplayHeight-16) + y = Scr.MyDisplayHeight - 16; + if(x + t->width < 16) + x = 16 - t->width; + if(y + t->height < 16) + y = 16 - t->height; + } + if(moved) + { + if(t->flags & ICONIFIED) + XMoveWindow(dpy,t->icon_w,x,y); + else + XMoveWindow(dpy,t->w,x,y); + XSync(dpy,0); + } + else + { + MoveResizePagerView(t); + } + SendInfo(fd,"Raise",t->w); + + if(t->flags & ICONIFIED) + XSetInputFocus (dpy, t->icon_w, RevertToParent, Event->xbutton.time); + else + XSetInputFocus (dpy, t->w, RevertToParent, Event->xbutton.time); + } + +} diff --git a/modules/FvwmSave/FvwmSave.c b/modules/FvwmSave/FvwmSave.c new file mode 100644 index 0000000..218e109 --- /dev/null +++ b/modules/FvwmSave/FvwmSave.c @@ -0,0 +1,392 @@ +/* This module, and the entire FvwmSaveDesktop program, and the concept for + * interfacing this module to the Window Manager, are all original work + * by Robert Nation and Mr. Per Persson + * + * Copyright 1994, Robert Nation and Mr. Per Persson. + * No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. */ + +#define TRUE 1 +#define FALSE + +#include "../../configure.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../fvwm/module.h" + +#include "FvwmSave.h" +#include "../../version.h" + +char *MyName; +int fd_width; +int fd[2]; + +struct list *list_root = NULL; + +Display *dpy; /* which display are we talking to */ +int ScreenWidth, ScreenHeight; +int screen; + +long Vx, Vy; + +/*********************************************************************** + * + * Procedure: + * main - start of module + * + ***********************************************************************/ +void main(int argc, char **argv) +{ + char *temp, *s; + char *display_name = NULL; + + /* Record the program name for error messages */ + temp = argv[0]; + + s=strrchr(argv[0], '/'); + if (s != NULL) + temp = s + 1; + + MyName = safemalloc(strlen(temp)+2); + strcpy(MyName,"*"); + strcat(MyName, temp); + + if((argc != 6)&&(argc != 7)) + { + fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",MyName, + VERSION); + exit(1); + } + + /* Open the X display */ + if (!(dpy = XOpenDisplay(display_name))) + { + fprintf(stderr,"%s: can't open display %s", MyName, + XDisplayName(display_name)); + exit (1); + } + screen= DefaultScreen(dpy); + ScreenHeight = DisplayHeight(dpy,screen); + ScreenWidth = DisplayWidth(dpy,screen); + + /* We should exit if our fvwm pipes die */ + signal (SIGPIPE, DeadPipe); + + fd[0] = atoi(argv[1]); + fd[1] = atoi(argv[2]); + + fd_width = GetFdWidth(); + + /* Create a list of all windows */ + /* Request a list of all windows, + * wait for ConfigureWindow packets */ + SendInfo(fd,"Send_WindowList",0); + + Loop(fd); +} + + +/*********************************************************************** + * + * Procedure: + * Loop - wait for data to process + * + ***********************************************************************/ +void Loop(int *fd) +{ + unsigned long header[3], *body; + char *cbody; + int body_length,count,count2=0,total; + + while(1) + { + /* read a packet */ + if(count = ReadFvwmPacket(fd[1],header, &body) > 0) + { + /* dispense with the new packet */ + process_message(header[1],body); + free(body); + } + } +} + + +/*********************************************************************** + * + * Procedure: + * Process message - examines packet types, and takes appropriate action + * + ***********************************************************************/ +void process_message(unsigned long type,unsigned long *body) +{ + switch(type) + { + case M_CONFIGURE_WINDOW: + if(!find_window(body[0])) + add_window(body[0],body); + break; + case M_NEW_PAGE: + list_new_page(body); + break; + case M_END_WINDOWLIST: + do_save(); + break; + default: + break; + } +} + + + + + +/*********************************************************************** + * + * Procedure: + * find_window - find a window in the current window list + * + ***********************************************************************/ +struct list *find_window(unsigned long id) +{ + struct list *l; + + if(list_root == NULL) + return NULL; + + for(l = list_root; l!= NULL; l= l->next) + { + if(l->id == id) + return l; + } + return NULL; +} + + + +/*********************************************************************** + * + * Procedure: + * add_window - add a new window in the current window list + * + ***********************************************************************/ +void add_window(unsigned long new_win, unsigned long *body) +{ + struct list *t; + + if(new_win == 0) + return; + + t = (struct list *)safemalloc(sizeof(struct list)); + t->id = new_win; + t->next = list_root; + t->frame_height = (int)body[6]; + t->frame_width = (int)body[5]; + t->base_width = (int)body[11]; + t->base_height = (int)body[12]; + t->width_inc = (int)body[13]; + t->height_inc = (int)body[14]; + t->frame_x = (int)body[3]; + t->frame_y = (int)body[4];; + t->title_height = (int)body[9];; + t->boundary_width = (int)body[10]; + t->flags = (unsigned long)body[8]; + t->gravity = body[21]; + list_root = t; +} + + + +/*********************************************************************** + * + * Procedure: + * list_new_page - capture new-page info + * + ***********************************************************************/ +void list_new_page(unsigned long *body) +{ + Vx = (long)body[0]; + Vy = (long)body[1]; +} +/*********************************************************************** + * + * Procedure: + * SIGPIPE handler - SIGPIPE means fvwm is dying + * + ***********************************************************************/ +void DeadPipe(int nonsense) +{ + exit(0); +} + + +/*********************************************************************** + * + * Procedure: + * writes a command line argument to file "out" + * checks for qoutes and stuff + * + ***********************************************************************/ +void write_string(FILE *out, char *line) +{ + int len,space = 0, qoute = 0,i; + + len = strlen(line); + + for(i=0;inext) + { + tname[0]=0; + + x1 = t->frame_x; + x2 = ScreenWidth - x1 - t->frame_width - 2; + if(x2 < 0) + x2 = 0; + y1 = t->frame_y; + y2 = ScreenHeight - y1 - t->frame_height - 2; + if(y2 < 0) + y2 = 0; + dheight = t->frame_height - t->title_height - 2*t->boundary_width; + dwidth = t->frame_width - 2*t->boundary_width; + dwidth -= t->base_width ; + dheight -= t->base_height ; + dwidth /= t->width_inc; + dheight /= t->height_inc; + + if ( t->flags & STICKY ) + { + tVx = 0; + tVy = 0; + } + else + { + tVx = Vx; + tVy = Vy; + } + sprintf(tname,"%dx%d",dwidth,dheight); + if ((t->gravity == EastGravity) || + (t->gravity == NorthEastGravity) || + (t->gravity == SouthEastGravity)) + sprintf(loc,"-%d",x2); + else + sprintf(loc,"+%d",x1+(int)tVx); + strcat(tname, loc); + + if((t->gravity == SouthGravity)|| + (t->gravity == SouthEastGravity)|| + (t->gravity == SouthWestGravity)) + sprintf(loc,"-%d",y2); + else + sprintf(loc,"+%d",y1+(int)tVy); + strcat(tname, loc); + + if ( XGetCommand( dpy, t->id, &command_list, &command_count ) ) + { + for (i=0; i < command_count; i++) + { + if ( strncmp( "-geo", command_list[i], 4) == 0) + { + i++; + continue; + } + if ( strncmp( "-ic", command_list[i], 3) == 0) + continue; + if ( strncmp( "-display", command_list[i], 8) == 0) + { + i++; + continue; + } + write_string(out,command_list[i]); + if(strstr(command_list[i], "xterm")) + { + fprintf( out, "-geometry %s ", tname ); + if ( t->flags & ICONIFIED ) + fprintf(out, "-ic "); + xtermline = 1; + } + } + if ( command_count > 0 ) + { + if ( xtermline == 0 ) + { + if ( t->flags & ICONIFIED ) + fprintf(out, "-ic "); + fprintf( out, "-geometry %s &\n", tname ); + } + else + { + fprintf( out, "&\n"); + } + } + XFreeStringList( command_list ); + xtermline = 0; + } + } + fprintf(out, "fvwm\n"); + fclose( out ); + exit(0); + +} + diff --git a/modules/FvwmSave/FvwmSave.h b/modules/FvwmSave/FvwmSave.h new file mode 100644 index 0000000..a1b3503 --- /dev/null +++ b/modules/FvwmSave/FvwmSave.h @@ -0,0 +1,44 @@ +#include "../../libs/fvwmlib.h" +#define STICKY 1 +#define ICONIFIED 32 /* is it an icon now? */ +struct list +{ + unsigned long id; + int frame_height; + int frame_width; + int base_width; + int base_height; + int width_inc; + int height_inc; + int frame_x; + int frame_y; + int title_height; + int boundary_width; + unsigned long flags; + unsigned long gravity; + struct list *next; +}; + +/************************************************************************* + * + * Subroutine Prototypes + * + *************************************************************************/ +void Loop(int *fd); +void SendInfo(int *fd,char *message,unsigned long window); +char *safemalloc(int length); +struct list *find_window(unsigned long id); +void add_window(unsigned long new_win, unsigned long *body); +void DeadPipe(int nonsense); +void process_message(unsigned long type,unsigned long *body); +void do_save(void); +void list_new_page(unsigned long *body); + +#ifdef BROKEN_SUN_HEADERS +#include "../../fvwm/sun_headers.h" +#endif + + +#ifdef NEEDS_ALPHA_HEADER +#include "../../fvwm/alpha_header.h" +#endif /* NEEDS_ALPHA_HEADER */ diff --git a/modules/FvwmSave/FvwmSave.man b/modules/FvwmSave/FvwmSave.man new file mode 100644 index 0000000..836d6ef --- /dev/null +++ b/modules/FvwmSave/FvwmSave.man @@ -0,0 +1,64 @@ +.\" t +.\" @(#)FvwmSave.1 1/28/94 +.TH FvwmSave 1.20 "Jan 28 1994" +.UC +.SH NAME +FvwmSave \- the FVWM desktop-layout saving module +.SH SYNOPSIS +FvwmSave is spawned by fvwm, so no command line invocation will work. + +.SH DESCRIPTION +When called, this module will attempt to save your current desktop +layout into a file called new.xinitrc. Ideally, this file will look just +like .xinitrc, but in reality, you will have to edit it to get a +useable configuration, so be sure to keep a backup of your old .xinitrc. + +Your applications must supply certain hints to the X window system. +Emacs, for example, does not, so FvwmSave can't get any +information from it. + +Also, FvwmSave assumes that certain command line options are +globally accepted by applications, which may not be the case. + +.SH COPYRIGHTS +The NoClutter program, and the concept for +interfacing this module to the Window Manager, are all original work +by Robert Nation + +Copyright 1994, Robert Nation. No guarantees or warranties or anything +are provided or implied in any way whatsoever. Use this program at your +own risk. Permission to use this program for any purpose is given, +as long as the copyright is kept intact. + + +.SH INITIALIZATION +During initialization, \fINoClutter\fP will eventually search a +configuration file which describes the time-outs and actions to take. +The configuration file is the same file that fvwm used during initialization. + +If the NoClutter executable is linked to another name, ie ln -s +NoClutter OtherClutter, then another module called OtherClutter can be +started, with a completely different configuration than NoClutter, +simply by changing the keyword NoClutter to OtherClutter. This way multiple +clutter-reduction programs can be used. + +.SH INVOCATION +NoClutter can be invoked by inserting the line 'Module NoClutter' in +the .fvwmrc file. This can be placed on a line by itself, if NoClutter +is to be spawned during fvwm's initialization, or can be bound to a +menu or mouse button or keystroke to invoke it later. Fvwm will search +directory specified in the ModulePath configuration option to attempt +to locate NoClutter. + +.SH CONFIGURATION OPTIONS +NoClutter reads the same .fvwmrc file as fvwm reads when it starts up, +and looks for lines similar to "*NoClutter 3600 Iconify". The format +of these lines is "*NoClutter [time] [command]", where command is any +fvwm built-in command, and time is the time in seconds between when a +window looses focus and when the command is executed. At most 3 +actions can be specified. + + +.SH AUTHOR +Robert Nation and Mr. Per Persson + (Omnion on IRC) diff --git a/modules/FvwmSave/Imakefile b/modules/FvwmSave/Imakefile new file mode 100644 index 0000000..b2fdf6a --- /dev/null +++ b/modules/FvwmSave/Imakefile @@ -0,0 +1,29 @@ +/* Imakefile for FvwmSave */ +/* Thu Aug 5 11:21:36 MET DST 1993, mj@dfv.rwth-aachen.de */ + +/* setup is done entirely in configuration.h now! */ +/* You should need to do much in here, excpt maybe add libraries */ + +/* I need to get the #define XPM from configuration.h if its in there,*/ +/* so that I can tell if I should include -lXpm */ +#include <../../configure.h> + +COMPILER + +DEPLIBS = $(DEPXLIB) ../../libs/libfvwmlib.a + +#ifdef AlphaArchitecture +LOCAL_LIBRARIES = $(XLIB) -ldnet_stub -L../../libs -lfvwmlib +#else +LOCAL_LIBRARIES = $(XLIB) -L../../libs -lfvwmlib +#endif + +LINTLIBS = $(LINTXLIB) + +SRCS = FvwmSave.c +OBJS = FvwmSave.o + +TARGET_DIR + +ComplexProgramTarget(FvwmSave) + diff --git a/modules/FvwmSaveDesk/FvwmSaveDesk.c b/modules/FvwmSaveDesk/FvwmSaveDesk.c new file mode 100644 index 0000000..c348247 --- /dev/null +++ b/modules/FvwmSaveDesk/FvwmSaveDesk.c @@ -0,0 +1,459 @@ +/* This module, and the entire FvwmSaveDesktop program, and the concept for + * interfacing this module to the Window Manager, are all original work + * by Robert Nation and Mr. Per Persson + * + * The concept to write an function definition instead of an new.xinitrc + * is from Carsten Paeth + * + * Copyright 1994, Robert Nation and Mr. Per Persson. + * No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. + * + * Copyright 1995, Carsten Paeth. + * No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. + * + */ + +#define TRUE 1 +#define FALSE 0 + +#include "../../configure.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../fvwm/module.h" + +#include "FvwmSaveDesk.h" +#include "../../version.h" + +char *MyName; +int fd_width; +int fd[2]; + +struct list *list_root = NULL; + +Display *dpy; /* which display are we talking to */ +int ScreenWidth, ScreenHeight; +int screen; + +long Vx, Vy; + +long CurDesk = 1; /* actual Desktop while being called */ + +/*********************************************************************** + * + * Procedure: + * main - start of module + * + ***********************************************************************/ +void main(int argc, char **argv) +{ + char *temp, *s; + char *display_name = NULL; + + /* Record the program name for error messages */ + temp = argv[0]; + + s=strrchr(argv[0], '/'); + if (s != NULL) + temp = s + 1; + + MyName = safemalloc(strlen(temp)+2); + strcpy(MyName,"*"); + strcat(MyName, temp); + + if((argc != 6)&&(argc != 7)) + { + fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",MyName, + VERSION); + exit(1); + } + + /* Open the X display */ + if (!(dpy = XOpenDisplay(display_name))) + { + fprintf(stderr,"%s: can't open display %s", MyName, + XDisplayName(display_name)); + exit (1); + } + screen= DefaultScreen(dpy); + ScreenHeight = DisplayHeight(dpy,screen); + ScreenWidth = DisplayWidth(dpy,screen); + + /* We should exit if our fvwm pipes die */ + signal (SIGPIPE, DeadPipe); + + fd[0] = atoi(argv[1]); + fd[1] = atoi(argv[2]); + + fd_width = GetFdWidth(); + + /* Create a list of all windows */ + /* Request a list of all windows, + * wait for ConfigureWindow packets */ + SendInfo(fd,"Send_WindowList",0); + + Loop(fd); +} + + +/*********************************************************************** + * + * Procedure: + * Loop - wait for data to process + * + ***********************************************************************/ +void Loop(int *fd) +{ + unsigned long header[3], *body; + char *cbody; + int body_length,count,count2=0,total; + + while(1) + { + /* read a packet */ + if(count = ReadFvwmPacket(fd[1],header,&body) > 0) + { + /* dispense with the new packet */ + process_message(header[1],body); + free(body); + } + } +} + + +/*********************************************************************** + * + * Procedure: + * Process message - examines packet types, and takes appropriate action + * + ***********************************************************************/ +void process_message(unsigned long type,unsigned long *body) +{ + switch(type) + { + case M_CONFIGURE_WINDOW: + if(!find_window(body[0])) + add_window(body[0],body); + break; + case M_NEW_PAGE: + list_new_page(body); + break; + case M_NEW_DESK: + CurDesk = (long)body[0]; + break; + case M_END_WINDOWLIST: + do_save(); + break; + default: + break; + } +} + + + +/*********************************************************************** + * + * Procedure: + * find_window - find a window in the current window list + * + ***********************************************************************/ +struct list *find_window(unsigned long id) +{ + struct list *l; + + if(list_root == NULL) + return NULL; + + for(l = list_root; l!= NULL; l= l->next) + { + if(l->id == id) + return l; + } + return NULL; +} + + + +/*********************************************************************** + * + * Procedure: + * add_window - add a new window in the current window list + * + ***********************************************************************/ +void add_window(unsigned long new_win, unsigned long *body) +{ + struct list *t; + + if(new_win == 0) + return; + + t = (struct list *)safemalloc(sizeof(struct list)); + t->id = new_win; + t->next = list_root; + t->frame_height = (int)body[6]; + t->frame_width = (int)body[5]; + t->base_width = (int)body[11]; + t->base_height = (int)body[12]; + t->width_inc = (int)body[13]; + t->height_inc = (int)body[14]; + t->frame_x = (int)body[3]; + t->frame_y = (int)body[4];; + t->title_height = (int)body[9];; + t->boundary_width = (int)body[10]; + t->flags = (unsigned long)body[8]; + t->gravity = body[21]; + t->desk = body[7]; + list_root = t; +} + + + +/*********************************************************************** + * + * Procedure: + * list_new_page - capture new-page info + * + ***********************************************************************/ +void list_new_page(unsigned long *body) +{ + Vx = (long)body[0]; + Vy = (long)body[1]; +} +/*********************************************************************** + * + * Procedure: + * SIGPIPE handler - SIGPIPE means fvwm is dying + * + ***********************************************************************/ +void DeadPipe(int nonsense) +{ + exit(0); +} + + +/*********************************************************************** + * + * Procedure: + * writes a command line argument to file "out" + * checks for qoutes and stuff + * + ***********************************************************************/ +void write_string(FILE *out, char *line) +{ + int len,space = 0, qoute = 0,i; + + len = strlen(line); + + for(i=0;iframe_x; + x2 = ScreenWidth - x1 - t->frame_width - 2; + if(x2 < 0) + x2 = 0; + y1 = t->frame_y; + y2 = ScreenHeight - y1 - t->frame_height - 2; + if(y2 < 0) + y2 = 0; + dheight = t->frame_height - t->title_height - 2*t->boundary_width; + dwidth = t->frame_width - 2*t->boundary_width; + dwidth -= t->base_width ; + dheight -= t->base_height ; + dwidth /= t->width_inc; + dheight /= t->height_inc; + + if ( t->flags & STICKY ) + { + tVx = 0; + tVy = 0; + } + else + { + tVx = Vx; + tVy = Vy; + } + sprintf(tname,"%dx%d",dwidth,dheight); + if ((t->gravity == EastGravity) || + (t->gravity == NorthEastGravity) || + (t->gravity == SouthEastGravity)) + sprintf(loc,"-%d",x2); + else + sprintf(loc,"+%d",x1+(int)tVx); + strcat(tname, loc); + + if((t->gravity == SouthGravity)|| + (t->gravity == SouthEastGravity)|| + (t->gravity == SouthWestGravity)) + sprintf(loc,"-%d",y2); + else + sprintf(loc,"+%d",y1+(int)tVy); + strcat(tname, loc); + + if ( XGetCommand( dpy, t->id, &command_list, &command_count ) ) + { + if (*curdesk != t->desk) + { + fprintf( out, " Desk \"I\" %ld 0\n", t->desk); + fflush ( out ); + *curdesk = t->desk; + } + + fprintf( out, " Exec \"I\" exec "); + fflush ( out ); + for (i=0; i < command_count; i++) + { + if ( strncmp( "-geo", command_list[i], 4) == 0) + { + i++; + continue; + } + if ( strncmp( "-ic", command_list[i], 3) == 0) + continue; + if ( strncmp( "-display", command_list[i], 8) == 0) + { + i++; + continue; + } + write_string(out,command_list[i]); + fflush ( out ); + if(strstr(command_list[i], "xterm")) + { + fprintf( out, "-geometry %s ", tname ); + if ( t->flags & ICONIFIED ) + fprintf(out, "-ic "); + xtermline = 1; + fflush ( out ); + } + } + if ( command_count > 0 ) + { + if ( xtermline == 0 ) + { + if ( t->flags & ICONIFIED ) + fprintf(out, "-ic "); + fprintf( out, "-geometry %s &\n", tname); + } + else + { + fprintf( out, "&\n"); + } + if (emit_wait) { + fprintf( out, " Wait \"I\" %s\n", command_list[0]); + fflush( out ); + } + } + XFreeStringList( command_list ); + xtermline = 0; + } +} + + +/*********************************************************************** + * + * Procedure: + * checks to see if we are supposed to take some action now, + * finds time for next action to be performed. + * + ***********************************************************************/ +void do_save(void) +{ + struct list *t; + char fnbuf[200]; + FILE *out; + int maxdesk = 0; + int actdesk = -1; + int curdesk; + + for (t = list_root; t != NULL; t = t->next) + if (t->desk > maxdesk) + maxdesk = t->desk; + + sprintf(fnbuf, "%s/.fvwmdesk", getenv( "HOME" ) ); + out = fopen( fnbuf, "w" ); + + fprintf( out, "Function \"StartupFunction\"\n"); + fflush ( out ); + + /* + * Generate all Desks except 'CurDesk' + */ + for (curdesk = 0; curdesk <= maxdesk; curdesk++) + { + for (t = list_root; t != NULL; t = t->next) + { + if (t->desk != CurDesk && curdesk == t->desk) + do_save_command(out, t, &actdesk, 1); + } + } + /* + * Generate 'CurDesk' + */ + for (t = list_root; t != NULL; t = t->next) + { + if (t->desk == CurDesk) + do_save_command(out, t, &actdesk, 0); + } + + if (actdesk != CurDesk) + fprintf( out, " Desk \"I\" %ld 0\n", CurDesk); + + fprintf( out, "EndFunction\n"); + fflush( out ); + fclose( out ); + exit(0); + +} + diff --git a/modules/FvwmSaveDesk/FvwmSaveDesk.h b/modules/FvwmSaveDesk/FvwmSaveDesk.h new file mode 100644 index 0000000..305e3e6 --- /dev/null +++ b/modules/FvwmSaveDesk/FvwmSaveDesk.h @@ -0,0 +1,45 @@ +#include "../../libs/fvwmlib.h" +#define STICKY 1 +#define ICONIFIED 32 /* is it an icon now? */ +struct list +{ + unsigned long id; + int frame_height; + int frame_width; + int base_width; + int base_height; + int width_inc; + int height_inc; + int frame_x; + int frame_y; + int title_height; + int boundary_width; + unsigned long flags; + unsigned long gravity; + long desk; + struct list *next; +}; + +/************************************************************************* + * + * Subroutine Prototypes + * + *************************************************************************/ +void Loop(int *fd); +void SendInfo(int *fd,char *message,unsigned long window); +char *safemalloc(int length); +struct list *find_window(unsigned long id); +void add_window(unsigned long new_win, unsigned long *body); +void DeadPipe(int nonsense); +void process_message(unsigned long type,unsigned long *body); +void do_save(void); +void list_new_page(unsigned long *body); + +#ifdef BROKEN_SUN_HEADERS +#include "../../fvwm/sun_headers.h" +#endif + + +#ifdef NEEDS_ALPHA_HEADER +#include "../../fvwm/alpha_header.h" +#endif /* NEEDS_ALPHA_HEADER */ diff --git a/modules/FvwmSaveDesk/FvwmSaveDesk.man b/modules/FvwmSaveDesk/FvwmSaveDesk.man new file mode 100644 index 0000000..5891464 --- /dev/null +++ b/modules/FvwmSaveDesk/FvwmSaveDesk.man @@ -0,0 +1,70 @@ +.\" t +.\" @(#)FvwmSaveDesk.1 6/20/95 +.TH FvwmSaveDesk 1.0 "Jul 20 1995" +.UC +.SH NAME +FvwmSaveDesk \- another FVWM desktop-layout saving module +.SH SYNOPSIS +FvwmSaveDesk is spawned by fvwm, so no command line invocation will work. + +.SH DESCRIPTION +When called, this module will attempt to save your current desktop +layout as a fvwm function definition into the file +.I .fvwmdesk +in your home directory. The function is named +.I StartupFunction +\. This Function can be called in Function +.I InitFunction +to startup all Programms on all Workspaces. +If fvwm is compiled with the M4 option, you can include this file in +.I .fvmrc +else you have to insert this file by hand. +Your applications must supply certain hints to the X window system. +Emacs, for example, does not, so FvwmSaveDesk can't get any +information from it. + +Also, FvwmSaveDesk assumes that certain command line options are +globally accepted by applications, which may not be the case. + +.SH SETUP IF FVWM IS COMPILED WITH THE M4 OPTION +Fvwm has to be called with the option + +-m4opt -I$HOME. + +The first line in .fvwmrc should be + +undefine(`include`), + +to avoid problems. +You can the include the file +.I .fvwmdesk +with + +sinclude(`.fvwmdesk') . + +Insert the following line into the Function +.I InitFunction + +Function "I" StartupFunction + +If you have GNU's m4 another possiblity is to compile fvwm with +GNU_M4_OPTION_P and use + +m4_include(`.fvwmdesk')m4_dnl + +So you don't need to undefine `include'. + +.SH INVOCATION +FvwmSaveDesk can be invoked by inserting the line 'Module FvwmSaveDesk' in +the +.I .fvwmrc +file. +This should be bound to a menu or mouse button or keystroke +to invoke it later. Fvwm will search directory specified in the ModulePath +configuration option to attempt to locate FvwmSaveDesk. + +.SH AUTHOR +Carsten Paeth (calle@calle.in-berlin.de) + +based on FvwmSave written by Robert Nation +and Mr. Per Persson (Omnion on IRC) diff --git a/modules/FvwmSaveDesk/Imakefile b/modules/FvwmSaveDesk/Imakefile new file mode 100644 index 0000000..b359a0f --- /dev/null +++ b/modules/FvwmSaveDesk/Imakefile @@ -0,0 +1,29 @@ +/* Imakefile for FvwmSaveDesk */ +/* Wed Jul 20 19:36:27 MET DST 1994 calle@calle.in-berlin.de */ + +/* setup is done entirely in configuration.h now! */ +/* You should need to do much in here, excpt maybe add libraries */ + +/* I need to get the #define XPM from configuration.h if its in there,*/ +/* so that I can tell if I should include -lXpm */ +#include <../../configure.h> + +COMPILER + +DEPLIBS = $(DEPXLIB) ../../libs/libfvwmlib.a + +#ifdef AlphaArchitecture +LOCAL_LIBRARIES = $(XLIB) -ldnet_stub -L../../libs -lfvwmlib +#else +LOCAL_LIBRARIES = $(XLIB) -L../../libs -lfvwmlib +#endif + +LINTLIBS = $(LINTXLIB) + +SRCS = FvwmSaveDesk.c +OBJS = FvwmSaveDesk.o + +TARGET_DIR + +ComplexProgramTarget(FvwmSaveDesk) + diff --git a/modules/FvwmSaveDesk/example/fvwmrc b/modules/FvwmSaveDesk/example/fvwmrc new file mode 100644 index 0000000..0f417c3 --- /dev/null +++ b/modules/FvwmSaveDesk/example/fvwmrc @@ -0,0 +1,284 @@ +# needed 'cause of M4 +undefine(`include') + +StdForeColor Black +StdBackColor grey +HiForeColor Black +HiBackColor DarkTurquoise +StickyForeColor Black +StickyBackColor #908090 +MenuForeColor Black +MenuBackColor DarkTurquoise +MenuStippleColor DeepSkyBlue + +Font fixed +WindowFont fixed +IconFont fixed + +MWMBorders +MWMButtons +MWMMenus +MWMDecorHints +MWMFunctionHints + +DecorateTransients + +IconBox -305 -295 -1 -105 +IconBox -105 5 -5 400 + +ButtonStyle 1 50x22 +ButtonStyle 2 50x50 +ButtonStyle 4 22x22 + +ModulePath /usr/lib/X11/fvwm + +PixmapPath /usr/include/X11/pixmaps +IconPath /usr/include/X11/bitmaps + +DeskTopSize 1x1 + +DeskTopScale 32 + +RandomPlacement +SmartPlacement + +Style "*" Color black/grey,Icon unknown1.xpm,HandleWidth 7,BorderWidth 4 + +Style "Fvwm*" NoTitle, NoHandles, Sticky, WindowListSkip,BorderWidth 0 +Style "Fvwm Pager" BorderWidth 4 +Style "FvwmPager" BorderWidth 4 +Style "FvwmBanner" StaysOnTop +Style "GoodStuff" NoTitle, NoHandles, Sticky, WindowListSkip,BorderWidth 4 +Style "xterm" Icon xterm.xpm, Color black/grey +Style "xcalc" Icon xcalc.xpm +Style "xman" Icon xman.xpm +Style "xmag" Icon mag_glass.xpm +Style "GoodStuff" Icon toolbox.xpm + + +Popup "Quit-Verify" + Title "Really Quit Fvwm? " + Quit "Yes, Really Quit " + Restart "Restart Fvwm " fvwm + Restart "Start mwm " mwm + Nop "" + Nop "No, Don't Quit " +EndPopup + +Popup "Module-Popup" + Title "Modules" + Module "GoodStuff" GoodStuff + Module "NoClutter" FvwmClean + Module "FvwmIdentify" FvwmIdent + Module "Banner" FvwmBanner + Module "Debug" FvwmDebug + Module "SaveDesktop" FvwmSaveDesk + Module "Pager" FvwmPager 0 3 + Module "FvwmWinList" FvwmWinList +EndPopup + + +Popup "Utilities" + Title "Utilities " + Exec "Xterm " exec xterm -ls & + Exec "Calculator " exec xcalc & + Exec "Xman " exec xman & + Exec "Xmag " exec xmag & + Nop "" + Popup "Modules" Module-Popup + Nop "" + Popup "Exit Fvwm " Quit-Verify +EndPopup + +# This defines the change workspace menu +Popup "Occupy-Workspace" + Title "Occupy Workspace" + WindowsDesk "Workspace &1" 0 + WindowsDesk "Workspace &2" 1 + WindowsDesk "Workspace &3" 2 + WindowsDesk "Workspace &4" 3 +EndPopup + +# This defines the most common window operations +Popup "Window Ops" + Title "Window Ops " + PopUp "Occupy Workspace" Occupy-Workspace + Move "&Move Alt+F7" + Resize "&Size Alt+F8" + Lower "&Lower Alt+F3" + Raise "Raise " + Stick "(Un)Stick " + Iconify "(Un)Mi&nimize Alt+F9" + Maximize "(Un)Ma&ximize Alt+F10" + Maximize "(Un)Maximize Vertical " 0 100 + Nop "" + Delete "&Close Alt+F4" + Destroy "&Kill! " +EndPopup + +Popup "Window Ops2" + PopUp "Occupy Workspace" Occupy-Workspace + Move "&Move Alt+F7" + Resize "&Size Alt+F8" + Iconify "(Un)Mi&nimize Alt+F9" + Maximize "(Un)Ma&ximize Alt+F10" + Lower "&Lower Alt+F3" + Nop "" + Delete "&Close Alt+F4" + Nop "" + Module "&ScrollBar" FvwmScroll 2 2 +EndPopup +Function "Iconify-and-Raise" + Iconify "Motion" + Raise "Motion" +EndPopup + +Function "Move-or-Lower" + Move "Motion" + Lower "Motion" + Lower "Click" + RaiseLower "DoubleClick" +EndFunction + +Function "Move-or-Iconify" + Move "Motion" + PopUp "Click" Window Ops2 + Iconify "DoubleClick" +EndFunction + +Function "windowops-or-die" + PopUp "Motion" Window Ops2 + PopUp "Click" Window Ops2 + Delete "DoubleClick" +EndFunction + +Function "Move-or-Raise" + Move "Motion" + Raise "Motion" + Raise "Click" + Iconify "DoubleClick" +EndFunction + +Function "Move-or-Lower" + Move "Motion" + Lower "Click" + RaiseLower "DoubleClick" +EndFunction +Function "Resize-or-Raise" + Resize "Motion" + Raise "Motion" + Raise "Click" + RaiseLower "DoubleClick" +EndFunction +Function "Resize-or-Lower" + Resize "Motion" + Lower "Click" + RaiseLower "DoubleClick" +EndFunction + +Mouse 1 R A PopUp "Utilities" +Mouse 2 R A PopUp "Window Ops" +Mouse 3 R A WindowList + +Mouse 0 1 A Function "windowops-or-die" +Mouse 0 2 A Maximize +Mouse 0 4 A Iconify + +Mouse 1 FS A Function "Resize-or-Raise" +Mouse 2 FS A Function "Resize-or-Lower" +Mouse 1 T A Function "Move-or-Raise" +Mouse 2 T A Function "Move-or-Lower" + +Mouse 1 I A Function "Move-or-Iconify" +Mouse 2 I A Function "Move-or-Iconify" +Mouse 3 I A PopUp "Window Ops2" +Mouse 3 FST A Function "windowops-or-die" + +Key Left A C Scroll -100 0 +Key Right A C Scroll +100 +0 +Key Up A C Scroll +0 -100 +Key Down A C Scroll +0 +100 + +Key Left A M Scroll -10 +0 +Key Right A M Scroll +10 +0 +Key Up A M Scroll +0 -10 +Key Down A M Scroll +0 +10 + +Key Left A SC CursorMove -1 0 +Key Right A SC CursorMove +1 +0 +Key Up A SC CursorMove +0 -1 +Key Down A SC CursorMove +0 +1 + +Key Left A SM CursorMove -10 +0 +Key Right A SM CursorMove +10 +0 +Key Up A SM CursorMove +0 -10 +Key Down A SM CursorMove +0 +10 + +Key F1 A M Popup "Window Ops" +Key F2 A M Popup "Utilities" +Key F3 A M Lower +Key F4 A M Destroy +Key F5 A M CirculateUp +Key F6 A M CirculateDown +Key F7 A M Move +Key F8 A M Resize +Key F9 A M Iconify +Key F10 A M Maximize + +Key L5 IW N RaiseLower +Key L5 IW S Lower +Key L5 IW C Raise +Key L7 IW A Iconify + +############################################################################# +# Stuff to do at start-up + +sinclude(`.fvwmdesk') + +Function "InitFunction" + Exec "I" xsetroot -solid steelblue + Module "I" GoodStuff + Module "I" FvwmPager 0 3 + Function "I" StartupFunction +EndFunction + +Function "RestartFunction" + Exec "I" xsetroot -solid steelblue + Module "I" GoodStuff + Module "I" FvwmPager 0 3 +EndFunction + +*GoodStuffFore Black +*GoodStuffBack #908090 +*GoodStuffFont fixed +*GoodStuffGeometry -5-5 +*GoodStuffRows 1 + +*GoodStuff Xterm xterm.xpm Exec "xterm" exec xterm -ls & +*GoodStuff Seyon modem.xpm Exec "Seyon" exec seyon & +*GoodStuff Mail mail2.xpm Exec "xterm" exec xterm -geometry 80x40 -e elm & +*GoodStuff News news.xpm Exec "xterm" exec xterm -geometry 80x40 -e tin & +*GoodStuff SaveDesc desk.xpm Module "SaveDesktop" FvwmSaveDesk + +*FvwmPagerBack #908090 +*FvwmPagerFore #484048 +*FvwmPagerHilight #cab3ca +*FvwmPagerGeometry x80-5-80 +*FvwmPagerLabel 0 General +*FvwmPagerLabel 1 Tmp +*FvwmPagerLabel 2 Mail/News +*FvwmPagerLabel 3 Compile/Modem +*FvwmPagerSmallFont 5x8 + +*FvwmIdentBack MidnightBlue +*FvwmIdentFore Yellow +*FvwmIdentFont -adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-* + +*FvwmWinListBack #908090 +*FvwmWinListFore Black +*FvwmWinListFont -adobe-helvetica-bold-r-*-*-10-*-*-*-*-*-*-* +*FvwmWinListAction Click1 Iconify -1,Raise +*FvwmWinListAction Click2 Iconify 1 +*FvwmWinListAction Click3 Module "FvwmIdent" FvwmIdent +*FvwmWinListUseSkipList +*FvwmWinListGeometry +0-1 diff --git a/modules/FvwmSaveDesk/example/xinitrc b/modules/FvwmSaveDesk/example/xinitrc new file mode 100755 index 0000000..1e43baf --- /dev/null +++ b/modules/FvwmSaveDesk/example/xinitrc @@ -0,0 +1,30 @@ +#!/bin/sh + +userresources=$HOME/.Xresources +usermodmap=$HOME/.Xmodmap +sysresources=/usr/lib/X11/xinit/.Xresources +sysmodmap=/usr/lib/X11/xinit/.Xmodmap + +# merge in defaults and keymaps + +if [ -f $sysresources ]; then + xrdb -merge $sysresources +fi + +if [ -f $sysmodmap ]; then + xmodmap $sysmodmap +fi + +if [ -f $userresources ]; then + xrdb -merge $userresources +fi + +if [ -f $usermodmap ]; then + xmodmap $usermodmap +fi + +if [ -f /usr/bin/X11/xsetroot ]; then + xsetroot -solid steelblue +fi + +fvwm -m4opt -I~ diff --git a/modules/FvwmScroll/FvwmScroll.c b/modules/FvwmScroll/FvwmScroll.c new file mode 100644 index 0000000..c2d834f --- /dev/null +++ b/modules/FvwmScroll/FvwmScroll.c @@ -0,0 +1,282 @@ +/* This module, and the entire NoClutter program, and the concept for + * interfacing this module to the Window Manager, are all original work + * by Robert Nation and Nobutaka Suzuki + * + * Copyright 1994, Robert Nation and Nobutaka Suzuki. + * No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. */ + +#define TRUE 1 +#define FALSE 0 + +#define YES "Yes" +#define NO "No" + +#include "../../configure.h" + +#include +#include +#include +#include +#include +#include +#if defined ___AIX || defined _AIX || defined __QNX__ || defined ___AIXV3 || defined AIXV3 || defined _SEQUENT_ +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../fvwm/module.h" +#include "FvwmScroll.h" +#include "../../version.h" + +char *MyName; +int fd_width; +int fd[2]; + +Display *dpy; /* which display are we talking to */ +Window Root; +int screen; +int x_fd; +int d_depth; +int ScreenWidth, ScreenHeight; + +char *BackColor = "black"; +char *ForeColor = "grey"; + +Window app_win; + +#define MW_EVENTS (ExposureMask | ButtonReleaseMask | KeyReleaseMask) + + +/*********************************************************************** + * + * Procedure: + * main - start of module + * + ***********************************************************************/ +void main(int argc, char **argv) +{ + char *temp, *s; + FILE *file; + char *display_name = NULL; + int Clength; + + /* Save the program name for error messages and config parsing */ + temp = argv[0]; + s=strrchr(argv[0], '/'); + if (s != NULL) + temp = s + 1; + + MyName = safemalloc(strlen(temp)+2); + strcpy(MyName,"*"); + strcat(MyName, temp); + Clength = strlen(MyName); + + if((argc != 6)&&(argc != 7)) + { + fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",MyName, + VERSION); + exit(1); + } + + if(argc == 7) + { + char *cptr; + extern int Reduction_H, Reduction_V; + + cptr = argv[6]; + while((isspace(*cptr))&&(*cptr != 0))cptr++; + Reduction_H = atoi(cptr); + while(!(isspace(*cptr))&&(*cptr != 0))cptr++; + while((isspace(*cptr))&&(*cptr != 0))cptr++; + Reduction_V = atoi(cptr); + } + /* Dead pipe == dead fvwm */ + signal (SIGPIPE, DeadPipe); + + fd[0] = atoi(argv[1]); + fd[1] = atoi(argv[2]); + + /* An application window may have already been selected - look for it */ + sscanf(argv[4],"%x",(unsigned int *)&app_win); + + /* Open the Display */ + if (!(dpy = XOpenDisplay(display_name))) + { + fprintf(stderr,"%s: can't open display %s", MyName, + XDisplayName(display_name)); + exit (1); + } + x_fd = XConnectionNumber(dpy); + screen= DefaultScreen(dpy); + Root = RootWindow(dpy, screen); + d_depth = DefaultDepth(dpy, screen); + + ScreenHeight = DisplayHeight(dpy,screen); + ScreenWidth = DisplayWidth(dpy,screen); + + /* scan config file for set-up parameters */ + /* Colors and fonts */ + file = fopen(argv[3],"r"); + if(file != (FILE *)NULL) + { + char line[256]; + char *tline; + + tline = fgets(line,(sizeof line)-1,file); + while(tline != (char *)0) + { + while(isspace(*tline))tline++; + if(strlen(tline)>1) + { + if(mystrncasecmp(tline,CatString3(MyName,"Fore",""), + Clength+4)==0) + { + CopyString(&ForeColor,&tline[Clength+4]); + } + else if(mystrncasecmp(tline,CatString3(MyName, "Back",""), + Clength+4)==0) + { + CopyString(&BackColor,&tline[Clength+4]); + } + } + tline = fgets(line,(sizeof line)-1,file); + } + } + + if(app_win == 0) + GetTargetWindow(&app_win); + + if(app_win == 0) + return; + + fd_width = GetFdWidth(); + + GrabWindow(app_win); + Loop(app_win); +} + + +/*********************************************************************** + * + * Detected a broken pipe - time to exit + * + **********************************************************************/ +void DeadPipe(int nonsense) +{ + extern Atom wm_del_win; + + XReparentWindow(dpy,app_win,Root,0,0); + send_clientmessage (app_win, wm_del_win, CurrentTime); + XSync(dpy,0); + exit(0); +} + + +/********************************************************************** + * + * If no application window was indicated on the command line, prompt + * the user to select one + * + *********************************************************************/ +void GetTargetWindow(Window *app_win) +{ + XEvent eventp; + int val = -10,trials; + Window target_win; + + trials = 0; + while((trials <100)&&(val != GrabSuccess)) + { + val=XGrabPointer(dpy, Root, True, + ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, Root, + XCreateFontCursor(dpy,XC_crosshair), + CurrentTime); + if(val != GrabSuccess) + { + sleep_a_little(1000); + } + trials++; + } + if(val != GrabSuccess) + { + fprintf(stderr,"%s: Couldn't grab the cursor!\n",MyName); + exit(1); + } + XMaskEvent(dpy, ButtonReleaseMask,&eventp); + XUngrabPointer(dpy,CurrentTime); + XSync(dpy,0); + *app_win = eventp.xany.window; + if(eventp.xbutton.subwindow != None) + *app_win = eventp.xbutton.subwindow; + + target_win = ClientWindow(*app_win); + if(target_win != None) + *app_win = target_win; +} + + +void nocolor(char *a, char *b) +{ + fprintf(stderr,"FvwmInitBanner: can't %s %s\n", a,b); +} + + + +/**************************************************************************** + * + * Find the actual application + * + ***************************************************************************/ +Window ClientWindow(Window input) +{ + Atom _XA_WM_STATE; + unsigned int nchildren; + Window root, parent, *children,target; + unsigned long nitems, bytesafter; + unsigned char *prop; + Atom atype; + int aformat; + int i; + + _XA_WM_STATE = XInternAtom (dpy, "WM_STATE", False); + + if (XGetWindowProperty (dpy,input, _XA_WM_STATE , 0L, + 3L , False, _XA_WM_STATE,&atype, + &aformat, &nitems, &bytesafter, + &prop) == Success) + { + if(prop != NULL) + { + XFree(prop); + return input; + } + } + + if(!XQueryTree(dpy, input, &root, &parent, &children, &nchildren)) + return None; + + for (i = 0; i < nchildren; i++) + { + target = ClientWindow(children[i]); + if(target != None) + { + XFree((char *)children); + return target; + } + } + XFree((char *)children); + return None; +} diff --git a/modules/FvwmScroll/FvwmScroll.h b/modules/FvwmScroll/FvwmScroll.h new file mode 100644 index 0000000..1809119 --- /dev/null +++ b/modules/FvwmScroll/FvwmScroll.h @@ -0,0 +1,35 @@ +#include "../../libs/fvwmlib.h" +char *safemalloc(int length); +void DeadPipe(int nonsense); +void GetTargetWindow(Window *app_win); +void sleep_a_little(int n); +void CopyString(char **dest, char *source); +char *CatString2(char *a, char *b); +void nocolor(char *a, char *b); +char *CatString3(char *a, char *b, char *c); +Window ClientWindow(Window input); + +void RelieveWindow(Window win,int x,int y,int w,int h, GC rgc,GC sgc); +void CreateWindow(int x, int y,int w, int h); +Pixel GetShadow(Pixel background); +Pixel GetHilite(Pixel background); +Pixel GetColor(char *name); +void Loop(Window target); +void RedrawWindow(Window target); +void change_window_name(char *str); +void send_clientmessage (Window w, Atom a, Time timestamp); +void GrabWindow(Window target); +void change_icon_name(char *str); +void RedrawLeftButton(GC rgc, GC sgc,int x1,int y1); +void RedrawRightButton(GC rgc, GC sgc,int x1,int y1); +void RedrawTopButton(GC rgc, GC sgc,int x1,int y1); +void RedrawBottomButton(GC rgc, GC sgc,int x1,int y1); + +#ifdef BROKEN_SUN_HEADERS +#include "../../fvwm/sun_headers.h" +#endif + +#ifdef NEEDS_ALPHA_HEADER +#include "../../fvwm/alpha_header.h" +#endif /* NEEDS_ALPHA_HEADER */ + diff --git a/modules/FvwmScroll/FvwmScroll.man b/modules/FvwmScroll/FvwmScroll.man new file mode 100644 index 0000000..da5d026 --- /dev/null +++ b/modules/FvwmScroll/FvwmScroll.man @@ -0,0 +1,76 @@ +.\" t +.\" @(#)FvwmScroll.1 4/14/94 +.TH FvwmScroll 1.20 "April 14 1994" +.UC +.SH NAME +FvwmScroll \- the FVWM scroll-bar module +.SH SYNOPSIS +FvwmScroll is spawned by fvwm, so no command line invocation will work. + +.SH DESCRIPTION +The FvwmScroll module prompts the user to select a target window, if +the module was not launched from within a window context in Fvwm. +After that, it adds scroll bars to the selected window, to reduce the +total desktop space consumed by the window. + + +FvwmScroll reads the same .fvwmrc file as fvwm reads when it starts up, +and looks for lines similar to "*FvwmScrollFore green". + +FvwmScroll should not be used with windows which move or resize +themselves, nor should it be used with windows which set the +WM_COLORMAP_WINDOWS property. Operation is fine with windows that have +a private colormap. + +.SH COPYRIGHTS +The FvwmScroll program, and the concept for +interfacing this module to the Window Manager, are all original work +by Robert Nation. + +Copyright 1994, Robert Nation. No guarantees or +warranties or anything +are provided or implied in any way whatsoever. Use this program at your +own risk. Permission to use this program for any purpose is given, +as long as the copyright is kept intact. + + +.SH INITIALIZATION +During initialization, \fIFvwmScroll\fP will eventually search a +configuration file which describes the colors to use. +The configuration file is the same file that fvwm used during initialization. + +If the FvwmScroll executable is linked to another name, ie ln -s +FvwmScroll MoreScroll, then another module called MoreScroll can be +started, with a completely different configuration than FvwmScroll, +simply by changing the keyword FvwmScroll to MoreScroll. + +.SH INVOCATION +FvwmScroll can be invoked by binding the action 'Module +FvwmScroll x y' to a menu or key-stroke in the .fvwmrc file. +The parameter x and y are integers, which describe the horizontal and +vertical window size reduction. +Fvwm will search +directory specified in the ModulePath configuration option to attempt +to locate FvwmScroll. Although nothing keeps you from launching +FvwmScroll at start-up time, you probably don't want to. + +.SH CONFIGURATION OPTIONS +FvwmScroll reads the same .fvwmrc file as fvwm reads when it starts up, +and looks for lines as listed below: + +.IP "*FvwmScrollFore \fIcolor\fP" +Tells the module to use \fIcolor\fP instead of grey for scroll bars +themselves. + +.IP "*FvwmScrollBack \fIcolor\fP" +Tells the module to use \fIcolor\fP instead of black for the window +background. + +.SH BUGS +When the scroll bars are removed by clicking on the button in the +lower right corner, the window does not restore its location +correctly. + +.SH AUTHOR +Robert Nation + diff --git a/modules/FvwmScroll/GrabWindow.c b/modules/FvwmScroll/GrabWindow.c new file mode 100644 index 0000000..e60c998 --- /dev/null +++ b/modules/FvwmScroll/GrabWindow.c @@ -0,0 +1,987 @@ +/* This module, and the entire GoodStuff program, and the concept for + * interfacing this module to the Window Manager, are all original work + * by Robert Nation + * + * Copyright 1993, Robert Nation. No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. */ + +#define TRUE 1 +#define FALSE 0 +#define MAX_ICON_NAME_LEN 255 + +#include "../../configure.h" + +#ifdef ISC +#include /* Saul */ +#endif + +#include +#include +#include +#include +#include +#include +#if defined ___AIX || defined _AIX || defined __QNX__ || defined ___AIXV3 || defined AIXV3 || defined _SEQUENT_ +#include +#endif +#include +#include +#include +#include "../../fvwm/module.h" + +#include +#include +#include +#include +#include + +#include "FvwmScroll.h" +char *MyName; + +Display *dpy; /* which display are we talking to */ +int x_fd,fd_width; +int Width = 300, Height = 300; +int target_width, target_height; +int target_x_offset = 0, target_y_offset = 0; +int exposed; +int Reduction_H = 2; +int Reduction_V = 2; + +#define BAR_WIDTH 21 +#define SCROLL_BAR_WIDTH 9 + +#define PAD_WIDTH2 3 +#define PAD_WIDTH3 5 + +Window Root; +int screen; +int d_depth; + +Window main_win,holder_win; +Pixel back_pix, fore_pix, hilite_pix,shadow_pix; +GC ReliefGC, ShadowGC; +extern char *ForeColor,*BackColor; + +#define MW_EVENTS (ExposureMask | StructureNotifyMask| ButtonReleaseMask |\ + ButtonPressMask | ButtonMotionMask | FocusChangeMask) + +Atom wm_del_win; +Atom _XA_WM_PROTOCOLS; +Atom _XA_WM_COLORMAP_WINDOWS; + +/**************************************************************************** + * + * Draws the relief pattern around a window + * + ****************************************************************************/ +void RelieveWindow(Window win,int x,int y,int w,int h, + GC rgc,GC sgc) +{ + XSegment seg[4]; + int i; + + i=0; + seg[i].x1 = x; seg[i].y1 = y; + seg[i].x2 = w+x-1; seg[i++].y2 = y; + + seg[i].x1 = x; seg[i].y1 = y; + seg[i].x2 = x; seg[i++].y2 = h+y-1; + + seg[i].x1 = x+1; seg[i].y1 = y+1; + seg[i].x2 = x+w-2; seg[i++].y2 = y+1; + + seg[i].x1 = x+1; seg[i].y1 = y+1; + seg[i].x2 = x+1; seg[i++].y2 = y+h-2; + XDrawSegments(dpy, win, rgc, seg, i); + + i=0; + seg[i].x1 = x; seg[i].y1 = y+h-1; + seg[i].x2 = w+x-1; seg[i++].y2 = y+h-1; + + seg[i].x1 = x+w-1; seg[i].y1 = y; + seg[i].x2 = x+w-1; seg[i++].y2 = y+h-1; + if(d_depth<2) + XDrawSegments(dpy, win, ShadowGC, seg, i); + else + XDrawSegments(dpy, win, sgc, seg, i); + + i=0; + seg[i].x1 = x+1; seg[i].y1 = y+h-2; + seg[i].x2 = x+w-2; seg[i++].y2 = y+h-2; + + seg[i].x1 = x+w-2; seg[i].y1 = y+1; + seg[i].x2 = x+w-2; seg[i++].y2 = y+h-2; + + XDrawSegments(dpy, win, sgc, seg, i); +} + +/************************************************************************ + * + * Sizes and creates the window + * + ***********************************************************************/ +XSizeHints mysizehints; +void CreateWindow(int x,int y, int w, int h) +{ + XGCValues gcv; + unsigned long gcm; + + + wm_del_win = XInternAtom(dpy,"WM_DELETE_WINDOW",False); + _XA_WM_PROTOCOLS = XInternAtom (dpy, "WM_PROTOCOLS", False); + + mysizehints.flags = PWinGravity| PResizeInc | PBaseSize | + PMaxSize | PMinSize | USSize | USPosition; + /* subtract one for the right/bottom border */ + mysizehints.width_inc = 1; + mysizehints.height_inc = 1; + mysizehints.base_height = BAR_WIDTH+PAD_WIDTH3; + mysizehints.base_width = BAR_WIDTH+PAD_WIDTH3; + + Width = w/Reduction_H + BAR_WIDTH + PAD_WIDTH3; + Height = h/Reduction_V + BAR_WIDTH + PAD_WIDTH3; + target_width = w; + target_height = h; + mysizehints.width = Width; + mysizehints.height = Height; + mysizehints.x = x; + mysizehints.y = y; + mysizehints.max_width = w + BAR_WIDTH + PAD_WIDTH3; + mysizehints.max_height = h + BAR_WIDTH + PAD_WIDTH3; + + mysizehints.win_gravity = NorthWestGravity; + + if(d_depth < 2) + { + back_pix = GetColor("black"); + fore_pix = GetColor("white"); + hilite_pix = back_pix; + shadow_pix = fore_pix; + } + else + { + back_pix = GetColor(BackColor); + fore_pix = GetColor(ForeColor); + hilite_pix = GetHilite(fore_pix); + shadow_pix = GetShadow(fore_pix); + + } + + main_win = XCreateSimpleWindow(dpy,Root,mysizehints.x,mysizehints.y, + mysizehints.width,mysizehints.height, + 0,fore_pix,back_pix); + XSetWMProtocols(dpy,main_win,&wm_del_win,1); + + XSetWMNormalHints(dpy,main_win,&mysizehints); + XSelectInput(dpy,main_win,MW_EVENTS); + change_window_name(MyName); + + holder_win = XCreateSimpleWindow(dpy,main_win,PAD_WIDTH3,PAD_WIDTH3, + mysizehints.width-BAR_WIDTH -PAD_WIDTH3, + mysizehints.height-BAR_WIDTH-PAD_WIDTH3, + 0,fore_pix,back_pix); + XMapWindow(dpy,holder_win); + gcm = GCForeground|GCBackground; + gcv.foreground = hilite_pix; + gcv.background = fore_pix; + ReliefGC = XCreateGC(dpy, Root, gcm, &gcv); + + gcm = GCForeground|GCBackground; + gcv.foreground = shadow_pix; + gcv.background = fore_pix; + ShadowGC = XCreateGC(dpy, Root, gcm, &gcv); + + _XA_WM_COLORMAP_WINDOWS = XInternAtom (dpy, "WM_COLORMAP_WINDOWS", False); + } + + + + + + + +/**************************************************************************** + * + * This routine computes the shadow color from the background color + * + ****************************************************************************/ +Pixel GetShadow(Pixel background) +{ + XColor bg_color; + XWindowAttributes attributes; + + XGetWindowAttributes(dpy,Root,&attributes); + + bg_color.pixel = background; + XQueryColor(dpy,attributes.colormap,&bg_color); + + bg_color.red = (unsigned short)((bg_color.red*50)/100); + bg_color.green = (unsigned short)((bg_color.green*50)/100); + bg_color.blue = (unsigned short)((bg_color.blue*50)/100); + + if(!XAllocColor(dpy,attributes.colormap,&bg_color)) + nocolor("alloc shadow",""); + + 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,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 + + 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); + + if(!XAllocColor(dpy,attributes.colormap,&bg_color)) + nocolor("alloc hilight",""); + + return bg_color.pixel; +} + + +/**************************************************************************** + * + * Loads a single color + * + ****************************************************************************/ +Pixel GetColor(char *name) +{ + XColor color; + XWindowAttributes attributes; + + XGetWindowAttributes(dpy,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; +} + +/*********************************************************************** + * + * Procedure: + * Loop - wait for data to process + * + ***********************************************************************/ +#define RIGHT 7 +#define LEFT 6 +#define BOTTOM 5 +#define TOP 4 +#define QUIT 3 +#define VERTICAL 2 +#define HORIZONTAL 1 +#define NONE 0 +int motion = NONE; + +void Loop(Window target) +{ + Window root; + int x,y,border_width,depth; + XEvent Event; + int tw,th; + char *temp; + char *prop = NULL; + Atom actual = None; + int actual_format; + unsigned long nitems, bytesafter; + + while(1) + { + XNextEvent(dpy,&Event); + switch(Event.type) + { + case Expose: + exposed = 1; + RedrawWindow(target); + break; + + case ConfigureNotify: + XGetGeometry(dpy,main_win,&root,&x,&y, + (unsigned int *)&tw,(unsigned int *)&th, + (unsigned int *)&border_width, + (unsigned int *)&depth); + if((tw != Width)||(th!= Height)) + { + XResizeWindow(dpy,holder_win,tw-BAR_WIDTH,th-BAR_WIDTH); + Width = tw; + Height = th; + if(target_y_offset + Height - BAR_WIDTH > target_height) + target_y_offset = target_height - Height + BAR_WIDTH; + if(target_y_offset < 0) + target_y_offset = 0; + if(target_x_offset < 0) + target_x_offset = 0; + if(target_x_offset + Width - BAR_WIDTH > target_width) + target_x_offset = target_width - Width + BAR_WIDTH; + + XMoveWindow(dpy,target,-target_x_offset, -target_y_offset); + exposed = 1; + RedrawWindow(target); + } + break; + + case ButtonPress: + if((Event.xbutton.y > Height-BAR_WIDTH) && + (Event.xbutton.x < SCROLL_BAR_WIDTH+PAD_WIDTH3)) + { + motion = LEFT; + exposed = 2; + RedrawWindow(target); + } + else if((Event.xbutton.y > Height-BAR_WIDTH) && + (Event.xbutton.x > Width-BAR_WIDTH-SCROLL_BAR_WIDTH-2) && + (Event.xbutton.x < Width-BAR_WIDTH)) + { + motion = RIGHT; + exposed = 2; + RedrawWindow(target); + } + else if((Event.xbutton.y < SCROLL_BAR_WIDTH+PAD_WIDTH3) && + (Event.xbutton.x > Width-BAR_WIDTH)) + { + motion = TOP; + exposed = 2; + RedrawWindow(target); + } + else if((Event.xbutton.y > Height-BAR_WIDTH-SCROLL_BAR_WIDTH-2) && + (Event.xbutton.y < Height-BAR_WIDTH)&& + (Event.xbutton.x > Width-BAR_WIDTH)) + { + motion = BOTTOM; + exposed = 2; + RedrawWindow(target); + } + else if((Event.xbutton.x > Width - BAR_WIDTH)&& + (Event.xbutton.y < Height- BAR_WIDTH)) + { + + motion = VERTICAL; + target_y_offset=(Event.xbutton.y-PAD_WIDTH3-SCROLL_BAR_WIDTH)* + target_height/ + (Height-BAR_WIDTH-PAD_WIDTH3 - 2*SCROLL_BAR_WIDTH); + if(target_y_offset+Height-BAR_WIDTH -PAD_WIDTH3 > target_height) + target_y_offset = target_height - Height+BAR_WIDTH+PAD_WIDTH3; + if(target_y_offset < 0) + target_y_offset = 0; + XMoveWindow(dpy,target,-target_x_offset, -target_y_offset); + RedrawWindow(target); + } + else if((Event.xbutton.y > Height- BAR_WIDTH ) && + (Event.xbutton.x < Width- BAR_WIDTH)) + { + motion=HORIZONTAL; + target_x_offset=(Event.xbutton.x -PAD_WIDTH3-SCROLL_BAR_WIDTH)* + target_width/ + (Width-BAR_WIDTH-PAD_WIDTH3-2*SCROLL_BAR_WIDTH); + if(target_x_offset < 0) + target_x_offset = 0; + + if(target_x_offset + Width - BAR_WIDTH -PAD_WIDTH3> target_width) + target_x_offset = target_width - Width + BAR_WIDTH+PAD_WIDTH3; + XMoveWindow(dpy,target,-target_x_offset, -target_y_offset); + RedrawWindow(target); + } + else if((Event.xbutton.y > Height- BAR_WIDTH ) && + (Event.xbutton.x > Width- BAR_WIDTH)) + { + exposed = 2; + motion=QUIT; + } + RedrawWindow(target); + break; + + case ButtonRelease: + if((Event.xbutton.y > Height- BAR_WIDTH ) && + (Event.xbutton.x > Width- BAR_WIDTH)&& + (motion==QUIT)) + { + XUnmapWindow(dpy,main_win); + XReparentWindow(dpy,target,Root,x,y); + XSync(dpy,0); + exit(0); + } + if((motion == LEFT)&&(Event.xbutton.y > Height-BAR_WIDTH) && + (Event.xbutton.x < SCROLL_BAR_WIDTH+PAD_WIDTH3)) + { + target_x_offset -= (Width-BAR_WIDTH-PAD_WIDTH2); + if(target_x_offset < 0) + target_x_offset = 0; + XMoveWindow(dpy,target,-target_x_offset, -target_y_offset); + motion = NONE; + exposed = 2; + } + else if((motion == RIGHT)&&(Event.xbutton.y > Height-BAR_WIDTH) && + (Event.xbutton.x > Width-BAR_WIDTH-SCROLL_BAR_WIDTH-2) && + (Event.xbutton.x < Width-BAR_WIDTH)) + { + target_x_offset += (Width-BAR_WIDTH-PAD_WIDTH2); + if(target_x_offset+Width-BAR_WIDTH -PAD_WIDTH3 > target_width) + target_x_offset = target_width - Width+BAR_WIDTH+PAD_WIDTH3; + XMoveWindow(dpy,target,-target_x_offset, -target_y_offset); + motion = NONE; + exposed = 2; + } + else if((motion == TOP)&& + (Event.xbutton.y Width-BAR_WIDTH)) + { + target_y_offset -= (Height-BAR_WIDTH-PAD_WIDTH2); + if(target_y_offset < 0) + target_y_offset = 0; + XMoveWindow(dpy,target,-target_x_offset, -target_y_offset); + motion = NONE; + exposed = 2; + } + else if((motion == BOTTOM)&& + (Event.xbutton.y > Height-BAR_WIDTH-SCROLL_BAR_WIDTH-2) && + (Event.xbutton.y < Height-BAR_WIDTH)&& + (Event.xbutton.x > Width-BAR_WIDTH)) + { + target_y_offset += (Height-BAR_WIDTH-PAD_WIDTH2); + if(target_y_offset+Height-BAR_WIDTH -PAD_WIDTH3 > target_height) + target_y_offset = target_height - Height+BAR_WIDTH+PAD_WIDTH3; + XMoveWindow(dpy,target,-target_x_offset, -target_y_offset); + motion = NONE; + exposed = 2; + } + if(motion == VERTICAL) + { + target_y_offset=(Event.xbutton.y-PAD_WIDTH3-SCROLL_BAR_WIDTH)*target_height/ + (Height-BAR_WIDTH-PAD_WIDTH3 - 2*SCROLL_BAR_WIDTH); + if(target_y_offset+Height-BAR_WIDTH -PAD_WIDTH3 > target_height) + target_y_offset = target_height - Height+BAR_WIDTH+PAD_WIDTH3; + if(target_y_offset < 0) + target_y_offset = 0; + XMoveWindow(dpy,target,-target_x_offset, -target_y_offset); + } + if(motion == HORIZONTAL) + { + target_x_offset=(Event.xbutton.x -PAD_WIDTH3-SCROLL_BAR_WIDTH)* target_width/ + (Width-BAR_WIDTH-PAD_WIDTH3-2*SCROLL_BAR_WIDTH); + if(target_x_offset < 0) + target_x_offset = 0; + + if(target_x_offset + Width - BAR_WIDTH -PAD_WIDTH3> target_width) + target_x_offset = target_width - Width + BAR_WIDTH+PAD_WIDTH3; + XMoveWindow(dpy,target,-target_x_offset, -target_y_offset); + } + RedrawWindow(target); + motion = NONE; + break; + + case MotionNotify: + if((motion == LEFT)&&((Event.xmotion.y < Height-BAR_WIDTH) || + (Event.xmotion.x > SCROLL_BAR_WIDTH+PAD_WIDTH3))) + { + motion = NONE; + exposed = 2; + } + else if((motion == RIGHT)&&((Event.xmotion.y < Height-BAR_WIDTH) || + (Event.xmotion.x < Width-BAR_WIDTH-SCROLL_BAR_WIDTH-2) || + (Event.xmotion.x > Width-BAR_WIDTH))) + { + motion = NONE; + exposed = 2; + } + else if((motion == TOP)&& + ((Event.xmotion.y>SCROLL_BAR_WIDTH+PAD_WIDTH3)|| + (Event.xmotion.x < Width-BAR_WIDTH))) + { + motion = NONE; + exposed = 2; + } + else if((motion == BOTTOM)&& + ((Event.xmotion.y < Height-BAR_WIDTH-SCROLL_BAR_WIDTH-2) || + (Event.xmotion.y > Height-BAR_WIDTH)|| + (Event.xmotion.x < Width-BAR_WIDTH))) + { + motion = NONE; + exposed = 2; + } + if(motion == VERTICAL) + { + target_y_offset=(Event.xmotion.y-PAD_WIDTH3-SCROLL_BAR_WIDTH)* + target_height/ + (Height-BAR_WIDTH-PAD_WIDTH3-2*SCROLL_BAR_WIDTH); + if(target_y_offset+Height-BAR_WIDTH -PAD_WIDTH3 > target_height) + target_y_offset = target_height - Height+BAR_WIDTH+PAD_WIDTH3; + if(target_y_offset < 0) + target_y_offset = 0; + XMoveWindow(dpy,target,-target_x_offset, -target_y_offset); + } + if(motion == HORIZONTAL) + { + target_x_offset=(Event.xmotion.x -PAD_WIDTH3-SCROLL_BAR_WIDTH)* + target_width/ + (Width-BAR_WIDTH-PAD_WIDTH3-2*SCROLL_BAR_WIDTH); + if(target_x_offset < 0) + target_x_offset = 0; + + if(target_x_offset + Width - BAR_WIDTH -PAD_WIDTH3> target_width) + target_x_offset = target_width - Width + BAR_WIDTH+PAD_WIDTH3; + XMoveWindow(dpy,target,-target_x_offset, -target_y_offset); + } + if((motion == QUIT)&& + ((Event.xbutton.y < Height- BAR_WIDTH )|| + (Event.xbutton.x < Width- BAR_WIDTH))) + { + motion = NONE; + exposed = 2; + } + RedrawWindow(target); + break; + case ClientMessage: + if ((Event.xclient.format==32) && + (Event.xclient.data.l[0]==wm_del_win)) + { + DeadPipe(1); + } + break; + case PropertyNotify: + if(Event.xproperty.atom == XA_WM_NAME) + { + if(XFetchName(dpy, target, &temp)==0) + temp = NULL; + change_window_name(temp); + } + else if (Event.xproperty.atom == XA_WM_ICON_NAME) + { + if (XGetWindowProperty (dpy, + target, Event.xproperty.atom, 0, + MAX_ICON_NAME_LEN, False, XA_STRING, + &actual,&actual_format, &nitems, + &bytesafter, (unsigned char **) &prop) + == Success && (prop != NULL)) + change_icon_name(prop); + } + else if(Event.xproperty.atom == XA_WM_HINTS) + { + XWMHints *wmhints; + + wmhints = XGetWMHints(dpy,target); + XSetWMHints(dpy,main_win, wmhints); + XFree(wmhints); + } + else if(Event.xproperty.atom == XA_WM_NORMAL_HINTS) + { + /* don't do Normal Hints. They alter the size of the window */ + } + else if (Event.xproperty.atom == _XA_WM_COLORMAP_WINDOWS) + { + } + break; + + case DestroyNotify: + DeadPipe(1); + break; + + case UnmapNotify: + break; + + case MapNotify: + XMapWindow(dpy,main_win); + break; + case FocusIn: + XSetInputFocus(dpy,target,RevertToParent,CurrentTime); + break; + case ColormapNotify: + { + XWindowAttributes xwa; + if(XGetWindowAttributes(dpy,target, &xwa) != 0) + { + XSetWindowColormap(dpy,main_win,xwa.colormap); + } + } + break; + default: + break; + } + } + return; +} + + + +/************************************************************************ + * + * Draw the window + * + ***********************************************************************/ +void RedrawWindow(Window target) +{ + static int xv= 0,yv= 0,hv=0,wv=0; + static int xh=0,yh=0,hh=0,wh=0; + int x,y,w,h; + XEvent dummy; + + while (XCheckTypedWindowEvent (dpy, main_win, Expose, &dummy)) + exposed |= 1; + + XSetWindowBorderWidth(dpy,target,0); + + RelieveWindow(main_win,PAD_WIDTH3-2,PAD_WIDTH3-2, + Width-BAR_WIDTH-PAD_WIDTH3+4, + Height-BAR_WIDTH-PAD_WIDTH3+4,ShadowGC,ReliefGC); + + y = (Height-BAR_WIDTH-PAD_WIDTH3-2*SCROLL_BAR_WIDTH)* + target_y_offset/target_height + + PAD_WIDTH2 + 2 + SCROLL_BAR_WIDTH; + x = Width-SCROLL_BAR_WIDTH- PAD_WIDTH2-2; + w = SCROLL_BAR_WIDTH; + h = (Height-BAR_WIDTH-PAD_WIDTH3-2*SCROLL_BAR_WIDTH)* + (Height-BAR_WIDTH-PAD_WIDTH3)/ + target_height; + if((y!=yv)||(x != xv)||(w != wv)||(h != hv)||(exposed & 1)) + { + yv = y; + xv = x; + wv = w; + hv = h; + XClearArea(dpy,main_win,x,PAD_WIDTH3+SCROLL_BAR_WIDTH, + w,Height-BAR_WIDTH-PAD_WIDTH3-2*SCROLL_BAR_WIDTH,False); + + RelieveWindow(main_win,x,y,w,h,ReliefGC,ShadowGC); + } + if(exposed & 1) + RelieveWindow(main_win,x-2,PAD_WIDTH2, + w+4,Height-BAR_WIDTH-PAD_WIDTH2+2,ShadowGC,ReliefGC); + if(exposed) + { + if(motion == TOP) + RedrawTopButton(ShadowGC,ReliefGC,x,PAD_WIDTH3); + else + RedrawTopButton(ReliefGC,ShadowGC,x,PAD_WIDTH3); + if(motion == BOTTOM) + RedrawBottomButton(ShadowGC,ReliefGC,x, + Height-BAR_WIDTH-SCROLL_BAR_WIDTH); + else + RedrawBottomButton(ReliefGC,ShadowGC,x, + Height-BAR_WIDTH-SCROLL_BAR_WIDTH); + } + + x = (Width-BAR_WIDTH-PAD_WIDTH3-2*SCROLL_BAR_WIDTH)*target_x_offset/ + target_width+PAD_WIDTH2+2 + SCROLL_BAR_WIDTH; + y = Height-SCROLL_BAR_WIDTH-PAD_WIDTH2-2; + w = (Width-BAR_WIDTH-PAD_WIDTH3-2*SCROLL_BAR_WIDTH)* + (Width-BAR_WIDTH-PAD_WIDTH3)/target_width; + h = SCROLL_BAR_WIDTH; + if((y!=yh)||(x != xh)||(w != wh)||(h != hh)||(exposed & 1)) + { + yh = y; + xh = x; + wh = w; + hh = h; + XClearArea(dpy,main_win,PAD_WIDTH3+SCROLL_BAR_WIDTH,y, + Width-BAR_WIDTH-PAD_WIDTH3-2*SCROLL_BAR_WIDTH,h,False); + RelieveWindow(main_win,x,y,w,h,ReliefGC,ShadowGC); + } + if(exposed& 1) + { + RelieveWindow(main_win,PAD_WIDTH2,y-2,Width-BAR_WIDTH-PAD_WIDTH2+2,h+4, + ShadowGC,ReliefGC); + } + if(exposed) + { + if(motion == LEFT) + RedrawLeftButton(ShadowGC,ReliefGC,PAD_WIDTH3,y); + else + RedrawLeftButton(ReliefGC,ShadowGC,PAD_WIDTH3,y); + if(motion ==RIGHT) + RedrawRightButton(ShadowGC,ReliefGC, + Width-BAR_WIDTH-SCROLL_BAR_WIDTH,y); + else + RedrawRightButton(ReliefGC,ShadowGC, + Width-BAR_WIDTH-SCROLL_BAR_WIDTH,y); + } + + if(exposed) + { + XClearArea(dpy,main_win,Width-BAR_WIDTH+2, + Height-BAR_WIDTH+2,BAR_WIDTH-3,BAR_WIDTH-3,False); + if(motion == QUIT) + RelieveWindow(main_win,Width-SCROLL_BAR_WIDTH-PAD_WIDTH2-4, + Height-SCROLL_BAR_WIDTH-PAD_WIDTH2-4, + SCROLL_BAR_WIDTH+4,SCROLL_BAR_WIDTH+4, + ShadowGC,ReliefGC); + else + RelieveWindow(main_win,Width-SCROLL_BAR_WIDTH-PAD_WIDTH2-4, + Height-SCROLL_BAR_WIDTH-PAD_WIDTH2-4, + SCROLL_BAR_WIDTH+4,SCROLL_BAR_WIDTH+4, + ReliefGC,ShadowGC); + } + exposed = 0; +} + + +/************************************************************************** + * Change the window name displayed in the title bar. + **************************************************************************/ +void change_window_name(char *str) +{ + XTextProperty name; + + if(str == NULL) + return; + + if (XStringListToTextProperty(&str,1,&name) == 0) + { + fprintf(stderr,"%s: cannot allocate window name",MyName); + return; + } + XSetWMName(dpy,main_win,&name); + XFree(name.value); +} + + +/************************************************************************** + * Change the window name displayed in the icon. + **************************************************************************/ +void change_icon_name(char *str) +{ + XTextProperty name; + + if(str == NULL)return; + if (XStringListToTextProperty(&str,1,&name) == 0) + { + fprintf(stderr,"%s: cannot allocate window name",MyName); + return; + } + XSetWMIconName(dpy,main_win,&name); + XFree(name.value); +} + + +/*************************************************************************** + * + * ICCCM Client Messages - Section 4.2.8 of the ICCCM dictates that all + * client messages will have the following form: + * + * event type ClientMessage + * message type _XA_WM_PROTOCOLS + * window tmp->w + * format 32 + * data[0] message atom + * data[1] time stamp + * + ****************************************************************************/ +void send_clientmessage (Window w, Atom a, Time timestamp) +{ + XClientMessageEvent ev; + + ev.type = ClientMessage; + ev.window = w; + ev.message_type = _XA_WM_PROTOCOLS; + ev.format = 32; + ev.data.l[0] = a; + ev.data.l[1] = timestamp; + XSendEvent (dpy, w, False, 0L, (XEvent *) &ev); +} + + +void GrabWindow(Window target) +{ + char *temp; + Window Junk,root; + unsigned int tw,th,border_width,depth; + int x,y; + char *prop = NULL; + Atom actual = None; + int actual_format; + unsigned long nitems, bytesafter; + + XUnmapWindow(dpy,target); + XSync(dpy,0); + XGetGeometry(dpy,target,&root,&x,&y, + (unsigned int *)&tw,(unsigned int *)&th, + (unsigned int *)&border_width, + (unsigned int *)&depth); + XSync(dpy,0); + + XTranslateCoordinates(dpy, target, Root, 0, 0, &x,&y, &Junk); + + CreateWindow(x,y,tw,th); + XSetWindowBorderWidth(dpy,target,0); + XReparentWindow(dpy,target, holder_win,0,0); + XMapWindow(dpy,target); + XSelectInput(dpy,target, PropertyChangeMask|StructureNotifyMask| + ColormapChangeMask); + if(XFetchName(dpy, target, &temp)==0) + temp = NULL; + if (XGetWindowProperty (dpy, + target, XA_WM_ICON_NAME, 0, + MAX_ICON_NAME_LEN, False, XA_STRING, + &actual,&actual_format, &nitems, + &bytesafter, (unsigned char **) &prop) + == Success && (prop != NULL)) + { + change_icon_name(prop); + XFree(prop); + } + change_window_name(temp); + { + XWMHints *wmhints; + + wmhints = XGetWMHints(dpy,target); + if(wmhints != NULL) + { + XSetWMHints(dpy,main_win, wmhints); + XFree(wmhints); + } + } + { + XWindowAttributes xwa; + if(XGetWindowAttributes(dpy,target, &xwa) != 0) + { + XSetWindowColormap(dpy,main_win,xwa.colormap); + } + } + + XMapWindow(dpy,main_win); + RedrawWindow(target); + XFree(temp); +} + + + + + +void RedrawLeftButton(GC rgc, GC sgc,int x1,int y1) +{ + XSegment seg[4]; + int i=0; + + seg[i].x1 = x1+1; seg[i].y1 = y1+SCROLL_BAR_WIDTH/2; + seg[i].x2 = x1+SCROLL_BAR_WIDTH - 2; seg[i++].y2 = y1+1; + + seg[i].x1 = x1; seg[i].y1 = y1+SCROLL_BAR_WIDTH/2; + seg[i].x2 = x1+SCROLL_BAR_WIDTH - 1; seg[i++].y2 = y1; + XDrawSegments(dpy, main_win, rgc, seg, i); + + i = 0; + seg[i].x1 = x1+1; seg[i].y1 =y1+ SCROLL_BAR_WIDTH/2; + seg[i].x2 = x1+SCROLL_BAR_WIDTH - 2; seg[i++].y2 =y1+ SCROLL_BAR_WIDTH - 2; + + seg[i].x1 = x1; seg[i].y1 = y1+SCROLL_BAR_WIDTH/2; + seg[i].x2 = x1+SCROLL_BAR_WIDTH - 1; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 1; + + seg[i].x1 = x1+SCROLL_BAR_WIDTH - 2; seg[i].y1 = y1+1; + seg[i].x2 = x1+SCROLL_BAR_WIDTH - 2; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 2; + + seg[i].x1 = x1+SCROLL_BAR_WIDTH - 1; seg[i].y1 = y1; + seg[i].x2 = x1+SCROLL_BAR_WIDTH - 1; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 1; + XDrawSegments(dpy,main_win, sgc, seg, i); +} + +void RedrawRightButton(GC rgc, GC sgc,int x1,int y1) +{ + XSegment seg[4]; + int i=0; + + seg[i].x1 = x1+1; seg[i].y1 = y1+1; + seg[i].x2 = x1+1; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 2; + + seg[i].x1 = x1; seg[i].y1 = y1; + seg[i].x2 = x1; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 1; + + seg[i].x1 = x1+1; seg[i].y1 = y1+1; + seg[i].x2 = x1+SCROLL_BAR_WIDTH - 2; seg[i++].y2 = y1+SCROLL_BAR_WIDTH/2; + + seg[i].x1 = x1; seg[i].y1 = y1; + seg[i].x2 = x1+SCROLL_BAR_WIDTH - 1; seg[i++].y2 = y1+SCROLL_BAR_WIDTH/2; + + XDrawSegments(dpy, main_win, rgc, seg, i); + + i = 0; + seg[i].x1 = x1; seg[i].y1 = y1+SCROLL_BAR_WIDTH - 2; + seg[i].x2 = x1+SCROLL_BAR_WIDTH - 2; seg[i++].y2 = y1+SCROLL_BAR_WIDTH/2; + + seg[i].x1 = x1; seg[i].y1 = y1+SCROLL_BAR_WIDTH - 1; + seg[i].x2 = x1+SCROLL_BAR_WIDTH - 1; seg[i++].y2 = y1+SCROLL_BAR_WIDTH/2; + XDrawSegments(dpy,main_win, sgc, seg, i); +} + +void RedrawTopButton(GC rgc, GC sgc,int x1,int y1) +{ + XSegment seg[4]; + int i=0; + + seg[i].x1 = x1+SCROLL_BAR_WIDTH/2; seg[i].y1 = y1+1; + seg[i].x2 = x1+1; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 2; + + seg[i].x1 = x1+SCROLL_BAR_WIDTH/2; seg[i].y1 = y1; + seg[i].x2 = x1+0; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 1; + XDrawSegments(dpy, main_win, rgc, seg, i); + + i = 0; + seg[i].x1 = x1+SCROLL_BAR_WIDTH/2; seg[i].y1 = y1+1; + seg[i].x2 = x1+SCROLL_BAR_WIDTH - 2; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 2; + + seg[i].x1 = x1+SCROLL_BAR_WIDTH/2; seg[i].y1 = y1; + seg[i].x2 = x1+SCROLL_BAR_WIDTH - 1; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 1; + + seg[i].x1 = x1+1; seg[i].y1 = y1+SCROLL_BAR_WIDTH - 2; + seg[i].x2 = x1+SCROLL_BAR_WIDTH - 2; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 2; + + seg[i].x1 = x1+0; seg[i].y1 = y1+SCROLL_BAR_WIDTH - 1; + seg[i].x2 = x1+SCROLL_BAR_WIDTH - 1; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 1; + XDrawSegments(dpy,main_win, sgc, seg, i); +} + +void RedrawBottomButton(GC rgc, GC sgc,int x1, int y1) +{ + XSegment seg[4]; + int i=0; + + seg[i].x1 = x1+1; seg[i].y1 = y1+1; + seg[i].x2 = x1+SCROLL_BAR_WIDTH/2; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 2; + + seg[i].x1 = x1; seg[i].y1 = y1+0; + seg[i].x2 = x1+SCROLL_BAR_WIDTH/2; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 1; + + seg[i].x1 = x1+1; seg[i].y1 = y1+1; + seg[i].x2 = x1+SCROLL_BAR_WIDTH - 2; seg[i++].y2 = y1+1; + + seg[i].x1 = x1; seg[i].y1 = y1+0; + seg[i].x2 = x1+SCROLL_BAR_WIDTH - 1; seg[i++].y2 = y1+0; + XDrawSegments(dpy,main_win, rgc, seg, i); + + i = 0; + seg[i].x1 = x1+SCROLL_BAR_WIDTH - 2; seg[i].y1 = y1+1; + seg[i].x2 = x1+SCROLL_BAR_WIDTH/2; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 2; + + seg[i].x1 = x1+SCROLL_BAR_WIDTH - 1; seg[i].y1 = y1+0; + seg[i].x2 = x1+SCROLL_BAR_WIDTH/2; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 1; + XDrawSegments(dpy, main_win, sgc, seg, i); +} + diff --git a/modules/FvwmScroll/Imakefile b/modules/FvwmScroll/Imakefile new file mode 100644 index 0000000..2652a2d --- /dev/null +++ b/modules/FvwmScroll/Imakefile @@ -0,0 +1,29 @@ +/* Imakefile for FvwmScroll */ +/* Thu Aug 5 11:21:36 MET DST 1993, mj@dfv.rwth-aachen.de */ + +/* setup is done entirely in configuration.h now! */ +/* You should need to do much in here, excpt maybe add libraries */ + +/* I need to get the #define XPM from configuration.h if its in there,*/ +/* so that I can tell if I should include -lXpm */ +#include <../../configure.h> + +COMPILER + +DEPLIBS = $(DEPXLIB) ../../libs/libfvwmlib.a + +#ifdef AlphaArchitecture +LOCAL_LIBRARIES = $(XLIB) -ldnet_stub -L../../libs -lfvwmlib +#else +LOCAL_LIBRARIES = $(XLIB) -L../../libs -lfvwmlib +#endif + +LINTLIBS = $(LINTXLIB) + +SRCS = FvwmScroll.c GrabWindow.c +OBJS = FvwmScroll.o GrabWindow.o + +TARGET_DIR + +ComplexProgramTarget(FvwmScroll) + diff --git a/modules/FvwmWinList/ButtonArray.c b/modules/FvwmWinList/ButtonArray.c new file mode 100644 index 0000000..39e157a --- /dev/null +++ b/modules/FvwmWinList/ButtonArray.c @@ -0,0 +1,253 @@ +/* FvwmWinList Module for Fvwm. + * + * Copyright 1994, Mike Finger (mfinger@mermaid.micro.umn.edu or + * Mike_Finger@atk.com) + * + * The functions in this source file that are the original work of Mike Finger. + * + * No guarantees or warantees or anything are provided or implied in any way + * whatsoever. Use this program at your own risk. Permission to use this + * program for any purpose is given, as long as the copyright is kept intact. + * + * Things to do: Convert to C++ (In Progress) + */ + +#include +#include +#include +#include "ButtonArray.h" +#include "Mallocs.h" + +#ifndef min +#define min(a,b) (((a)<(b)) ? (a) : (b)) +#define max(a,b) (((a)>(b)) ? (a) : (b)) +#endif + +extern XFontStruct *ButtonFont; +extern Display *dpy; +extern Window win; +extern GC shadow,hilite,graph; + +/****************************************************************************** + InitArray - Initialize the arrary of buttons +******************************************************************************/ +void InitArray(ButtonArray *array,int x,int y,int w,int h) +{ + array->count=0; + array->head=array->tail=NULL; + array->x=x; + array->y=y; + array->w=w; + array->h=h; +} + +/****************************************************************************** + UpdateArray - Update the array specifics. x,y, width, height +******************************************************************************/ +void UpdateArray(ButtonArray *array,int x,int y,int w, int h) +{ +Button *temp; + if (x!=-1) array->x=x; + if (y!=-1) array->y=y; + if (w!=-1) array->w=w; + if (h!=-1) array->h=h; + for(temp=array->head;temp!=NULL;temp=temp->next) temp->needsupdate=1; +} + +/****************************************************************************** + AddButton - Allocate space for and add the button to the bottom +******************************************************************************/ +int AddButton(ButtonArray *array, char *title, int up) +{ +Button *new; + new=(Button *)safemalloc(sizeof(Button)); + new->title=safemalloc(strlen(title)+1); + strcpy(new->title,title); + new->up=up; + new->tw=XTextWidth(ButtonFont,title,strlen(title)); + new->next=NULL; + new->needsupdate=1; + + if (array->head==NULL) array->head=array->tail=new; + else { + array->tail->next=new; + array->tail=new; + } + array->count++; + return (array->count-1); +} + +/****************************************************************************** + UpdateButton - Change the name/stae of a button +******************************************************************************/ +int UpdateButton(ButtonArray *array, int butnum, char *title, int up) +{ +Button *temp; + temp=find_n(array,butnum); + if (temp!=NULL) { + if (title!=NULL) { + temp->title=(char *)realloc(temp->title,strlen(title)+1); + strcpy(temp->title,title); + temp->tw=XTextWidth(ButtonFont,title,strlen(title)); + } + if (up!=-1) temp->up=up; + } else return -1; + temp->needsupdate=1; + return 1; +} + +/****************************************************************************** + RemoveButton - Delete a button from the list +******************************************************************************/ +void RemoveButton(ButtonArray *array, int butnum) +{ +Button *temp,*temp2; + if (butnum==0) { + temp2=array->head; + temp=array->head=array->head->next; + } else { + temp=find_n(array,butnum-1); + if (temp==NULL) return; + temp2=temp->next; + temp->next=temp2->next; + } + + if (array->tail==temp2) array->tail=temp; + + FreeButton(temp2); + + if (temp!=array->head) temp=temp->next; + for(temp;temp!=NULL;temp=temp->next) temp->needsupdate=1; +} + +/****************************************************************************** + find_n - Find the nth button in the list (Use internally) +******************************************************************************/ +Button *find_n(ButtonArray *array, int n) +{ +Button *temp; +int i; + temp=array->head; + for(i=0;inext); + return temp; +} + +/****************************************************************************** + FreeButton - Free space allocated to a button +******************************************************************************/ +void FreeButton(Button *ptr) +{ + if (ptr != NULL) { + if (ptr->title!=NULL) free(ptr->title); + free(ptr); + } +} + +/****************************************************************************** + FreeAllButtons - Free the whole array of buttons +******************************************************************************/ +void FreeAllButtons(ButtonArray *array) +{ +Button *temp,*temp2; + for(temp=array->head;temp!=NULL;) { + temp2=temp; + temp=temp->next; + FreeButton(temp2); + } +} + +/****************************************************************************** + DoButton - Draw the specified button. (Used internally) +******************************************************************************/ +void DoButton(Button *ptr, int x, int y, int w, int h) +{ +int up,Fontheight,newx; + up=ptr->up; + + Fontheight=ButtonFont->ascent+ButtonFont->descent; + + XClearArea(dpy,win,x,y,w,h,False); + XDrawLine(dpy,win,(up) ? hilite : shadow,x,y,x+w-1,y); + XDrawLine(dpy,win,(up) ? hilite : shadow,x,y+1,x+w-2,y+1); + + XDrawLine(dpy,win,(up) ? hilite : shadow,x,y,x,y+h-1); + XDrawLine(dpy,win,(up) ? hilite : shadow,x+1,y,x+1,y+h-2); + + XDrawLine(dpy,win,(up) ? shadow : hilite,x,y+h,x+w,y+h); + XDrawLine(dpy,win,(up) ? shadow : hilite,x+1,y+h-1,x+w,y+h-1); + + XDrawLine(dpy,win,(up) ? shadow : hilite,x+w,y+h,x+w,y); + XDrawLine(dpy,win,(up) ? shadow : hilite,x+w-1,y+h,x+w-1,y+1); + newx=(w-ptr->tw)/2; + XDrawString(dpy,win,graph,x+newx,y+3+ButtonFont->ascent,ptr->title,strlen(ptr->title)); + ptr->needsupdate=0; +} + +/****************************************************************************** + DrawButtonArray - Draw the whole array (all=1), or only those that need. +******************************************************************************/ +void DrawButtonArray(ButtonArray *array,int all) +{ +Button *temp; +int i; + for(temp=array->head,i=0;temp!=NULL;temp=temp->next,i++) + if (temp->needsupdate || all) { + DoButton(temp,array->x,array->y+(i*(array->h+1)),array->w,array->h); + } +} + +/****************************************************************************** + SwitchButton - Alternate the state of a button +******************************************************************************/ +void SwitchButton(ButtonArray *array,int butnum) +{ +Button *temp; + temp=find_n(array,butnum); + temp->up=!temp->up; + temp->needsupdate=1; + DrawButtonArray(array,0); +} + +/****************************************************************************** + WhichButton - Based on x,y which button was pressed +******************************************************************************/ +int WhichButton(ButtonArray *array,int x, int y) +{ +int num; + num=y/(array->h+1); + if (xx || x>array->x+array->w || num<0 || num>array->count-1) num=-1; + return(num); +} + +/****************************************************************************** + ButtonName - Return the name of the button +******************************************************************************/ +char *ButtonName(ButtonArray *array, int butnum) +{ +Button *temp; + temp=find_n(array,butnum); + return temp->title; +} + +/****************************************************************************** + PrintButtons - Print the array of button names to the console. (Debugging) +******************************************************************************/ +void PrintButtons(ButtonArray *array) +{ +Button *temp; + ConsoleMessage("List of Buttons:\n"); + for(temp=array->head;temp!=NULL;temp=temp->next) + ConsoleMessage(" %s is %s\n",temp->title,(temp->up) ? "Up":"Down"); +} + +/****************************************************************************** + ButtonArrayMaxWidth - Calculate the width needed for the widest title +******************************************************************************/ +int ButtonArrayMaxWidth(ButtonArray *array) +{ +Button *temp; +int x=0; + for(temp=array->head;temp!=NULL;temp=temp->next) + x=max(temp->tw,x); + return x; +} diff --git a/modules/FvwmWinList/ButtonArray.h b/modules/FvwmWinList/ButtonArray.h new file mode 100644 index 0000000..b2c82df --- /dev/null +++ b/modules/FvwmWinList/ButtonArray.h @@ -0,0 +1,41 @@ +/* FvwmWinList Module for Fvwm. + * + * Copyright 1994, Mike Finger (mfinger@mermaid.micro.umn.edu or + * Mike_Finger@atk.com) + * + * The functions in this header file that are the original work of Mike Finger. + * + * No guarantees or warantees or anything are provided or implied in any way + * whatsoever. Use this program at your own risk. Permission to use this + * program for any purpose is given, as long as the copyright is kept intact. + * + * Things to do: Convert to C++ (In Progress) + */ + +/* Struct definitions */ +typedef struct button { + char *title; + int up,needsupdate,tw; + struct button *next; +} Button; + +typedef struct { + int count; + Button *head,*tail; + int x,y,w,h; +} ButtonArray; + +/* Function Prototypes */ +void InitArray(ButtonArray *array,int x,int y,int w,int h); +void UpdateArray(ButtonArray *array,int x,int y,int w, int h); +int AddButton(ButtonArray *array, char *title, int up); +int UpdateButton(ButtonArray *array, int butnum, char *title, int up); +void RemoveButton(ButtonArray *array, int butnum); +Button *find_n(ButtonArray *array, int n); +void FreeButton(Button *ptr); +void FreeAllButtons(ButtonArray *array); +void DoButton(Button *ptr, int x, int y, int w, int h); +void DrawButtonArray(ButtonArray *array, int all); +void SwitchButton(ButtonArray *array,int butnum); +int WhichButton(ButtonArray *array,int x, int y); +void PrintButtons(ButtonArray *array); diff --git a/modules/FvwmWinList/CHANGELOG b/modules/FvwmWinList/CHANGELOG new file mode 100644 index 0000000..8a1c871 --- /dev/null +++ b/modules/FvwmWinList/CHANGELOG @@ -0,0 +1,64 @@ +March 21st, 1994: (All the patches should have been fixed/replaced by new mods) + - Changed to + - Added to Mallocs.c + - Fonts now work. (Stupid me) + - Added options: + *FvwmWinListGeometry {+-}{+-}x (size is ignored) + *FvwmWinListAction + Only Click1, Click2, Click3 are allowed as actions right now + Responses can be any Fvwm built in, or a comma seperated list of such. + (ie: '*FvwmWinListAction Click1 Iconify -1, Raise' will deiconify the + window and then raise it) + Click1 defaults to 'Iconify -1, Raise' + Click2 defaults to 'Iconify' + Click3 defaults to 'Lower' + (See config.sample for an example) + *FvwmWinListUseSkipList + Will not show the windows listed in a 'WindowListSkip' line. + *FvwmWinListNoAnchor + FvwmWinList will, by default, anchor the corner which has gravity, use + this to undo it. (btw, NW gravity and NoAnchor provide the same result. + (+x+y=NorthWest,+x-y=SouthWest,-x+y=NorthEast,-x-y=SouthEast) + This is so you can place the window list in the lower corners and + the list will not wrap past the screen edge. + +March 25st, 1994: (The patch should have be fixed/replaced by new mods) + - FvwmWinListUseIconNames + As it says, it will use the icon names instead of using the window + names. People have mentioned that some window names become to long. + - FvwmWinList now skips windows if the name in the WindowListSkip line + matches the windows name, icon name, resource name, or resource class. + (This is the same way the built-in fvwm window list works) + - Changed some code so it doesn't redraw the window so often. + - Added man page. + +April 5th, 1994: (Patches should be overtaken by this release) + - Allowed FvwmWinList to be started up with an arguemnt 'Transient' to allow + it to work like the build in window list. Right now if you use it in + transient mode it will only execute the command for Click1. Looking + for suggestions about using other buttons. Was considering using + modifiers (ie. Shift means button 2, etc) + - FvwmWinList now uses MWMDecorHints. (Makes the 'Transient' mode look good) + - Buttons now stay down until you actually release the button. You can click + and hold the button down and move across the buttons and the will go up + and down as to enter leave the area. Actions are performed on button + release and not on press. + - FvwmWinList will unmap itself if it has no windows to display and will + remap itself when a new window it can display is opened. If there + are no windows to display and you are using it in transient mode, it + will not come up. + +April 16th, 1994: + - Patched to use the new style way of WindowSkipList + - Cleaned up some definitions + +May 8th, 1994: This patch replaces the April 16th patch + - Re-did the patch because of bad hunk. + - Added strcasecmp for those who have 'NEED_STRCASECMP' defined. + - Fixed WinList drifting problem with BorderWidth of 0 + +May 9th, 1994: + - Removed support for the old style of WindowSkipList, you must use Styles. + - Hopefully, the above will speed up processing of the list from fvwm and + it will not hang. Please let me know if you still have problems, you + might. diff --git a/modules/FvwmWinList/Colors.c b/modules/FvwmWinList/Colors.c new file mode 100644 index 0000000..8afbadc --- /dev/null +++ b/modules/FvwmWinList/Colors.c @@ -0,0 +1,105 @@ +/* Part of the FvwmWinList Module for Fvwm. + * + * Copyright 1994, Mike Finger (mfinger@mermaid.micro.umn.edu or + * Mike_Finger@atk.com) + * + * The author makes not guarantees or warantees, either express or + * implied. Feel free to use any contained here for any purpose, as long + * and this and any other applicible copyrights are kept intact. + + * The functions in this source file were originally part of the GoodStuff + * and FvwmIdent modules for Fvwm, so there copyrights are also included: + * + * Copyright 1994, Robert Nation and Nobutaka Suzuki. + * No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. */ + +#include "../../configure.h" +#include +#include +#include "Colors.h" + +#ifndef min +#define min(a,b) (((a)<(b)) ? (a) : (b)) +#define max(a,b) (((a)>(b)) ? (a) : (b)) +#endif + +extern Display *dpy; +extern Window Root; + +/**************************************************************************** + Loads a single color +*****************************************************************************/ +Pixel GetColor(char *name) +{ + XColor color; + XWindowAttributes attributes; + + XGetWindowAttributes(dpy,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; +} + +/**************************************************************************** + This routine computes the hilight color from the background color +*****************************************************************************/ +Pixel GetHilite(Pixel background) +{ + XColor bg_color, white_p; + XWindowAttributes attributes; + + XGetWindowAttributes(dpy,Root,&attributes); + + bg_color.pixel = background; + XQueryColor(dpy,attributes.colormap,&bg_color); + + white_p.pixel = GetColor("white"); + XQueryColor(dpy,attributes.colormap,&white_p); + + 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); + + if(!XAllocColor(dpy,attributes.colormap,&bg_color)) + nocolor("alloc hilight",""); + + return bg_color.pixel; +} + +/**************************************************************************** + This routine computes the shadow color from the background color +*****************************************************************************/ +Pixel GetShadow(Pixel background) +{ + XColor bg_color; + XWindowAttributes attributes; + + XGetWindowAttributes(dpy,Root,&attributes); + + bg_color.pixel = background; + XQueryColor(dpy,attributes.colormap,&bg_color); + + bg_color.red = (unsigned short)((bg_color.red*50)/100); + bg_color.green = (unsigned short)((bg_color.green*50)/100); + bg_color.blue = (unsigned short)((bg_color.blue*50)/100); + + if(!XAllocColor(dpy,attributes.colormap,&bg_color)) + nocolor("alloc shadow",""); + + return bg_color.pixel; +} + +void nocolor(char *a, char *b) +{ + fprintf(stderr,"FvwmWinList: can't %s %s\n", a,b); +} diff --git a/modules/FvwmWinList/Colors.h b/modules/FvwmWinList/Colors.h new file mode 100644 index 0000000..0a36186 --- /dev/null +++ b/modules/FvwmWinList/Colors.h @@ -0,0 +1,19 @@ +/* Part of the FvwmWinList Module for Fvwm. + * + * The functions in this header file were originally part of the GoodStuff + * and FvwmIdent modules for Fvwm, so there copyrights are listed: + * + * Copyright 1994, Robert Nation and Nobutaka Suzuki. + * No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. */ + +#include + +/* Function Prototypes */ +Pixel GetColor(char *name); +Pixel GetHilite(Pixel background); +Pixel GetShadow(Pixel background); +void nocolor(char *a, char *b); + diff --git a/modules/FvwmWinList/FvwmWinList.c b/modules/FvwmWinList/FvwmWinList.c new file mode 100644 index 0000000..bfeaa1a --- /dev/null +++ b/modules/FvwmWinList/FvwmWinList.c @@ -0,0 +1,804 @@ +/* FvwmWinList Module for Fvwm. + * + * Copyright 1994, Mike Finger (mfinger@mermaid.micro.umn.edu or + * Mike_Finger@atk.com) + * + * The author makes not guarantees or warantees, either express or + * implied. Feel free to use any contained here for any purpose, as long + * and this and any other applicible copyrights are kept intact. + + * The functions in this source file that are based on part of the FvwmIdent + * module for Fvwm are noted by a small copyright atop that function, all others + * are copyrighted by Mike Finger. For those functions modified/used, here is + * the full, origonal copyright: + * + * Copyright 1994, Robert Nation and Nobutaka Suzuki. + * No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. */ + +#define TRUE 1 +#define FALSE + +#define NO_CONSOLE + +#ifndef min +#define min(a,b) (((a)<(b)) ? (a) : (b)) +#define max(a,b) (((a)>(b)) ? (a) : (b)) +#endif + +#define YES "Yes" +#define NO "No" + +#include "../../configure.h" + +#include +#include +#include +#include +#include +#include +#include +#if defined ___AIX || defined _AIX || defined __QNX__ || defined ___AIXV3 || defined AIXV3 || defined _SEQUENT_ +#include +#endif +#include +#include +#ifdef ISC /* Saul */ +#include /* Saul */ +#endif /* Saul */ +#include +#include +#include +#include +#include +#include +#include + +#include "../../fvwm/module.h" +#include "../../version.h" +#include "FvwmWinList.h" +#include "ButtonArray.h" +#include "List.h" +#include "Colors.h" +#include "Mallocs.h" + +#define GRAB_EVENTS (ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|EnterWindowMask|LeaveWindowMask) + +#define SomeButtonDown(a) ((a)&Button1Mask||(a)&Button2Mask||(a)&Button3Mask) + +/* File type information */ +FILE *console; +int fd_width; +int Fvwm_fd[2]; +int x_fd; + +/* X related things */ +Display *dpy; +Window Root, win; +int screen,d_depth,ScreenWidth,ScreenHeight; +Pixel back, fore; +GC graph,shadow,hilite; +XFontStruct *ButtonFont; +int fontheight; +static Atom wm_del_win; +Atom MwmAtom = None; + +/* Module related information */ +char *Module; +int WindowIsUp=0,win_width=5,win_height=5,win_grav,win_x,win_y,win_title,win_border; +int Clength,Transient=0,Pressed=0,ButPressed,Checked=0; +ButtonArray buttons; +List windows; +char *ClickAction[3]={"Iconify -1,Raise","Iconify","Lower"},*EnterAction, + *BackColor = "white",*ForeColor = "black",*geometry=""; +char *font_string = "fixed"; +int UseSkipList=0,Anchor=1,UseIconNames=0; + +/****************************************************************************** + Main - Setup the XConnection,request the window list and loop forever + Based on main() from FvwmIdent: + Copyright 1994, Robert Nation and Nobutaka Suzuki. +******************************************************************************/ +void main(int argc, char **argv) +{ +char *temp, *s; + + /* Open the console for messages */ + OpenConsole(); + + /* Save the program name for error messages and config parsing */ + temp = argv[0]; + s=strrchr(argv[0], '/'); + if (s != NULL) + temp = s + 1; + + /* Setup my name */ + Module = safemalloc(strlen(temp)+2); + strcpy(Module,"*"); + strcat(Module, temp); + Clength = strlen(Module); + + if((argc != 6)&&(argc != 7)) { + fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",Module, + VERSION); + ConsoleMessage("%s Version %s should only be executed by fvwm!\n",Module, + VERSION); + exit(1); + } + + + if ((argc==7)&&(!mystrcasecmp(argv[6],"Transient"))) Transient=1; + + Fvwm_fd[0] = atoi(argv[1]); + Fvwm_fd[1] = atoi(argv[2]); + + signal (SIGPIPE, DeadPipe); + + /* Parse the config file */ + ParseConfig(argv[3]); + + /* Setup the XConnection */ + StartMeUp(); + + InitArray(&buttons,0,0,win_width,fontheight+6); + InitList(&windows); + + fd_width = GetFdWidth(); + + /* Request a list of all windows, + * wait for ConfigureWindow packets */ + SendFvwmPipe("Send_WindowList",0); + + /* Recieve all messages from Fvwm */ + EndLessLoop(); +} + +/****************************************************************************** + EndLessLoop - Read and redraw until we get killed, blocking when can't read +******************************************************************************/ +void EndLessLoop() +{ +fd_set readset; +struct timeval tv; + + while(1) { + FD_ZERO(&readset); + FD_SET(Fvwm_fd[1],&readset); + FD_SET(x_fd,&readset); + tv.tv_sec=0; + tv.tv_usec=0; +#ifdef __hpux + if (!select(fd_width,(int *)&readset,NULL,NULL,&tv)) { + XPending(dpy); + FD_ZERO(&readset); + FD_SET(Fvwm_fd[1],&readset); + FD_SET(x_fd,&readset); + select(fd_width,(int *)&readset,NULL,NULL,NULL); + } +#else + if (!select(fd_width,&readset,NULL,NULL,&tv)) { + XPending(dpy); + FD_ZERO(&readset); + FD_SET(Fvwm_fd[1],&readset); + FD_SET(x_fd,&readset); + select(fd_width,&readset,NULL,NULL,NULL); + } +#endif + if (FD_ISSET(x_fd,&readset)) LoopOnEvents(); + if (!FD_ISSET(Fvwm_fd[1],&readset)) continue; + ReadFvwmPipe(); + } +} + +/****************************************************************************** + ReadFvwmPipe - Read a single message from the pipe from Fvwm + Originally Loop() from FvwmIdent: + Copyright 1994, Robert Nation and Nobutaka Suzuki. +******************************************************************************/ +void ReadFvwmPipe() +{ + int count,total,count2=0,body_length; + unsigned long header[3],*body; + char *cbody; + if(ReadFvwmPacket(Fvwm_fd[1],header,&body) > 0) + { + ProcessMessage(header[1],body); + free(body); + } +} + +/****************************************************************************** + ProcessMessage - Process the message coming from Fvwm + Skeleton based on processmessage() from FvwmIdent: + Copyright 1994, Robert Nation and Nobutaka Suzuki. +******************************************************************************/ +void ProcessMessage(unsigned long type,unsigned long *body) +{ +int redraw=0,i; +long flags; +char *name,*string; + + switch(type) { + case M_ADD_WINDOW: + case M_CONFIGURE_WINDOW: + if (body[0]==win) { + win_x=(int)body[3]; + win_y=(int)body[4]; + win_title=(int)body[9]; + win_border=(int)body[10]; + if (win_border!=0) win_border++; + } + if (FindItem(&windows,body[0])!=-1) break; + if (!(body[8]&WINDOWLISTSKIP) || !UseSkipList) + AddItem(&windows,body[0],body[8]); + break; + case M_DESTROY_WINDOW: + if ((i=DeleteItem(&windows,body[0]))==-1) break; + RemoveButton(&buttons,i); + if (WindowIsUp) AdjustWindow(); + redraw=1; + break; + case M_WINDOW_NAME: + case M_ICON_NAME: + if ((type==M_ICON_NAME && !UseIconNames) || + (type==M_WINDOW_NAME && UseIconNames)) break; + if ((i=UpdateItemName(&windows,body[0],(char *)&body[3]))==-1) break; + string=(char *)&body[3]; + name=makename(string,ItemFlags(&windows,body[0])); + if (UpdateButton(&buttons,i,name,-1)==-1) + AddButton(&buttons,name,1); + free(name); + if (WindowIsUp) AdjustWindow(); + redraw=1; + break; + case M_DEICONIFY: + case M_ICONIFY: + if ((i=FindItem(&windows,body[0]))==-1) break; + flags=ItemFlags(&windows,body[0]); + if (type==M_DEICONIFY && !(flags&ICONIFIED)) break; + if (type==M_ICONIFY && flags&ICONIFIED) break; + flags^=ICONIFIED; + UpdateItemFlags(&windows,body[0],flags); + string=ItemName(&windows,i); + name=makename(string,flags); + if (UpdateButton(&buttons,i,name,-1)!=-1) redraw=1; + free(name); + break; + case M_END_WINDOWLIST: + if (!WindowIsUp) MakeMeWindow(); + redraw=1; + break; + case M_NEW_DESK: + break; + case M_NEW_PAGE: + break; + } + + if (redraw && WindowIsUp==1) RedrawWindow(0); +} + +/****************************************************************************** + SendFvwmPipe - Send a message back to fvwm + Based on SendInfo() from FvwmIdent: + Copyright 1994, Robert Nation and Nobutaka Suzuki. +******************************************************************************/ +void SendFvwmPipe(char *message,unsigned long window) +{ +int w; +char *hold,*temp,*temp_msg; + hold=message; + + while(1) { + temp=strchr(hold,','); + if (temp!=NULL) { + temp_msg=malloc(temp-hold+1); + strncpy(temp_msg,hold,(temp-hold)); + temp_msg[(temp-hold)]='\0'; + hold=temp+1; + } else temp_msg=hold; + + write(Fvwm_fd[0],&window, sizeof(unsigned long)); + + w=strlen(temp_msg); + write(Fvwm_fd[0],&w,sizeof(int)); + write(Fvwm_fd[0],temp_msg,w); + + /* keep going */ + w=1; + write(Fvwm_fd[0],&w,sizeof(int)); + + if(temp_msg!=hold) free(temp_msg); + else break; + } +} + +/*********************************************************************** + Detected a broken pipe - time to exit + Based on DeadPipe() from FvwmIdent: + Copyright 1994, Robert Nation and Nobutaka Suzuki. + **********************************************************************/ +void DeadPipe(int nonsense) +{ + ShutMeDown(1); +} + +/****************************************************************************** + WaitForExpose - Used to wait for expose event so we don't draw too early +******************************************************************************/ +void WaitForExpose(void) +{ +XEvent Event; + while(1) { + XNextEvent(dpy,&Event); + if (Event.type==Expose) { + if (Event.xexpose.count==0) break; + } + } +} + +/****************************************************************************** + RedrawWindow - Update the needed lines and erase any old ones +******************************************************************************/ +void RedrawWindow(int force) +{ + DrawButtonArray(&buttons,force); + if (XQLength(dpy) && !force) LoopOnEvents(); +} + +/****************************************************************************** + ConsoleMessage - Print a message on the console. Works like printf. +******************************************************************************/ +void ConsoleMessage(char *fmt, ...) +{ +#ifndef NO_CONSOLE +va_list args; +FILE *filep; + if (console==NULL) filep=stderr; + else filep=console; + va_start(args,fmt); + vfprintf(filep,fmt,args); + va_end(args); +#endif +} + +/****************************************************************************** + OpenConsole - Open the console as a way of sending messages +******************************************************************************/ +int OpenConsole() +{ +#ifndef NO_CONSOLE + if ((console=fopen("/dev/console","w"))==NULL) { + fprintf(stderr,"%s: cannot open console\n",Module); + return 0; + } +#endif + return 1; +} + +/****************************************************************************** + ParseConfig - Parse the configuration file fvwm to us to use + Based on part of main() from FvwmIdent: + Copyright 1994, Robert Nation and Nobutaka Suzuki. +******************************************************************************/ +void ParseConfig(char *file) +{ +char line[256]; +char *tline; +FILE *ptr; + ptr=fopen(file,"r"); + if(ptr != (FILE *)NULL) { + + tline = fgets(line,(sizeof line)-1,ptr); + while(tline != (char *)0) { + while(isspace(*tline))tline++; + if(strlen(tline)>1) { + if(mystrncasecmp(tline, CatString3(Module, "Font",""),Clength+4)==0) + CopyString(&font_string,&tline[Clength+4]); + else if(mystrncasecmp(tline,CatString3(Module,"Fore",""), Clength+4)==0) + CopyString(&ForeColor,&tline[Clength+4]); + else if(mystrncasecmp(tline,CatString3(Module, "Geometry",""), Clength+8)==0) + CopyString(&geometry,&tline[Clength+8]); + else if(mystrncasecmp(tline,CatString3(Module, "Back",""), Clength+4)==0) + CopyString(&BackColor,&tline[Clength+4]); + else if(mystrncasecmp(tline,CatString3(Module, "NoAnchor",""), + Clength+8)==0) Anchor=0; + else if(mystrncasecmp(tline,CatString3(Module, "Action",""), Clength+6)==0) + LinkAction(&tline[Clength+6]); + else if(mystrncasecmp(tline,CatString3(Module, "UseSkipList",""), + Clength+11)==0) UseSkipList=1; + else if(mystrncasecmp(tline,CatString3(Module, "UseIconNames",""), + Clength+12)==0) UseIconNames=1; + } + tline = fgets(line,(sizeof line)-1,ptr); + } + + } +} + +/****************************************************************************** + LoopOnEvents - Process all the X events we get +******************************************************************************/ +void LoopOnEvents() +{ +int num; +char buffer[10]; +XEvent Event; +Window dummyroot,dummychild; +int x,x1,y,y1; +unsigned int dummy1; + + if (Transient && !Checked) { + XQueryPointer(dpy,win,&dummyroot,&dummychild,&x1,&y1,&x,&y,&dummy1); + num=WhichButton(&buttons,x,y); + if (num!=-1) { + Pressed=1; + ButPressed=num; + SwitchButton(&buttons,num); + } else Pressed=0; + Checked=1; + } + + while(XPending(dpy)) { + XNextEvent(dpy,&Event); + + switch(Event.type) { + case ButtonRelease: + if (Pressed) { + num=WhichButton(&buttons,Event.xbutton.x,Event.xbutton.y); + if (num!=-1) { + SendFvwmPipe(ClickAction[(Transient) ? 0:Event.xbutton.button-1], + ItemID(&windows,num)); + SwitchButton(&buttons,num); + } + } + if (Transient) ShutMeDown(0); + Pressed=0; + ButPressed=-1; + break; + case ButtonPress: + num=WhichButton(&buttons,Event.xbutton.x,Event.xbutton.y); + if (num != -1) { + SwitchButton(&buttons,num); + ButPressed=num; + } else ButPressed=-1; + Pressed=1; + break; + case Expose: + if (Event.xexpose.count==0) + RedrawWindow(1); + break; + case KeyPress: + num=XLookupString(&Event.xkey,buffer,10,NULL,0); + if (num==1) { + if (buffer[0]=='q' || buffer[0]=='Q') ShutMeDown(0); + else if (buffer[0]=='i' || buffer[0]=='I') PrintList(&windows); + else if (buffer[0]=='b' || buffer[0]=='B') PrintButtons(&buttons); + } + break; + case ClientMessage: + if ((Event.xclient.format==32) && (Event.xclient.data.l[0]==wm_del_win)) + ShutMeDown(0); + case EnterNotify: + if (!SomeButtonDown(Event.xcrossing.state)) break; + num=WhichButton(&buttons,Event.xcrossing.x,Event.xcrossing.y); + if (num!=-1) { + SwitchButton(&buttons,num); + ButPressed=num; + } else ButPressed=-1; + Pressed=1; + break; + case LeaveNotify: + if (!SomeButtonDown(Event.xcrossing.state)) break; + if (ButPressed!=-1) SwitchButton(&buttons,ButPressed); + Pressed=0; + break; + case MotionNotify: + if (!Pressed) break; + num=WhichButton(&buttons,Event.xmotion.x,Event.xmotion.y); + if (num==ButPressed) break; + if (ButPressed!=-1) SwitchButton(&buttons,ButPressed); + if (num!=-1) { + SwitchButton(&buttons,num); + ButPressed=num; + } else ButPressed=-1; + break; + } + } +} + +/****************************************************************************** + AdjustWindow - Resize the window according to maxwidth by number of buttons +******************************************************************************/ +void AdjustWindow() +{ +int new_width=0,new_height=0,tw,i,total; +char *temp; + + total=ItemCount(&windows); + if (!total) { + if (WindowIsUp==1) { + XUnmapWindow(dpy,win); + WindowIsUp=2; + } + return; + } + for(i=0;i0) win_height=new_height; + if (new_width>0) win_width=new_width; + if (WindowIsUp==2) { + XMapWindow(dpy,win); + WindowIsUp=1; + WaitForExpose(); + } +} + +/****************************************************************************** + makename - Based on the flags return me '(name)' or 'name' +******************************************************************************/ +char *makename(char *string,long flags) +{ +char *ptr; + ptr=safemalloc(strlen(string)+3); + if (flags&ICONIFIED) strcpy(ptr,"("); + else strcpy(ptr,""); + strcat(ptr,string); + if (flags&ICONIFIED) strcat(ptr,")"); + return ptr; +} + +/****************************************************************************** + LinkAction - Link an response to a users action +******************************************************************************/ +void LinkAction(char *string) +{ +char *temp; + temp=string; + while(isspace(*temp)) temp++; + if(mystrncasecmp(temp, "Click1", 6)==0) + CopyString(&ClickAction[0],&temp[6]); + else if(mystrncasecmp(temp, "Click2", 6)==0) + CopyString(&ClickAction[1],&temp[6]); + else if(mystrncasecmp(temp, "Click3", 6)==0) + CopyString(&ClickAction[2],&temp[6]); + else if(mystrncasecmp(temp, "Enter", 5)==0) + CopyString(&EnterAction,&temp[5]); +} + +/****************************************************************************** + MakeMeWindow - Create and setup the window we will need +******************************************************************************/ +void MakeMeWindow(void) +{ +XSizeHints hints; +XGCValues gcval; +unsigned long gcmask; +unsigned int dummy1,dummy2; +int x,y,ret,count; +Window dummyroot,dummychild; + + if ((count=ItemCount(&windows))==0 && Transient) ShutMeDown(0); + AdjustWindow(); + + hints.width=win_width; + hints.height=win_height; + hints.win_gravity=NorthWestGravity; + hints.flags=PSize|PWinGravity|PResizeInc; + hints.width_inc=0; + hints.height_inc=0; + + if (geometry!= NULL) { + ret=XParseGeometry(geometry,&x,&y,&dummy1,&dummy2); + + if (ret&XValue && ret &YValue) { + hints.x=x; + if (ret&XNegative) hints.x+=XDisplayWidth(dpy,screen)-win_width; + hints.y=y; + if (ret&YNegative) hints.y+=XDisplayHeight(dpy,screen)-win_height; + hints.flags|=USPosition; + } + + if (ret&XNegative) { + if (ret&YNegative) hints.win_gravity=SouthEastGravity; + else hints.win_gravity=NorthEastGravity; + } else { + if (ret&YNegative) hints.win_gravity=SouthWestGravity; + else hints.win_gravity=NorthWestGravity; + } + + } + + if (Transient) { + XQueryPointer(dpy,Root,&dummyroot,&dummychild,&hints.x,&hints.y,&x,&y,&dummy1); + hints.win_gravity=NorthWestGravity; + hints.flags |= USPosition; + } + win_grav=hints.win_gravity; + win_x=hints.x; + win_y=hints.y; + + if(d_depth < 2) { + back = GetColor("white"); + fore = GetColor("black"); + } else { + back = GetColor(BackColor); + fore = GetColor(ForeColor); + } + + win=XCreateSimpleWindow(dpy,Root,hints.x,hints.y,hints.width,hints.height,1, + fore,back); + + wm_del_win=XInternAtom(dpy,"WM_DELETE_WINDOW",False); + XSetWMProtocols(dpy,win,&wm_del_win,1); + + XSetWMNormalHints(dpy,win,&hints); + + if (!Transient) { + XGrabButton(dpy,1,AnyModifier,win,True,GRAB_EVENTS,GrabModeAsync, + GrabModeAsync,None,None); + XGrabButton(dpy,2,AnyModifier,win,True,GRAB_EVENTS,GrabModeAsync, + GrabModeAsync,None,None); + XGrabButton(dpy,3,AnyModifier,win,True,GRAB_EVENTS,GrabModeAsync, + GrabModeAsync,None,None); + SetMwmHints(MWM_DECOR_ALL|MWM_DECOR_RESIZEH|MWM_DECOR_MAXIMIZE|MWM_DECOR_MINIMIZE, + MWM_FUNC_ALL|MWM_FUNC_RESIZE|MWM_FUNC_MAXIMIZE|MWM_FUNC_MINIMIZE, + MWM_INPUT_MODELESS); + } else { + SetMwmHints(0,MWM_FUNC_ALL,MWM_INPUT_MODELESS); + } + + gcval.foreground=fore; + gcval.background=back; + gcval.font=ButtonFont->fid; + gcmask=GCForeground|GCBackground|GCFont; + graph=XCreateGC(dpy,Root,gcmask,&gcval); + + if(d_depth < 2) + gcval.foreground=GetShadow(fore); + else + gcval.foreground=GetShadow(back); + gcval.background=back; + gcmask=GCForeground|GCBackground; + shadow=XCreateGC(dpy,Root,gcmask,&gcval); + + gcval.foreground=GetHilite(back); + gcval.background=back; + gcmask=GCForeground|GCBackground; + hilite=XCreateGC(dpy,Root,gcmask,&gcval); + + XSelectInput(dpy,win,(ExposureMask | KeyPressMask)); + + ChangeWindowName(&Module[1]); + + if (ItemCount(&windows)>0) { + XMapRaised(dpy,win); + WaitForExpose(); + WindowIsUp=1; + } else WindowIsUp=2; + + if (Transient) { + if ( XGrabPointer(dpy,win,True,GRAB_EVENTS,GrabModeAsync,GrabModeAsync, + None,None,CurrentTime)!=GrabSuccess) ShutMeDown(1); + XQueryPointer(dpy,Root,&dummyroot,&dummychild,&hints.x,&hints.y,&x,&y,&dummy1); + if (!SomeButtonDown(dummy1)) ShutMeDown(0); + } + +} + +/****************************************************************************** + StartMeUp - Do X initialization things +******************************************************************************/ +void StartMeUp() +{ + if (!(dpy = XOpenDisplay(""))) { + fprintf(stderr,"%s: can't open display %s", Module, + XDisplayName("")); + exit (1); + } + x_fd = XConnectionNumber(dpy); + screen= DefaultScreen(dpy); + Root = RootWindow(dpy, screen); + d_depth = DefaultDepth(dpy, screen); + + ScreenHeight = DisplayHeight(dpy,screen); + ScreenWidth = DisplayWidth(dpy,screen); + + if ((ButtonFont=XLoadQueryFont(dpy,font_string))==NULL) { + if ((ButtonFont=XLoadQueryFont(dpy,"fixed"))==NULL) exit(1); + } + + fontheight=ButtonFont->ascent+ButtonFont->descent; + + win_width=XTextWidth(ButtonFont,"XXXXXXXXXXXXXXX",10); + + +} + +/****************************************************************************** + ShutMeDown - Do X client cleanup +******************************************************************************/ +void ShutMeDown(int exitstat) +{ + FreeList(&windows); + FreeAllButtons(&buttons); + XFreeGC(dpy,graph); + if (WindowIsUp) XDestroyWindow(dpy,win); + XCloseDisplay(dpy); + exit(exitstat); +} + +/****************************************************************************** + ChangeWindowName - Self explanitory + Original work from FvwmIdent: + Copyright 1994, Robert Nation and Nobutaka Suzuki. +******************************************************************************/ +void ChangeWindowName(char *str) +{ +XTextProperty name; + if (XStringListToTextProperty(&str,1,&name) == 0) { + fprintf(stderr,"%s: cannot allocate window name.\n",Module); + return; + } + XSetWMName(dpy,win,&name); + XSetWMIconName(dpy,win,&name); + XFree(name.value); +} + +/************************************************************************** + * + * Sets mwm hints + * + *************************************************************************/ +/* + * Now, if we (hopefully) have MWW - compatible window manager , + * say, mwm, ncdwm, or else, we will set useful decoration style. + * Never check for MWM_RUNNING property.May be considered bad. + */ + +void SetMwmHints(unsigned int value, unsigned int funcs, unsigned int input) +{ +PropMwmHints prop; + + if (MwmAtom==None) + { + MwmAtom=XInternAtom(dpy,"_MOTIF_WM_HINTS",False); + } + if (MwmAtom!=None) + { + /* sh->mwm.decorations contains OR of the MWM_DECOR_XXXXX */ + prop.decorations= value; + prop.functions = funcs; + prop.inputMode = input; + prop.flags = MWM_HINTS_DECORATIONS| MWM_HINTS_FUNCTIONS | MWM_HINTS_INPUT_MODE; + + /* HOP - LA! */ + XChangeProperty (dpy,win, + MwmAtom, MwmAtom, + 32, PropModeReplace, + (unsigned char *)&prop, + PROP_MWM_HINTS_ELEMENTS); + } +} + + diff --git a/modules/FvwmWinList/FvwmWinList.h b/modules/FvwmWinList/FvwmWinList.h new file mode 100644 index 0000000..82ad3b8 --- /dev/null +++ b/modules/FvwmWinList/FvwmWinList.h @@ -0,0 +1,107 @@ +#include "../../libs/fvwmlib.h" +/* FvwmWinList Module for Fvwm. + * + * Copyright 1994, Mike Finger (mfinger@mermaid.micro.umn.edu or + * Mike_Finger@atk.com) + * + * The author makes not guarantees or warantees, either express or + * implied. Feel free to use any contained here for any purpose, as long + * and this and any other applicible copyrights are kept intact. + + * The functions in this header file that are based on part of the FvwmIdent + * module for Fvwm are noted by a small copyright atop that function, all others + * are copyrighted by Mike Finger. For those functions modified/used, here is + * the full, original copyright: + * + * Copyright 1994, Robert Nation and Nobutaka Suzuki. + * No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. */ + +#define STICKY 1 /* Does window stick to glass? */ +#define ONTOP 2 /* does window stay on top */ +#define BORDER 4 /* Is this decorated with border*/ +#define TITLE 8 /* Is this decorated with title */ +#define ICONIFIED 32 /* is it an icon now? */ +#define TRANSIENT 64 /* is it a transient window? */ +#define WINDOWLISTSKIP 262144 + +/* Motif window hints */ +typedef struct +{ + CARD32 flags; + CARD32 functions; + CARD32 decorations; + INT32 inputMode; +} PropMotifWmHints; + +typedef PropMotifWmHints PropMwmHints; + +/* Motif window hints */ +#define MWM_HINTS_FUNCTIONS (1L << 0) +#define MWM_HINTS_DECORATIONS (1L << 1) +#define MWM_HINTS_INPUT_MODE (1L << 2) + +/* bit definitions for MwmHints.functions */ +#define MWM_FUNC_ALL (1L << 0) +#define MWM_FUNC_RESIZE (1L << 1) +#define MWM_FUNC_MOVE (1L << 2) +#define MWM_FUNC_MINIMIZE (1L << 3) +#define MWM_FUNC_MAXIMIZE (1L << 4) +#define MWM_FUNC_CLOSE (1L << 5) + +/* values for MwmHints.input_mode */ +#define MWM_INPUT_MODELESS 0 +#define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1 +#define MWM_INPUT_SYSTEM_MODAL 2 +#define MWM_INPUT_FULL_APPLICATION_MODAL 3 + +/* bit definitions for MwmHints.decorations */ +#define MWM_DECOR_ALL (1L << 0) +#define MWM_DECOR_BORDER (1L << 1) +#define MWM_DECOR_RESIZEH (1L << 2) +#define MWM_DECOR_TITLE (1L << 3) +#define MWM_DECOR_MENU (1L << 4) +#define MWM_DECOR_MINIMIZE (1L << 5) +#define MWM_DECOR_MAXIMIZE (1L << 6) + +#define PROP_MOTIF_WM_HINTS_ELEMENTS 4 +#define PROP_MWM_HINTS_ELEMENTS PROP_MOTIF_WM_HINTS_ELEMENTS + +/************************************************************************* + Subroutine Prototypes +**************************************************************************/ +void EndLessLoop(void); +void ReadFvwmPipe(void); +void ProcessMessage(unsigned long type,unsigned long *body); +void SendFvwmPipe(char *message,unsigned long window); +void DeadPipe(int nonsense); +void MakeMeWindow(void); +void WaitForExpose(void); +void RedrawWindow(int force); +void StartMeUp(void); +void ShutMeDown(int exitstat); +void ConsoleMessage(char *fmt,...); +int OpenConsole(void); +void ParseConfig(char *file); +void LoopOnEvents(void); +void AdjustWindow(void); +char *makename(char *string,long flags); +void ChangeWindowName(char *str); +void LinkAction(char *string); +void AddToSkipList(char *string); +int InSkipList(char *string); +void PrintSkipList(void); +void FvwmNameMessage(long *body); +void SetMwmHints(unsigned int value,unsigned int funcs,unsigned int input); + +int matchWildcards(char *pattern, char *string); + +#ifdef BROKEN_SUN_HEADERS +#include "../../fvwm/sun_headers.h" +#endif + +#ifdef NEEDS_ALPHA_HEADER +#include "../../fvwm/alpha_header.h" +#endif /* NEEDS_ALPHA_HEADER */ diff --git a/modules/FvwmWinList/FvwmWinList.man b/modules/FvwmWinList/FvwmWinList.man new file mode 100644 index 0000000..b001398 --- /dev/null +++ b/modules/FvwmWinList/FvwmWinList.man @@ -0,0 +1,109 @@ +.\" t +.\" @(#)FvwmWinList.1 5/9/94 +.TH FvwmWinList 0.4g "May 9th, 1994" +.UC +.SH NAME +FvwmWinList \- the FVWM window list module +.SH SYNOPSIS +FvwmWinList is spawned by fvwm, so no command line invocation will work. + +.SH DESCRIPTION +The FvwmWinList module provides a widow list made up of buttons, each +corresponding to a window that FVWM is managing. Clicking on the buttons +with any of the three mouse buttons will either do a default action or +can be user configured. Like the other modules, FvwmWinList only works +when fvwm is used as the window manager. + +.SH COPYRIGHTS +The FvwmWinList module is the original work of Mike Finger. + +Copyright 1994, Mike Finger. The author makes no guarantees or warranties of +any kind about the use of this module. Use this modules at your own risk. +You may freely use this module or any portion of it for any purpose as long +as the copyright is kept intact. + +.SH INITIALIZATION +During initialization, \fIFvwmWinList\fP will scan the same configuration file +that FVWM used during startup to find the options that pertain to it. These +options are discussed in a later section. + +.SH INVOCATION +FvwmWinList can be invoked by fvwm during initialization by inserting the +line 'Module FvwmWinList' in the .fvwmrc file. + +FvwmWinList can also be bound to a keystroke, mouse button, or menu option to +be invoked later, in this case using 'Transient' as an argument will cause +FvwmWinList to resemble the built in window list. + +FvwmWinList must reside in a directory that is listed in the ModulePath option +of FVWM for it to be executed by FVWM. + +.SH CONFIGURATION OPTIONS +The following options can be placed in the .fvwmrc file + +.IP "*FvwmWinListGeometry \fI{+-}x{+-}\fP" +Specifies the location and gravity of the FvwmWinList window. At the current +time, size is not supported and FvwmWinList will resize itself as buttons are +added. If the NoAnchor option is not specified then the windows gravity +corner will be anchored, and the window will grow in the opposite direction. +(i.e. If the geometry is specified -5-5, that is SoutEastGravity. This will +cause the window to draw up and to the left as windows are added) + +.IP "*FvwmWinListFont \fIfont\fP" +Specifies the font to be used for labeling the buttons. + +.IP "*FvwmWinListFore \fIcolor\fP" +Specifies the color to use for the button names. + +.IP "*FvwmWinListBack \fIcolor\fP" +Specifies the color for the buttons. + +.IP "*FvwmWinListUseSkipList +Tells FvwmWinList to not show the windows that are listed on a WindowListSkip +line if the configuration file. + +.IP "*FvwmWinListNoAnchor +By default, FvwmWinList will anchor the gravity corner so the window will grow +in the opposite direction. This undoes that option. + +.IP "*FvwmWinListUseIconNames +Tells FvwmWinList to use the icon name of the window instead of the full window +name. This is useful to keep the width of the window small. + +.IP "*FvwmWinListAction \fIaction response[,reponse...]\fP" +Tells FvwmWinList to do \fIresponse\fP when \fIaction\fP is done. The +currently supported \fIaction\fPs are: Click1, Click2, Click3. The currently +supported \fIresponse\fPs are any fvwm built-in commands, including modules +and functions. + +.SH SAMPLE CONFIGURATION +The following are excepts from a .fvwmrc file which describe FvwmWinList +initialization commands: + +.nf +.sp +######## +# Pop up the window list in tranient mode on button 3 press & hold + +Mouse 3 R A Module "FvwmWinList" FvwmWinList Transient + +########################## Window-Lister ############################### +*FvwmWinListBack DarkOliveGreen +*FvwmWinListFore PaleGoldenRod +*FvwmWinListFont -*-new century schoolbook-bold-r-*-*-*-120-*-*-*-*-*-* +*FvwmWinListAction Click1 Iconify -1,Raise +*FvwmWinListAction Click2 Iconify +*FvwmWinListAction Click3 Module "FvwmIdent" FvwmIdent +*FvwmWinListUseSkipList +*FvwmWinListUseIconNames +*FvwmWinListGeometry -50-85 +# I like it achored +#*FvwmWinListNoAnchor + +.sp +.fi + +.SH AUTHOR +Mike Finger (mfinger@mermaid.micro.umn.edu) + (Mike_Finger@atk.com) + (doodman on IRC, check the #linux channel) diff --git a/modules/FvwmWinList/Imakefile b/modules/FvwmWinList/Imakefile new file mode 100644 index 0000000..b6a4cc8 --- /dev/null +++ b/modules/FvwmWinList/Imakefile @@ -0,0 +1,31 @@ + +/* Imakefile for fvwm - Identify */ +/* Thu Aug 5 11:21:36 MET DST 1993, mj@dfv.rwth-aachen.de */ + + +/* setup is done entirely in configuration.h now! */ +/* You should need to do much in here, excpt maybe add libraries */ + +/* I need to get the #define XPM from configuration.h if its in there, */ +/* so that I can tell if I should include -lXpm */ +#include <../../configure.h> + +COMPILER + +DEPLIBS = $(DEPXLIB) ../../libs/libfvwmlib.a + +#ifdef AlphaArchitecture +LOCAL_LIBRARIES = $(XLIB) -ldnet_stub -L../../libs -lfvwmlib +#else +LOCAL_LIBRARIES = $(XLIB) -L../../libs -lfvwmlib +#endif + +LINTLIBS = $(LINTXLIB) + +SRCS = FvwmWinList.c List.c ButtonArray.c Mallocs.c Colors.c +OBJS = FvwmWinList.o List.o ButtonArray.o Mallocs.o Colors.o + +TARGET_DIR + +ComplexProgramTarget(FvwmWinList) + diff --git a/modules/FvwmWinList/List.c b/modules/FvwmWinList/List.c new file mode 100644 index 0000000..cf0b1c6 --- /dev/null +++ b/modules/FvwmWinList/List.c @@ -0,0 +1,236 @@ +/* FvwmWinList Module for Fvwm. + * + * Copyright 1994, Mike Finger (mfinger@mermaid.micro.umn.edu or + * Mike_Finger@atk.com) + * + * The functions in this source file are the original work of Mike Finger. + * + * No guarantees or warantees or anything are provided or implied in any way + * whatsoever. Use this program at your own risk. Permission to use this + * program for any purpose is given, as long as the copyright is kept intact. + * + * Things to do: Convert to C++ (In Progress) + */ + +#include "../../configure.h" +#include +#include +#include "List.h" +#include "Mallocs.h" +#include "../../fvwm/module.h" + + +#ifdef BROKEN_SUN_HEADERS +#include "../../fvwm/sun_headers.h" +#endif + +#ifdef NEEDS_ALPHA_HEADER +#include "../../fvwm/alpha_header.h" +#endif /* NEEDS_ALPHA_HEADER */ + + +/****************************************************************************** + InitList - Initialize the list +******************************************************************************/ +void InitList(List *list) +{ + list->head=list->tail=NULL; + list->count=0; +} + +/****************************************************************************** + AddItem - Allocates spaces for and appends an item to the list +******************************************************************************/ +void AddItem(List *list, long id,long flags) +{ +Item *new; + new=(Item *)safemalloc(sizeof(Item)); + new->id=id; + new->name=NULL; + new->flags=flags; + new->next=NULL; + + if (list->tail==NULL) list->head=list->tail=new; + else { + list->tail->next=new; + list->tail=new; + } + list->count++; +} + +/****************************************************************************** + FindItem - Find the item in the list matching the id +******************************************************************************/ +int FindItem(List *list, long id) +{ +Item *temp; +int i; + for(i=0,temp=list->head;temp!=NULL && temp->id!=id;i++,temp=temp->next); + if (temp==NULL) return -1; + return i; +} + +/****************************************************************************** + UpdateItem - Update the item in the list, setting name & flags as necessary. +******************************************************************************/ +int UpdateItemName(List *list, long id, char *string) +{ +Item *temp; +int i; + for(i=0,temp=list->head;temp!=NULL && id!=temp->id;i++,temp=temp->next); + if (temp==NULL) return -1; + UpdateString(&temp->name,string); + return i; +} + +int UpdateItemFlags(List *list, long id, long flags) +{ +Item *temp; +int i; + for(i=0,temp=list->head;temp!=NULL && id!=temp->id;i++,temp=temp->next); + if (temp==NULL) return -1; + if (flags!=-1) temp->flags=flags; + return i; +} + +/****************************************************************************** + FreeItem - Frees allocated space for an Item +******************************************************************************/ +void FreeItem(Item *ptr) +{ + if (ptr != NULL) { + if (ptr->name!=NULL) free(ptr->name); + free(ptr); + } +} + +/****************************************************************************** + DeleteItem - Deletes an item from the list +******************************************************************************/ +int DeleteItem(List *list,long id) +{ +Item *temp,*temp2; +int i; + if (list->head==NULL) return -1; + if (list->head->id==id) { + temp2=list->head; + temp=list->head=list->head->next; + i=-1; + } else { + for(i=0,temp=list->head;temp->next!=NULL && temp->next->id!=id; + i++,temp=temp->next); + if (temp->next==NULL) return -1; + temp2=temp->next; + temp->next=temp2->next; + } + + if (temp2==list->tail) list->tail=temp; + + FreeItem(temp2); + list->count--; + return i+1; +} + +/****************************************************************************** + FreeList - Free the entire list of Items +******************************************************************************/ +void FreeList(List *list) +{ +Item *temp,*temp2; + for(temp=list->head;temp!=NULL;) { + temp2=temp; + temp=temp->next; + FreeItem(temp2); + } + list->count=0; +} + +/****************************************************************************** + PrintList - Print the list of item on the console. (Debugging) +******************************************************************************/ +void PrintList(List *list) +{ +Item *temp; + ConsoleMessage("List of Items:\n"); + ConsoleMessage(" %10s %-15s %-15s %-15s %-15s Flgs\n","ID","Name","I-Name", + "R-Name","R-Class"); + ConsoleMessage(" ---------- --------------- --------------- --------------- --------------- ----\n"); + for(temp=list->head;temp!=NULL;temp=temp->next) { + ConsoleMessage(" %10ld %-15.15s %4d\n",temp->id, + (temp->name==NULL) ? "" : temp->name, + temp->flags); + } +} + +/****************************************************************************** + ItemName - Return the name of an Item +******************************************************************************/ +char *ItemName(List *list, int n) +{ +Item *temp; +int i; + for(i=0,temp=list->head;temp!=NULL && inext); + if (temp==NULL) return NULL; + return temp->name; +} + +/****************************************************************************** + ItemFlags - Return the flags for an item +******************************************************************************/ +long ItemFlags(List *list, long id) +{ +Item *temp; + for(temp=list->head;temp!=NULL && id!=temp->id;temp=temp->next); + if (temp==NULL) return -1; + else return temp->flags; +} + +/****************************************************************************** + XorFlags - Exclusive of the flags with the specified value. +******************************************************************************/ +long XorFlags(List *list, int n, long value) +{ +Item *temp; +int i; +long ret; + for(i=0,temp=list->head;temp!=NULL && inext) + if (temp==NULL) return -1; + ret=temp->flags; + temp->flags^=value; + return ret; +} + +/****************************************************************************** + ItemCount - Return the number of items inthe list +******************************************************************************/ +int ItemCount(List *list) +{ + return list->count; +} + +/****************************************************************************** + ItemID - Return the ID of the item in the list. +******************************************************************************/ +long ItemID(List *list, int n) +{ +Item *temp; +int i; + for(i=0,temp=list->head;temp!=NULL && inext); + if (temp==NULL) return -1; + return temp->id; +} + +/****************************************************************************** + CopyItem - Copy an item from one list to another +******************************************************************************/ +void CopyItem(List *dest, List *source, int n) +{ +Item *temp; +int i; + for(i=0,temp=source->head;temp!=NULL && inext); + if (temp==NULL) return; + AddItem(dest,temp->id,temp->flags); + UpdateItemName(dest,temp->id,temp->name); + DeleteItem(source,temp->id); +} + diff --git a/modules/FvwmWinList/List.h b/modules/FvwmWinList/List.h new file mode 100644 index 0000000..89ed01d --- /dev/null +++ b/modules/FvwmWinList/List.h @@ -0,0 +1,43 @@ +/* FvwmWinList Module for Fvwm. + * + * Copyright 1994, Mike Finger (mfinger@mermaid.micro.umn.edu or + * Mike_Finger@atk.com) + * + * The functions in this source file that are the original work of Mike Finger. + * + * No guarantees or warantees or anything are provided or implied in any way + * whatsoever. Use this program at your own risk. Permission to use this + * program for any purpose is given, as long as the copyright is kept intact. + * + * Things to do: Convert to C++ (In Progress) + */ + +/* Structure definitions */ +typedef struct item { + long id; + char *name; + long flags; + struct item *next; +} Item; + +typedef struct { + Item *head,*tail; + int count; +} List; + +/* Function Prototypes */ +void InitList(List *list); +void AddItem(List *list, long id, long flags); +int FindItem(List *list, long id); +int UpdateItemName(List *list, long id, char *string); +int UpdateItemFlags(List *list, long id, long flags); +void FreeItem(Item *ptr); +int DeleteItem(List *list,long id); +void FreeList(List *list); +void PrintList(List *list); +char *ItemName(List *list, int n); +long ItemFlags(List *list, long id ); +long XorFlags(List *list, int n, long value); +int ItemCount(List *list); +long ItemID(List *list, int n); +void CopyItem(List *dest,List *source,int n); diff --git a/modules/FvwmWinList/Mallocs.c b/modules/FvwmWinList/Mallocs.c new file mode 100644 index 0000000..3b4c6f9 --- /dev/null +++ b/modules/FvwmWinList/Mallocs.c @@ -0,0 +1,63 @@ +/* FvwmWinList Module for Fvwm. + * + * Copyright 1994, Mike Finger (mfinger@mermaid.micro.umn.edu or + * Mike_Finger@atk.com) + * + * The author makes not guarantees or warantees, either express or + * implied. Feel free to use any contained here for any purpose, as long + * and this and any other applicible copyrights are kept intact. + + * The functions in this source file that are based on part of the FvwmIdent + * module for Fvwm are noted by a small copyright atop that function, all others + * are copyrighted by Mike Finger. For those functions modified/used, here is + * the full, original copyright: + * + * Copyright 1994, Robert Nation and Nobutaka Suzuki. + * No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. */ + +#include "../../configure.h" +#include +#include +#include +#include +#include + +#ifdef BROKEN_SUN_HEADERS +#include "../../fvwm/sun_headers.h" +#endif + +#ifdef NEEDS_ALPHA_HEADER +#include "../../fvwm/alpha_header.h" +#endif /* NEEDS_ALPHA_HEADER */ + +extern char *Module; + +/****************************************************************************** + saferealloc - safely reallocate memory or exit if fails. (Doesn't work right) +******************************************************************************/ +char *saferealloc(char *ptr, int length) +{ +char *newptr; + + if(length <=0) length=1; + + newptr=realloc(ptr,length); + if (ptr == (char *)0) { + fprintf(stderr,"%s:realloc failed",Module); + exit(1); + } + return ptr; +} + +void UpdateString(char **string,char *value) +{ + if (value==NULL) return; + if (*string==NULL) *string=(char *)safemalloc(strlen(value)+1); + else *string=(char *)realloc(*string,strlen(value)+1); + strcpy(*string,value); +} + + diff --git a/modules/FvwmWinList/Mallocs.h b/modules/FvwmWinList/Mallocs.h new file mode 100644 index 0000000..4fd0f74 --- /dev/null +++ b/modules/FvwmWinList/Mallocs.h @@ -0,0 +1,28 @@ +/* FvwmWinList Module for Fvwm. + * + * Copyright 1994, Mike Finger (mfinger@mermaid.micro.umn.edu or + * Mike_Finger@atk.com) + * + * The author makes not guarantees or warantees, either express or + * implied. Feel free to use any contained here for any purpose, as long + * and this and any other applicible copyrights are kept intact. + + * The functions in this source file that are based on part of the FvwmIdent + * module for Fvwm are noted by a small copyright atop that function, all others + * are copyrighted by Mike Finger. For those functions modified/used, here is + * the full, original copyright: + * + * Copyright 1994, Robert Nation and Nobutaka Suzuki. + * No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. */ + +/* Function Prototypes */ +char *safemalloc(int length); +char *saferealloc(char *ptr, int length); +void sleep_a_little(int n); +void CopyString(char **dest, char *source); +char *CatString2(char *a, char *b); +void UpdateString(char **string,char *value); + diff --git a/modules/FvwmWinList/README b/modules/FvwmWinList/README new file mode 100644 index 0000000..bfb946b --- /dev/null +++ b/modules/FvwmWinList/README @@ -0,0 +1,114 @@ +If you have read the a previous README on this, you may want to skip to the +CHANGELOG. This file is very familiar to the last README. + +Well, here is a summary of what it will do (* = new): + - All memory in managed dynamically by linked lists, keeping in the spirit + of Fvwm to use as little memory as possible. + - Display all windows that Fvwm knows about in Fvwm style buttons + - Iconifying a window will place () around its name in the list + - Can be nicely shutdown by typing 'Q' or 'q' inside the window + - FvwmWinListGeometry {+-}{+-}x (size is ignored) + - FvwmWinListAction + Only Click1, Click2, Click3 are allowed as actions right now + Responses can be any Fvwm built in, or a comma seperated list of such. + (ie: '*FvwmWinListAction Click1 Iconify -1, Raise' will deiconify the + window and then raise it) + Click1 defaults to 'Iconify -1, Raise' + Click2 defaults to 'Iconify' + Click3 defaults to 'Lower' + (See config.sample for an example) + - FvwmWinListUseSkipList + Will not show the windows listed with a 'WindowListSkip' style. + - FvwmWinListNoAnchor + FvwmWinList will, by default, anchor the corner which has gravity, use + this to undo it. (btw, NW gravity and NoAnchor provide the same result. + (+x+y=NorthWest,+x-y=SouthWest,-x+y=NorthEast,-x-y=SouthEast) + This is so you can place the window list in the lower corners and + the list will not wrap past the screen edge. + - FvwmWinListUseIconNames + As it says, it will use the icon names instead of using the window + names. People have mentioned that some window names become to long. + - Allowed FvwmWinList to be started up with an arguemnt 'Transient' to allow + it to work like the build in window list. Right now if you use it in + transient mode it will only execute the command for Click1. Looking + for suggestions about using other buttons. Was considering using + modifiers (ie. Shift means button 2, etc) + - FvwmWinList now uses MWMDecorHints. (Makes the 'Transient' mode look good) + - Buttons now stay down until you actually release the button. You can click + and hold the button down and move across the buttons and the will go up + and down as to enter leave the area. Actions are performed on button + release and not on press. + - FvwmWinList will unmap itself if it has no windows to display and will + remap itself when a new window it can display is opened. If there + are no windows to display and you are using it in transient mode, it + will not come up. + +I have only run this under Linux on my 386/40 with 8megs, please let me know +if you experience problems with compiling, running, or performance. I want +to tune it to run as efficient as possible, later in life. + +Now, the things I still want to do with it. If you have suggestions, please +send them to me, want to make this as useful as possible. + +To do: (in no particular order) + - Add the following configurable options: + - FvwmWinlistAction + Add more actions, like press, release, motion, 2x click, slide, etc., + instead of just Click + - FvwmWinlistOrientaion (down|across) + Should the buttons be a vertical or a horizontal list + - FvwmWinlistMaxWidth + Where x is the max pixel width of the window. + - FvwmWinlistTooLong (wrap|truncate|initials) + What to do if the names are too long. (assuming you set MaxWidth) + - Allow the user to setup what is in the Op's and Detail's menu + - Possible allow diffent fonts/colors for submenus. + - Rob mentioned some people would like icons in the list if the window + if iconified. I personally like the (), although I am a but biased. + Let me know what you think/want, I will try. + - Place a small 3-D pixmap/bitmap next-to/around the windows that are + iconified instead of the (). + - Like to allow resizing of the window and have the buttons match the window + (ie. You make it wider you get 2 columns of buttons, etc.) + + - Fix the following: + - The function saferealloc, based on safemalloc by Rob Nation still doesn't + work correctly, I left it in the Mallocs.c file but I use the normal + realloc now. (Being lazy on this one) + - Make compile compatability for all systems + - Tune FvwmWinList to be more efficient (Low priority, right now) + +I am open to, actually I am trolling for, suggestions/improvments/ideas/rags +on this. + +Here is a list of files included in the tar file: + +ButtonArray.c +ButtonArray.h +CHANGELOG +Colors.c +Colors.h +FvwmWinList.README +FvwmWinList.c +FvwmWinList.h +Imakefile +List.c +List.h +Mallocs.c +Mallocs.h +config.sample +wild.c + +You can unpack it by: + +cd /foo/fvwm/modules +gzip -dc FvwmWinList-0.1.tar.gz | tar xf - + +That will unpack the source into /foo/fvwm/modules/FvwmWinList. + + +If you want a binary distribution or diffs, let me know. + +Enjoy, +Mike +mfinger@mermaid.micro.umn.edu or Mike_Finger@atk.com diff --git a/modules/FvwmWinList/config.sample b/modules/FvwmWinList/config.sample new file mode 100644 index 0000000..003fdc5 --- /dev/null +++ b/modules/FvwmWinList/config.sample @@ -0,0 +1,17 @@ +################### +# Pop up the window list on click and hold of mouse button 3 + +Mouse 3 R A Module "FvwmWinList" FvwmWinList Transient + +########################## Window-Lister ############################### +*FvwmWinListBack DarkOliveGreen +*FvwmWinListFore PaleGoldenRod +*FvwmWinListFont -*-new century schoolbook-bold-r-*-*-*-120-*-*-*-*-*-* +*FvwmWinListAction Click1 Focus,Iconify -1,Focus +*FvwmWinListAction Click2 Iconify +*FvwmWinListAction Click3 Module "FvwmIdent" FvwmIdent +*FvwmWinListUseSkipList +*FvwmWinListUseIconNames +*FvwmWinListGeometry -50-85 +# I like it achored +#*FvwmWinListNoAnchor diff --git a/modules/GoodStuff/GoodStuff.c b/modules/GoodStuff/GoodStuff.c new file mode 100644 index 0000000..701d989 --- /dev/null +++ b/modules/GoodStuff/GoodStuff.c @@ -0,0 +1,1527 @@ +/* This module, and the entire GoodStuff program, and the concept for + * interfacing this module to the Window Manager, are all original work + * by Robert Nation + * + * Copyright 1993, Robert Nation. No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. */ + +#define TRUE 1 +#define FALSE + +#include "../../configure.h" + +#ifdef ISC +#include /* Saul */ +#endif + +#include +#include +#include +#include +#include +#include +#if defined ___AIX || defined _AIX || defined __QNX__ || defined ___AIXV3 || defined AIXV3 || defined _SEQUENT_ +#include +#endif +#include +#include +#include +#include "../../fvwm/module.h" + +#include +#include +#include +#include +#include + +#include "GoodStuff.h" +#include "../../version.h" +char *MyName; + +XFontStruct *font; + +Display *dpy; /* which display are we talking to */ +int x_fd,fd_width; + +Window Root; +int screen; +int d_depth; + +char *GoodStuffBack = "#908090"; +char *GoodStuffFore = "black"; +char *font_string = "fixed"; + +Pixel hilite_pix, back_pix, shadow_pix, fore_pix; +GC NormalGC,ShadowGC,ReliefGC; +Window main_win; +int Width, Height,win_x,win_y; + +#define MW_EVENTS (ExposureMask | StructureNotifyMask| ButtonReleaseMask |\ + ButtonPressMask) + +int num_buttons = 0; +int num_rows = 0; +int num_columns = 0; +int max_icon_width = 30,max_icon_height = 0; +int ButtonWidth,ButtonHeight; +int x= -100000,y= -100000,w= -1,h= -1,gravity = NorthWestGravity; +int new_desk = 0; +int pageing_enabled = 1; +int ready = 0; + +int CurrentButton = -1; +int fd[2]; + +struct button_info Buttons[MAX_BUTTONS]; +char *iconPath = NULL; +char *pixmapPath = NULL; + +static Atom wm_del_win; +Atom _XA_WM_PROTOCOLS; +Atom _XA_WM_NAME; + +/*********************************************************************** + * + * Procedure: + * main - start of fvwm + * + *********************************************************************** + */ +void main(int argc, char **argv) +{ + char *display_name = NULL; + int i,j; + Window root; + int x,y,border_width,depth,button; + char *temp, *s; + char set_mask_mesg[50]; + temp = argv[0]; + + s=strrchr(argv[0], '/'); + if (s != NULL) + temp = s + 1; + + + MyName = safemalloc(strlen(temp)+1); + strcpy(MyName, temp); + + for(i=0;i max_icon_width) + max_icon_width = Buttons[i].icon_w/Buttons[i].BWidth; + if(Buttons[i].icon_h/Buttons[i].BHeight > max_icon_height) + max_icon_height = Buttons[i].icon_h/Buttons[i].BHeight; + } + + CreateWindow(); + for(i=0;iascent - font->descent; + } + + ih = Buttons[button].icon_h + 4 ; + iw = Buttons[button].icon_w + 4 ; + + ConstrainSize(&Buttons[button].hints, + &Buttons[button].icon_w, + &Buttons[button].icon_h); + + XResizeWindow(dpy,Buttons[button].IconWin, + Buttons[button].icon_w, + Buttons[button].icon_h); + XMoveWindow(dpy,Buttons[button].IconWin, + j*ButtonWidth + + (iw - Buttons[button].icon_w)/2, + i*ButtonHeight + + (ih - Buttons[button].icon_h)/2); + + + } + } + RedrawWindow(-1); + } + break; + + case ButtonPress: + CurrentRow = (Event.xbutton.y/ButtonHeight); + CurrentColumn = (Event.xbutton.x/ButtonWidth); + CurrentButton = CurrentColumn + CurrentRow*num_columns; + for(i=0;i<=CurrentRow;i++) + for(j=0;j<= CurrentColumn; j++) + if(Buttons[i*num_columns+j].title!= NULL) + { + if(((CurrentRow - i)< Buttons[i*num_columns+j].BHeight)&& + (CurrentColumn-j)< Buttons[i*num_columns+j].BWidth) + { + CurrentButton = i*num_columns+j; + } + } + RedrawWindow(CurrentButton); + break; + + case ButtonRelease: + CurrentRow = (Event.xbutton.y/ButtonHeight); + CurrentColumn = (Event.xbutton.x/ButtonWidth); + NewButton = CurrentColumn + CurrentRow*num_columns; + for(i=0;i<=CurrentRow;i++) + for(j=0;j<= CurrentColumn; j++) + if(Buttons[i*num_columns+j].title!= NULL) + { + if(((CurrentRow - i)< Buttons[i*num_columns+j].BHeight)&& + (CurrentColumn-j)< Buttons[i*num_columns+j].BWidth) + { + NewButton = i*num_columns+j; + } + } + if(NewButton == CurrentButton) + { + SendInfo(fd,Buttons[CurrentButton].action,0); + + if((Buttons[CurrentButton].action)&& + (mystrncasecmp(Buttons[CurrentButton].action,"exec",4)== 0)) + { + /* Look for Exec "identifier", in which + * case the button stays down until window + * "identifier" materializes */ + i=4; + while((Buttons[CurrentButton].action[i] != 0)&& + (Buttons[CurrentButton].action[i] != '"')) + i++; + i2=i+1; + while((Buttons[CurrentButton].action[i2] != 0)&& + (Buttons[CurrentButton].action[i2] != '"')) + i2++; + if(i2 - i >1) + { + Buttons[CurrentButton].hangon = safemalloc(i2-i); + strncpy(Buttons[CurrentButton].hangon, + &Buttons[CurrentButton].action[i+1],i2-i-1); + Buttons[CurrentButton].hangon[i2-i-1] = 0; + Buttons[CurrentButton].up = 0; + Buttons[CurrentButton].swallow = 0; + } + + } + } + CurrentButton = -1; + RedrawWindow(CurrentButton); + break; + case ClientMessage: + if ((Event.xclient.format==32) && + (Event.xclient.data.l[0]==wm_del_win)) + { + DeadPipe(1); + } + break; + case PropertyNotify: + for(i=0;iascent - font->descent)>>1; + + for(i=0;i (BW-4))&&(len>0)) + { + len--; + w=XTextWidth(font,Buttons[button].title,len); + } + if(len>0) + { + if((Buttons[button].icon_w>0)&& + (Buttons[button].icon_h>0)) + { + yoff2 = BH - font->descent - 4; + XDrawString(dpy,main_win,NormalGC, + j*ButtonWidth+((BW - w)>>1), + i*ButtonHeight+yoff2, + Buttons[button].title, len); + } + else + { + XDrawString(dpy,main_win,NormalGC, + j*ButtonWidth+((BW - w)>>1), + i*ButtonHeight+yoff, + Buttons[button].title, len); + } + } + } + if((Buttons[button].action)&& + (mystrncasecmp(Buttons[button].action,"TogglePage",10)==0)&& + (pageing_enabled == 0)) + { + RelieveWindow(main_win,j*ButtonWidth, i*ButtonHeight, + BW, BH, ShadowGC,ReliefGC); + } + else if((Buttons[button].action)&& + (mystrncasecmp(Buttons[button].action,"Desk",4)==0)) + { + sscanf(&Buttons[button].action[4],"%d %d",&val1,&val2); + if((val1 == 0)&&(val2 == new_desk)) + { + RelieveWindow(main_win,j*ButtonWidth, i*ButtonHeight, + BW, BH, ShadowGC,ReliefGC); + } + else + RelieveWindow(main_win,j*ButtonWidth, i*ButtonHeight, + BW, BH, + (CurrentButton==button)?ShadowGC:ReliefGC, + (CurrentButton==button)?ReliefGC:ShadowGC); + } + else if(Buttons[button].up == 1) + { + RelieveWindow(main_win,j*ButtonWidth, i*ButtonHeight, + BW, BH, + (CurrentButton == button)?ShadowGC:ReliefGC, + (CurrentButton == button)?ReliefGC:ShadowGC); + } + else + { + RelieveWindow(main_win,j*ButtonWidth, i*ButtonHeight, + BW, BH, ShadowGC,ReliefGC); + } + } + } + } +} + +/**************************************************************************** + * + * Draws the relief pattern around a window + * + ****************************************************************************/ +FVWM_INLINE void RelieveWindow(Window win,int x,int y,int w,int h, + GC rgc,GC sgc) +{ + XSegment seg[4]; + int i; + + i=0; + seg[i].x1 = x; seg[i].y1 = y; + seg[i].x2 = w+x-1; seg[i++].y2 = y; + + seg[i].x1 = x; seg[i].y1 = y; + seg[i].x2 = x; seg[i++].y2 = h+y-1; + + seg[i].x1 = x+1; seg[i].y1 = y+1; + seg[i].x2 = x+w-2; seg[i++].y2 = y+1; + + seg[i].x1 = x+1; seg[i].y1 = y+1; + seg[i].x2 = x+1; seg[i++].y2 = y+h-2; + XDrawSegments(dpy, win, rgc, seg, i); + + i=0; + seg[i].x1 = x; seg[i].y1 = y+h-1; + seg[i].x2 = w+x-1; seg[i++].y2 = y+h-1; + + seg[i].x1 = x+w-1; seg[i].y1 = y; + seg[i].x2 = x+w-1; seg[i++].y2 = y+h-1; + if(d_depth<2) + XDrawSegments(dpy, win, ShadowGC, seg, i); + else + XDrawSegments(dpy, win, sgc, seg, i); + + i=0; + seg[i].x1 = x+1; seg[i].y1 = y+h-2; + seg[i].x2 = x+w-2; seg[i++].y2 = y+h-2; + + seg[i].x1 = x+w-2; seg[i].y1 = y+1; + seg[i].x2 = x+w-2; seg[i++].y2 = y+h-2; + + XDrawSegments(dpy, win, sgc, seg, i); +} + +/************************************************************************ + * + * Sizes and creates the window + * + ***********************************************************************/ +XSizeHints mysizehints; +void CreateWindow(void) +{ + XGCValues gcv; + unsigned long gcm; + int actual_buttons_used,first_avail_button,i,j,k; + + wm_del_win = XInternAtom(dpy,"WM_DELETE_WINDOW",False); + _XA_WM_PROTOCOLS = XInternAtom (dpy, "WM_PROTOCOLS", False); + + /* load the font */ + if ((font = XLoadQueryFont(dpy, font_string)) == NULL) + { + if ((font = XLoadQueryFont(dpy, "fixed")) == NULL) + { + fprintf(stderr,"%s: No fonts available\n",MyName); + exit(1); + } + }; + + /* Allow for multi-width/height buttons */ + actual_buttons_used = 0; + first_avail_button = num_buttons; + for(i=0;i MAX_BUTTONS) + { + fprintf(stderr,"%s: Out of Buttons!\n",MyName); + exit(0); + } + num_buttons = actual_buttons_used; + + /* size and create the window */ + if((num_rows == 0)&&(num_columns == 0)) + num_rows = 2; + if(num_columns == 0) + { + num_columns = num_buttons/num_rows; + while(num_rows * num_columns < num_buttons) + num_columns++; + } + if(num_rows == 0) + { + num_rows = num_buttons/num_columns; + while(num_rows * num_columns < num_buttons) + num_rows++; + } + + while(num_rows * num_columns < num_buttons) + num_columns++; + + /* Now have allocated enough space for the buttons, need to shuffle to + * make room for the big ones. */ + for(i=0;i 1)||(Buttons[i].BWidth > 1)) + { + /* if not enough room underneath, give up */ + if(num_rows - (i/num_columns) < Buttons[i].BHeight) + { + fprintf(stderr,"%s: Button too tall. Giving up\n",MyName); + fprintf(stderr,"Button = %d num_rows = %d bheight = %d h = %d\n", + i,num_rows,Buttons[i].BHeight, + num_rows - (i/num_columns)); + Buttons[i].BHeight = 1; + } + if(num_columns - (i %num_columns) < Buttons[i].BWidth) + { + fprintf(stderr,"%s: Button too wide. Giving up.\n",MyName); + fprintf(stderr,"Button = %d num_columns = %d bwidth = %d w = %d\n", + i,num_columns,Buttons[i].BWidth, + num_columns - (i%num_rows)); + Buttons[i].BWidth = 1; + } + for(k=0;k0)||(k>0)) + { + if((Buttons[i+j+k*num_columns].title== NULL)&& + (Buttons[i+j+k*num_columns].action== NULL)&& + (Buttons[i+j+k*num_columns].icon_file== NULL)) + { + Buttons[i+j+k*num_columns].BWidth = 0; + Buttons[i+j+k*num_columns].BHeight = 0; + } + else + { + first_avail_button = i+1; + while((first_avail_button= num_buttons) + { + fprintf(stderr,"%s: Button Confusion!\n",MyName); + exit(1); + } + + /* Move target info to end of original list */ + Buttons[first_avail_button].action = + Buttons[i+j+k*num_columns].action; + Buttons[first_avail_button].title = + Buttons[i+j+k*num_columns].title; + Buttons[first_avail_button].icon_file = + Buttons[i+j+k*num_columns].icon_file; + Buttons[first_avail_button].BWidth = + Buttons[i+j+k*num_columns].BWidth; + Buttons[first_avail_button].BHeight = + Buttons[i+j+k*num_columns].BHeight; + Buttons[first_avail_button].icon_w = + Buttons[i+j+k*num_columns].icon_w; + Buttons[first_avail_button].icon_h = + Buttons[i+j+k*num_columns].icon_h; + Buttons[first_avail_button].iconPixmap = + Buttons[i+j+k*num_columns].iconPixmap; + Buttons[first_avail_button].icon_maskPixmap = + Buttons[i+j+k*num_columns].icon_maskPixmap; + Buttons[first_avail_button].IconWin = + Buttons[i+j+k*num_columns].IconWin; + Buttons[first_avail_button].hints = + Buttons[i+j+k*num_columns].hints; + Buttons[first_avail_button].icon_depth = + Buttons[i+j+k*num_columns].icon_depth; + Buttons[first_avail_button].hangon = + Buttons[i+j+k*num_columns].hangon; + Buttons[first_avail_button].swallow = + Buttons[i+j+k*num_columns].swallow; + Buttons[i+j+k*num_columns].action = NULL; + Buttons[i+j+k*num_columns].title = NULL; + Buttons[i+j+k*num_columns].icon_file = NULL; + Buttons[i+j+k*num_columns].IconWin = None; + Buttons[i+j+k*num_columns].iconPixmap = None; + Buttons[i+j+k*num_columns].icon_maskPixmap = None; + Buttons[i+j+k*num_columns].icon_w = 0; + Buttons[i+j+k*num_columns].icon_h = 0; + Buttons[i+j+k*num_columns].icon_depth = 0; + Buttons[i+j+k*num_columns].swallow = 0; + Buttons[i+j+k*num_columns].module = 0; + Buttons[i+j+k*num_columns].hangon = NULL; + Buttons[i+j+k*num_columns].up = 1; + Buttons[i+j+k*num_columns].BWidth = 0; + Buttons[i+j+k*num_columns].BHeight = 0; + } + } + } + } + } + + + + mysizehints.flags = PWinGravity| PResizeInc | PBaseSize; + /* subtract one for the right/bottom border */ + mysizehints.width = (max_icon_width+8)*num_columns-1; + mysizehints.height=(font->ascent+font->descent+12+max_icon_height)* + num_rows-1; + mysizehints.width_inc = num_columns; + mysizehints.height_inc = num_rows; + mysizehints.base_height = num_rows - 1; + mysizehints.base_width = num_columns - 1; + + if(w > -1) + { + w = w - w%num_columns; + mysizehints.width = w; + h = h - w%num_rows; + mysizehints.height = h; + mysizehints.flags |= USSize; + } + + if(x > -100000) + { + if (x< 0) + { + mysizehints.x = DisplayWidth(dpy,screen) + x - mysizehints.width - 2; + gravity = NorthEastGravity; + } + else + mysizehints.x = x; + if ( y<0) + { + mysizehints.y = DisplayHeight(dpy,screen) + y - mysizehints.height-2; + gravity = SouthWestGravity; + } + else + mysizehints.y = y; + + if((x < 0) && (y < 0)) + gravity = SouthEastGravity; + mysizehints.flags |= USPosition; + } + + mysizehints.win_gravity = gravity; +#define BW 1 + if(d_depth < 2) + { + back_pix = GetColor("white"); + fore_pix = GetColor("black"); + hilite_pix = back_pix; + shadow_pix = fore_pix; + } + else + { + back_pix = GetColor(GoodStuffBack); + fore_pix = GetColor(GoodStuffFore); + hilite_pix = GetHilite(back_pix); + shadow_pix = GetShadow(back_pix); + + } + + main_win = XCreateSimpleWindow(dpy,Root,mysizehints.x,mysizehints.y, + mysizehints.width,mysizehints.height, + BW,fore_pix,back_pix); + XSetWMProtocols(dpy,main_win,&wm_del_win,1); + + XSetWMNormalHints(dpy,main_win,&mysizehints); + XSelectInput(dpy,main_win,MW_EVENTS); + change_window_name(MyName); + + gcm = GCForeground|GCBackground; + gcv.foreground = hilite_pix; + gcv.background = back_pix; + ReliefGC = XCreateGC(dpy, Root, gcm, &gcv); + + gcm = GCForeground|GCBackground; + gcv.foreground = shadow_pix; + gcv.background = back_pix; + ShadowGC = XCreateGC(dpy, Root, gcm, &gcv); + + gcm = GCForeground|GCBackground|GCFont; + gcv.foreground = fore_pix; + gcv.background = back_pix; + gcv.font = font->fid; + NormalGC = XCreateGC(dpy, Root, gcm, &gcv); +} + + + + + + + +/**************************************************************************** + * + * This routine computes the shadow color from the background color + * + ****************************************************************************/ +Pixel GetShadow(Pixel background) +{ + XColor bg_color; + XWindowAttributes attributes; + + XGetWindowAttributes(dpy,Root,&attributes); + + bg_color.pixel = background; + XQueryColor(dpy,attributes.colormap,&bg_color); + + bg_color.red = (unsigned short)((bg_color.red*50)/100); + bg_color.green = (unsigned short)((bg_color.green*50)/100); + bg_color.blue = (unsigned short)((bg_color.blue*50)/100); + + if(!XAllocColor(dpy,attributes.colormap,&bg_color)) + nocolor("alloc shadow",""); + + 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,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 + + 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); + + if(!XAllocColor(dpy,attributes.colormap,&bg_color)) + nocolor("alloc hilight",""); + + return bg_color.pixel; +} + + +void nocolor(char *a, char *b) +{ + fprintf(stderr,"%s: can't %s %s\n", MyName, a,b); +} + + +/**************************************************************************** + * + * Loads a single color + * + ****************************************************************************/ +Pixel GetColor(char *name) +{ + XColor color; + XWindowAttributes attributes; + + XGetWindowAttributes(dpy,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; +} + + +/************************************************************************ + * + * Dead pipe handler + * + ***********************************************************************/ +void DeadPipe(int nonsense) +{ + int i,j,button; + + for(i=0;i1)&& + (mystrncasecmp(tline,CatString3("*", MyName, "Geometry"),Clength+9)==0)) + { + tmp = &tline[Clength+9]; + while(((isspace(*tmp))&&(*tmp != '\n'))&&(*tmp != 0)) + { + tmp++; + } + tmp[strlen(tmp)-1] = 0; + + flags = XParseGeometry(tmp,&g_x,&g_y,&width,&height); + if (flags & WidthValue) + w = width; + if (flags & HeightValue) + h = height; + if (flags & XValue) + x = g_x; + if (flags & YValue) + y = g_y; + } + else if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline,CatString3("*",MyName,"Font"),Clength+5)==0)) + { + CopyString(&font_string,&tline[Clength+5]); + } + else if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline,CatString3("*",MyName,"Rows"),Clength+5)==0)) + { + len=sscanf(&tline[Clength+5],"%d",&num_rows); + if(len < 1) + num_rows = 0; + } + else if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline,CatString3("*",MyName,"Columns"),Clength+8)==0)) + { + len=sscanf(&tline[Clength+8],"%d",&num_columns); + if(len < 1) + num_columns = 0; + } + else if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline,CatString3("*",MyName,"Fore"),Clength+5)==0)) + { + CopyString(&GoodStuffFore,&tline[Clength+5]); + } + else if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline,CatString3("*",MyName, "Back"),Clength+5)==0)) + { + CopyString(&GoodStuffBack,&tline[Clength+5]); + } + else if((strlen(&tline[0])>1)&& + (mystrncasecmp(tline,CatString3("*", MyName, ""),Clength+1)==0)&& + (num_buttons < MAX_BUTTONS)) + { + match_string(&tline[Clength+1]); + } + else if((strlen(&tline[0])>1)&&(mystrncasecmp(tline,"IconPath",8)==0)) + { + CopyString(&iconPath,&tline[8]); + } + else if((strlen(&tline[0])>1)&&(mystrncasecmp(tline,"PixmapPath",10)==0)) + { + CopyString(&pixmapPath,&tline[10]); + } + tline = fgets(line,(sizeof line)-1,fd); + orig_tline = tline; + } + + return; +} + + +/************************************************************************** + * + * Parses a button command line from the config file + * + *************************************************************************/ +void match_string(char *tline) +{ + int len,i,i2,n; + char *ptr,*start,*end,*tmp; + + /* Get a size argument, if any */ + while(isspace(*tline)&&(*tline != '\n')&&(*tline != 0)) + tline++; + if( *tline == '(') + { + int thisw= 0,thish = 0; + + tline++; + sscanf((tline),"%dx%d",&thisw,&thish); + while((*tline != ')')&&(*tline != '\n')&&(*tline != 0)) + tline++; + tline++; + if(thisw > 0) + Buttons[num_buttons].BWidth = thisw; + if(thish > 0) + Buttons[num_buttons].BHeight = thish; + } + + /* skip spaces */ + while(isspace(*tline)&&(*tline != '\n')&&(*tline != 0)) + tline++; + + /* read next word. Its the button label. Users can specify "" + * NoIcon, or whatever to skip the label */ + /* read to next space */ + start = tline; + end = tline; + while((!isspace(*end))&&(*end!='\n')&&(*end!=0)) + end++; + len = end - start; + ptr = safemalloc(len+1); + strncpy(ptr,start,len); + ptr[len] = 0; + Buttons[num_buttons].title = ptr; + + /* read next word. Its the icon bitmap/pixmap label. Users can specify "" + * NoIcon, or whatever to skip the label */ + /* read to next space */ + start = end; + /* skip spaces */ + while(isspace(*start)&&(*start != '\n')&&(*start != 0)) + start++; + end = start; + while((!isspace(*end))&&(*end!='\n')&&(*end!=0)) + end++; + len = end - start; + ptr = safemalloc(len+1); + strncpy(ptr,start,len); + ptr[len] = 0; + Buttons[num_buttons].icon_file = ptr; + + tline = end; + /* skip spaces */ + while(isspace(*tline)&&(*tline != '\n')&&(*tline != 0)) + tline++; + + if(mystrncasecmp(tline,"swallow",7)==0) + { + /* Look for swallow "identifier", in which + * case GoodStuff spawns and gobbles up window */ + i=7; + while((tline[i] != 0)&& + (tline[i] != '"')) + i++; + i2=i+1; + while((tline[i2] != 0)&& + (tline[i2] != '"')) + i2++; + if(i2 - i >1) + { + Buttons[num_buttons].hangon = safemalloc(i2-i); + strncpy(Buttons[num_buttons].hangon,&tline[i+1],i2-i-1); + Buttons[num_buttons].hangon[i2-i-1] = 0; + Buttons[num_buttons].swallow = 1; + } + n = 7; + while((isspace(tline[n]))&&(tline[n]!=0)) + n++; + len = strlen(&tline[n]); + tmp = tline + n + len -1; + while(((isspace(*tmp))||(*tmp == '\n'))&&(tmp >=(tline + n))) + { + tmp--; + len--; + } + ptr = safemalloc(len+6); + if(mystrncasecmp(&tline[n],"Module",6)==0) + { + ptr[0] = 0; + Buttons[num_buttons].module = 1; + } + else + strcpy(ptr,"Exec "); + i2 = strlen(ptr); + strncat(ptr,&tline[n],len); + ptr[i2+len]=0; + SendText(fd,ptr,0); + free(ptr); + Buttons[num_buttons++].action = NULL; + } + else + { + len = strlen(tline); + tmp = tline + len -1; + while(((isspace(*tmp))||(*tmp == '\n'))&&(tmp >=tline)) + { + tmp--; + len--; + } + ptr = safemalloc(len+1); + strncpy(ptr,tline,len); + ptr[len]=0; + Buttons[num_buttons++].action = ptr; + } + return; +} + +/************************************************************************** + * Change the window name displayed in the title bar. + **************************************************************************/ +void change_window_name(char *str) +{ + XTextProperty name; + + if (XStringListToTextProperty(&str,1,&name) == 0) + { + fprintf(stderr,"%s: cannot allocate window name",MyName); + return; + } + XSetWMName(dpy,main_win,&name); + XSetWMIconName(dpy,main_win,&name); + XFree(name.value); +} + + + +/*************************************************************************** + * + * Waits for next X event, or for an auto-raise timeout. + * + ****************************************************************************/ +int My_XNextEvent(Display *dpy, XEvent *event) +{ + fd_set in_fdset; + unsigned long header[3]; + int body_length; + int count,count2 = 0; + static int miss_counter = 0; + unsigned long *body; + int total; + char *cbody; + + if(XPending(dpy)) + { + XNextEvent(dpy,event); + return 1; + } + + FD_ZERO(&in_fdset); + FD_SET(x_fd,&in_fdset); + FD_SET(fd[1],&in_fdset); + +#ifdef __hpux + select(fd_width,(int *)&in_fdset, 0, 0, NULL); +#else + select(fd_width,&in_fdset, 0, 0, NULL); +#endif + + + if(FD_ISSET(x_fd, &in_fdset)) + { + if(XPending(dpy)) + { + XNextEvent(dpy,event); + miss_counter = 0; + return 1; + } + else + miss_counter++; + if(miss_counter > 100) + DeadPipe(0); + } + + if(FD_ISSET(fd[1], &in_fdset)) + { + if(count = ReadFvwmPacket(fd[1], header, &body) > 0) + { + process_message(header[1],body); + free(body); + } + } + return 0; +} + +void CheckForHangon(unsigned long *body) +{ + int button,i,j; + char *cbody; + + cbody = (char *)&body[3]; + for(i=0;iw + * format 32 + * data[0] message atom + * data[1] time stamp + * + ****************************************************************************/ +void send_clientmessage (Window w, Atom a, Time timestamp) +{ + XClientMessageEvent ev; + + ev.type = ClientMessage; + ev.window = w; + ev.message_type = _XA_WM_PROTOCOLS; + ev.format = 32; + ev.data.l[0] = a; + ev.data.l[1] = timestamp; + XSendEvent (dpy, w, False, 0L, (XEvent *) &ev); +} + + +void swallow(unsigned long *body) +{ + char *temp; + int button,i,j,iw,ih; + long supplied; + + for(i=0;iascent - font->descent; + } + if (!XGetWMNormalHints (dpy, Buttons[button].IconWin, + &Buttons[button].hints, + &supplied)) + Buttons[button].hints.flags = 0; + ih = Buttons[button].icon_h + 4; + iw = Buttons[button].icon_w + 4; + ConstrainSize(&Buttons[button].hints, &Buttons[button].icon_w, + &Buttons[button].icon_h); + + XResizeWindow(dpy,(Window)body[0], Buttons[button].icon_w, + Buttons[button].icon_h); + XMoveWindow(dpy,Buttons[button].IconWin, + j*ButtonWidth + + (iw - Buttons[button].icon_w)/2, + i*ButtonHeight + + (ih - Buttons[button].icon_h)/2); + + XFetchName(dpy, Buttons[button].IconWin, &temp); + XClearArea(dpy,main_win,j*ButtonWidth, i*ButtonHeight, + ButtonWidth,ButtonHeight,0); + if(strcmp(Buttons[button].title,"-")!=0) + CopyString(&Buttons[button].title, temp); + RedrawWindow(-1); + XFree(temp); + } + } +} + + + +/*********************************************************************** + * + * Procedure: + * ConstrainSize - adjust the given width and height to account for the + * constraints imposed by size hints + * + * The general algorithm, especially the aspect ratio stuff, is + * borrowed from uwm's CheckConsistency routine. + * + ***********************************************************************/ +void ConstrainSize (XSizeHints *hints, int *widthp, int *heightp) +{ +#define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) ) +#define _min(a,b) (((a) < (b)) ? (a) : (b)) + + + int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta; + int baseWidth, baseHeight; + int dwidth = *widthp, dheight = *heightp; + + if(hints->flags & PMinSize) + { + minWidth = hints->min_width; + minHeight = hints->min_height; + if(hints->flags & PBaseSize) + { + baseWidth = hints->base_width; + baseHeight = hints->base_height; + } + else + { + baseWidth = hints->min_width; + baseHeight = hints->min_height; + } + } + else if(hints->flags & PBaseSize) + { + minWidth = hints->base_width; + minHeight = hints->base_height; + baseWidth = hints->base_width; + baseHeight = hints->base_height; + } + else + { + minWidth = 1; + minHeight = 1; + baseWidth = 1; + baseHeight = 1; + } + + if(hints->flags & PMaxSize) + { + maxWidth = hints->max_width; + maxHeight = hints->max_height; + } + else + { + maxWidth = 10000; + maxHeight = 10000; + } + if(hints->flags & PResizeInc) + { + xinc = hints->width_inc; + yinc = hints->height_inc; + } + else + { + xinc = 1; + yinc = 1; + } + + /* + * First, clamp to min and max values + */ + if (dwidth < minWidth) dwidth = minWidth; + if (dheight < minHeight) dheight = minHeight; + + if (dwidth > maxWidth) dwidth = maxWidth; + if (dheight > maxHeight) dheight = maxHeight; + + + /* + * Second, fit to base + N * inc + */ + dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth; + dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight; + + + /* + * Third, adjust for aspect ratio + */ +#define maxAspectX hints->max_aspect.x +#define maxAspectY hints->max_aspect.y +#define minAspectX hints->min_aspect.x +#define minAspectY hints->min_aspect.y + /* + * The math looks like this: + * + * minAspectX dwidth maxAspectX + * ---------- <= ------- <= ---------- + * minAspectY dheight maxAspectY + * + * If that is multiplied out, then the width and height are + * invalid in the following situations: + * + * minAspectX * dheight > minAspectY * dwidth + * maxAspectX * dheight < maxAspectY * dwidth + * + */ + + if (hints->flags & PAspect) + { + if (minAspectX * dheight > minAspectY * dwidth) + { + delta = makemult(minAspectX * dheight / minAspectY - dwidth, + xinc); + if (dwidth + delta <= maxWidth) + dwidth += delta; + else + { + delta = makemult(dheight - dwidth*minAspectY/minAspectX, + yinc); + if (dheight - delta >= minHeight) dheight -= delta; + } + } + + if (maxAspectX * dheight < maxAspectY * dwidth) + { + delta = makemult(dwidth * maxAspectY / maxAspectX - dheight, + yinc); + if (dheight + delta <= maxHeight) + dheight += delta; + else + { + delta = makemult(dwidth - maxAspectX*dheight/maxAspectY, + xinc); + if (dwidth - delta >= minWidth) dwidth -= delta; + } + } + } + + *widthp = dwidth; + *heightp = dheight; + return; +} + diff --git a/modules/GoodStuff/GoodStuff.h b/modules/GoodStuff/GoodStuff.h new file mode 100644 index 0000000..9be3e26 --- /dev/null +++ b/modules/GoodStuff/GoodStuff.h @@ -0,0 +1,76 @@ +#include "../../libs/fvwmlib.h" +/************************************************************************* + * + * Subroutine Prototypes + * + *************************************************************************/ +extern void CreateWindow(void); +extern Pixel GetColor(char *name); +extern Pixel GetHilite(Pixel background); +extern Pixel GetShadow(Pixel background); +extern void nocolor(char *a, char *b); +extern void RedrawWindow(int); +extern void match_string(char *tline); +extern void Loop(void); +extern void ParseOptions(char *); +extern char *safemalloc(int length); +extern void change_window_name(char *str); +extern int My_XNextEvent(Display *dpy, XEvent *event); +extern FVWM_INLINE void RelieveWindow(Window win,int x,int y,int w,int h,GC rGC,GC sGC); +extern void DeadPipe(int nonsense); +extern void LoadIconFile(int button); +extern void CreateIconWindow(int button); +extern void ConfigureIconWindow(int button,int row, int column); +extern void DrawIconWindow(int button); +extern void GetBitmapFile(int button); +extern void GetXPMFile(int button); +void process_message(unsigned long type,unsigned long *body); +void send_clientmessage (Window w, Atom a, Time timestamp); +void swallow(unsigned long *body); +void ConstrainSize (XSizeHints *hints, int *widthp, int *height); + +extern Display *dpy; /* which display are we talking to */ +extern Window Root; +extern Window main_win; +extern int screen; +extern int d_depth; +extern Pixel back_pix, fore_pix; +extern GC NormalGC; +extern GC ReliefGC; +extern int ButtonWidth,ButtonHeight; +extern XFontStruct *font; +#define MAX_BUTTONS 100 + +struct button_info +{ + char *action; + char *title; + char *icon_file; + int BWidth; /* Width of this button in "buttons" */ + int BHeight; + int icon_w; + int icon_h; + Pixmap iconPixmap; /* pixmap for the icon */ + Pixmap icon_maskPixmap; /* pixmap for the icon mask */ + Window IconWin; + XSizeHints hints; + int icon_depth; + char *hangon; + char up; + char swallow; + char module; +}; + +extern struct button_info Buttons[MAX_BUTTONS]; + +extern char *iconPath; +extern char *pixmapPath; + +#ifdef BROKEN_SUN_HEADERS +#include "../../fvwm/sun_headers.h" +#endif + +#ifdef NEEDS_ALPHA_HEADER +#include "../../fvwm/alpha_header.h" +#endif /* NEEDS_ALPHA_HEADER */ + diff --git a/modules/GoodStuff/GoodStuff.man b/modules/GoodStuff/GoodStuff.man new file mode 100644 index 0000000..6c3f24a --- /dev/null +++ b/modules/GoodStuff/GoodStuff.man @@ -0,0 +1,161 @@ +.\" t +.\" @(#)GoodStuff.1 1/28/94 +.TH GoodStuff 1.20 "Jan 28 1994" +.UC +.SH NAME +GoodStuff \- the FVWM button panel module +.SH SYNOPSIS +GoodStuff is spawned by fvwm, so no command line invocation will work. + +.SH DESCRIPTION +The GoodStuff module provides a button panel which sits on the X +terminal's root window. The user can press the buttons at any time, +and trigger invocation of a user-specified command by the window +manager. GoodStuff only works when fvwm is used as the window manager. + +The button panel can be of any configuration or geometry, and can have +monochrome or color icons to represent the actions which would be +invoked. + +.SH COPYRIGHTS +The GoodStuff program, and the concept for +interfacing this module to the Window Manager, are all original work +by Robert Nation + +Copyright 1993, Robert Nation. No guarantees or warranties or anything +are provided or implied in any way whatsoever. Use this program at your +own risk. Permission to use this program for any purpose is given, +as long as the copyright is kept intact. + + +.SH INITIALIZATION +During initialization, \fIGoodStuff\fP will search for a configuration +file which describes the button panel geometry, color, icons, and +actions. The format of +this files will be described later. The configuration file will be the +one which fvwm used during its initialization. + +If the GoodStuff executable is linked to another name, ie ln -s +GoodStuff TermStuff, then another module called TermStuff can be +started, with a completely different configuration than GoodStuff, +simply by changing the keywords Good??? to Term???. This way multiple +button-bars can be used. + +.SH INVOCATION +GoodStuff can be invoked by inserting the line 'Module GoodStuff' in +the .fvwmrc file. This can be placed on a line by itself, if GoodStuff +is to be spawned during fvwm's initialization, or can be bound to a +menu or mouse button or keystroke to invoke it later. Fvwm will search +directory specified in the ModulePath configuration option to attempt +to locate GoodStuff. + +.SH CONFIGURATION OPTIONS +The following options can be placed in the .fvwmrc file + +.IP "*GoodStuffGeometry \fIgeometry\fP" +Specifies the GoodStuff window location and/or size. If the size is +not specified, GoodStuff will auto-size itself in a reasonable manner. +The geometry is a standard X11 window geometry specification. + +.IP "*GoodStuffFont \fIfont\fP" +Specifies the font to be used for labeling the buttons. + +.IP "*GoodStuffRows \fIrows\fP" +Specifies the number of rows of buttons to be created. If unspecified, +2 rows will be used. + +.IP "*GoodStuffColumns \fIcolumns\fP" +Specifies the number of columns of buttons to be created. If unspecified, +the number of columns will be set to the number of buttons requested, +divided by the number of rows. If both the rows and columns are +specified, but do not specify as many buttons as are defined, then the +users columns specification will be ignored. + +.IP "*GoodStuffFore \fIcolor\fP" +Specifies the color for button label text and monochrome icons. + +.IP "*GoodStuffBack \fIcolor\fP" +Specifies the color for the buttons. + +.IP "*GoodStuff\fI[(w x h)]\fP \fIlabel icon command\fP" +Specifies a window manager built-in command, as described in the fvwm +man page, which should be executed when a button is pressed. The label +field is the text which will be written on the button. The icon field +specifies an X11 bitmap file or XPM color icon file, containing the +icon to display on the button. GoodStuff will search through the path +specified in the fvwm IconPath or PixmapPath configuration items to +find the icon file. If the optional \fI(w x h)\fP is specified, then +this button will be \fIw\fP times the normal button width and \fIh\fP +times the normal button height. If label is "-" then the button label +will not be displayed. + +If \fIcommand\fP is an fvwm Exec command, then the button will remain +pushed in until a window whose name or class matches the +qouted portion of the command is encountered. This is intended to +provide visual feedback to the user that the action he has requested +will be performed. If the qouted portion +contains no characters, then the button will pop out immediately. +Note that users can continue pressing the button, and re-executing the +command, even when it looks "pressed in." + +A single extension to the fvwm built-in command set is provided. +A command of the form: *GoodStuff junk clock.xpm Swallow "Clock" +rclock & will cause GoodStuff to spawn an rclock process, and capture +the first window whose name or resource is "Clock", and display it in +the button-bar. This is handy for applications like xclock, xbiff, and +xload. Modules can be swallowed by specifying SwallowModule instead +of just "swallow" NOTE: if you use xclock for this application, you will want +to specify xclock -padding 0. + + +.SH SAMPLE CONFIGURATION +The following are excepts from a .fvwmrc file which describe GoodStuff +initialization commands: + +.nf +.sp +############################################################## +# Load any modules which should be started during +# fvwm initialization +ModulePath /usr/lib/X11/fvwm:/usr/bin/X11 +Module GoodStuff + +# Make goodstuff title-bar-less, sticky, and give it an icon +NoTitle GoodStuff +Sticky GoodStuff +Icon "GoodStuff" toolbox.xpm + +############################################################## +############################################################## +#Definitions used by the modules +*GoodStuffFore Black +*GoodStuffBack #908090 + +*GoodStuffGeometry -135-5 +*GoodStuffRows 1 +*GoodStuffFont -adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-* + +*GoodStuff Resize resize.xpm Resize +*GoodStuff Move arrows2.xpm Move +*GoodStuff Lower Down Lower +*GoodStuff Raise Up Raise +*GoodStuff Kill bomb.xpm Destroy + +*GoodStuff Dopey rterm.xpm Exec "big_win" xterm -T big_win -geometry 80x50& +*GoodStuff Snoopy rterm.xpm Exec "small_win" xterm -T small_wi & +*GoodStuff Xcalc rcalc.xpm Exec "Calculator" xcalc & +*GoodStuff XMag magnifying_glass2.xpm Exec "xmag" xmag & +*GoodStuff Mail mail2.xpm Exec "xmh" xmh & +*GoodStuff(4x1) - whatever SwallowModule "Fvwm Pager" FvwmPager 0 3 +.sp +.fi + +The last line is a little tricky - it spawns an FvwmPager module, and +captures it to display in a quadruple width button. Since "-" is used +for the button label, the Pager will be resized to be as big as +possible within the button's borders. "whatever", of course, is a +non-existent icon file, and will be ignored by GoodStuff. + +.SH AUTHOR +Robert Nation + diff --git a/modules/GoodStuff/Imakefile b/modules/GoodStuff/Imakefile new file mode 100644 index 0000000..9e98841 --- /dev/null +++ b/modules/GoodStuff/Imakefile @@ -0,0 +1,33 @@ +/* Imakefile for GoodStuff */ +/* Thu Aug 5 11:21:36 MET DST 1993, mj@dfv.rwth-aachen.de */ + +/* setup is done entirely in configuration.h now! */ +/* You should need to do much in here, excpt maybe add libraries */ + +/* I need to get the #define XPM from configuration.h if its in there,*/ +/* so that I can tell if I should include -lXpm */ +#include <../../configure.h> + +COMPILER + +#ifdef XPM +XPMLIB = XPMLIBRARY +#endif + +DEPLIBS = $(DEPXLIB) ../../libs/libfvwmlib.a + +#ifdef AlphaArchitecture +LOCAL_LIBRARIES = $(XPMLIB) $(XLIB) -ldnet_stub -L../../libs -lfvwmlib +#else +LOCAL_LIBRARIES = $(XPMLIB) $(XLIB) -L../../libs -lfvwmlib +#endif + +LINTLIBS = $(LINTXLIB) + +SRCS = GoodStuff.c icons.c +OBJS = GoodStuff.o icons.o + +TARGET_DIR + +ComplexProgramTarget(GoodStuff) + diff --git a/modules/GoodStuff/icons.c b/modules/GoodStuff/icons.c new file mode 100644 index 0000000..bdbbb0e --- /dev/null +++ b/modules/GoodStuff/icons.c @@ -0,0 +1,233 @@ +/* This module, and the entire GoodStuff program, and the concept for + * interfacing this module to the Window Manager, are all original work + * by Robert Nation + * + * Copyright 1993, Robert Nation. No guarantees or warantees or anything + * are provided or implied in any way whatsoever. Use this program at your + * own risk. Permission to use this program for any purpose is given, + * as long as the copyright is kept intact. */ +/*********************************************************************** + * + * Derived from fvwm icon code + * + ***********************************************************************/ + +#include "../../configure.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef NeXT +#include +#endif + +#include "GoodStuff.h" + +#ifdef XPM +#include +#endif /* XPM */ +#ifdef SHAPE +#include +#endif /* SHAPE */ + + +/**************************************************************************** + * + * Loads an icon file into a pixmap + * + ****************************************************************************/ +void LoadIconFile(int button) +{ +#ifndef NO_ICONS + /* First, check for a monochrome bitmap */ + if(Buttons[button].icon_file != NULL) + GetBitmapFile(button); + + /* Next, check for a color pixmap */ + if((Buttons[button].icon_file != NULL)&& + (Buttons[button].icon_w == 0)&&(Buttons[button].icon_h == 0)) + GetXPMFile(button); +#endif +} + +/**************************************************************************** + * + * Creates an Icon Window + * + ****************************************************************************/ +void CreateIconWindow(int button) +{ +#ifndef NO_ICONS + unsigned long valuemask; /* mask for create windows */ + XSetWindowAttributes attributes; /* attributes for create windows */ + + if((Buttons[button].icon_w == 0)&&(Buttons[button].icon_h == 0)) + return; + + attributes.background_pixel = back_pix; + attributes.event_mask = ExposureMask; + valuemask = CWEventMask | CWBackPixel; + + Buttons[button].IconWin = + XCreateWindow(dpy, main_win, 0, 0, Buttons[button].icon_w, + Buttons[button].icon_w, 0, CopyFromParent, + CopyFromParent,CopyFromParent,valuemask,&attributes); + return; +#endif +} + +/**************************************************************************** + * + * Combines icon shape masks after a resize + * + ****************************************************************************/ +void ConfigureIconWindow(int button,int row, int column) +{ +#ifndef NO_ICONS + int x,y,w,h; + int xoff,yoff; + Pixmap temp; + + if((Buttons[button].icon_w == 0)&&(Buttons[button].icon_h == 0)) + return; + + if(Buttons[button].swallow != 0) + return; + + w = Buttons[button].icon_w; + h = Buttons[button].icon_h; + if(w > Buttons[button].BWidth*ButtonWidth - 8) + w = Buttons[button].BWidth*ButtonWidth - 8; + if(strcmp(Buttons[button].title,"-")==0) + { + if(h>Buttons[button].BHeight*ButtonHeight-8) + h= Buttons[button].BHeight*ButtonHeight-8; + } + else + { + if(h>Buttons[button].BHeight*ButtonHeight-8-font->ascent-font->descent) + h= Buttons[button].BHeight*ButtonHeight-8-font->ascent-font->descent; + } + + + if(w < 1) + w = 1; + if(h < 1) + h = 1; + + x = column*ButtonWidth; + y = row*ButtonHeight; + xoff = (Buttons[button].BWidth*ButtonWidth - w)>>1; + yoff = (Buttons[button].BHeight*ButtonHeight - (h + font->ascent + font->descent))>>1; + + if(xoff < 2) + xoff = 2; + if(yoff < 2) + yoff = 2; + x += xoff; + y += yoff; + + XMoveResizeWindow(dpy, Buttons[button].IconWin, x,y,w,h); + +#ifdef XPM +#ifdef SHAPE + if (Buttons[button].icon_maskPixmap != None) + { + xoff = (w - Buttons[button].icon_w)>>1; + yoff = (h - Buttons[button].icon_h)>>1; + XShapeCombineMask(dpy, Buttons[button].IconWin, ShapeBounding, 0, 0, + Buttons[button].icon_maskPixmap, ShapeSet); + } +#endif +#endif + if(Buttons[button].icon_depth == -1) + { + temp = Buttons[button].iconPixmap; + Buttons[button].iconPixmap = + XCreatePixmap(dpy,Root, Buttons[button].icon_w, + Buttons[button].icon_h,d_depth); + XCopyPlane(dpy,temp,Buttons[button].iconPixmap,NormalGC, + 0,0,Buttons[button].icon_w,Buttons[button].icon_h, + 0,0,1); + } + XSetWindowBackgroundPixmap(dpy, Buttons[button].IconWin,Buttons[button].iconPixmap); + + XClearWindow(dpy,Buttons[button].IconWin); +#endif +} + +/*************************************************************************** + * + * Looks for a monochrome icon bitmap file + * + **************************************************************************/ +void GetBitmapFile(int button) +{ +#ifndef NO_ICONS + char *path = NULL; + int HotX,HotY; + + path = findIconFile(Buttons[button].icon_file, iconPath,R_OK); + if(path == NULL)return; + + if(XReadBitmapFile (dpy, Root,path,(unsigned int *)&Buttons[button].icon_w, + (unsigned int *)&Buttons[button].icon_h, + &Buttons[button].iconPixmap, + (int *)&HotX, + (int *)&HotY) != BitmapSuccess) + { + Buttons[button].icon_w = 0; + Buttons[button].icon_h = 0; + } + else + { + Buttons[button].icon_depth = -1; + } + Buttons[button].icon_maskPixmap = None; + free(path); +#endif +} + + +/**************************************************************************** + * + * Looks for a color XPM icon file + * + ****************************************************************************/ +void GetXPMFile(int button) +{ +#ifndef NO_ICONS +#ifdef XPM + XWindowAttributes root_attr; + XpmAttributes xpm_attributes; + char *path = NULL; + + path = findIconFile(Buttons[button].icon_file, pixmapPath,R_OK); + if(path == NULL)return; + + XGetWindowAttributes(dpy,Root,&root_attr); + xpm_attributes.colormap = root_attr.colormap; + xpm_attributes.valuemask = XpmSize | XpmReturnPixels|XpmColormap; + if(XpmReadFileToPixmap(dpy, Root, path, + &Buttons[button].iconPixmap, + &Buttons[button].icon_maskPixmap, + &xpm_attributes) == XpmSuccess) + { + Buttons[button].icon_w = xpm_attributes.width; + Buttons[button].icon_h = xpm_attributes.height; + Buttons[button].icon_depth = d_depth; + } + free(path); +#endif /* XPM */ +#endif +} + diff --git a/sample.fvwmrc/4Dwm.fvwmrc b/sample.fvwmrc/4Dwm.fvwmrc new file mode 100644 index 0000000..e2edcca --- /dev/null +++ b/sample.fvwmrc/4Dwm.fvwmrc @@ -0,0 +1,507 @@ +############################################################################# +# +# Here's rob's MWM like configuration, +# with lots of changes to make it more like the Indigo Magic desktop +# seen on Irix 5.2 machines (i.e. Indies, newer Indigo^2's) by +# tabaer@magnus.acs.ohio-state.edu. + +# +# (This is actually a set of bug reports masquerading as a sample config) +# +# WARNING: This is as much my personal preference as anything else. +# The button and menu layout is based on my experiences with SGI +# machines at Ohio State and NASA-Lewis, so your mileage may vary... +# --tabaer@magnus +# +# This configuration file expects the following options to be compiled into +# fvwm: +# HOTKEYS +# MENUCOLOR +# MODULES +# SHAPE +# XPM +# +# Also, the following options SHOULD NOT be enabled: +# NO_ICONS +# NON_VIRTUAL +# PRUNE +# +# This config is known to work with fvwm 1.21b, and should work with later +# versions as well. +########################################################################### + +########################################################################### +# Set up the major operating modes + +# Colors for non-selected windows, menus, and the panner +StdForeColor Black +StdBackColor LightGray + +# Colors for the selected window +HiForeColor Yellow +HiBackColor RoyalBlue + +# Menu colors +MenuForeColor Black +MenuBackColor LightGray + +# Fonts - one for menus, a second for window titles, and a third for icons +Font -*-helvetica-medium-o-*-*-12-*-*-*-*-*-*-* +WindowFont -*-helvetica-bold-r-*-*-12-*-*-*-*-*-*-* +IconFont -*-helvetica-medium-r-*-*-10-*-*-*-*-*-*-* + +# Force SGI-ish Motif compliance +MWMButtons +MWMDecorHints +MWMFunctionHints +MWMMenus +BoundaryWidth 6 +NoBoundaryWidth 0 +ButtonStyle 1 50x22 +ButtonStyle 2 50x50 +ButtonStyle 4 22x22 +DecorateTransients + +# Set the icon box to be at the top of the screen next to the toolchest +IconBox 130 5 600 150 + +# Set the desk top size in units of physical screen size +# and the reduction scale used for the panner/pager +DeskTopSize 1x1 +DeskTopScale 32 + +########################################################################### +# Set up the Modules + +ModulePath /usr/X11/lib/X11/fvwm:/usr/X11/bin:/usr/local/bin + +# SGI-ish button bar using GoodStuff +Module GoodStuff +*GoodStuffGeometry +5+5 +*GoodStuffColumns 1 +*GoodStuffFont -adobe-helvetica-bold-o-*-*-12-*-*-*-*-*-*-* +*GoodStuffFore Black +*GoodStuffBack LightGray +# A minor complaint about the GoodStuff button: the GoodStuff window +# doesn't size itself width-wise correctly, so it chops off the last letter +# on a couple of the button labels. I'd like to see GoodStuff with the +# button text left-justified and the icons right-justified, like in SGI's +# toolchest, but I'll have to hack that out myself when I get the time. +# Perhaps there's a way to set up GoodStuff so that button appearance +# is configurable, too. Also, is there any way to get the popup menus to +# cascade off the buttons, rather than appearing over them? --tabaer@magnus +# +#*GoodStuff Button Icon Command +*GoodStuff Shells /home/tabaer/popup.xbm PopUp "Shells" Shells +*GoodStuff Windows /home/tabaer/popup.xbm PopUp "Windows" Windows +*GoodStuff Tools /home/tabaer/popup.xbm PopUp "Tools" Tools +*GoodStuff Demos /home/tabaer/popup.xbm PopUp "Demos" Demos +*GoodStuff R-Hosts /home/tabaer/popup.xbm PopUp "R-Hosts" R-Hosts +*GoodStuff System /home/tabaer/popup.xbm PopUp "System" System +*GoodStuff EMACS /usr/include/X11/xlogo32 Exec "EMACS" exec /usr/appl/bin/lemacs-19.10 & + +# Irix-5.2 like pager +Module FvwmPager 0 2 +*FvwmPagerGeometry 135x60+5+675 +*FvwmPagerFore Black +*FvwmPagerBack LightGray +*FvwmPagerHilight White +*FvwmPagerLabel 0 Global + +############################################################################ +# Configuration of specific windows using the new Style command +Style "*" Icon /usr/include/X11/bitmaps/xlogo32, StartNormal, StartsAnywhere +Style "Console" Icon /usr/include/X11/bitmaps/Term +Style "emacs*" Icon /usr/include/X11/pixmaps/e/emacs2.xpm +Style "Fudgit" Icon /usr/include/X11/pixmaps/g/graphp.xpm +Style "Fvwm*" StaysOnTop, Sticky +Style "ghostview" Icon /usr/include/X11/pixmaps/g/gv.xpm +Style "Gnuplot" Icon /usr/include/X11/pixmaps/m/math.xpm +Style "GoodStuff" NoIcon, NoTitle, NoHandles, StaysOnTop, Sticky +Style "News" Icon /usr/include/X11/pixmaps/mail2.xpm +Style "oclock" NoHandles, NoTitle +Style "RLaB" Icon /usr/include/X11/pixmaps/m/matrix1.xpm +Style "rxvt" Icon /usr/include/X11/bitmaps/Term +Style "velvet" Icon /home/tabaer/fem.xbm +Style "xbiff" NoTitle +Style "xclock" NoTitle, Sticky +Style "xosview*" NoTitle, Sticky +Style "XSpread*" Icon /usr/include/X11/pixmaps/s/spreadsh.2.xpm +Style "xterm" Icon /usr/include/X11/bitmaps/Term + +############################################################################## +# Now define the menus - defer bindings until later +# The first three menus are very basic and are used in several places. +# --tabaer@magnus + +# This menu is invoked as a sub-menu - it allows you to quit, +# restart, or switch to another WM. +Popup "Quit-Verify" + Title "Really Quit Fvwm?" + Nop "This may log you out!" + Nop "" + Quit "Yes, Really Quit" + Restart "Restart fvwm" fvwm + Restart "Start twm" /usr/bin/X11/twm + Restart "Start olwm" /usr/openwin/bin/olwm + Restart "Start olvwm" /usr/openwin/bin/olvwm + Nop "" + Nop "No, Don't Quit" +EndPopup + +PopUp "WindowManagers" + Restart "Restart fvwm" fvwm + Restart "Start twm" /usr/bin/X11/twm + Restart "Start olwm" /usr/openwin/bin/olwm + Restart "Start olvwm" /usr/openwin/bin/olvwm +EndPopUp + +# This menu checks to make sure you REALLY want to log out, +# assuming killing the WM will kick you out of X. +PopUp "Logout-Verify" + Title "Do You REALLY want to log out? + Nop "" + Quit "Yes, log me out." + Nop "No, cancel that." +EndPopUp + +# The following menus form the bulk of the menu system I have hanging +# off the GoodStuff modules; they contain most of my commonly used +# X-based tools. Note that I use rxvt instead of xterm for most of my +# shells due to memory constraints; if you use xterms or some variant +# thereof (aixterm, cxterm, kxterm, etc.) you'll need to change quite +# a few things. --tabaer@magnus + +# A menu of VT100 size shells +PopUp "80x25" + Title "80x25 Shells" + Nop "" + Exec "Black on gray" exec rxvt -geometry 80x25 -fg Black -bg LightGray & + Exec "Black on white" exec rxvt -geometry 80x25 -fg Black -bg White & + Exec "Gold on black" exec rxvt -geometry 80x25 -fg gold1 -bg Black & + Exec "Green on black" exec rxvt -geomtery 80x25 -fg green2 -bg Black & + Exec "White on black" exec rxvt -geometry 80x25 -fg White -bg Black & + Exec "Yellow on blue" exec rxvt -geometry 80x25 -fg Yellow -bg Blue & +EndPopUp + +# A menu of slightly larger shells +PopUp "80x40" + Title "80x40 Shells" + Nop "" + Exec "Black on gray" exec rxvt -geometry 80x40 -fg Black -bg LightGray & + Exec "Black on white" exec rxvt -geometry 80x40 -fg Black -bg White & + Exec "Gold on black" exec rxvt -geometry 80x40 -fg gold1 -bg Black & + Exec "Green on black" exec rxvt -geometry 80x40 -fg green2 -bg Black & + Exec "White on black" exec rxvt -geometry 80x40 -fg White -bg Black & + Exec "Yellow on blue" exec rxvt -geometry 80x40 -fg Yellow -bg Blue & +EndPopUp + +PopUp "Apps" + Title "Applications" + Nop "" + Exec "X Spreadsheet" exec xspread & + Exec "PostScript Previewer" exec ghostview & + Exec "Pixmap Previewer" exec xv & +EndPopUp + +PopUp "AudioDemos" + Title "Audio Demos" + Nop "" +EndPopUp + +# All sorts of different time pieces +PopUp "Clocks" + Title "Clocks" + Nop "" + Exec "Analog Clock" exec xclock -analog & + Exec "Digital Clock" exec xclock -digital & + Exec "Round Clock" exec oclock & +EndPopUp + +# A set of NASTY time killers... +PopUp "Games" + Title "Games" + Nop "" + Exec "GnuChess" exec xboard & + Exec "Lander" exec xlander & + Exec "Xvier" exec xvier & + Exec "Doubledeck Solitaire" exec spider & + Exec "Puzzles" exec xpuzzle & + Exec "Make 5" exec xmake5 & +EndPopUp + +PopUp "MiscShells" + Title "Misc. Shells" + Nop "" + Exec "Tcl" exec rxvt -T Tcl -n Tcl -e tclsh & + Exec "TclX" exec rxvt -T TclX -n TclX -e tcl & + Exec "Wish (Tk)" exec rxvt -T Tk -n Tk -e wish & + Exec "WishX (TkX)" exec rxvt -T TkX -n TkX -e wishx & +EndPopUp + +# A menu of various and sundry background graphics on my machine. +# --tabaer@magnus +PopUp "Pixmaps" + Title "Backgrounds" + Nop "" + Exec "MIT Logo" exec xsetroot -bg White -fg LightSkyBlue -bitmap /usr/include/X11/bitmaps/mensetmanus & + Exec "X Logo" exec xsetroot -bg White -fg Black -bitmap /usr/include/X11/bitmaps/xlogo64 & + Exec "Escher Knots" exec xsetroot -bg LightSkyBlue -fg Black -bitmap /usr/include/X11/bitmaps/escherknot & + Exec "Woman" exec xsetroot -bg White -fg Black -bitmap /usr/include/X11/bitmaps/woman & +EndPopUp + +# Several math/science/engineering related applications +PopUp "SciEngr" + Title "Science/Engineering" + Nop "" + Exec "RLaB" exec rxvt -T RLaB -n RLaB -e /usr/local/bin/rlab & + Exec "GnuPlot" exec rxvt -T GnuPlot -n GnuPlot -e /usr/local/bin/gnuplot & +# I need other stuff here, but that'll come later... --tabaer@magnus +EndPopUp + +# Menu of silly things every X setup should have +PopUp "Toys" + Title "Toys" + Nop "" + Exec "Eyeballs" exec xeyes & + Exec "Ideal Gases" exec xgas & +EndPopUp + +# Here are the top-level menus hanging off GoodStuff. As you'll see, +# they call other menus a lot. --tabaer@magnus + +PopUp "Shells" + Title "Shells" + Nop "" + PopUp "80x25" 80x25 + PopUp "80x40" 80x40 + PopUp "Misc" MiscShells +EndPopUp + +PopUp "Windows" + Title "Windows" + Nop "" + PopUp "Set Background" Pixmaps + Nop "Set Screen Saver" + PopUp "Window Managers" WindowManagers + Nop "" + CirculateUp "Shuffle Up" + CirculateDown "Shuffle Down" + Nop "Tidy Icons (?)" + Nop "" + Nop "Restore All (?)" + Nop "Minimize All (?)" + Refresh "Refresh All" +EndPopUp + +PopUp "Tools" + Title "Tools" + Nop "" + Exec "Online Help" exec /usr/local/tkinfo-0.6/tkinfo & + Exec "Online Manual" exec xman & + PopUp "Clocks" Clocks + Exec "Calculator" exec xcalc & + Exec "Calendar" exec ical & + Exec "Clipboard" exec xclipboard & + PopUp "Engineering Apps." SciEngr + Exec "Memory Usage" exec xmem & + PopUp "Misc. Apps." Apps + Exec "Seyon" exec seyon -modems /dev/cua1 & + Exec "System Load" exec xosview -l & +EndPopUp + +PopUp "Demos" + Title "Demos" + Nop "" + PopUp "Audio Demos" AudioDemos + PopUp "X Demos and Toys" Toys + PopUp "X Games" Games +EndPopUp + +PopUp "R-Hosts" + Title "Remote Hosts" + Nop "" + Exec "Archie" exec xarchie & + Exec "World-Wide Web" exec /usr/local/bin/chimera & + Exec "News" exec rxvt -T News -i News -e /usr/local/bin/trn & +EndPopUp + +PopUp "System" + Title "System + Nop "" + Exec "Lock Terminal" exec xlock -mode random & + Nop "" + PopUp "Log Out" Logout-Verify +EndPopUp + +# The next few menus are mostly used in the root window. They control +# basic things like window placement, iconification, and logging out. +# --tabaer@magnus + +# This defines the most common window operations +# As with the key bindings (see below), these were appropriated from +# a stock SGI .4Dwmrc file +Popup "Window Ops" +# I'm not 100% sure what the "Restore" option is supposed to do in stock +# mwm/4Dwm, or if there's an equivalent in fvwm. Right now I just have +# Restore defined the same as (De)Iconify. --tabaer@magnus + Iconify "Restore (Alt-F5)" + Move "Move (Alt-F7)" + Resize "Resize (Alt-F8)" + Iconify "Minimize (Alt-F9)" + Maximize "Maximize (Alt-F10)" + Raise "Raise (Alt-F1)" + Lower "Lower (Alt-F3)" + WindowList "WinList (Alt-F6)" + Nop "" + Destroy "Close (Alt-F4)" + Delete "Quit (Alt-F2)" +EndPopup + +# 4dwm-ish root window menu +PopUp "RootMenu" + Title "FVWM" + Nop "" + Exec "Lock Terminal" exec xlock -mode random & + PopUp "Log Out" Logout-Verify +EndPopUp + +#4dwm-ish long root window +PopUp "LongRootMenu" + Title "FVWM" + Nop "" + Exec "New Window" exec rxvt & + CirculateUp "Shuffle Up" + CirculateDown "Shuffle Down" + Nop "Tidy Icons (?)" + Nop "Restore All (?)" + Refresh "Refresh All" + Nop "" + Restart "Restart fvwm" fvwm + PopUp "Quit fvwm" Quit-Verify + Nop "" + Exec "Lock Terminal" exec xlock -mode random & + PopUp "Log Out" Logout-Verify +EndPopUp + +############################################################################ +# Now define some handy complex functions + +# This one moves the window if you drag the mouse, raises the window if you +# click, or does a RaiseLower if you double-click +Function "Move-or-Raise" + Move "Motion" +# Raise "Motion" + Raise "Click" + RaiseLower "DoubleClick" +EndFunction + +# This one moves and then lowers the window if you drag the mouse, +# only lowers the window if you click, or does a RaiseLower if you double +# click +Function "Move-or-Lower" + Move "Motion" + Lower "Motion" + Lower "Click" + RaiseLower "DoubleClick" +EndFunction + +# This one resizes and then raises the window if you drag the mouse, +# only raises the window if you click, or does a RaiseLower if you double +# click +Function "Resize-or-Raise" + Resize "Motion" + Raise "Motion" + Raise "Click" + RaiseLower "DoubleClick" +EndFunction + +Function "Move-or-Iconify" + Move "Motion" + PopUp "Click" Window Ops + Iconify "DoubleClick" +EndFunction + +# This does the Motif thing of killing the window when you +# double-click the top left button. --tabaer@magnus +Function "Die-on-DoubleClick" + Destroy "DoubleClick" + PopUp "Click" Window Ops +EndFunction + +############################################################################## +# This defines the mouse bindings + +# First, for the mouse in the root window +# I use the AnyModifier option for the modifier field, so you can hold down +# any shift-control-whatever combination you want! + +# Button Context Modifi Function +Mouse 1 R A PopUp "LongRootMenu" +# Mouse button 2 calls up the Tools menu in case GoodStuff doesn't work +Mouse 2 R A PopUp "Tools" +Mouse 3 R A PopUp "RootMenu" + +# Now the title bar buttons +# Any button in the left title-bar button gives the window ops menu +# Any button in the right title-bar button Iconifies the window +# Note the use of "Mouse 0" for AnyButton. + +# Button Context Modifi Function +Mouse 0 1 A Function "Die-on-DoubleClick" +Mouse 0 2 A Maximize +Mouse 0 4 A Iconify + +# Now the rest of the frame +# Here I invoke my complex functions for Move-or-lower, Move-or-raise, +# and Resize-or-Raise. +# Button 1 in the corner pieces, with any modifiers, gives resize or raise +Mouse 1 FS A Function "Resize-or-Raise" +Mouse 2 FS A Function "Resize-or-Raise" +Mouse 1 T A Function "Move-or-Raise" +Mouse 2 T A Function "Move-or-Raise" +Mouse 1 I A Function "Move-or-Iconify" +Mouse 2 I A Function "Move-or-Iconify" + +############################################################################ +# Now some keyboard shortcuts. + +# press arrow in the root window, and move the pointer by 1% of a page +Key Left R N CursorMove -1 0 +Key Right R N CursorMove +1 +0 +Key Up R N CursorMove +0 -1 +Key Down R N CursorMove +0 +1 + +# press shift arrow anywhere, and move the pointer by 5% of a page +Key Left A S CursorMove -5 0 +Key Right A S CursorMove +5 +0 +Key Up A S CursorMove +0 -5 +Key Down A S CursorMove +0 +5 + +# press shift arrow + control key, and move the pointer by 10% of a page +Key Left A SC CursorMove -10 +0 +Key Right A SC CursorMove +10 +0 +Key Up A SC CursorMove +0 -10 +Key Down A SC CursorMove +0 +10 + +# press shift arrow + meta key, and move the pointer by 20% of a page +Key Left A SM CursorMove -20 +0 +Key Right A SM CursorMove +20 +0 +Key Up A SM CursorMove +0 -20 +Key Down A SM CursorMove +0 +20 + +# Keyboard accelerators +# These are "borrowed" from the .4Dwmrc file on an SGI I use, +# except for AltF2 and AltF6 which I added for completeness. +# I think the other are standard Motif. --tabaer@magnus +Key F1 WFST M Raise +Key F2 WFST M Delete +Key F3 WFST M Lower +Key F4 WFST M Destroy +Key F5 WFST M Raise +Key F6 A M WindowList +Key F7 WFST M Move +Key F8 WFST M Resize +Key F9 WFST M Iconify +Key F10 WFST M Maximize + diff --git a/sample.fvwmrc/README b/sample.fvwmrc/README new file mode 100644 index 0000000..27e5c18 --- /dev/null +++ b/sample.fvwmrc/README @@ -0,0 +1,10 @@ +This is where I'm collecting .fvwmrc files that people might find useful. +Mostly, these files cause fvwm to emulate some other window manager. + +These are not to be considered finished works. Anyone who can improve them +is welcome to, and should send me anything worthwhile + +If you use the m4 patches, look into adding undefine(`include') +just before your iconPath or pixmapPath line. + +Rob Nation diff --git a/sample.fvwmrc/minimal.fvwmrc b/sample.fvwmrc/minimal.fvwmrc new file mode 100644 index 0000000..20514fe --- /dev/null +++ b/sample.fvwmrc/minimal.fvwmrc @@ -0,0 +1,472 @@ +# Unfortunately, order does matter in this file +# The correct order for inserting configurations is: +# 1. Colors +# 2. Assorted configuration paramters such as ClickToFocus, or MWMBorders +# 3. Path setup (ModulePath, PixmapPath, IconPath) +# 4. Style settings, including the default style Style "*" ... +# 5. InitFunction and ResetFunction definitions. +# 6. Other Functions. Functions cannot be forward referenced from +# other functions, but they can be backward referenced. +# 7. Menus definitions. Same caveats about forward referencing +# 8. Key and Mouse Bindings. +# 9. Module options. + +# The order of steps 5, 6, and 7 is not critical, as long as there are +# no forward references to functions or menus. + +# If you get it wrong, the most common problem is that color or font settings +# are ignored +########################################################################### +# This sample is set up to try to conserve memory. A few techniques are +# used: +# 1. Only "fixed" font is used. +# 2. The internal pager is used instead of the module. +# 3. The FvwmWinList is used instead of the internal one. +# 4. rxvt is used instead of xterm. +# 5. Color icons are avoided. +########################################################################### +# set up the colors + +# this is used for the selected window +HiForeColor Black +HiBackColor #c06077 + +PagerBackColor #5c54c0 +PagerForeColor orchid + +StickyForeColor Black +StickyBackColor #60c0a0 + +# Menu colors +MenuForeColor Black +MenuBackColor grey +MenuStippleColor SlateGrey + +########################################################################### +# Set up the major operating modes +# +######################## FOCUS STUFF ############################## +# Set windows to auto-raise after 750 milliseconds if you like it. +# Autoraise can sometimes obscure pop-up windows. Performance is now +# similar to olvwm's auto-raise feature. +#AutoRaise 750 + +# Normally, we'll be in focus-follows mouse mode, but uncomment this +# for mwm-style click-to-focus +#ClickToFocus + +######################## ICON STUFF ############################## +# Auto Place Icons is a nice feature.... +# This creates two icon boxes, one on the left side, then one on the +# bottom. Leaves room in the upper left for my clock and xbiff, +# room on the bottom for the Pager. +#IconBox -150 90 -5 -140 +#IconBox 5 -140 -140 -5 +IconBox -70 1 -1 -140 + +# If you uncomment this, and make sure that the WindowList is bound to +# something, it works pretty much like an icon manager. +#SuppressIcons + +# StubbornIcons makes icons de-iconify into their original position on the +# desktop, instead of on the current page. +#StubbornIcons + +# With AutoPlacement, icons will normally place themselves underneath active +# windows. This option changes that. +#StubbornIconPlacement + +# If you want ALL you icons to follow you around the desktop (Sticky), try +# this +#StickyIcons + +######################## MWM EMULATION ####################### +# +# My feeling is that everyone should use MWMDecorHints and MWMFunctionHints, +# since some applications depend on having the window manager respect them + +# MWMFunction hints parses the function information in the MOTIF_WM_HINTS +# property, and prohibits use of these functions on the window. Appropriate +# portions of the window decorations are removed. +MWMFunctionHints + +# MWMDecor hints parses the decoration information in the MOTIF_WM_HINTS +# property, and removes these decoratons from the window. This does not affect +# the functions that can be performed via the menus. +MWMDecorHints + +# These are affect minor aspects for the look-and-feel. +# Sub-menus placement mwm-style? +# MWMMenus +# mwm-style border reliefs (less deep than default fvwm) ? +# MWMBorders +# Maximize button does mwm-inversion thingy +# MWMButtons +######################## MISCELLANEOUS STUFF ####################### +# If you don't like the default 150 msec click delay for the complex functions +# change this and uncomment it. +#ClickTime 150 + +# OpaqueMove has a number (N) attached to it (default 5), if the window occupies +# less than N% of the screen, opaque move is used. 0 <= N <= 100 +# OpaqueMove 100 + +# flip by whole pages on the edge of the screen. +EdgeScroll 100 100 + +# A modest delay before flipping pages seems to be nice... +# I thresh in a 50 pixel Move-resistance too, just so people +# can try it out. +EdgeResistance 250 50 + + +######################## WINDOW PLACEMENT ####################### +# RandomPlacement prevents user interaction while placing windows: +# RandomPlacement + +# SmartPlacement makes new windows pop-up in blank regions of screen if possible, +# otherwise falls back to random or interactive placement. +SmartPlacement + +# With SmartPlacement, windows will normally place themselves over icons. Uncomment +# this to change that. +#StubbornPlacement + +# NoPPosition instructs fvwm to ignore the PPosition field in window geometry hints. +# Emacs annoyingly sets PPosition to (0,0)! +NoPPosition + + +######################## DECORATIONS ####################### +# If you want decorated transient windows, uncomment this: +#DecorateTransients + +########################################################################## +# Setup paths for icons and modules +# +# ModulePath is a colon-separated list, just like regular unix PATH +ModulePath /local/homes/dsp/nation/modules:/usr/lib/X11/fvwm + +# Icon paths +IconPath /usr/include/X11/bitmaps/ + +########################################################################### +# Set up the virtual desktop and pager + +#set the desk top size in units of physical screen size +DeskTopSize 2x2 + +# and the reduction scale used for the panner/pager +DeskTopScale 32 + + +# Use the Fvwm Pager +Pager -5 -5 + +############################################################################# +# Initialization Functions + +Function "InitFunction" + Exec "I" exec rxvt & + Exec "I" exec rclock -ic & +EndFunction + +############################################################################ +# list the windows that don't want a title bar +Style "*" BorderWidth 3, HandleWidth 4, Color Black/#60a0c0,Icon default.xbm +Style "Fvwm*" NoTitle, NoHandles,Sticky,StaysOnTop,WindowListSkip +Style "GoodStuff" NoTitle, NoHandles,Sticky,WindowListSkip +Style "*lock" NoTitle,NoHandles,Sticky,WindowListSkip +Style "xbiff" NoTitle,NoHandles,Sticky +Style "GoodStuff" NoTitle +Style "?ppeed*" NoTitle + + +############################################################################ +# Now define some handy complex functions + +# This one moves and then raises the window if you drag the mouse, +# only raises the window if you click, or does a RaiseLower if you double +# click +Function "Move-or-Raise" + Move "Motion" + Raise "Motion" + Raise "Click" + RaiseLower "DoubleClick" +EndFunction + +# This one maximizes vertically if you click (leaving room for the GoodStuff bar at the +# bottom, or does a full maximization if you double click, or a true full vertical +# maximization if you just hold the mouse button down. +Function "maximize_func" + Maximize "Motion" 0 100 + Maximize "Click" 0 92 + Maximize "DoubleClick" 100 100 +EndFunction + + +# This one moves and then lowers the window if you drag the mouse, +# only lowers the window if you click, or does a RaiseLower if you double +# click +Function "Move-or-Lower" + Move "Motion" + Lower "Motion" + Lower "Click" + RaiseLower "DoubleClick" +EndFunction + +# This one moves or (de)iconifies: +Function "Move-or-Iconify" + Move "Motion" + Iconify "DoubleClick" +EndFunction + +# This one resizes and then raises the window if you drag the mouse, +# only raises the window if you click, or does a RaiseLower if you double +# click +Function "Resize-or-Raise" + Resize "Motion" + Raise "Motion" + Raise "Click" + RaiseLower "DoubleClick" +EndFunction + + +# This is provided as a hint only. +# Move to a known page on the desktop, then start an application in a +# known location. Could also switch to a known desktop, I guess +#Function "abs_coord" +# GoToPage "Immediate" 1,1 +# Exec "Immediate" exec xcalc -geometry +100+100& +#EndFunction + + +############################################################################## +#now define the menus - defer bindings until later + +# This menu is invoked as a sub-menu - it allows you to quit, +# restart, or switch to another WM. +Popup "Quit-Verify" + Title "Really Quit Fvwm?" + Quit "Yes, Really Quit" + Restart "Restart Fvwm" fvwm + Restart "Start twm" twm + Restart "Start tvtwm" tvtwm + Restart "Start mwm" mwm + Restart "Start olwm" /usr/openwin/bin/olwm + Nop "" + Nop "No, Don't Quit" +EndPopup + +# Provides a list of modules to fire off +Popup "Module-Popup" + Title "Modules" + Module "GoodStuff" GoodStuff + Module "NoClutter" FvwmClean + Module "Identify" FvwmIdent + Move "Move" + Module "SaveDesktop" FvwmSave + Module "Debug" FvwmDebug + Module "Pager" FvwmPager 0 2 + Module "Pager" FvwmPager 1 2 +EndPopup + +# This menu will fire up some very common utilities +Popup "Utilities" + Title "Utilities" + Exec "Xterm" exec xterm -e tcsh & + Exec "Rxvt" exec rxvt & + Exec "Top" exec rxvt -T Top -n Top -e top & + Exec "Calculator" exec xcalc & + Exec "Xman" exec xman & + Exec "Xmag" exec xmag & + Nop "" + Popup "Exit Fvwm" Quit-Verify + Popup "Modules" Module-Popup +EndPopup + +# This defines the most common window operations +Popup "Window Ops" + Title "Window Ops" + Function "Move" Move-or-Raise + Function "Resize" Resize-or-Raise + Raise "Raise" + Lower "Lower" + Iconify "(De)Iconify" + Stick "(Un)Stick" + Maximize "(Un)Maximize" + Maximize "(Un)Maximize Vertical" 0 100 + Nop "" + Destroy "Destroy" + Delete "Delete" + Nop "" + Refresh "Refresh Screen" + Nop "" + Desk "Next Desk" 1 0 + Desk "Previous Desk" -1 0 + +EndPopup + +# A trimmed down version of "Window Ops", good for binding to decorations +Popup "Window Ops2" + Function "Move" Move-or-Raise + Function "Resize" Resize-or-Raise + Raise "Raise" + Lower "Lower" + Iconify "Iconify" + Stick "(Un)Stick" + Nop "" + Destroy "Destroy" + Delete "Delete" + Nop "" + Module "ScrollBar" FvwmScroll +EndPopup + +############################################################################# +# One more complex function - couldn't be defined earlier because it used +# pop-up menus +# +# This creates a motif-ish sticky menu for the title-bar window-ops +# pop-up +# Menu acts like normal twm menu if you just hold the button down, +# but if you click instead, the menu stays up, motif style +Function "window_ops_func" + PopUp "Click" Window Ops2 + PopUp "Motion" Window Ops2 +# Motif would add +# Delete "DoubleClick" +EndFunction + + +############################################################################## +# This defines the mouse bindings + +# First, for the mouse in the root window +# Button 1 gives the Utilities menu +# Button 2 gives the Window Ops menu +# Button 3 gives the WindowList (like TwmWindows) +# I use the AnyModifier (A) option for the modifier field, so you can hold down +# any shift-control-whatever combination you want! + +# Button Context Modifi Function +Mouse 1 R A PopUp "Utilities" +Mouse 2 R A PopUp "Window Ops" + + + +# Now the title bar buttons +# Any button in the left title-bar button gives the window ops menu +# Any button in the right title-bar button Iconifies the window +# Any button in the rightmost title-bar button maximizes +# Note the use of "Mouse 0" for AnyButton. + +# Button Context Modifi Function +Mouse 0 1 A Function "window_ops_func" +Mouse 0 2 A Function "maximize_func" +Mouse 0 4 A Iconify + +# Now the rest of the frame +# Here I invoke my complex functions for Move-or-lower, Move-or-raise, +# and Resize-or-Raise. +# Button 1 in the corner pieces, with any modifiers, gives resize or raise +Mouse 1 F A Function "Resize-or-Raise" +# Button 1 in the title, sides, or icon, w/ any modifiers, gives move or raise +Mouse 1 TS A Function "Move-or-Raise" + +# Button 1 in an icons gives move for a drag, de-iconify for a double-click, +# nothing for a single click +# Button 2 in an icon, w/ any modifiers, gives de-iconify + +Mouse 1 I A Function "Move-or-Iconify" +Mouse 2 I A Iconify + +# Button 2 in the corners, sides, or title-bar gives the window ops menu +Mouse 2 FST A Function "window_ops_func" + +Mouse 3 R A Module "t" FvwmWinList transient +############################################################################ +# Now some keyboard shortcuts. + +# Arrow Keys +# press arrow + control anywhere, and scroll by 1 page +Key Left A C Scroll -100 0 +Key Right A C Scroll +100 +0 +Key Up A C Scroll +0 -100 +Key Down A C Scroll +0 +100 + +# press arrow + meta key, and scroll by 1/10 of a page +Key Left A M Scroll -10 +0 +Key Right A M Scroll +10 +0 +Key Up A M Scroll +0 -10 +Key Down A M Scroll +0 +10 + +# press shift arrow + control anywhere, and move the pointer by 1% of a page +Key Left A SC CursorMove -1 0 +Key Right A SC CursorMove +1 +0 +Key Up A SC CursorMove +0 -1 +Key Down A SC CursorMove +0 +1 + +# press shift arrow + meta key, and move the pointer by 1/10 of a page +Key Left A SM CursorMove -10 +0 +Key Right A SM CursorMove +10 +0 +Key Up A SM CursorMove +0 -10 +Key Down A SM CursorMove +0 +10 + +# Keyboard accelerators +Key F1 A M Popup "Utilities" +Key F2 A M Popup "Window Ops" +Key F3 A M Module "t" FvwmWinList +Key F4 A M Iconify +Key F5 A M Move +Key F6 A M Resize +Key F7 A M CirculateUp +Key F8 A M CirculateDown +Key F9 R A Exec exec "rxvt" rxvt & + +#Page Up/Dapge Down keys are used to scroll by one desktop page +# in any context, press page up/down + control +# in root context, just pressing page up/down is OK +# +# I prefer the non-wrapping scroll. These are for example purposes only +#Key Next A C Scroll 100000 0 +#Key Next R N Scroll 100000 0 +#Key Prior A C Scroll -100000 0 +#Key Prior R N Scroll -100000 0 + + +############################################################################ +############################################################################ +#Definitions used by the modules + +###################### GoodStuff button-bar ################################ +# Colors + +# Geometry - really likes to pick its own size, but giving a position is OK +*GoodStuffGeometry +0-1 + +# Layout: specify rows or columns, not both +# *GoodStuffColumns 1 +*GoodStuffRows 1 + +# Define the buttons to use..... +*GoodStuff Raise Up Popup "Window Ops" + +*GoodStuff Paging clamp.xpm TogglePage + +#Buttons for some other desktops. +*GoodStuff Desk-0 desk.xpm Desk 0 0 +*GoodStuff Desk-1 desk.xpm Desk 0 1 +*GoodStuff Desk-2 desk.xpm Desk 0 2 +*GoodStuff Desk-3 desk.xpm Desk 0 3 + +######################### No Clutter ######################################## +# I only wrote NoClutter as a simple test case, but maybe some big sites like +# universities really have usage problems (too many open windows).... +# Time delays are in seconds. +*FvwmNoClutter 3600 Iconify 1 +*FvwmNoClutter 86400 Delete +*FvwmNoCLutter 172800 Destroy + +*FvwmPagerGeometry -1-1 +*FvwmPagerColumns 1 + diff --git a/sample.fvwmrc/mwm.fvwmrc b/sample.fvwmrc/mwm.fvwmrc new file mode 100644 index 0000000..ca3dbc2 --- /dev/null +++ b/sample.fvwmrc/mwm.fvwmrc @@ -0,0 +1,470 @@ +# Unfortunately, order does matter in this file +# The correct order for inserting configurations is: +# 1. Colors +# 2. Assorted configuration paramters such as ClickToFocus, or MWMBorders +# 3. Path setup (ModulePath, PixmapPath, IconPath) +# 4. Style settings, including the default style Style "*" ... +# 5. InitFunction and ResetFunction definitions. +# 6. Other Functions. Functions cannot be forward referenced from +# other functions, but they can be backward referenced. +# 7. Menus definitions. Same caveats about forward referencing +# 8. Key and Mouse Bindings. +# 9. Module options. + +# The order of steps 5, 6, and 7 is not critical, as long as there are +# no forward references to functions or menus. + +# If you get it wrong, the most common problem is that color or font settings +# are ignored + +# If you use this, you should either compile with +# -DMENU_HOTKEYS, or you should remove the & from the +# menu item labels +# +# Use of -DWINDOWLIST_HOTKEYS is recommended, but not +# required. + +############################################################################# +# set up the colors +# +# this is used for the selected window +HiForeColor Black +HiBackColor #5f9ea0 + +# these are used for unselected sticky windows +StickyForeColor Black +StickyBackColor #908090 + +# Menu colors +MenuForeColor Black +MenuBackColor grey +MenuStippleColor SlateGrey + + +############################################################################ +# Now the fonts - one for menus/icons, another for window titles +Font fixed +WindowFont fixed + +########################################################################### +# Set up the major operating modes +# +############################################################################# +# Use inferior motif-like everything +# Wimpy shallow chiselling on decorations +MWMBorders +# Only shows title-bar buttons depressed, reverses patern style on far +# right button when maximized +MWMButtons +# MWM - style (look and feel) menus +MWMMenus +# Try to abide by mwm decoration hints... +MWMDecorHints +# Try to abide by mwm function hints... +MWMFunctionHints + +DecorateTransients + +# Set windows to auto-raise after 750 milliseconds +#AutoRaise 750 + +# Normally, we'll be in focus-follows mouse mode, but uncomment this +# for mwm-style click-to-focus +ClickToFocus + +# Auto Place Icons is a nice feature.... +IconBox 5 -80 -140 -5 +IconBox 5 -160 -140 -85 +IconBox 5 -240 -140 -165 +IconBox 5 -320 -140 -245 + +# If you uncomment this, and make sure that the WindowList is bound to +# something, it works pretty much like an icon manager. +#SuppressIcons + +# If you don't like the default 150 msec click delay for the complex functions +# change this and uncomment it. +#ClickTime 150 + +ButtonStyle 1 50x22 +ButtonStyle 2 50x50 +ButtonStyle 4 22x22 + +########################################################################## +# Assorted paths to important files +# +# ModulePath is a colon-separated list, just like regular unix PATH +ModulePath /usr/lib/X11/fvwm + +# Pixmap and icon paths are also colon separated lists +PixmapPath /usr/include/X11/pixmaps +IconPath /usr/include/X11/bitmaps + +########################################################################### +# Set up the virtual desktop and pager + +#set the desk top size in units of physical screen size +DeskTopSize 2x2 + +# and the reduction scale used for the panner/pager +DeskTopScale 32 + +# flip by whole pages on the edge of the screen. +EdgeScroll 100 100 + +# A modest delay before flipping pages seems to be nice... +# I thresh in a 50 pixel Move-resistance too, just so people +# can try it out. +EdgeResistance 250 50 + +RandomPlacement + +############################################################################ +# Set the decoration styles and window options +# Order is important!!!! +# If compatible styles are set for a single window in multiple Style +# commands, then the styles are ORed together. If conflicting styles +# are set, the last one specified is used. + +# These commands should command before any menus or functions are defined, +# and before the internal pager is started. + +# change the default width. +Style "*" Color Black/#d3d3d3,Icon unknown1.xpm,HandleWidth 11,BorderWidth 6 + +Style "Fvwm*" NoTitle, NoHandles, Sticky, WindowListSkip,BorderWidth 0 +Style "Fvwm Pager" StaysOnTop +Style "FvwmPager" StaysOnTop +Style "FvwmBanner" StaysOnTop +Style "GoodStuff" NoTitle, NoHandles, Sticky, WindowListSkip,BorderWidth 0 +Style "*lock" NoTitle, NoHandles, Sticky, WindowListSkip +Style "xbiff" NoTitle, Sticky, WindowListSkip +Style "Maker" StartsOnDesk 1 +Style "matlab" StartsOnDesk 3 +Style "signal" StartsOnDesk 3 +Style "rxvt" Icon term.xpm +Style "xterm" Icon xterm.xpm, Color black/grey +Style "Appointment" Icon datebook.xpm +Style "xcalc" Icon xcalc.xpm +Style "xbiff" Icon mail1.xpm +Style "xmh" Icon mail1.xpm, StartsOnDesk 2 +Style "xman" Icon xman.xpm +Style "xvgr" Icon graphs.xpm +Style "matlab" Icon math4.xpm +Style "xmag" Icon mag_glass.xpm +Style "xgraph" Icon graphs.xpm +Style "GoodStuff" Icon toolbox.xpm + + +############################################################################# +# Stuff to do at start-up + +Function "InitFunction" + Module "I" FvwmBanner + Exec "I" xpmroot /usr/include/X11/pixmaps/fvwm.xpm & + Module "I" GoodStuff + Module "I" FvwmPager 0 3 + Exec "I" exec xterm -geometry 80x64+0+0 & + Wait "I" xterm + Desk "I" 0 2 + Exec "I" exec xterm + Wait "I" xterm + Desk "I" 0 0 +EndFunction + +Function "RestartFunction" + Exec "I" xsetroot -solid "#266294" + Module "I" GoodStuff + Module "I" FvwmPager 0 3 +EndFunction + + +############################################################################## +#now define the menus - defer bindings until later + +# This menu is invoked as a sub-menu - it allows you to quit, +# restart, or switch to another WM. +Popup "Quit-Verify" + Title "Really Quit Fvwm? " + Quit "Yes, Really Quit " + Restart "Restart Fvwm " fvwm + Restart "Start twm " twm + Restart "Start mwm " mwm + Restart "Start olwm " /usr/openwin/bin/olwm + Nop "" + Nop "No, Don't Quit " +EndPopup + +# Provides a list of modules to fire off +Popup "Module-Popup" + Title "Modules" + Module "GoodStuff" GoodStuff + Module "NoClutter" FvwmClean + Module "FvwmIdentify" FvwmIdent + Module "Banner" FvwmBanner + Module "Debug" FvwmDebug + Module "SaveDesktop" FvwmSave + Module "Pager" FvwmPager 0 3 + Module "FvwmWinList" FvwmWinList +EndPopup + + +# This menu will fire up some very common utilities +Popup "Utilities" + Title "Utilities " + Exec "Xterm " exec xterm & + Exec "Rxvt " exec rxvt & + Exec "Top " exec rxvt -T Top -n Top -e top & + Exec "Calculator " exec xcalc & + Exec "Xman " exec xman & + Exec "Xmag " exec xmag & + Nop "" + Popup "Modules" Module-Popup + Nop "" + Popup "Exit Fvwm " Quit-Verify +EndPopup + +# This defines the most common window operations +Popup "Window Ops" + Title "Window Ops " + Move "&Move Alt+F7" + Resize "&Size Alt+F8" + Lower "&Lower Alt+F3" + Raise "Raise " + Stick "(Un)Stick " + Iconify "(Un)Mi&nimize Alt+F9" + Maximize "(Un)Ma&ximize Alt+F10" + Maximize "(Un)Maximize Vertical " 0 100 + Nop "" + Close "&Close Alt+F4" +EndPopup + +Popup "Window Ops2" + Move "&Move Alt+F7" + Resize "&Size Alt+F8" + Iconify "(Un)Mi&nimize Alt+F9" + Maximize "(Un)Ma&ximize Alt+F10" + Lower "&Lower Alt+F3" + Nop "" + Close "&Close Alt+F4" + Nop "" + Module "&ScrollBar" FvwmScroll 2 2 +EndPopup +Function "Iconify-and-Raise" + Iconify "Motion" + Raise "Motion" +EndPopup + +############################################################################ +# Now define some handy complex functions + +# This one moves and then lowers the window if you drag the mouse, +# only lowers the window if you click, or does a RaiseLower if you double +# click +Function "Move-or-Lower" + Move "Motion" + Lower "Motion" + Lower "Click" + RaiseLower "DoubleClick" +EndFunction + +Function "Move-or-Iconify" + Move "Motion" + PopUp "Click" Window Ops2 + Iconify "DoubleClick" +EndFunction + +Function "windowops-or-die" + PopUp "Motion" Window Ops2 + PopUp "Click" Window Ops2 + Close "DoubleClick" + +EndFunction + +Function "Move-or-Raise" + Move "Motion" + Raise "Motion" + Raise "Click" + Iconify "DoubleClick" +EndFunction + +Function "Move-or-Lower" + Move "Motion" + Lower "Click" + RaiseLower "DoubleClick" +EndFunction +Function "Resize-or-Raise" + Resize "Motion" + Raise "Motion" + Raise "Click" + RaiseLower "DoubleClick" +EndFunction +Function "Resize-or-Lower" + Resize "Motion" + Lower "Click" + RaiseLower "DoubleClick" +EndFunction +############################################################################## +# This defines the mouse bindings + +# First, for the mouse in the root window +# Button 1 gives the Utilities menu +# Button 2 gives the Window Ops menu +# Button 3 gives the WindowList (like TwmWindows) +# I use the AnyModifier option for the modifier field, so you can hold down +# any shift-control-whatever combination you want! + +# Button Context Modifi Function +Mouse 1 R A PopUp "Utilities" +Mouse 2 R A PopUp "Window Ops" +Mouse 3 R A WindowList + + + +# Now the title bar buttons +# Any button in the left title-bar button gives the window ops menu +# Any button in the right title-bar button Iconifies the window +# Note the use of "Mouse 0" for AnyButton. + +# Button Context Modifi Function +Mouse 0 1 A Function "windowops-or-die" +Mouse 0 2 A Maximize +Mouse 0 4 A Iconify + +# Now the rest of the frame +# Here I invoke my complex functions for Move-or-lower, Move-or-raise, +# and Resize-or-Raise. +# Button 1 in the corner pieces, with any modifiers, gives resize or raise +Mouse 1 FS A Function "Resize-or-Raise" +Mouse 2 FS A Function "Resize-or-Lower" +Mouse 1 T A Function "Move-or-Raise" +Mouse 2 T A Function "Move-or-Lower" + +Mouse 1 I A Function "Move-or-Iconify" +Mouse 2 I A Function "Move-or-Iconify" +Mouse 3 I A PopUp "Window Ops2" +Mouse 3 FST A Function "windowops-or-die" + + +############################################################################ +# Now some keyboard shortcuts. + +# Arrow Keys +# press arrow + control anywhere, and scroll by 1 page +Key Left A C Scroll -100 0 +Key Right A C Scroll +100 +0 +Key Up A C Scroll +0 -100 +Key Down A C Scroll +0 +100 + +# press arrow + meta key, and scroll by 1/10 of a page +Key Left A M Scroll -10 +0 +Key Right A M Scroll +10 +0 +Key Up A M Scroll +0 -10 +Key Down A M Scroll +0 +10 + +# press shift arrow + control anywhere, and move the pointer by 1% of a page +Key Left A SC CursorMove -1 0 +Key Right A SC CursorMove +1 +0 +Key Up A SC CursorMove +0 -1 +Key Down A SC CursorMove +0 +1 + +# press shift arrow + meta key, and move the pointer by 1/10 of a page +Key Left A SM CursorMove -10 +0 +Key Right A SM CursorMove +10 +0 +Key Up A SM CursorMove +0 -10 +Key Down A SM CursorMove +0 +10 + +# Keyboard accelerators +Key F1 A M Popup "Window Ops" +Key F2 A M Popup "Utilities" +Key F3 A M Lower +Key F4 A M Destroy +Key F5 A M CirculateUp +Key F6 A M CirculateDown +Key F7 A M Move +Key F8 A M Resize +Key F9 A M Iconify +Key F10 A M Maximize + +#Page Up/Dapge Down keys are used to scroll by one desktop page +# in any context, press page up/down + control +# in root context, just pressing page up/down is OK +# +# I prefer the non-wrapping scroll. These are for example purposes only +#Key Next A C Scroll 100000 0 +#Key Next R N Scroll 100000 0 +#Key Prior A C Scroll -100000 0 +#Key Prior R N Scroll -100000 0 + + +# Useful olwm type things for Sun keyboards. +Key L5 IW N RaiseLower +Key L5 IW S Lower +Key L5 IW C Raise +Key L7 IW A Iconify + +############################################################################ +############################################################################ +## +## Module Definitions +## +############################################################################ +############################################################################ + +###################### GoodStuff button-bar ################################ +# Colors +*GoodStuffFore Black +*GoodStuffBack #908090 + +# Font +*GoodStuffFont fixed + +# Geometry - really likes to pick its own size, but giving a position is OK +*GoodStuffGeometry -1-90 + +# Layout: specify rows or columns, not both +*GoodStuffColumns 1 + +# Define the buttons to use..... +*GoodStuff Kill rbomb.xpm Destroy + +# xterm or rxvts on remote machines can be done like this +# Output re-direction is csh style, not sh style +# You will want to substitute your own hosts here! + +*GoodStuff Dopey rterm.xpm Exec "" rsh dopey "exec xterm -T dopey -display $HOSTDISPLAY &/dev/null & "& +*GoodStuff Grumpy rterm.xpm Exec "" rsh grumpy "exec xterm -T grumpy -display $HOSTDISPLAY &/dev/null & "& +*GoodStuff Snoopy rterm.xpm Exec "" rsh snoopy "exec xterm -T snoopy -display $HOSTDISPLAY &/dev/null & "& +*GoodStuff Xcalc rcalc.xpm Exec "" xcalc & +*GoodStuff mail mail2.xpm Exec "" xmh & + +*GoodStuff Paging clamp.xpm TogglePage + +########################### Pager ######################################### +*FvwmPagerBack #908090 +*FvwmPagerFore #484048 +*FvwmPagerHilight #cab3ca +*FvwmPagerGeometry x80-1-1 +*FvwmPagerLabel 0 Misc +*FvwmPagerLabel 1 FrameMaker +*FvwmPagerLabel 2 Mail +*FvwmPagerLabel 3 Matlab +*FvwmPagerSmallFont 5x8 + +########################## Window-Identifier ############################### +# Just choose colors and a fonts +*FvwmIdentBack MidnightBlue +*FvwmIdentFore Yellow +*FvwmIdentFont -adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-* + + + +##########################FvwmWinList################################## +*FvwmWinListBack #908090 +*FvwmWinListFore Black +*FvwmWinListFont -adobe-helvetica-bold-r-*-*-10-*-*-*-*-*-*-* +*FvwmWinListAction Click1 Iconify -1,Raise +*FvwmWinListAction Click2 Iconify 1 +*FvwmWinListAction Click3 Module "FvwmIdent" FvwmIdent +*FvwmWinListUseSkipList +*FvwmWinListGeometry +0-1 diff --git a/sample.fvwmrc/system.fvwmrc b/sample.fvwmrc/system.fvwmrc new file mode 100644 index 0000000..6db655c --- /dev/null +++ b/sample.fvwmrc/system.fvwmrc @@ -0,0 +1,572 @@ +# Unfortunately, order does matter in this file +# The correct order for inserting configurations is: +# 1. Colors +# 2. Assorted configuration paramters such as ClickToFocus, or MWMBorders +# 3. Path setup (ModulePath, PixmapPath, IconPath) +# 4. Style settings, including the default style Style "*" ... +# 5. InitFunction and ResetFunction definitions. +# 6. Other Functions. Functions cannot be forward referenced from +# other functions, but they can be backward referenced. +# 7. Menus definitions. Same caveats about forward referencing +# 8. Key and Mouse Bindings. +# 9. Module options. + +# The order of steps 5, 6, and 7 is not critical, as long as there are +# no forward references to functions or menus. + +# If you get it wrong, the most common problem is that color or font settings +# are ignored + +########################################################################### +# set up the colors +# +# OK some people like bright clear colors on their window decorations. +# These people, I guess would mostly be from nice sunny/good weather places +# line California. +# +# StdForeColor Black +# StdBackColor LightSkyBlue +# HiForeColor yellow +# HiBackColor PeachPuff1 +# PagerBackColor BlanchedAlmond + +# Me, I'm from Upstate New York, and live in New Hampshire, so I prefer +# these dark muddy colors... + +# this is used for the selected window +HiForeColor Black +HiBackColor #c06077 + +#PagerBackColor #5c54c0 +#PagerForeColor orchid + +StickyForeColor Black +StickyBackColor #60c0a0 + +# Menu colors +MenuForeColor Black +MenuBackColor grey +MenuStippleColor SlateGrey + +############################################################################ +# Now the fonts - one for menus, another for window titles, another for icons +#Font -adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-* +Font -*-times-medium-i-*-*-*-120-*-*-*-*-*-* +WindowFont -adobe-helvetica-bold-r-*-*-12-*-*-*-*-*-*-* +#IconFont -adobe-helvetica-medium-r-*-*-11-*-*-*-*-*-*-* +IconFont fixed + +########################################################################### +# Set up the major operating modes +# +######################## FOCUS STUFF ############################## +# Set windows to auto-raise after 750 milliseconds if you like it. +# Autoraise can sometimes obscure pop-up windows. Performance is now +# similar to olvwm's auto-raise feature. +#AutoRaise 750 + +# Normally, we'll be in focus-follows mouse mode, but uncomment this +# for mwm-style click-to-focus +#ClickToFocus + +######################## ICON STUFF ############################## +# Auto Place Icons is a nice feature.... +# This creates two icon boxes, one on the left side, then one on the +# bottom. Leaves room in the upper left for my clock and xbiff, +# room on the bottom for the Pager. +#IconBox -150 90 -5 -140 +#IconBox 5 -140 -140 -5 +IconBox -70 1 -1 -140 + +# If you uncomment this, and make sure that the WindowList is bound to +# something, it works pretty much like an icon manager. +#SuppressIcons + +# StubbornIcons makes icons de-iconify into their original position on the +# desktop, instead of on the current page. +#StubbornIcons + +# With AutoPlacement, icons will normally place themselves underneath active +# windows. This option changes that. +#StubbornIconPlacement + +# If you want ALL you icons to follow you around the desktop (Sticky), try +# this +#StickyIcons + +######################## MWM EMULATION ####################### +# +# My feeling is that everyone should use MWMDecorHints and MWMFunctionHints, +# since some applications depend on having the window manager respect them + +# MWMFunction hints parses the function information in the MOTIF_WM_HINTS +# property, and prohibits use of these functions on the window. Appropriate +# portions of the window decorations are removed. +MWMFunctionHints + +# MWM is kinda picky about what can be done to transients, and it was keeping +# me from iconifying some windows that I like to iconify, so here's an +# over-ride that will allow me to do the operation, even tough the menu +# item is shaded out. +MWMHintOverride + +# MWMDecor hints parses the decoration information in the MOTIF_WM_HINTS +# property, and removes these decoratons from the window. This does not affect +# the functions that can be performed via the menus. +MWMDecorHints + +# These are affect minor aspects for the look-and-feel. +# Sub-menus placement mwm-style? +# MWMMenus +# mwm-style border reliefs (less deep than default fvwm) ? +# MWMBorders +# Maximize button does mwm-inversion thingy +# MWMButtons +######################## MISCELLANEOUS STUFF ####################### +# If you don't like the default 150 msec click delay for the complex functions +# change this and uncomment it. +#ClickTime 150 + +# OpaqueMove has a number (N) attached to it (default 5). +# if the window occupies less than N% of the screen, +# then opaque move is used. 0 <= N <= 100 +# OpaqueMove 100 + +# flip by whole pages on the edge of the screen. +EdgeScroll 100 100 + +# A modest delay before flipping pages seems to be nice... +# I thresh in a 50 pixel Move-resistance too, just so people +# can try it out. +EdgeResistance 250 50 + + +######################## WINDOW PLACEMENT ####################### +# RandomPlacement prevents user interaction while placing windows: +# RandomPlacement + +# SmartPlacement makes new windows pop-up in blank regions of screen +# if possible, or falls back to random or interactive placement. +SmartPlacement + +# With SmartPlacement, windows will normally place themselves over icons. +# Uncomment this to change that. +#StubbornPlacement + +# NoPPosition instructs fvwm to ignore the PPosition field in window +# geometry hints. Emacs annoyingly sets PPosition to (0,0)! +NoPPosition + + +######################## DECORATIONS ####################### +# If you want decorated transient windows, uncomment this: +#DecorateTransients + + +########################################################################### +# Set up the virtual desktop and pager + +#set the desk top size in units of physical screen size +DeskTopSize 2x2 + +# and the reduction scale used for the panner/pager +DeskTopScale 32 + +########################################################################## +# Module path and paths to the icons +# +# ModulePath is a colon-separated list, just like regular unix PATH +ModulePath /usr/lib/X11/fvwm +PixmapPath /usr/include/X11/pixmaps/ +IconPath /usr/include/X11/bitmaps/ + +############################################################################ +# Set the decoration styles and window options +# Order is important!!!! +# If compatible styles are set for a single window in multiple Style +# commands, then the styles are ORed together. If conflicting styles +# are set, the last one specified is used. + +# These commands should command before any menus or functions are defined, +# and before the internal pager is started. + +# change the default width. +Style "*" BorderWidth 5, HandleWidth 5, Color Black/#60a0c0,Icon unknown1.xpm + +Style "Fvwm*" NoTitle, NoHandles, Sticky, WindowListSkip,BorderWidth 0 +Style "Fvwm Pager" StaysOnTop +Style "FvwmPager" StaysOnTop +Style "FvwmBanner" StaysOnTop +Style "GoodStuff" NoTitle, NoHandles, Sticky, WindowListSkip,BorderWidth 0 +Style "*lock" NoTitle, NoHandles, Sticky, WindowListSkip +Style "xbiff" NoTitle, Sticky, WindowListSkip +Style "Maker" StartsOnDesk 1 +Style "matlab" StartsOnDesk 3 +Style "signal" StartsOnDesk 3 +Style "rxvt" Icon term.xpm +Style "xterm" Icon xterm.xpm, Color black/grey +Style "Appointment" Icon datebook.xpm, NoButton 2, NoButton 4 +Style "xcalc" Icon xcalc.xpm, NoButton 2 +Style "xbiff" Icon mail1.xpm, NoButton 2 +Style "xmh" Icon mail1.xpm, StartsOnDesk 2, NoButton 2 +Style "xman" Icon xman.xpm +Style "xvgr" Icon graphs.xpm +Style "matlab" Icon math4.xpm +Style "xmag" Icon mag_glass.xpm +Style "xgraph" Icon graphs.xpm +Style "GoodStuff" Icon toolbox.xpm + +# Change the Maximize and iconify buttons to up and down triangles. + +ButtonStyle : 2 4 50x35@1 65x65@0 35x65@0 50x35@1 +ButtonStyle : 4 4 50x65@1 35x35@1 65x35@1 50x65@0 + +############################################################################# + +# Stuff to do at start-up + +Function "InitFunction" + Module "I" FvwmBanner + Exec "I" xpmroot /usr/include/X11/pixmaps/fvwm.xpm & + Module "I" GoodStuff + Exec "I" exec xterm -geometry 80x64+0+0 & + Wait "I" xterm + Desk "I" 0 2 + Exec "I" exec xterm -geometry +0+0 & + Wait "I" xterm + Desk "I" 0 0 +EndFunction + +Function "RestartFunction" + Exec "I" xsetroot -solid "#266294" + Module "I" GoodStuff +EndFunction + + +############################################################################ +# Now define some handy complex functions + +# This one moves and then raises the window if you drag the mouse, +# only raises the window if you click, or does a RaiseLower if you double +# click +Function "Move-or-Raise" + Move "Motion" + Raise "Motion" + Raise "Click" + RaiseLower "DoubleClick" +EndFunction + +# This one maximizes vertically if you click (leaving room for the GoodStuff bar at the +# bottom, or does a full maximization if you double click, or a true full vertical +# maximization if you just hold the mouse button down. +Function "maximize_func" + Maximize "Motion" 0 100 + Maximize "Click" 0 80 + Maximize "DoubleClick" 100 100 +EndFunction + + +# This one moves and then lowers the window if you drag the mouse, +# only lowers the window if you click, or does a RaiseLower if you double +# click +Function "Move-or-Lower" + Move "Motion" + Lower "Motion" + Lower "Click" + RaiseLower "DoubleClick" +EndFunction + +# This one moves or (de)iconifies: +Function "Move-or-Iconify" + Move "Motion" + Iconify "DoubleClick" +EndFunction + +# This one resizes and then raises the window if you drag the mouse, +# only raises the window if you click, or does a RaiseLower if you double +# click +Function "Resize-or-Raise" + Resize "Motion" + Raise "Motion" + Raise "Click" + RaiseLower "DoubleClick" +EndFunction + + +# This is provided as a hint only. +# Move to a known page on the desktop, then start an application in a +# known location. Could also switch to a known desktop, I guess +#Function "abs_coord" +# GoToPage "Immediate" 1,1 +# Exec "Immediate" exec xcalc -geometry +100+100& +#EndFunction + + +############################################################################## +#now define the menus - defer bindings until later + +# This menu is invoked as a sub-menu - it allows you to quit, +# restart, or switch to another WM. +Popup "Quit-Verify" + Title "Really Quit Fvwm?" + Quit "Yes, Really Quit" + Restart "Restart Fvwm" fvwm + Restart "Start twm" twm + Restart "Start tvtwm" tvtwm + Restart "Start mwm" mwm + Restart "Start olwm" /usr/openwin/bin/olwm + Nop "" + Nop "No, Don't Quit" +EndPopup + +# Provides a list of modules to fire off +Popup "Module-Popup" + Title "Modules" + Module "GoodStuff" GoodStuff + Module "Clean-Up" FvwmClean + Module "Identify" FvwmIdent + Module "SaveDesktop" FvwmSave + Module "Debug" FvwmDebug + Module "Pager" FvwmPager 0 3 + Module "FvwmWinList" FvwmWinList +EndPopup + +# This menu will fire up some very common utilities +Popup "Utilities" + Title "Utilities" + Exec "Xterm" exec xterm -e tcsh & + Exec "Rxvt" exec rxvt & + Exec "Top" exec rxvt -T Top -n Top -e top & + Exec "Calculator" exec xcalc & + Exec "Xman" exec xman & + Exec "Xmag" exec xmag & + Nop "" + Popup "Modules" Module-Popup + Nop "" + Popup "Exit Fvwm" Quit-Verify +EndPopup + +# This defines the most common window operations +Popup "Window Ops" + Title "Window Ops" + Function "Move" Move-or-Raise + Function "Resize" Resize-or-Raise + Raise "Raise" + Lower "Lower" + Iconify "(De)Iconify" + Stick "(Un)Stick" + Function "(Un)Maximize" maximize_func + Nop "" + Destroy "Destroy" + Close "Close" + Nop "" + Refresh "Refresh Screen" +EndPopup + +# A trimmed down version of "Window Ops", good for binding to decorations +Popup "Window Ops2" + Function "Move" Move-or-Raise + Function "Resize" Resize-or-Raise + Raise "Raise" + Lower "Lower" + Iconify "Iconify" + Stick "(Un)Stick" + Nop "" + Destroy "Destroy" + Close "Close" + Nop "" + Module "ScrollBar" FvwmScroll 2 2 +EndPopup + +############################################################################# +# One more complex function - couldn't be defined earlier because it used +# pop-up menus +# +# This creates a motif-ish sticky menu for the title-bar window-ops +# pop-up +# Menu acts like normal twm menu if you just hold the button down, +# but if you click instead, the menu stays up, motif style +Function "window_ops_func" + PopUp "Click" Window Ops2 + PopUp "Motion" Window Ops2 +# Motif would add: +# I'll add it too, it can be mighty handy. + Close "DoubleClick" +EndFunction + + +############################################################################## +# This defines the mouse bindings + +# First, for the mouse in the root window +# Button 1 gives the Utilities menu +# Button 2 gives the Window Ops menu +# Button 3 gives the WindowList (like TwmWindows) +# I use the AnyModifier (A) option for the modifier field, so you can hold down +# any shift-control-whatever combination you want! + +# Button Context Modifi Function +Mouse 1 R A PopUp "Utilities" +Mouse 2 R A PopUp "Window Ops" +Mouse 3 R A Module "winlist" FvwmWinList transient + + + +# Now the title bar buttons +# Any button in the left title-bar button gives the window ops menu +# Any button in the right title-bar button Iconifies the window +# Any button in the rightmost title-bar button maximizes +# Note the use of "Mouse 0" for AnyButton. + +# Button Context Modifi Function +Mouse 0 1 A Function "window_ops_func" +Mouse 0 2 A Function "maximize_func" +Mouse 0 4 A Iconify + +# Now the rest of the frame +# Here I invoke my complex functions for Move-or-lower, Move-or-raise, +# and Resize-or-Raise. +# Button 1 in the corner pieces, with any modifiers, gives resize or raise +Mouse 1 F A Function "Resize-or-Raise" +# Button 1 in the title, sides, or icon, w/ any modifiers, gives move or raise +Mouse 1 TS A Function "Move-or-Raise" + +# Button 1 in an icons gives move for a drag, de-iconify for a double-click, +# nothing for a single click +# Button 2 in an icon, w/ any modifiers, gives de-iconify + +Mouse 1 I A Function "Move-or-Iconify" +Mouse 2 I A Iconify + +# Button 2 in the corners, sides, or title-bar gives the window ops menu +Mouse 2 FST A Function "window_ops_func" +# Button 3 anywhere in the decoration (except the title-bar buttons) +# does a raise-lower +Mouse 3 TSIF A RaiseLower + +# Button 3 in the window, with the Modifier-1 key (usually alt or diamond) +# gives Raise-Lower. Used to use control here, but that interferes with xterm +Mouse 3 W M RaiseLower + +############################################################################ +# Now some keyboard shortcuts. + +# Arrow Keys +# press arrow + control anywhere, and scroll by 1 page +Key Left A C Scroll -100 0 +Key Right A C Scroll +100 +0 +Key Up A C Scroll +0 -100 +Key Down A C Scroll +0 +100 + +# press arrow + meta key, and scroll by 1/10 of a page +Key Left A M Scroll -10 +0 +Key Right A M Scroll +10 +0 +Key Up A M Scroll +0 -10 +Key Down A M Scroll +0 +10 + +# press shift arrow + control anywhere, and move the pointer by 1% of a page +Key Left A SC CursorMove -1 0 +Key Right A SC CursorMove +1 +0 +Key Up A SC CursorMove +0 -1 +Key Down A SC CursorMove +0 +1 + +# press shift arrow + meta key, and move the pointer by 1/10 of a page +Key Left A SM CursorMove -10 +0 +Key Right A SM CursorMove +10 +0 +Key Up A SM CursorMove +0 -10 +Key Down A SM CursorMove +0 +10 + +# Keyboard accelerators +Key F1 A M Popup "Utilities" +Key F1 A M Popup "Utilities" +Key F2 A M Popup "Window Ops" +Key F3 A M Module "WindowList" FvwmWinList +Key F4 A M Iconify +Key F5 A M Move +Key F6 A M Resize +Key F7 A M CirculateUp +Key F8 A M CirculateDown + +#Page Up/Dapge Down keys are used to scroll by one desktop page +# in any context, press page up/down + control +# in root context, just pressing page up/down is OK +# +# I prefer the non-wrapping scroll. These are for example purposes only +#Key Next A C Scroll 100000 0 +#Key Next R N Scroll 100000 0 +#Key Prior A C Scroll -100000 0 +#Key Prior R N Scroll -100000 0 + + +############################################################################ +############################################################################ +#Definitions used by the modules + +###################### GoodStuff button-bar ################################ +# Colors +*GoodStuffFore Black +*GoodStuffBack #908090 + +# Font +*GoodStuffFont -adobe-helvetica-bold-r-*-*-10-*-*-*-*-*-*-* +# Geometry - really likes to pick its own size, but giving a position is OK +*GoodStuffGeometry -1-1 + +# Layout: specify rows or columns, not both +*GoodStuffRows 2 + +# Define the buttons to use..... +*GoodStuff Kill rbomb.xpm Destroy + +# xterm or rxvts on remote machines can be done like this +# Output re-direction is csh style, not sh style +# You will want to substitute your own hosts here! + +*GoodStuff Dopey rterm.xpm Exec "" rsh dopey "exec xterm -T dopey -display $HOSTDISPLAY &/dev/null & "& +*GoodStuff Grumpy rterm.xpm Exec "" rsh grumpy "exec xterm -T grumpy -display $HOSTDISPLAY &/dev/null & "& +*GoodStuff Snoopy rterm.xpm Exec "" rsh snoopy "exec xterm -T snoopy -display $HOSTDISPLAY &/dev/null & "& +*GoodStuff Xcalc rcalc.xpm Exec "" xcalc & +*GoodStuff mail mail2.xpm Exec "" xmh & + +*GoodStuff Paging clamp.xpm TogglePage +*GoodStuff - clock.xpm Swallow "xclock" xclock -bg \#908090 -geometry -1500-1500 -padding 0 +*GoodStuff(4x1) - whatever SwallowModule "FvwmPager" FvwmPager 0 3 + + +######################### No Clutter ######################################## +# I only wrote NoClutter as a simple test case, but maybe some big sites like +# universities really have usage problems (too many open windows).... +# Time delays are in seconds. +*FvwmNoClutter 3600 Iconify 1 +*FvwmNoClutter 86400 Delete +*FvwmNoCLutter 172800 Destroy + +########################## Window-Identifier ############################### +# Just choose colors and a fonts +*FvwmIdentBack MidnightBlue +*FvwmIdentFore Yellow +*FvwmIdentFont -adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-* + +########################### Pager ######################################### +*FvwmPagerBack #908090 +*FvwmPagerFore #484048 +*FvwmPagerFont -adobe-helvetica-bold-r-*-*-10-*-*-*-*-*-*-* +*FvwmPagerHilight #cab3ca +*FvwmPagerGeometry -1-1 +*FvwmPagerLabel 0 Misc +*FvwmPagerLabel 1 Maker +*FvwmPagerLabel 2 Mail +*FvwmPagerLabel 3 Matlab +*FvwmPagerSmallFont 5x8 + + +##########################FvwmWinList################################## +*FvwmWinListBack #908090 +*FvwmWinListFore Black +*FvwmWinListFont -adobe-helvetica-bold-r-*-*-10-*-*-*-*-*-*-* +*FvwmWinListAction Click1 Iconify -1,Focus +*FvwmWinListAction Click2 Iconify +*FvwmWinListAction Click3 Module "FvwmIdent" FvwmIdent +*FvwmWinListUseSkipList +*FvwmWinListGeometry +0-1 + diff --git a/tar_script b/tar_script new file mode 100755 index 0000000..92e21cc --- /dev/null +++ b/tar_script @@ -0,0 +1,5 @@ +tar -cvf fvwm-core.tar ChangeLog Imakefile MakeMakefiles README.Install configure.h fvwm.README version.h documentation/WhereToGetIt documentation/error_codes documentation/m4_hacks documentation/mailing_list fvwm sample.fvwmrc libs + +tar -cvf fvwm-modules.tar documentation/modules.tex modules xpmroot +tar -cvf fvwm-icons.tar fvwm_icons + diff --git a/version.h b/version.h new file mode 100644 index 0000000..7cfa1f2 --- /dev/null +++ b/version.h @@ -0,0 +1,2 @@ +#define VERSION "1.24r" + diff --git a/xpmroot/Imakefile b/xpmroot/Imakefile new file mode 100644 index 0000000..21f9f71 --- /dev/null +++ b/xpmroot/Imakefile @@ -0,0 +1,33 @@ +/* Imakefile for xpmroot */ +/* Thu Aug 5 11:21:36 MET DST 1993, mj@dfv.rwth-aachen.de */ + +/* setup is done entirely in configuration.h now! */ +/* You should need to do much in here, excpt maybe add libraries */ + +/* I need to get the #define XPM from configuration.h if its in there, */ +/* so that I can tell if I should include -lXpm */ +#include <../configure.h> + +COMPILER + +#ifdef XPM +XPMLIB = XPMLIBRARY + +DEPLIBS = $(DEPXLIB) ../libs/libfvwmlib.a + +#ifdef AlphaArchitecture +LOCAL_LIBRARIES = $(XPMLIB) $(XLIB) -ldnet_stub -L../libs -lfvwmlib +#else +LOCAL_LIBRARIES = $(XPMLIB) $(XLIB) -L../libs -lfvwmlib +#endif + +FVWM_BIN_DIR +LINTLIBS = $(LINTXLIB) + +SRCS = xpmroot.c +OBJS = xpmroot.o + +ComplexProgramTarget(xpmroot) + +#endif + diff --git a/xpmroot/xpmroot.c b/xpmroot/xpmroot.c new file mode 100644 index 0000000..a8096ee --- /dev/null +++ b/xpmroot/xpmroot.c @@ -0,0 +1,128 @@ +/**************************************************************************** + * This is an all new program to set the root window to an Xpm pixmap. + * Copyright 1993, Rob Nation + * You may use this file for anything you want, as long as the copyright + * is kept intact. No guarantees of any sort are made in any way regarding + * this program or anything related to it. + ****************************************************************************/ + +#include "../configure.h" + +#include +#include +#include +#include +#include +#include +#include "../version.h" +#include "../libs/fvwmlib.h" +int save_colors = 0; +Display *dpy; +int screen; +Window root; +char *display_name = NULL; +void SetRootWindow(char *tline); +Pixmap rootXpm; + +int main(int argc, char **argv) +{ + Atom prop, type; + int format; + unsigned long length, after; + unsigned char *data; + + if(argc != 2) + { + fprintf(stderr,"Xpmroot Version %s\n",VERSION); + fprintf(stderr,"Usage: xpmroot xpmfile\n"); + fprintf(stderr,"Try Again\n"); + exit(1); + } + dpy = XOpenDisplay(display_name); + if (!dpy) + { + fprintf(stderr, "Xpmroot: unable to open display '%s'\n", + XDisplayName (display_name)); + exit (2); + } + screen = DefaultScreen(dpy); + root = RootWindow(dpy, screen); + + SetRootWindow(argv[1]); + + prop = XInternAtom(dpy, "_XSETROOT_ID", False); + + (void)XGetWindowProperty(dpy, root, prop, 0L, 1L, True, AnyPropertyType, + &type, &format, &length, &after, &data); + if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0)) + XKillClient(dpy, *((Pixmap *)data)); + + XChangeProperty(dpy, root, prop, XA_PIXMAP, 32, PropModeReplace, + (unsigned char *) &rootXpm, 1); + XSetCloseDownMode(dpy, RetainPermanent); + XCloseDisplay(dpy); + return 0; +} + + +void SetRootWindow(char *tline) +{ + XWindowAttributes root_attr; + XpmAttributes xpm_attributes; + Pixmap shapeMask; + int val; + + XGetWindowAttributes(dpy,root,&root_attr); + xpm_attributes.colormap = root_attr.colormap; + xpm_attributes.valuemask = XpmSize | XpmReturnPixels|XpmColormap; + if((val = XpmReadFileToPixmap(dpy,root, tline, + &rootXpm, &shapeMask, + &xpm_attributes))!= XpmSuccess) + { + if(val == XpmOpenFailed) + fprintf(stderr, "Couldn't open pixmap file\n"); + else if(val == XpmColorFailed) + fprintf(stderr, "Couldn't allocated required colors\n"); + else if(val == XpmFileInvalid) + fprintf(stderr, "Invalid Format for an Xpm File\n"); + else if(val == XpmColorError) + fprintf(stderr, "Invalid Color specified in Xpm FIle\n"); + else if(val == XpmNoMemory) + fprintf(stderr, "Insufficient Memory\n"); + exit(1); + } + + XSetWindowBackgroundPixmap(dpy, root, rootXpm); + save_colors = 1; + XClearWindow(dpy,root); + +} + + +#ifdef NEEDS_STRCASECMP +int strcasecmp(char *s1,char *s2) +{ + int c1,c2; + int n,n2; + + n=strlen(s1); + n2=strlen(s2); + if(n!=n2) + return 1; + + for (;;) + { + c1 = *s1; + c2 = *s2; + if (!c1 || !c2) + return(c1 - c2); + if (isupper(c1)) + c1 = 'a' - 1 + (c1 & 31); + if (isupper(c2)) + c2 = 'a' - 1 + (c2 & 31); + if (c1 != c2) + return(c1 - c2); + n--,s1++,s2++; + } +} +#endif diff --git a/xpmroot/xpmroot.man b/xpmroot/xpmroot.man new file mode 100644 index 0000000..95ab929 --- /dev/null +++ b/xpmroot/xpmroot.man @@ -0,0 +1,16 @@ +'\" t +.\" @(#)xpmroot.1 1.01 8/10/93 +.TH XPMROOT 1.01 "13 August 1993" +.UC +.SH NAME +xpmroot \- Sets the root window of the current X display to an Xpm pixmap +.SH SYNOPSIS +\fBxpmroot\fP \fIfile\fP +.SH DESCRIPTION +\fIxpmroot\fP reads the Xpm file specified in the command line +and displays it in the root window. +.SH BUGS +Repeated use of xpmroot with different xpm pixmaps will use up slots in +your color table pretty darn fast. +.SH AUTHOR +Rob Nation