wmi

git clone git://oldgit.suckless.org/wmi/
Log | Files | Refs | LICENSE

commit 854471326fd9423ccd2399ccb92bfcff647374f0
Author: Anselm R Garbe <garbeam@gmail.com>
Date:   Wed,  9 Sep 2009 13:25:00 +0100

up

Diffstat:
AUTHORS | 11+++++++++++
BUGS | 7+++++++
CONTRIB | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
COPYING | 21+++++++++++++++++++++
ChangeLog | 418+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
FAQ | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
INSTALL | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
LICENSE.txt | 21+++++++++++++++++++++
Makefile.am | 19+++++++++++++++++++
Makefile.in | 591+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
NEWS | 2++
README | 5+++++
TODO | 26++++++++++++++++++++++++++
aclocal.m4 | 933+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
action.cpp | 145+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
action.h | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
actions.cpp | 1037+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
actions.h | 170+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
atoms.cpp | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
atoms.h | 50++++++++++++++++++++++++++++++++++++++++++++++++++
bar.cpp | 44++++++++++++++++++++++++++++++++++++++++++++
bar.h | 47+++++++++++++++++++++++++++++++++++++++++++++++
binder.cpp | 742+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
binder.h | 233+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
box.cpp | 50++++++++++++++++++++++++++++++++++++++++++++++++++
box.h | 39+++++++++++++++++++++++++++++++++++++++
client.cpp | 884+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
client.h | 155+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
clientbar.cpp | 348+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
clientbar.h | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
config.h.in | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
configure | 8075+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
configure.ac | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
container.h | 272+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cursors.cpp | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cursors.h | 40++++++++++++++++++++++++++++++++++++++++
draw.cpp | 535+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
draw.h | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
examples/session-managers/kdm-entry | 14++++++++++++++
examples/statustext-deleuze.sh | 27+++++++++++++++++++++++++++
examples/statustext-gavin.sh | 29+++++++++++++++++++++++++++++
examples/statustext.sh | 45+++++++++++++++++++++++++++++++++++++++++++++
examples/themes/accent-theme.conf | 48++++++++++++++++++++++++++++++++++++++++++++++++
examples/themes/flat-cyan-theme.conf | 47+++++++++++++++++++++++++++++++++++++++++++++++
examples/themes/flat-grey-theme.conf | 47+++++++++++++++++++++++++++++++++++++++++++++++
examples/themes/gold-theme.conf | 48++++++++++++++++++++++++++++++++++++++++++++++++
examples/themes/laotse-theme.conf | 47+++++++++++++++++++++++++++++++++++++++++++++++
examples/themes/lunatic-theme.conf | 47+++++++++++++++++++++++++++++++++++++++++++++++
examples/themes/peacock-theme.conf | 48++++++++++++++++++++++++++++++++++++++++++++++++
expander.cpp | 118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
expander.h | 37+++++++++++++++++++++++++++++++++++++
float.cpp | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
float.h | 30++++++++++++++++++++++++++++++
font.cpp | 34++++++++++++++++++++++++++++++++++
font.h | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
frame.cpp | 458+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
frame.h | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
inputbar.cpp | 463+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
inputbar.h | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
install-sh | 325+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
kernel.cpp | 1294+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
kernel.h | 253+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
label.cpp | 110+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
label.h | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
launcher.cpp | 114+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
launcher.h | 42++++++++++++++++++++++++++++++++++++++++++
loader.cpp | 195+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
loader.h | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
logger.cpp | 39+++++++++++++++++++++++++++++++++++++++
logger.h | 36++++++++++++++++++++++++++++++++++++
main.cpp | 343+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
man/Makefile.am | 2++
man/Makefile.in | 387+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
man/actions.conf.5 | 366+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
man/common.conf.5 | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
man/session.conf.5 | 37+++++++++++++++++++++++++++++++++++++
man/theme.conf.5 | 237+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
man/wmi.1 | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
man/wmiremote.1 | 41+++++++++++++++++++++++++++++++++++++++++
menu.cpp | 408+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
menu.h | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
missing | 360+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
monitor.cpp | 1040+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
monitor.h | 270+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
prompt.cpp | 22++++++++++++++++++++++
prompt.h | 39+++++++++++++++++++++++++++++++++++++++
rectangle.cpp | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
rectangle.h | 45+++++++++++++++++++++++++++++++++++++++++++++
shortcut.cpp | 103+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
shortcut.h | 50++++++++++++++++++++++++++++++++++++++++++++++++++
singleton.h | 33+++++++++++++++++++++++++++++++++
slot.cpp | 477+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
slot.h | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
split.cpp | 382+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
split.h | 46++++++++++++++++++++++++++++++++++++++++++++++
src/Makefile.am | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/Makefile.in | 495+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
statusbar.cpp | 353+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
statusbar.h | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
theme.cpp | 141+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
theme.h | 105+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
thing.cpp | 361+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
thing.h | 125+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tree.cpp | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tree.h | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
util.cpp | 496+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
util.h | 144+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
validators.cpp | 377+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
validators.h | 127+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
version.h.in | 1+
widget.cpp | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
widget.h | 50++++++++++++++++++++++++++++++++++++++++++++++++++
wmi.h | 44++++++++++++++++++++++++++++++++++++++++++++
wmi.spec | 122+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
wmi.spec.in | 122+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
wmiremote.cpp | 162+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
workspace.cpp | 987+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
workspace.h | 197+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
xcore.cpp | 686+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
xcore.h | 329+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
xfont.cpp | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
xfont.h | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
xft.m4 | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
xftfont.cpp | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
xftfont.h | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
125 files changed, 31460 insertions(+), 0 deletions(-)

diff --git a/AUTHORS b/AUTHORS @@ -0,0 +1,11 @@ +$Id: AUTHORS 735 2004-09-27 18:36:45Z garbeam $ + +Current developers of the WMI: + + - Anselm R. Garbe <anselmg at t-online.de> + - Marcel Manthe <-0m0- at web.de> + - Oliver Rendgen <oli at hypeo.de> (Documentation) + - John Pham <jhnphm at gmail.com> (Debian packager) + - PEYROUX Jean <alnix at phear.org> (BSD ports maintainer) + - Matthew Allen <matthew at lith.com> (Art asset developer) + - Dr. Johann Pfefferl <johann.pfefferl at agfa.com> diff --git a/BUGS b/BUGS @@ -0,0 +1,7 @@ +$Id: BUGS 735 2004-09-27 18:36:45Z garbeam $ + +Grep the wmi-devel mailinglist on http://wmi.berlios.de for known bugs. +If your bug is not known or seems not to be, just post a mail to +Anselm R. Garbe <anselmg at t-online.de> or to the wmi-devel list. + +We don't use the BerliOS bugtracker yet. diff --git a/CONTRIB b/CONTRIB @@ -0,0 +1,53 @@ +$Id: CONTRIB 735 2004-09-27 18:36:45Z garbeam $ + +Current contributors: + + - Ryan Sorensen <rcsorensen at gmail.com> + (contributed transient mode patch) + - grayrest (varuious valueable feedback) + - zahod (contributed new default theme - industrial theme) + - Martin Moncrieffe (valueable feedback concerning mathematica) + - Hans Ulrich Niedermann (contributed rpm spec file for wmi trunk) + - Michael Ihde (contributed doxygen comments, some patches) + - Wilson Oliveira (contributed the WMIConf tool) + - carmee (contributed various feedback) + - Mathieu L (contributed various feedback) + - Brian Dorsey (contributed various feedback) + - Rajesh Menon (contributed various feedback) + - Oliver Kopp (contributed various feedback) + - Andreas Gunnarsson <wmi at zzlevo.net> + (contributed Split::neighbor() patch) + - AntThyKem <antthykem at tiscali.fr> + (contributed rpm package) + - Fernando Tarlá Cardoso Lemos <fernandotcl at spymac.com> + (contributed the wasplite theme, which is based on Matthews wasp theme) + - Fabian Braennstroem <f.braennstroem at gmx.de> + (contributed archlinux stable and current packages) + - Kathryn Andersen <kat_lists at katspace.com> + (contributed nice theme and valuable newbie feedback) + - Markus Lindorfer <markus.lindorfer at liwest.at> + (contributed patch to compile on Solaris) + - Marcin Pawlik <wapkil at o2.pl> + (contributed Control-keys patch for input mode) + - Gavin McCullagh <lists_gmc at fiachra.ucd.ie> + (contributed various ideas, active WMI user) + - Fernan Bolando <fernanbolando at mailc.net> + (one of the most active WMI testers, various ideas) + - Frank Ehmsen <ehmsen at gmx.de> (bug reports and various ideas) + - Gavin McCullagh <gavin at fiachra.ucd.ie> (various feedback) + - Fernan Bolando <fernanbolando at mailc.net> (various feedback) + +Inactive contributors/older contributors: + + - Rainer Trusch (bug reports and some ideas) + - Hannes Klas <greathun at gmx.de> (Wiki) + - Stefan Kuttler <Deleuze at gmx.net> (Inventor of project name) + +Special thanks to following people who gave very useful feedback from +the very beginning of development: + + - Dr. Frank Boehme (Various ideas, hints, feedback) + - Mark Weinem (Various ideas, hints, feedback) + - Tuncer M zayamut Ayaz (Provided some WMI paper corrections) + - Robert Lillack <rob at lillack.de> (Ideas about window management) + - et al. diff --git a/COPYING b/COPYING @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/ChangeLog b/ChangeLog @@ -0,0 +1,418 @@ +$Id: ChangeLog 735 2004-09-27 18:36:45Z garbeam $ + +wmi-10: + * cycling workspaces focusses the last focussed client + * toggle-statusbar-mode for displaying client title instead of + workspace pager and detached-clients, useful for long client + names + * renamed startup-action.name to startup.chain, now you can provide + arbitrary action names in a comma separated list for the startup.chain, + default is single "rehash" action + * removed groups + * renamed ex-floatbar into clientbar + * renamed toggle-status-mode into toggle-clientbar-mode + * improved mode pager button on client bar, filled means that there're + clients attached, unfilled means, no clients attached + * removed statusbar.status-width option which is calculated now + automatically + * renamed toggle-focus-mode into toggle-mode + * new menu button on new clientbar + * new menu for fast selection of clients and fast attaching detached + clients, also for fast action invocation + * new common.conf option 'menu.actions' for actions definition + within menu + * applied several patches by Dr. Pfefferl + * fixed BUG-24 (label overlapping) + * fixed toggle-max issues + * removed cycle-frame-* + * fixed bar and button sizes + * new theme colors for focus requests + color.focusreq.background + color.focusreq.text + color.focusreq.shine + color.focusreq.shadow + * changed default theme to zahod's industrial theme contribution + * implemented race prevention for EnterNotify's of sloppy focus stuff + with floating clients + * fixed broken destroy-* actions + * improved sticky handling, now sticky does not mean raised on top + * detached clients will get attached again after restart + * fixed following BUGS + BUG-51 (detaching firefox crashed wmi) + BUG-50 (endless resizing due to missing increment hint handling) + BUG-49 (destroy action have been broken) + BUG-39 (don't run startup.chain on restart) -> invalid, no bug + * implemented new actions 'hook-client' and 'unhook-client' which + make it possible to hook clients to specific workspaces + * Eliminated several BadWindow and BadMatch occurences + * autocompletion.mode option of common.conf reappeared, now + with two possibilities - 'default' and 'regex' + * improved menu with missing button functions, especially right click + on workspace items or clients (middle button click now inserts cut + buffer into client) + * new action 'toggle-sloppy-mode' which toggles the sloppy focussing + on the fly + * removed resize-move.info option, because bar is not supported anymore, + be a fan of pseudo resize info centered within pseudo client borders + * implemented meters controlled by wmiremote with special syntax - + wmiremote -m <percentage>#<text>,<precentage>#<text>,... + * Marcel implemented regexp support for input mode, just compile wmi + with --with-posix-regex and set autocompletion.mode=regex in + common.conf to enable it + * new slot.tabs entry for common.conf to create several slot tabs, use + this option like slot.tabs=default,icq,dockapps + * renamed toggle-client-bar into toggle-clientbar + * renamed toggle-status-bar into toggle-statusbar + * renamed toggle-inputmode into inputmode + * each workspace remembers the last focussed slot tab now + * removed --with-stacked-tabbing compile option, use cycle.mode= option + in common.conf instead + * improved clientbar illumination + * fixed toggle-slot brokeness after snap 558 + * now using Container for slot tabs also + * using CClient and CFrame (Container types) for workspace/monitor stuff, + to also support stacked tabbing for frames, detached, floating and sticky + clients + * slot raises on every mode change action + * shortcut handling is now improved + * new widget class for menu, slot and bar with default methods + * WM_TRANSIENT_FOR is taken into account now when setting maximized/float + settings for new windows through a patch by Ryan Sorensen + * new default.transient-mode={float,max} for default placement of + transients + * some general transient fixes + * sloppy focus focusses windows only, not raising them (raise with + click instead) + * slot improvements finished now - new cycle-slot-tab-prev/next + actions, implemented focus for slot, now you can easily focus an + slot app through mouse-over (enter) events + * toggle-mode now validates if senseful (if no client is attached + within the specific mode, toggle-mode is invalid) + * new colors for meters - + color.meter.background + color.meter.figure + color.meter.border.shine + color.meter.border.shadow + * new default.bar-mode={show,hide} and default.border-mode={show,hide} + options for common.conf to show hide borders/bars of + clients/frames by default + * implemented slot.mode={overlap,non-overlap} to get a + (non-)overlapping slot + * implemented '~' expansion for input mode + * new kill-slot-client action for killing focussed slot client + * new regex-mode for the input-line. compile with '--with-posix-regex' + and turn it on in common.conf with 'autocompletion.mode=regex' + * WMI shows a special box now when awaiting more keystrokes + (e.g. in sequential shortcut chains) + * implemented raise action, this fits better with current focussing + model (to prevent FocusOnClick if a client is already focused) + * mouse shortcuts are only allowed in single shortcuts or shortcut + chain prefixes but not in chain shortcuts + * improved shortcut handling with following ratpoison-alike + behavior - if you press same keystroke of a shortcut chain twice, + it'll send to the client (instead processed), this works only with + shortcut chains, not with simple shortcuts + * fixed several bogus window occurances + * removed slot.adjustment property - slot now always is adjusted + top-down (because of new overlap mode this is needed/simplified) + * renamed bind-keys action to bind-shortcut + * new action toggle-shortcuts implemented which ungrabs all + keybindings, except itself and inputmode keybinding until next + toggle-shortcuts action + * slot now takes only the height it needs (especially useful for + overlap mode of slot) + * implemented new select-monitor action for multihead configurations + * renamed attach-client to attach-last-client + * new attach-client action which provides a list of all detached + clients in input mode + * splitted color.meter.figure into three new colors as follows - + color.meter.figure.high (>66) + color.meter.figure.normal (<33) + color.meter.figure.low (else) + * improved wmiremote -m syntax, now wmi understands + wmiremote -m '!80#apm' as color negation from high to low or + vice versa + * applied Johann Pfefferl's patch which fixes + BUG-03 (if frame is resized over boundaries it gets obscured) + * fixed slot toggling bug reported by Kathryn Andersen + * lower has reappeared as Kathryn requested + * improved select-frame-* policy which prefers last directional + focussed frame before lowest distance policy (was a feature + request by grayrest) + * IconicState apps are started detached now + * reenabled slot solid filling till down bar when slot.style=solid + and slot.mode=non-overlap options are given in this specific way + * hook-client now works also for slot-tabs (you've to explicitly + focus the slot'ed client to hook it to a specific tab) + * action grab-move implemented which is bound by default to + mod1+Button1 to grab floating clients for moving (useful if + titlebars/borders are hidden) + * normalized the meter syntax from NN#<text> to NN%<text> (% is new + delimeter) + * frame.colwidth option for tiled mode (1..99) + * frame.autodestroy option for autodestroying frames (empty + frames are allowed now) ('yes' or 'no') + * frame.mode option which takes 'tabbed' or 'tiled' as argument + * toggle-tiled and zoom-client actions for tiled mode + * fixed slot persistence bug + * fixed frame resize related problems on workspace change + * new colors for tiled definitions + color.tiled.shine.focussed + color.tiled.shadow.focussed + color.tiled.shine.normal + color.tiled.shadow.normal + * closed open bugs, most are fixed, some multihead issues and some + fullscreen issues still exist + * updated manual pages + + + +wmi-9: + * split toggle-bars to show-bars, hide-bars + * split toggle-borders to show-borders, hide-borders + * rename toggle-unfocussed-group to hide-other-groups, show-other-groups + * removed lock actions cause of minimalism issues, use xlock instead, + also removed lock.password from common.conf + * added new startup-action.name property into common.conf which invokes + a startup action after start or restart of WMI + * implemented bar/slot visibility on a per workspace basis + * fixed cycle-workspace-prev issues + * tab based autocompletion, new common.conf property + 'autocompletion.mode={confirm,auto}', confirm means use tab + instead of autocomplete after each key press + * implemented button bindings in conjunction with a valid modifier + * implemented cycle-{workspace,group}-prev/next if WMI is not compiled + with stacked tabbing order supported which focusses prev/next + workspace or group in the logical order (not in the stacking order) + * implemented previous behavior also with cycle-{frame,client}-* + * implemented Lock keys handling, now NumLock and ScrollLock are + ignored by shortcuts if they're on or off + * implemented new autocompletion.mode for common.conf (also new default) + autoconfirm, thie is a mixture of original autocompletion and newer + confirm feature. + * new restart action implemented (currently without session management) + * new slot.adjustment property which provides top, center and bottom + adjustment of dockapps + * new slot.style property which provides a solid background filling + of the slot with bar background color (solid) or ignores it + (transparent) + * implemented new slot-client and unslot-client actions for moving + clients which aren't handled in the slot by default (because they + aren't Withdrawn) for let them go to the slot and back + * action arguments can now be smuggled to actions also via input + mode, e.g. exec*xterm, create-workspace+5, etc. + * gravity support, now emacs behaves ok (and all related bugs) + * removed explicit Settings class (not needed anymore) + * removed explicit Bindings class (not needed anymore) + * various code refactorings to met new fixed issues more convenient + * removed other-groups.mode option because we already have + show-/hide-other-groups on the fly (which is more senseful, think + of floating dialog boxes of maximized apps ;)) + * bar and slot visibility per workspace is now persistated in + session info + * the diamond box now looks like a honeycomb + * implemented prevent button invocation when a client/frame is not focussed + * removed sloppy mode, now all frames/clients are focusable through + a simple click + * toggle-pointer removed because we've no sloppy mode or warpPointer + stuff anymore + * implemented new select-client-id action + * fixed several multihead issues + * applied Andreas Gunnarsson nextNeighbor (Split) patch + * fixed broken multihead support + * removed resize-move.mode, because opaque move/resizing is not + really needed (KISS) + * improved split stuff, now select-frame-dir works perfect, also + all resizings work perfectly + * made transient handling ICCCM compliant + * removed double-parenting of clients attached to frames, now several + menu-popup issues should been fixed + * fixed gvim resize bug (maybe xemacs too, but not tested yet) + * fixed transient related crash bug (at least existant in ImageMagick) + * allow bar/slot overlapping of floating clients (also outside viewport area) + * implemented new action 'fit-client' which fits a floating client into + worksapce area, if it has been moved outside visible workspace area + or is greater + * created configure argument --without-slot which disables the slot + at compile time + * fixed slot configure request issues (resize gkrellm when it + requests it) + * fixed (un)slot-client issues with xterm and other clients with + decoration + * fixed accidental slot placements of withdrawn clients + * fixed broken buttons/menus in various apps, especially in motif + apps + * fixed focus loss bug when focussing an empty group + * implemented group and workspace focussing remembering for session + handling + * fixed workspace pager updates for mouse wheel cycling + * fixed workspace frame re-adjusting bug when select or cycle + workspaces + * re-enabled sloppy frame focussing + * fixed bugs + BUG-20 (ddd crash), + BUG-19 (xmms, plan), + BUG-18 (grace), + BUG-17 (menus in acroread), + BUG-16 (larger clients than screen), + BUG-15 (document scrolling in acroread), + BUG-12 (resize issues of gvim), + BUG-08 (xv large images), + BUG-07 (matlab menu choosing), + BUG-06 (scan windows), + BUG-02 (middle point issues with toggle-client-mode), + BUG-01 (Xnest) + * fixed gmplayer issues + * fixed cycle-frame-prev/next bugs + * fixed bugs + BUG-27 (resizing transients) + BUG-10 (advi crash) + * input mode now gets raised if status bar is invisible + * beginning with double tab in input mode, next entry will be + focussed + * focused group raises all clients again + * improved split algorithm (now supports directional state resizing) + * new banish action implemented (equivalent to ratpoison) + * improved input mode again + * fixed bugs + BUG-37 (exec with / prefix) + BUG-34 was reported as user error + BUG-38 (restart ignored floating clients) + BUG-36 (focus issue after lower) + BUG-35 (bar visibility issues on cycle-workspace) + BUG-32 (workspace focus when select-client) + BUG-31 (client walking on continues toggle-client-mode) + BUG-28 (transient crahses) + BUG-25 (pseudo clients after restart) + BUG-23 (eiphany crash, may have been transient related) + BUG-22 (SDL app focus fix) + BUG-14 (title change of minimized apps) + BUG-11 (emacs builtin window cycling) + BUG-09 (rox self-resizing) + BUG-05 (ssh-tunneled gnuplot crash) + BUG-04 (ssh somehost password dialog crash) + BUG-02 (outside frame middlepoint crash) + BUG-32 (gkrellm crash in slot) + BUG-26 (rox d'n'd didn't worked) + BUG-13 (chain action arguments stuff) + BUG-30 (bogus client area issues) + * updated manual pages + +wmi-8: + * select-client action for monitor-wide fast focussing of clients + * cycle-frame action readded for cycling frames + * toggle-frames action added for toggling frames + (older raise-all-frames has been removed) + * cycle-group action added for group based cycling + * cycle-prev/next removed + * attach-all-clients action implemented which attaches all detached + clients to the current workspace + * changed tab colorization of unfocussed clients of the active group + to a different default than unfocussed clients of inactive groups + * dynamic border width configuration for frames and clients + * toggle-border(s) actions for toggling the border on the fly + * new stacking order remebering of all WMI objects (clients, + frames, groups, workspaces) implemented + * unfocussed-groups.mode option for common.conf implemented (this + option has two modes (show/hide) which is used for default hiding + other (unfocussed) groups + * toggle-unfocussed-groups action which toggles the visibility of + unfocussed groups implemented + * lock implemented using lock.password common.conf property + * sticky group (monitor-wide) implemented with new actions + * sticky-client action implemented which makes a client sticky + * unsticky-client action implemented which resets a sticky client + to normal floating state + * added frame.buttons option to common.conf for frame button visibility + * applied Marcin Pawliks control keys patch for input mode + * applied Markus Lindorfers patch for Solaris support + * implemented Xft support + * implemented new shortcut handling with abstract syntax + {extern,intern,chain}.<name>.keys=[<mod(s)>*<key>::]*<mod(s)>*<key> + * implemented new option 'default.client-mode' to common.conf + which sets the default mode for unknown apps. + * wmiremote -p pretty prints current key bindungs of running WMI + session as ASCII art to the terminal + * implemented mouse-wheel based workspace and group cycling + * eliminated various compiler warnings (mostly unserious ones) + * destroy-action for self-defined chain and extern actions implemented + * implemented select-frames action + * removed autowarping the pointer + * drastic code size optimizations (removed useless inlines, + made unsigned to explicit unsigned int, etc.) + * renamed toggle-frames to toggle-focus-mode + * renamed toggle-client-state to toggle-client-mode + * new default key bindings only using alt*<...>, shift*alt*<...> and + ctrl*alt*<...> + * removed detachAllButton from floatbar (consistency reasons) + * removed all left frame buttons + * close button now scales better by big fonts (only 3 pixel center) + * toggle-focus-mode button in floatbar now gives feedback about + active mode like (overlapping=floating/non-overlapping=maximized) + * implemented bigger tolerance for diagonal resize pointer + * new slot behavior for NeXTish dockapps (gkrellm experimental) + removed slot.width and slot.justification, fast invocation menu + not implemented yet, cause this should be done externally + * removed autoraising of grouped clients if a floating client + is attached/focussed + * ICCCM overwork (should solve most known BUGs) + * focus clients through click into client area with alt key pressed + * written welcome section in wmi(1) manual page for newbies + * pop up manual page wmi(1) within xterm when wmi is started first + * moved actions detail description to actions.conf file + +wmi-7: + * overworked split handling (tree map layout) + * wmiremote supports remote action invocation + * overworked theme engine/look'n'feel + * support for size hints + * fixed xterm startup issues + * layer handling completely overworked, renamed to group + * overworked input mode + * new end-record actions + * various serious bug fixings + * simplified shrink/grow handling + * simplified/consistentified cycling + * improved detach-all handling + * renamed max-client-to-screen to toggle-max + * new toggle-bars action + * new manual pages + * new various configuration options in common.conf + * removed "common." prefix in common.conf + * changed release schema + * new join-frame-* action to join frames (opposite of split-frame-*) + * new send-client-* action to move a client from one frame to another + +wmi-6: + * renamed several actions + * new default color scheme + * code size minimization/optimzation + * rudimentary slot behavior implemented + * new floating app bar + * new layer handling implemented + * fixed many major bugs + * removed tweak stuff + +wmi-5: + * overworked window handling for max/min size hints + * several new actions (toggle-*, exec-term, lower, raise) + * bind key auto completion for action names + * exec argument auto completion + * floating mode for frames enabled + * resize handling overwork + * borderless clients support + * major bug fixing for several crashes + * maps have been renamed to chains + * bar neighbor handling/toggle-*-bar overwork + * cursor fixes + * client grabbing performance boost + +wmi-4: + * new window concept implemented + * several major bugs fixed + * fully refactored WMI + +wmi-1 - wmi-3: + * don't remember exactly, very experimental milestones + * there've been only 5 hackers who used wmi around this + time beside the author itself diff --git a/FAQ b/FAQ @@ -0,0 +1,96 @@ +$Id: FAQ 735 2004-09-27 18:36:45Z garbeam $ + +General +------- + +Q: How do I split frames? +A: First make sure, that your clients are maximized (through click on +maximize button or invoking toggle-client-mode action). +Second make sure, that at least two clients are running within the +focussed frame. If so, just use one of the split-frame-* actions. +Btw. the opposite of split-frame-* is join-frame-*. + +Q: It seems that the actions don't work? Nothing happens if I try to use +exec action? +A: Simply answer: you've to press RETURN after each action in input +mode. + +Q: How can I directly select workspaces? +A: You can use select-workspace action, but you can also define some +shortcuts to select a specific workspace fast through chains. Just +define following lines in your $HOME/.wmi/actions.conf file: +chain.selws1.seq="select-workspace+workspace 1" +chain.selws1.keys=alt+1 +chain.selws2.seq="select-workspace+workspace 2" +chain.selws2.keys=alt+1 +This enables alt+1 and alt+2 for direct workspace selection. + +Q: How could I determine all installed Xft fonts? +A: Use 'fc-list ""' command. + +Q: How could WMI be minimalist if it has hundreds of actions and +is highly customizable? +A: Compared to other window managers WMI is minimalist because it +concentrates on basic internal actions which can be extended through +chains or wmiremote scripts, but wether supports menus and icons nor +built-in dialogs for various things which may be found in conventional +window managers. +But WMI is not as minimalist as evilwm, larswm or failsafewm. + +Q: Why is WMI compared with vim? +A: When WMI was specified, the author was much oriented on the vi-like +approach of usage. First, it is designated to make it possible to control +everything from input mode, similiar to vim. But you can control +everything also via shortcuts, if you've configured any, also similiar +to vim mappings. Second, you've only one input mode where the statusbar +is located, this is similiar to vim. In opposite the emacs approach +is to provide input bars under each buffer. And third, the splitting +concept of WMI is pretty much oriented on the buffer splitting concept +of vim. +To sum up: The WMI input mode is for window manipulation, the vim +command mode is for file manipulation. + + +Configuration +------------- + +Q: The Xft fonts appear large, what can I do? +A: Have a look at +http://pdx.freedesktop.org/~fontconfig/fontconfig-user.html, this should +help you configure the fonts to a size and style you'd prefer. + +Q: Ion is more powerful than WMI, because WMI lacks of Lua support. +A: Really? Who bars you from using Lua in conjunction with wmiremote? + +Q: Why is Lua not used as Ion does? +A: I'm not against Lua in general, it's a simple Turing-complete +procedural language as many others. You may like it or not. +I think that the Lua integration in WMI would be adverse. +First, it's double-complexity, because the time you invest in learning +Lua could be invested to enhance your knowledge of C++ to implement +native window manager improvements. Second, it's a bottleneck, because +you're going to control fast native C++ code with interpreted Lua logic. +Third, Lua would be an additional build- and runtime dependency, but WMI +is designed to be a minimalist window manager. +If you really need Lua 'integration' anyway, just use it in +conjunction with wmiremote. + +Q: How do I undefine the default key bindings? +A: Insert some dummy action to your actions.conf and bind the keys you +want to make avaliable for applications to it (eg. alt+q since some +browsers use that one to quit): +extern.dummy.cmd="" +extern.dummy.cmd=alt+q +in wmi-9 there will also be an action "toggle-all-keys" to undefine +all keys (useful for nested remote WMI sessions) + + +Development +----------- + +Q: Why X resource management isn't used for configuration files? +A: Several reasons: + - the self-made settings behavior is more simple + - iteration over user defined keys is no problem/very simple + - configuration is homogetic + - the self-made settings behavior performs better diff --git a/INSTALL b/INSTALL @@ -0,0 +1,104 @@ +$Id: INSTALL 735 2004-09-27 18:36:45Z garbeam $ + +1. Required Software + +Make sure you have installed at least following software: + +* automake-1.5+ +* autoconf-2.5+ +* gcc-2.95+ +* X11R6 with Xlib and X headers +* STL library and headers + + +2. Installation of an SVN snapshot: + +# ./autogen.sh +# ./configure +# make +# sudo make install + + +3. Installation of a released version: + +# ./configure +# make +# sudo make install + + +4. Some build notes about configure arguments + +4.1. Notes for Xft support + +If you've installed Xft and freetype WMI will build with +Xft support by default. If Xft is not installed WMI won't +build with Xft support. If you explicitly don't want Xft +support, although having Xft installed just use following +configure argument: + +./configure --without-xft + +4.2. Notes for stacked tabbing + +WMI supports stacked tabbing with stack-alike visual +feedback within frame bars, groups and pagers. This feature +is not seen in any other window manager but disabled by +default. It's highly recommended to give it a try. All +focussed clients, groups, workspaces are arranged in +stacking order from left to right, the topmost element +is arranged leftwards and the bottom element is arranged +rightwards. +This results that the focussed element (e.g. a client in +a frame bar or group bar) appears always left, thus the +focus never changes, but the titles and order. +Just use following configure argument: + +./configure --with-stacked-tabbing + +4.3. Notes for debug support + +To run WMI with verbose debug output you've to configure it +with debug support: + +./configure --with-debug + +4.4. Notes for diamond box + +By default WMI draws a diamond box while resizing/moving +clients. If you don't like drawing the diamond box you +can disable it using: + +./configure --without-diamond + +4.5. Notes for disabling the slot + +By default WMI is built with slot support. +If you don't need it you can disable it using: + +./configure --without-slot + + +5. Start WMI + +To start WMI as your default window manager add following line +to your $HOME/.xinitrc: + +exec wmi + +and type + +# startx + +afterwards to launch X and the WMI. + + +6. Further Help + +To get in contact with WMI you should read at least the manual +pages wmi(1) and actions.conf(5). + + +7. Contact + +If you've problems visit http://wmi.berlios.de to get further +information. diff --git a/LICENSE.txt b/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/Makefile.am b/Makefile.am @@ -0,0 +1,19 @@ +SUBDIRS = src man +MAINTAINERCLEANFILES = aclocal.m4 config.h.in configure Makefile.in stamp-h.in +ACLOCAL_AMFLAGS = -I . +EXTRA_DIST = BUGS CONTRIB FAQ LICENSE.txt xft.m4 examples/statustext.sh examples/statustext-gavin.sh examples/statustext-deleuze.sh examples/themes/flat-grey-theme.conf examples/themes/accent-theme.conf examples/themes/flat-cyan-theme.conf examples/themes/gold-theme.conf examples/themes/laotse-theme.conf examples/themes/lunatic-theme.conf examples/themes/peacock-theme.conf examples/session-managers/kdm-entry wmi.spec.in wmi.spec +CLEANFILES = wmi.spec + +# Yes, we could create wmi.spec from configure.in, but +# - Makefile.am content is easier to maintain +# - wmi.spec is rebuilt faster from wmi.spec.in if generated in +# Makefile.am + +wmi.spec: $(srcdir)/wmi.spec.in Makefile + sed \ + -e 's,[@]RPM_NAME[@],$(PACKAGE),g' \ + -e "s,[@]RPM_VERSION[@],$$(echo '$(VERSION)' | sed -e 's/-/./g'),g" \ + -e 's,[@]TAR_NAME[@],$(PACKAGE),g' \ + -e 's,[@]TAR_VERSION[@],$(VERSION),g' \ + < $(srcdir)/wmi.spec.in > wmi.spec + diff --git a/Makefile.in b/Makefile.in @@ -0,0 +1,591 @@ +# Makefile.in generated by automake 1.8.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = . +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = . +DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(srcdir)/version.h.in $(top_srcdir)/configure AUTHORS COPYING \ + ChangeLog INSTALL NEWS TODO install-sh missing +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/./xft.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno configure.status.lineno +mkinstalldirs = $(mkdir_p) +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = version.h +depcomp = +am__depfiles_maybe = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-exec-recursive install-info-recursive \ + install-recursive installcheck-recursive installdirs-recursive \ + pdf-recursive ps-recursive uninstall-info-recursive \ + uninstall-recursive +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + { test ! -d $(distdir) \ + || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -fr $(distdir); }; } +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build_alias = @build_alias@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +SUBDIRS = src man +MAINTAINERCLEANFILES = aclocal.m4 config.h.in configure Makefile.in stamp-h.in +ACLOCAL_AMFLAGS = -I . +EXTRA_DIST = BUGS CONTRIB FAQ LICENSE.txt xft.m4 examples/statustext.sh examples/statustext-gavin.sh examples/statustext-deleuze.sh examples/themes/flat-grey-theme.conf examples/themes/accent-theme.conf examples/themes/flat-cyan-theme.conf examples/themes/gold-theme.conf examples/themes/laotse-theme.conf examples/themes/lunatic-theme.conf examples/themes/peacock-theme.conf examples/session-managers/kdm-entry wmi.spec.in wmi.spec +CLEANFILES = wmi.spec +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --gnu --ignore-deps'; \ + cd $(srcdir) && $(AUTOMAKE) --gnu --ignore-deps \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) + +config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: $(am__configure_deps) + cd $(top_srcdir) && $(AUTOHEADER) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +version.h: $(top_builddir)/config.status $(srcdir)/version.h.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +uninstall-info-am: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -z "$$unique" && unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + $(am__remove_distdir) + mkdir $(distdir) + $(mkdir_p) $(distdir)/. $(distdir)/examples $(distdir)/examples/session-managers $(distdir)/examples/themes + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || mkdir "$(distdir)/$$subdir" \ + || exit 1; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="../$(top_distdir)" \ + distdir="../$(distdir)/$$subdir" \ + distdir) \ + || exit 1; \ + fi; \ + done + -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r $(distdir) +dist-gzip: distdir + $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist-bzip2: distdir + $(AMTAR) chof - $(distdir) | bzip2 -9 -c >$(distdir).tar.bz2 + $(am__remove_distdir) + +dist-tarZ: distdir + $(AMTAR) chof - $(distdir) | compress -c >$(distdir).tar.Z + $(am__remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +dist dist-all: distdir + $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(AMTAR) xf - ;;\ + *.tar.bz2*) \ + bunzip2 -c $(distdir).tar.bz2 | $(AMTAR) xf - ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(AMTAR) xf - ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && cd $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck + $(am__remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}' +distuninstallcheck: + @cd $(distuninstallcheck_dir) \ + && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile config.h +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +info: info-recursive + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-info-am + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \ + check-am clean clean-generic clean-recursive ctags \ + ctags-recursive dist dist-all dist-bzip2 dist-gzip dist-shar \ + dist-tarZ dist-zip distcheck distclean distclean-generic \ + distclean-hdr distclean-recursive distclean-tags \ + distcleancheck distdir distuninstallcheck dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic maintainer-clean-recursive \ + mostlyclean mostlyclean-generic mostlyclean-recursive pdf \ + pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ + uninstall-info-am + + +# Yes, we could create wmi.spec from configure.in, but +# - Makefile.am content is easier to maintain +# - wmi.spec is rebuilt faster from wmi.spec.in if generated in +# Makefile.am + +wmi.spec: $(srcdir)/wmi.spec.in Makefile + sed \ + -e 's,[@]RPM_NAME[@],$(PACKAGE),g' \ + -e "s,[@]RPM_VERSION[@],$$(echo '$(VERSION)' | sed -e 's/-/./g'),g" \ + -e 's,[@]TAR_NAME[@],$(PACKAGE),g' \ + -e 's,[@]TAR_VERSION[@],$(VERSION),g' \ + < $(srcdir)/wmi.spec.in > wmi.spec +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/NEWS b/NEWS @@ -0,0 +1,2 @@ +$ Id: $ +Visit http://wmi.berlios.de for current news about the WMI. diff --git a/README b/README @@ -0,0 +1,5 @@ +$Id: README 59 2004-04-07 16:26:27Z garbeam $ + +Get further information from: http://wmi.berlios.de + +--Anselm R. Garbe diff --git a/TODO b/TODO @@ -0,0 +1,26 @@ +$Id: TODO 637 2004-09-08 23:09:49Z garbeam $ + +See wmi-devel mailinglist at http://wmi.berlios.de for details. + +19:37 < zahod_> Garbeam, hmm, looks like you use +color.frame.shadow/shine.normal for unfocused +clients in larsmode, which are set to black by default, +thus you can't see the borders if you use black background in +your terminals. 19:40 < zahod_> and if you change it to +color.frame.background.normal, then you will have the same +problems with white terminals, probably two of the most common +colors 19:41 < zahod_> so I think an theme.conf option would be good + + +TODOs for wmii-1: + ++ mod1+button3 resize similar to grab-move function +? history for input mode (remembers last actions) ++ resize increments handling ++ client request colormap support ++ window-snap-to-border for everything(!) ++ Drag'n'drop client detach/attaching like Ion does + +FUTURE refactoring: + +- Implement more self-destroying methods (themes deallocation, etc.) diff --git a/aclocal.m4 b/aclocal.m4 @@ -0,0 +1,933 @@ +# generated automatically by aclocal 1.8.4 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 +# Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# -*- Autoconf -*- +# Copyright (C) 2002, 2003 Free Software Foundation, Inc. +# Generated from amversion.in; do not edit by hand. + +# 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, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.8"]) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION so it can be traced. +# This function is AC_REQUIREd by AC_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], + [AM_AUTOMAKE_VERSION([1.8.4])]) + +# AM_AUX_DIR_EXPAND + +# Copyright (C) 2001, 2003 Free Software Foundation, Inc. + +# 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, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997, 2000, 2001, 2003 Free Software Foundation, Inc. + +# 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, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# serial 6 + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ(2.52)dnl + ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE]) +AC_SUBST([$1_FALSE]) +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]) +fi])]) + +# serial 7 -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 +# Free Software Foundation, Inc. + +# 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, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "GCJ", or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH]) +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + +# 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, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +#serial 2 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # So let's grep whole file. + if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + grep '^DEP_FILES *= *[[^ @%:@]]' < "$mf" > /dev/null || continue + # Extract the definition of DEP_FILES from the Makefile without + # running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR" + # We invoke sed twice because it is the simplest approach to + # changing $(DEPDIR) to its actual value in the expansion. + for file in `sed -n ' + /^DEP_FILES = .*\\\\$/ { + s/^DEP_FILES = // + :loop + s/\\\\$// + p + n + /\\\\$/ b loop + p + } + /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Like AC_CONFIG_HEADER, but automatically create stamp file. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 2000, 2001, 2003 Free Software Foundation, Inc. + +# 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, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# serial 7 + +# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. +AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) + +# Do all the work for Automake. -*- Autoconf -*- + +# This macro actually does too much some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 +# Free Software Foundation, Inc. + +# 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, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# serial 11 + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.58])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +# test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && + test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AM_MISSING_PROG(AMTAR, tar) +AM_PROG_INSTALL_SH +AM_PROG_INSTALL_STRIP +AC_REQUIRE([AM_PROG_MKDIR_P])dnl +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl + +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +]) +]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $1 | $1:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. + +# Copyright (C) 2001, 2003 Free Software Foundation, Inc. + +# 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, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +install_sh=${install_sh-"$am_aux_dir/install-sh"} +AC_SUBST(install_sh)]) + +# -*- Autoconf -*- +# Copyright (C) 2003 Free Software Foundation, Inc. + +# 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, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# serial 1 + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + +# 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, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# serial 2 + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo done +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# -*- Autoconf -*- + + +# Copyright (C) 1997, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. + +# 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, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# serial 3 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) + +# AM_PROG_MKDIR_P +# --------------- +# Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise. + +# Copyright (C) 2003, 2004 Free Software Foundation, Inc. + +# 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, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories +# created by `make install' are always world readable, even if the +# installer happens to have an overly restrictive umask (e.g. 077). +# This was a mistake. There are at least two reasons why we must not +# use `-m 0755': +# - it causes special bits like SGID to be ignored, +# - it may be too restrictive (some setups expect 775 directories). +# +# Do not use -m 0755 and let people choose whatever they expect by +# setting umask. +# +# We cannot accept any implementation of `mkdir' that recognizes `-p'. +# Some implementations (such as Solaris 8's) are not thread-safe: if a +# parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c' +# concurrently, both version can detect that a/ is missing, but only +# one can create it and the other will error out. Consequently we +# restrict ourselves to GNU make (using the --version option ensures +# this.) +AC_DEFUN([AM_PROG_MKDIR_P], +[if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + # Keeping the `.' argument allows $(mkdir_p) to be used without + # argument. Indeed, we sometimes output rules like + # $(mkdir_p) $(somedir) + # where $(somedir) is conditionally defined. + # (`test -n '$(somedir)' && $(mkdir_p) $(somedir)' is a more + # expensive solution, as it forces Make to start a sub-shell.) + mkdir_p='mkdir -p -- .' +else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + for d in ./-p ./--version; + do + test -d $d && rmdir $d + done + # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. + if test -f "$ac_aux_dir/mkinstalldirs"; then + mkdir_p='$(mkinstalldirs)' + else + mkdir_p='$(install_sh) -d' + fi +fi +AC_SUBST([mkdir_p])]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + +# 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, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# serial 2 + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# ------------------------------ +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) + +# _AM_SET_OPTIONS(OPTIONS) +# ---------------------------------- +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# +# Check to make sure that the build environment is sane. +# + +# Copyright (C) 1996, 1997, 2000, 2001, 2003 Free Software Foundation, Inc. + +# 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, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# serial 3 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + +# AM_PROG_INSTALL_STRIP + +# Copyright (C) 2001, 2003 Free Software Foundation, Inc. + +# 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, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +m4_include([./xft.m4]) diff --git a/action.cpp b/action.cpp @@ -0,0 +1,145 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: action.cpp 734 2004-09-27 18:15:45Z garbeam $ + +extern "C" { +#include <stdlib.h> +#include <string.h> +} + +#include "wmi.h" + +#include "action.h" +#include "actions.h" +#include "kernel.h" +#include "monitor.h" +#include "prompt.h" +#include "shortcut.h" +#include "validators.h" + + +Action::Action(string id, ToPerform toPerform, + IsValid isValid, Type type, char *argument) +{ + id_ = id; + toPerform_ = toPerform; + isValid_ = isValid; + type_ = type; + argument_ = argument; + shortcut_ = 0; + listenOn_ = 0; +} + +Action::~Action() { + if (argument_) { + free(argument_); + } +} + +void Action::perform() { + // great HACK to return from maximized frames back to normality + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + + if (focusedMonitor->isThingMaximized() && + (toPerform_ != &Actions::cycleClientNext) && + (toPerform_ != &Actions::cycleClientPrev) && + (toPerform_ != &Actions::toggleBar) && + (toPerform_ != &Actions::toggleMaximization)) + { + + focusedMonitor->toggleThingMaximization(); + } + + if (KERNEL->isRecording() && + (toPerform_ != &Actions::endChainRecord) && + (toPerform_ != &Actions::endScriptRecord) && + (toPerform_ != &Actions::inputMode)) + { + KERNEL->recordedActions()->push_back( + new Action(id_, 0, 0, type_, argument_ ? strdup(argument_) : 0)); + } + + Actions actions = *Actions::instance(); + + if (isValid()) { + (actions.*toPerform_)(this, argument_); // call action + } +} + +bool Action::isValid() { + Validators validators = *Validators::instance(); + + return (validators.*isValid_)(); +} + +Prompt *Action::prompt(unsigned int index) { + + unsigned int i = 0; + for (LPrompt::iterator it = prompts_.begin(); + it != prompts_.end(); it++) + { + if (i == index) { + return (*it); + } + i++; + } + + // should never occure + return 0; +} + +string Action::id() const { + return id_; +} + +unsigned int Action::promptsCount() const { + return prompts_.size(); +} + + +IsValid Action::getIsValid() const { + return isValid_; +} + +void Action::setShortcut(Shortcut *shortcut) { + shortcut_ = shortcut; + listenOn_ = shortcut; +} + +Shortcut *Action::shortcut() const { + return shortcut_; +} + +void Action::setArgument(char *argument) { + argument_ = argument; +} + +char *Action::argument() const { + return argument_; +} + +Action::Type Action::type() const { + return type_; +} + +void Action::setType(Type type) { + type_ = type; +} + + +LPrompt *Action::prompts() { + return &prompts_; +} + +ToPerform Action::getToPerform() const { + return toPerform_; +} + +void Action::setListenOn(Shortcut *listenOn) { + listenOn_ = listenOn; +} + +Shortcut *Action::listenOn() const { + return listenOn_; +} diff --git a/action.h b/action.h @@ -0,0 +1,95 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: action.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __ACTION_H +#define __ACTION_H + +extern "C" { +#include <X11/Xlib.h> +} + +#include <list> +#include <string> +#include "wmi.h" + +class Action; +class Actions; +class Prompt; +class Shortcut; +class Validators; + +// Method pointer type for actions +typedef void (Actions::*ToPerform)(Action *, const char *); +typedef bool (Validators::*IsValid)(); + +typedef list<Prompt *> LPrompt; + +/** Interface for all actions which will be performed by WMI. */ +class Action +{ + +public: + + enum Type {INTERN, EXTERN, SEQUENCE, UNKNOWN}; + + Action(string id, ToPerform toPerform, + IsValid isValid, Type type = INTERN, char *argument = 0); + + ~Action(); + + string id() const; + + unsigned int promptsCount() const; + + /** Performs the action. */ + void perform(); + + /** Returns <code>true</code> if the actions is possible. */ + bool isValid(); + + /** Returns the is possible method pointer. */ + IsValid getIsValid() const; + + void setShortcut(Shortcut *shortcut); + + Shortcut *shortcut() const; + + void setArgument(char *argument); + + char *argument() const; + + Type type() const; + + void setType(Type type); + + /** Returns prompt for argument at position 'index'. */ + Prompt *prompt(unsigned int index); + + LPrompt *prompts(); + + ToPerform getToPerform() const; + + void setListenOn(Shortcut *listenOn); + + Shortcut *listenOn() const; + +private: + + string id_; + ToPerform toPerform_; + IsValid isValid_; + + // for keyboard bindings + Shortcut *shortcut_; + Shortcut *listenOn_; + + // for special stuff + char *argument_; + Type type_; + LPrompt prompts_; + +}; + +#endif // __ACTION_H diff --git a/actions.cpp b/actions.cpp @@ -0,0 +1,1037 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: actions.cpp 734 2004-09-27 18:15:45Z garbeam $ + +extern "C" { +#include <assert.h> +#include <X11/Xlib.h> +} +#include <sstream> +#include <map> + +#include "actions.h" + +#include "action.h" +#include "binder.h" +#include "client.h" +#include "clientbar.h" +#include "frame.h" +#include "inputbar.h" +#include "launcher.h" +#include "kernel.h" +#include "monitor.h" +#include "logger.h" +#include "expander.h" +#include "prompt.h" +#include "slot.h" +#include "util.h" +#include "validators.h" +#include "workspace.h" + +Actions::Actions() { +} + +Actions::~Actions() { +} + +void Actions::initInternActions(MBindings *actionBindings) { + Action *action = 0; + + (*actionBindings)["restart"] = new Action("restart", &Actions::restart, &Validators::isAlwaysPossible); + (*actionBindings)["quit"] = new Action("quit", &Actions::quit, &Validators::isAlwaysPossible); + (*actionBindings)["save-settings"] = new Action("save-settings", &Actions::saveSettings, &Validators::isAlwaysPossible); + + (*actionBindings)["begin-record"] = new Action("begin-record", &Actions::beginChainRecord, &Validators::validateBeginRecord); + + action = new Action("end-record-chain", &Actions::endChainRecord, &Validators::validateEndRecord); + action->prompts()->push_back(new Prompt("action name : ", 0)); + (*actionBindings)["end-record-chain"] = action; + + action = new Action("end-record-script", &Actions::endScriptRecord, + &Validators::validateEndRecord); + action->prompts()->push_back(new Prompt("script path : ", 0)); + (*actionBindings)["end-record-script"] = action; + + (*actionBindings)["cancel-record"] = new Action("cancel-record", &Actions::cancelRecord, &Validators::validateCancelRecord); + + action = new Action("exec-term", &Actions::executeTerm, + &Validators::isWorkspaceFocused); + action->prompts()->push_back(new Prompt("command : ", &Binder::queryCommandForPattern)); + (*actionBindings)["exec-term"] = action; + + (*actionBindings)["rehash"] = new Action("rehash", &Actions::rehash, &Validators::isAlwaysPossible); + + action = new Action("exec", &Actions::execute, + &Validators::isWorkspaceFocused); + action->prompts()->push_back(new Prompt("command : ", &Binder::queryCommandForPattern)); + (*actionBindings)["exec"] = action; + + action = new Action("destroy-action", &Actions::destroyAction, + &Validators::validateDestroyAction); + action->prompts()->push_back(new Prompt("action to destroy : ", + &Binder::queryExternChainActionsForPattern)); + (*actionBindings)["destroy-action"] = action; + +#ifdef SLOT_SUPPORT + (*actionBindings)["slot-client"] = new Action("slot-client", &Actions::slotClient, &Validators::isClientFocused); + (*actionBindings)["unslot-client"] = new Action("unslot-client", &Actions::unslotClient, &Validators::existsSlotClient); + (*actionBindings)["toggle-slot"] = new Action("toggle-slot", &Actions::toggleSlot, &Validators::isAlwaysPossible); + (*actionBindings)["cycle-slot-tab-next"] = new Action("cycle-slot-tab-next", &Actions::cycleSlotTabNext, &Validators::existSlotTabs); + (*actionBindings)["cycle-slot-tab-prev"] = new Action("cycle-slot-tab-prev", &Actions::cycleSlotTabPrev, &Validators::existSlotTabs); + (*actionBindings)["kill-slot-client"] = new Action("kill-slot-client", &Actions::killSlotClient, &Validators::existsSlotClient); +#endif // SLOT_SUPPORT + + (*actionBindings)["toggle-client-sticky"] = new Action("toggle-client-sticky", &Actions::toggleClientSticky, &Validators::isClientFocused); + + (*actionBindings)["toggle-client-mode"] = new Action("toggle-client-mode", &Actions::toggleClientMode, &Validators::isFrameOrClientFrameFocused); + (*actionBindings)["grow-left"] = new Action("grow-left", &Actions::growLeft, &Validators::validateResizeLeft); + (*actionBindings)["grow-right"] = new Action("grow-right", &Actions::growRight, &Validators::validateResizeRight); + (*actionBindings)["grow-up"] = new Action("grow-up", &Actions::growUp, &Validators::validateResizeUp); + (*actionBindings)["grow-down"] = new Action("grow-down", &Actions::growDown, &Validators::validateResizeDown); + (*actionBindings)["shrink-left"] = new Action("shrink-left", &Actions::shrinkLeft, &Validators::validateResizeRight); + (*actionBindings)["shrink-right"] = new Action("shrink-right", &Actions::shrinkRight, &Validators::validateResizeLeft); + (*actionBindings)["shrink-up"] = new Action("shrink-up", &Actions::shrinkUp, &Validators::validateResizeDown); + (*actionBindings)["shrink-down"] = new Action("shrink-down", &Actions::shrinkDown, &Validators::validateResizeUp); + (*actionBindings)["move-client-left"] = new Action("move-client-left", &Actions::moveClientLeft, &Validators::isFloatingClientFocused); + (*actionBindings)["move-client-right"] = new Action("move-client-right", &Actions::moveClientRight, &Validators::isFloatingClientFocused); + (*actionBindings)["move-client-up"] = new Action("move-client-up", &Actions::moveClientUp, &Validators::isFloatingClientFocused); + (*actionBindings)["move-client-down"] = new Action("move-client-down", &Actions::moveClientDown, &Validators::isFloatingClientFocused); + (*actionBindings)["show-bars"] = new Action("show-bars", &Actions::showBars, &Validators::isFrameOrClientFrameFocused); + (*actionBindings)["hide-bars"] = new Action("hide-bars", &Actions::hideBars, &Validators::isFrameOrClientFrameFocused); + (*actionBindings)["toggle-bar"] = new Action("toggle-bar", &Actions::toggleBar, &Validators::isFrameOrClientFrameFocused); + (*actionBindings)["show-borders"] = new Action("show-borders", &Actions::showBorders, &Validators::isFrameOrClientFrameFocused); + (*actionBindings)["hide-borders"] = new Action("hide-borders", &Actions::hideBorders, &Validators::isFrameOrClientFrameFocused); + (*actionBindings)["toggle-border"] = new Action("toggle-border", &Actions::toggleBorder, &Validators::isFrameOrClientFrameFocused); + (*actionBindings)["toggle-statusbar"] = new Action("toggle-statusbar", &Actions::toggleStatusBar, &Validators::isAlwaysPossible); + (*actionBindings)["toggle-clientbar"] = new Action("toggle-clientbar", &Actions::toggleClientBar, &Validators::isAlwaysPossible); + (*actionBindings)["kill-client"] = new Action("kill-client", &Actions::killClient, &Validators::isClientFocused); + (*actionBindings)["cycle-client-next"] = new Action("cycle-client-next", &Actions::cycleClientNext, &Validators::existClients); + (*actionBindings)["cycle-workspace-next"] = new Action("cycle-workspace-next", &Actions::cycleWorkspaceNext, &Validators::existWorkspaces); + + (*actionBindings)["toggle-mode"] = new Action("toggle-mode", &Actions::toggleMode, &Validators::validateToggleMode); + + action = new Action("select-monitor", &Actions::selectMonitor, &Validators::existMonitors); + action->prompts()->push_back(new Prompt("monitor : ", + &Binder::queryMonitorsForPattern)); + (*actionBindings)["select-monitor"] = action; + + action = new Action("select-workspace", &Actions::selectWorkspace, &Validators::existWorkspaces); + action->prompts()->push_back(new Prompt("workspace : ", + &Binder::queryWorkspacesForPattern)); + (*actionBindings)["select-workspace"] = action; + + action = new Action("select-client", + &Actions::selectClient, &Validators::validateSelectClient); + action->prompts()->push_back(new Prompt("client : ", + &Binder::queryClientsForPattern)); + (*actionBindings)["select-client"] = action; + + action = new Action("select-client-id", + &Actions::selectClientId, &Validators::validateSelectClient); + action->prompts()->push_back(new Prompt("client id: ", + &Binder::queryClientIdsForPattern)); + (*actionBindings)["select-client-id"] = action; + + (*actionBindings)["hook-client"] = new Action("hook-client", &Actions::hookClient, &Validators::validateHookClient); + (*actionBindings)["unhook-client"] = new Action("unhook-client", &Actions::unhookClient, &Validators::validateUnhookClient); + + (*actionBindings)["cycle-client-prev"] = new Action("cycle-client-prev", &Actions::cycleClientPrev, &Validators::existClients); + (*actionBindings)["cycle-workspace-prev"] = new Action("cycle-workspace-prev", &Actions::cycleWorkspacePrev, &Validators::existWorkspaces); + (*actionBindings)["split-frame-left"] = new Action("split-frame-left", &Actions::splitFrameLeft, &Validators::existClientsWithinFrame); + (*actionBindings)["split-frame-right"] = new Action("split-frame-right", &Actions::splitFrameRight, &Validators::existClientsWithinFrame); + (*actionBindings)["split-frame-up"] = new Action("split-frame-up", &Actions::splitFrameUp, &Validators::existClientsWithinFrame); + (*actionBindings)["split-frame-down"] = new Action("split-frame-down", &Actions::splitFrameDown, &Validators::existClientsWithinFrame); + (*actionBindings)["join-frame-left"] = new Action("join-frame-left", &Actions::joinFrameLeft, &Validators::existsFrameLeft); + (*actionBindings)["join-frame-right"] = new Action("join-frame-right", &Actions::joinFrameRight, &Validators::existsFrameRight); + (*actionBindings)["join-frame-up"] = new Action("join-frame-up", &Actions::joinFrameUp, &Validators::existsFrameUp); + (*actionBindings)["join-frame-down"] = new Action("join-frame-down", &Actions::joinFrameDown, &Validators::existsFrameDown); + (*actionBindings)["send-client-left"] = new Action("send-client-left", &Actions::sendClientLeft, &Validators::existsFrameLeft); + (*actionBindings)["send-client-right"] = new Action("send-client-right", &Actions::sendClientRight, &Validators::existsFrameRight); + (*actionBindings)["send-client-up"] = new Action("send-client-up", &Actions::sendClientUp, &Validators::existsFrameUp); + (*actionBindings)["send-client-down"] = new Action("send-client-down", &Actions::sendClientDown, &Validators::existsFrameDown); + (*actionBindings)["detach-all-clients"] = new Action("detach-all-clients", &Actions::detachAllClients, &Validators::existClients); + (*actionBindings)["attach-all-clients"] = new Action("attach-all-clients", &Actions::attachAllClients, &Validators::existDetachedClients); + (*actionBindings)["detach-client"] = new Action("detach-client", &Actions::detachClient, &Validators::isClientFocused); + (*actionBindings)["attach-last-client"] = new Action("attach-last-client", &Actions::attachLastClient, &Validators::existsDetachedClient); + (*actionBindings)["inputmode"] = new Action("inputmode", &Actions::inputMode, &Validators::validateInputMode); + + action = new Action("attach-client", + &Actions::attachClient, &Validators::existDetachedClients); + action->prompts()->push_back(new Prompt("client : ", + &Binder::queryDetachedClientsForPattern)); + (*actionBindings)["attach-client"] = action; + + action = new Action("create-action", &Actions::createAction, + &Validators::isAlwaysPossible); + action->prompts()->push_back(new Prompt("command : ", &Binder::queryCommandForPattern)); + action->prompts()->push_back(new Prompt("action name : ", 0)); + (*actionBindings)["create-action"] = action; + + action = new Action("create-workspace", &Actions::createWorkspace, &Validators::isAlwaysPossible); + action->prompts()->push_back(new Prompt("workspace name : ", 0)); + (*actionBindings)["create-workspace"] = action; + + (*actionBindings)["destroy-frame"] = new Action("destroy-frame", &Actions::destroyFrame, &Validators::validateDestroyFrame); + (*actionBindings)["destroy-workspace"] = new Action("destroy-workspace", &Actions::destroyWorkspace, &Validators::validateDestroyWorkspace); + + action = new Action("bind-shortcut", &Actions::bindShortcut, + &Validators::isAlwaysPossible); + action->prompts()->push_back(new Prompt("action to bind : ", + &Binder::queryActionKeysWithoutValidationForPattern)); + action->prompts()->push_back(new Prompt("keys <modifier>+<key> : ", 0)); + (*actionBindings)["bind-shortcut"] = action; + + action = new Action("rename-workspace", &Actions::renameWorkspace, &Validators::isWorkspaceFocused); + action->prompts()->push_back(new Prompt("new name : ", 0)); + (*actionBindings)["rename-workspace"] = action; + + (*actionBindings)["select-frame-left"] = new Action("select-frame-left", &Actions::selectFrameLeft, &Validators::existsFrameLeft); + (*actionBindings)["select-frame-right"] = new Action("select-frame-right", &Actions::selectFrameRight, &Validators::existsFrameRight); + (*actionBindings)["select-frame-up"] = new Action("select-frame-up", &Actions::selectFrameUp, &Validators::existsFrameUp); + (*actionBindings)["select-frame-down"] = new Action("select-frame-down", &Actions::selectFrameDown, &Validators::existsFrameDown); + + (*actionBindings)["swap-frame-left"] = new Action("swap-frame-left", &Actions::swapFrameLeft, &Validators::existsFrameLeft); + (*actionBindings)["swap-frame-right"] = new Action("swap-frame-right", &Actions::swapFrameRight, &Validators::existsFrameRight); + (*actionBindings)["swap-frame-up"] = new Action("swap-frame-up", &Actions::swapFrameUp, &Validators::existsFrameUp); + (*actionBindings)["swap-frame-down"] = new Action("swap-frame-down", &Actions::swapFrameDown, &Validators::existsFrameDown); + + (*actionBindings)["swap-client-left"] = new Action("swap-client-left", &Actions::swapClientLeft, &Validators::existsFrameLeft); + (*actionBindings)["swap-client-right"] = new Action("swap-client-right", &Actions::swapClientRight, &Validators::existsFrameRight); + (*actionBindings)["swap-client-up"] = new Action("swap-client-up", &Actions::swapClientUp, &Validators::existsFrameUp); + (*actionBindings)["swap-client-down"] = new Action("swap-client-down", &Actions::swapClientDown, &Validators::existsFrameDown); + + (*actionBindings)["toggle-max"] = new Action("toggle-max", &Actions::toggleMaximization, &Validators::isFrameOrClientFrameFocused); + + (*actionBindings)["raise"] = new Action("raise", &Actions::raise, &Validators::isClientFocused); + (*actionBindings)["lower"] = new Action("lower", &Actions::lower, &Validators::isClientFocused); + (*actionBindings)["fit-client"] = new Action("fit-client", &Actions::fitClient, &Validators::isClientFocused); + (*actionBindings)["banish"] = new Action("banish", &Actions::banish, &Validators::isAlwaysPossible); + (*actionBindings)["toggle-clientbar-mode"] = new Action("toggle-clientbar-mode", &Actions::toggleClientBarMode, &Validators::isAlwaysPossible); + (*actionBindings)["toggle-sloppy-mode"] = new Action("toggle-sloppy-mode", &Actions::toggleSloppyMode, &Validators::isAlwaysPossible); + (*actionBindings)["toggle-shortcuts"] = new Action("toggle-shortcuts", &Actions::toggleShortcuts, &Validators::isAlwaysPossible); + (*actionBindings)["grab-move"] = new Action("grab-move", &Actions::grabMove, &Validators::isClientFrameFocused); + (*actionBindings)["toggle-tiled"] = new Action("toggle-tiled", &Actions::toggleTiled, &Validators::existClientsWithinFrame); + (*actionBindings)["zoom-client"] = new Action("zoom-client", &Actions::zoomClient, &Validators::existClientsWithinFrame); + +} + +void Actions::selectFrameLeft(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + workspace->selectFrame(LEFT); +} + +void Actions::selectFrameRight(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + workspace->selectFrame(RIGHT); +} + +void Actions::selectFrameUp(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + workspace->selectFrame(UP); +} + +void Actions::selectFrameDown(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + workspace->selectFrame(DOWN); +} + +void Actions::toggleShortcuts(Action *caller, const char *argument) { + KERNEL->toggleShortcuts(); +} + +void Actions::restart(Action *caller, const char *argument) { + KERNEL->restart(); +} + +void Actions::quit(Action *caller, const char *argument) { + KERNEL->stop(); +} + +void Actions::saveSettings(Action *caller, const char *argument) { + KERNEL->saveSettings(); +} + +void Actions::execute(Action *caller, const char *command) { + + Launcher::instance()->exec(command); +} + +void Actions::executeTerm(Action *caller, const char *command) { + MSettings *commonSettings = KERNEL->commonSettings(); + string cmd = Util::get(commonSettings, (string)"terminal") + " " + command; + + Launcher::instance()->exec(cmd); +} + +void Actions::cycleClientNext(Action *caller, const char *argument) { + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + workspace->cycleClientNext(); +} + +void Actions::cycleClientPrev(Action *caller, const char *argument) { + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + workspace->cycleClientPrev(); +} + +void Actions::attachAllClients(Action *caller, const char *argument) { + Monitor *monitor = KERNEL->focusedMonitor(); + monitor->attachAllClients(); +} + +void Actions::detachAllClients(Action *caller, const char *argument) { + Monitor *monitor = KERNEL->focusedMonitor(); + monitor->detachAllClients(); +} + +void Actions::detachClient(Action *caller, const char *argument) { + Monitor *monitor = KERNEL->focusedMonitor(); + monitor->detachClient(); +} + +#ifdef SLOT_SUPPORT +void Actions::unslotClient(Action *caller, const char *argument) { + Monitor *monitor = KERNEL->focusedMonitor(); + assert(monitor != 0); + + monitor->unslotClient(); +} + +void Actions::slotClient(Action *caller, const char *argument) { + Monitor *monitor = KERNEL->focusedMonitor(); + assert(monitor != 0); + + monitor->slotClient(); +} + +void Actions::toggleSlot(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + assert(monitor != 0); + + monitor->toggleSlot(); +} + +void Actions::cycleSlotTabNext(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + monitor->cycleSlotTabNext(); +} + +void Actions::cycleSlotTabPrev(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + monitor->cycleSlotTabPrev(); +} + +void Actions::killSlotClient(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + KERNEL->killClient(monitor->slot()->focused()->focused()); +} + +#endif // SLOT_SUPPORT + +void Actions::attachClient(Action *caller, const char *argument) { + Monitor *monitor = KERNEL->focusedMonitor(); + + monitor->attachClientByName(argument); +} + +void Actions::attachLastClient(Action *caller, const char *argument) { + Monitor *monitor = KERNEL->focusedMonitor(); + + monitor->attachLastClient(); +} + +void Actions::toggleClientSticky(Action *caller, const char *argument) { + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + workspace->toggleClientSticky(); +} + +void Actions::toggleClientMode(Action *caller, const char *argument) { + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + workspace->toggleClientMode(); +} + +void Actions::toggleMode(Action *caller, const char *argument) { + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + + workspace->toggleMode(); +} + +void Actions::cycleWorkspaceNext(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + assert(monitor != 0); + + monitor->focus(monitor->next()); +} + +void Actions::cycleWorkspacePrev(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + assert(monitor != 0); + + monitor->focus(monitor->prev()); +} + +void Actions::growLeft(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + Thing *thing = workspace->focusedThing(); + assert(thing); + + workspace->resize(thing, LEFT, true); +} + +void Actions::growRight(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + Thing *thing = workspace->focusedThing(); + assert(thing); + + workspace->resize(thing, RIGHT, true); +} + +void Actions::growUp(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + Thing *thing = workspace->focusedThing(); + assert(thing); + + workspace->resize(thing, UP, true); +} + +void Actions::growDown(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + Thing *thing = workspace->focusedThing(); + assert(thing); + + workspace->resize(thing, DOWN, true); +} + +void Actions::shrinkLeft(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + Thing *thing = workspace->focusedThing(); + assert(thing); + + workspace->resize(thing, LEFT, false); +} + +void Actions::shrinkRight(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + Thing *thing = workspace->focusedThing(); + assert(thing); + + workspace->resize(thing, RIGHT, false); +} + +void Actions::shrinkUp(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + Thing *thing = workspace->focusedThing(); + assert(thing); + + workspace->resize(thing, UP, false); +} + +void Actions::shrinkDown(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + Thing *thing = workspace->focusedThing(); + assert(thing); + + workspace->resize(thing, DOWN, false); +} + +void Actions::moveClientLeft(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + Client *client = monitor->focusedClient(); + if (client) { + workspace->moveClient(LEFT); + } +} + +void Actions::moveClientRight(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + Client *client = monitor->focusedClient(); + if (client) { + workspace->moveClient(RIGHT); + } +} + +void Actions::moveClientUp(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + Client *client = monitor->focusedClient(); + if (client) { + workspace->moveClient(UP); + } +} + +void Actions::moveClientDown(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + Client *client = monitor->focusedClient(); + if (client) { + workspace->moveClient(DOWN); + } +} + +void Actions::sendClientLeft(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + Client *client = monitor->focusedClient(); + if (client) { + workspace->sendClient(LEFT); + } +} + +void Actions::sendClientRight(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + Client *client = monitor->focusedClient(); + if (client) { + workspace->sendClient(RIGHT); + } +} + +void Actions::sendClientUp(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + Client *client = monitor->focusedClient(); + if (client) { + workspace->sendClient(UP); + } +} + +void Actions::sendClientDown(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + Client *client = monitor->focusedClient(); + if (client) { + workspace->sendClient(DOWN); + } +} + +void Actions::joinFrameLeft(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + workspace->joinFrame(LEFT); +} + +void Actions::joinFrameRight(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + workspace->joinFrame(RIGHT); +} + +void Actions::joinFrameUp(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + workspace->joinFrame(UP); +} + +void Actions::joinFrameDown(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + workspace->joinFrame(DOWN); +} + +void Actions::splitFrameLeft(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + workspace->splitFrame(LEFT); +} + +void Actions::splitFrameRight(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + workspace->splitFrame(RIGHT); +} + +void Actions::splitFrameUp(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + workspace->splitFrame(UP); +} + +void Actions::splitFrameDown(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + workspace->splitFrame(DOWN); +} + +void Actions::showBorders(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + workspace->toggleBorders(true); +} + +void Actions::hideBorders(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + workspace->toggleBorders(false); +} + +void Actions::toggleBorder(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + Thing *thing = workspace->focusedThing(); + if (thing) { + if (thing->borderWidth()) { + thing->setBorderWidth(0); + } + else { + thing->setBorderWidth(KERNEL->borderWidth()); + } + thing->resize(); + } +} + +void Actions::showBars(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + workspace->toggleBars(true); +} + +void Actions::hideBars(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + workspace->toggleBars(false); +} + +void Actions::toggleBar(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + assert(workspace); + + Thing *thing = workspace->focusedThing(); + if (thing) { + thing->setTitleBarHeight(thing->titleBarHeight() ? + 0 : monitor->titleBarHeight()); + thing->resize(); + } +} + +void Actions::toggleClientBar(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + assert(monitor != 0); + + monitor->toggleClientBar(); +} + +void Actions::toggleStatusBar(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + assert(monitor != 0); + + monitor->toggleStatusBar(); +} + +void Actions::inputMode(Action *caller, const char *argument) { + + Monitor *monitor = KERNEL->focusedMonitor(); + assert(monitor != 0); + + monitor->inputBar()->runKey(KERNEL->defaultPrompt()); +} + +void Actions::killClient(Action *caller, const char *argument) { + + KERNEL->killClient(KERNEL->focusedClient()); +} + +void Actions::sequence(Action *caller, const char *command) { + + Launcher::instance()->execSeq(caller, command); +} + +void Actions::createAction(Action *caller, const char *argument) { + + string arg = argument; + LOGDEBUG("arg: " + arg); + unsigned int argDelim = arg.find_last_of('+'); + if (argDelim == string::npos) { + return; + } + string cmd = arg.substr(0, argDelim); + string bind = arg.substr(argDelim + 1); + + if ((bind.length() < 1) || (cmd.length() < 1)) { + return; + } + Action *action = new Action(bind, &Actions::execute, + &Validators::isWorkspaceFocused, Action::EXTERN, + (char *)cmd.c_str()); + (*KERNEL->actionBindings())[bind] = action; + (*KERNEL->actionSettings())["extern." + action->id() + ".cmd"] = cmd; +} + +void Actions::createWorkspace(Action *caller, const char *argument) { + + assert(argument != 0); + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + + focusedMonitor->createNewWorkspace(argument); +} + + +void Actions::bindShortcut(Action *caller, const char *argument) { + + KERNEL->bindShortcut(argument); +} + +// TODO: ungrab potentially keys before removing +void Actions::destroyAction(Action *caller, const char *argument) { + + Action *action = Util::get(KERNEL->actionBindings(), argument); + if (action && (action->type() != Action::INTERN)) { + + Util::remove(KERNEL->actionBindings(), argument); + string prefix = (action->type() == Action::EXTERN) ? "extern." : + "chain."; + prefix += argument; + Util::remove(KERNEL->actionSettings(), prefix); + } +} + +void Actions::destroyWorkspace(Action *caller, const char *argument) { + Monitor *monitor = KERNEL->focusedMonitor(); + assert(monitor != 0); + + monitor->destroyWorkspace(monitor->focused()); +} + +void Actions::selectMonitor(Action *caller, const char *argument) { + + KERNEL->selectMonitor(argument); +} + +void Actions::selectWorkspace(Action *caller, const char *argument) { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->workspaceForName(argument); + if (workspace) { + focusedMonitor->focus(workspace); + } +} + +void Actions::selectClientId(Action *caller, const char *argument) { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + + focusedMonitor->focusClientById(argument); +} + +void Actions::selectClient(Action *caller, const char *argument) { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + + focusedMonitor->focusClientByName(argument); +} + +void Actions::renameWorkspace(Action *caller, const char *argument) { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + assert(focusedMonitor != 0); + + focusedMonitor->renameWorkspace(focusedMonitor->focused(), + argument); +} + +void Actions::swapFrameLeft(Action *caller, const char *argument) { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + assert(workspace); + + workspace->swapFrame(LEFT); +} + +void Actions::swapFrameRight(Action *caller, const char *argument) { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + assert(workspace); + + workspace->swapFrame(RIGHT); +} + +void Actions::swapFrameUp(Action *caller, const char *argument) { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + assert(workspace); + + workspace->swapFrame(UP); +} + +void Actions::swapFrameDown(Action *caller, const char *argument) { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + assert(workspace); + + workspace->swapFrame(DOWN); +} + +void Actions::swapClientLeft(Action *caller, const char *argument) { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + assert(workspace); + + workspace->swapClient(LEFT); +} + +void Actions::swapClientRight(Action *caller, const char *argument) { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + assert(workspace); + + workspace->swapClient(RIGHT); +} + +void Actions::swapClientUp(Action *caller, const char *argument) { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + assert(workspace); + + workspace->swapClient(UP); +} + +void Actions::swapClientDown(Action *caller, const char *argument) { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + assert(workspace); + + workspace->swapClient(DOWN); +} + + +void Actions::toggleMaximization(Action *caller, const char *argument) { + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + + focusedMonitor->toggleThingMaximization(); +} + +void Actions::toggleClientBarMode(Action *caller, const char *argument) { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + ClientBar *clientBar = focusedMonitor->clientBar(); + + clientBar->setMode((clientBar->mode() == ClientBar::PAGER) ? + ClientBar::CLIENTINFO : ClientBar::PAGER); + clientBar->illuminate(); +} + +void Actions::fitClient(Action *caller, const char *argument) { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + + workspace->fitClient(); +} + +void Actions::lower(Action *caller, const char *argument) { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + + workspace->lower(); +} + +void Actions::raise(Action *caller, const char *argument) { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + + workspace->raise(); +} + +void Actions::rehash(Action *caller, const char *argument) { + + Expander::instance()->rehash(); +} + +void Actions::beginChainRecord(Action *caller, const char *argument) { + KERNEL->beginRecording(); +} + +void Actions::endChainRecord(Action *caller, const char *argument) { + KERNEL->endChainRecording(argument); +} + +void Actions::endScriptRecord(Action *caller, const char *argument) { + KERNEL->endScriptRecording(argument); +} + +void Actions::cancelRecord(Action *caller, const char *argument) { + KERNEL->cancelRecording(); +} + +void Actions::banish(Action *caller, const char *argument) { + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + focusedMonitor->banish(); +} + +void Actions::unhookClient(Action *caller, const char *argument) { + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + + focusedMonitor->unhookClient(); +} + +void Actions::hookClient(Action *caller, const char *argument) { + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + + focusedMonitor->hookClient(); +} + +void Actions::toggleSloppyMode(Action *caller, const char *argument) { + KERNEL->toggleSloppyMode(); +} + +void Actions::grabMove(Action *caller, const char *argument) { + KERNEL->grabMove(); +} + +void Actions::zoomClient(Action *caller, const char *argument) { + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + Frame *frame = workspace->focusedFrame(); + + if (frame) { + frame->zoomClient(); + } +} + +void Actions::toggleTiled(Action *caller, const char *argument) { + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + Frame *frame = workspace->focusedFrame(); + if (frame) { + frame->toggleTiled(); + } +} + +void Actions::destroyFrame(Action *caller, const char *argument) { + Monitor *monitor = KERNEL->focusedMonitor(); + Workspace *workspace = monitor->focused(); + + if (workspace->focusedFrame()) { + workspace->destroyFrame(workspace->focusedFrame()); + } +} diff --git a/actions.h b/actions.h @@ -0,0 +1,170 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: actions.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __ACTIONS_H +#define __ACTIONS_H + +#include "singleton.h" + +#include <map> +#include "wmi.h" + +class Action; + +class Bindings; +class Kernel; +class Monitor; + +typedef map<string, Action *, less<string> > MBindings; + +/** + * Actions singleton class which delegates end-user interface to the + * appropriate business logic of WMI. + */ +class Actions : public Singleton<Actions> +{ + +public: + Actions(); + ~Actions(); + + void initInternActions(MBindings *actionBindings); + + // new macro record stuff + void beginChainRecord(Action *caller, const char *argument); + void endChainRecord(Action *caller, const char *argument); + void endScriptRecord(Action *caller, const char *argument); + void cancelRecord(Action *caller, const char *argument); + + // intern actions + void quit(Action *caller, const char *argument); + void restart(Action *caller, const char *argument); + + void rehash(Action *caller, const char *argument); + + void circulateWindowsUp(Action *caller, const char *argument); + + void toggleClientMode(Action *caller, const char *argument); + void toggleClientSticky(Action *caller, const char *argument); + void executeTerm(Action *caller, const char *command); + + void growLeft(Action *caller, const char *argument); + void growRight(Action *caller, const char *argument); + void growUp(Action *caller, const char *argument); + void growDown(Action *caller, const char *argument); + + void shrinkLeft(Action *caller, const char *argument); + void shrinkRight(Action *caller, const char *argument); + void shrinkUp(Action *caller, const char *argument); + void shrinkDown(Action *caller, const char *argument); + + void moveClientLeft(Action *caller, const char *argument); + void moveClientRight(Action *caller, const char *argument); + void moveClientUp(Action *caller, const char *argument); + void moveClientDown(Action *caller, const char *argument); + + void showBars(Action *caller, const char *argument); + void hideBars(Action *caller, const char *argument); + void toggleBar(Action *caller, const char *argument); + void toggleBorder(Action *caller, const char *argument); + void showBorders(Action *caller, const char *argument); + void hideBorders(Action *caller, const char *argument); + void toggleStatusBar(Action *caller, const char *argument); + void toggleClientBar(Action *caller, const char *argument); + void inputMode(Action *caller, const char *argument); + void toggleMode(Action *caller, const char *argument); + + void killClient(Action *caller, const char *argument); + + void cycleClientNext(Action *caller, const char *argument); + void cycleWorkspaceNext(Action *caller, const char *argument); + void cycleClientPrev(Action *caller, const char *argument); + void cycleWorkspacePrev(Action *caller, const char *argument); + + void joinFrameLeft(Action *caller, const char *argument); + void joinFrameRight(Action *caller, const char *argument); + void joinFrameUp(Action *caller, const char *argument); + void joinFrameDown(Action *caller, const char *argument); + + void sendClientLeft(Action *caller, const char *argument); + void sendClientRight(Action *caller, const char *argument); + void sendClientUp(Action *caller, const char *argument); + void sendClientDown(Action *caller, const char *argument); + + void splitFrameLeft(Action *caller, const char *argument); + void splitFrameRight(Action *caller, const char *argument); + void splitFrameUp(Action *caller, const char *argument); + void splitFrameDown(Action *caller, const char *argument); + + void attachClient(Action *caller, const char *argument); + void attachLastClient(Action *caller, const char *argument); + void detachClient(Action *caller, const char *argument); + void detachAllClients(Action *caller, const char *argument); + void attachAllClients(Action *caller, const char *argument); + + void createAction(Action *caller, const char *argument); + void createWorkspace(Action *caller, const char *argument); + + void destroyAction(Action *caller, const char *argument); + void destroyFrame(Action *caller, const char *argument); + void destroyWorkspace(Action *caller, const char *argument); + + void bindShortcut(Action *caller, const char *argument); + + void renameWorkspace(Action *caller, const char *argument); + void selectWorkspace(Action *caller, const char *argument); + void selectMonitor(Action *caller, const char *argument); + void selectClient(Action *caller, const char *argument); + void selectClientId(Action *caller, const char *argument); + + void selectFrameLeft(Action *caller, const char *argument); + void selectFrameRight(Action *caller, const char *argument); + void selectFrameUp(Action *caller, const char *argument); + void selectFrameDown(Action *caller, const char *argument); + + void swapFrameLeft(Action *caller, const char *argument); + void swapFrameRight(Action *caller, const char *argument); + void swapFrameUp(Action *caller, const char *argument); + void swapFrameDown(Action *caller, const char *argument); + + void swapClientLeft(Action *caller, const char *argument); + void swapClientRight(Action *caller, const char *argument); + void swapClientUp(Action *caller, const char *argument); + void swapClientDown(Action *caller, const char *argument); + +#ifdef SLOT_SUPPORT + void unslotClient(Action *caller, const char *argument); + void slotClient(Action *caller, const char *argument); + void toggleSlot(Action *caller, const char *argument); + void cycleSlotTabPrev(Action *caller, const char *argument); + void cycleSlotTabNext(Action *caller, const char *argument); + void killSlotClient(Action *caller, const char *argument); +#endif // SLOT_SUPPORT + + void toggleMaximization(Action *caller, const char *argument); + void toggleShortcuts(Action *caller, const char *argument); + + void lower(Action *caller, const char *argument); + void raise(Action *caller, const char *argument); + void saveSettings(Action *caller, const char *argument); + + // extern actions only use execute + void execute(Action *caller, const char *command); + + // map sequences only use sequences + void sequence(Action *caller, const char *command); + + void hookClient(Action *caller, const char *argument); + void unhookClient(Action *caller, const char *argument); + void fitClient(Action *caller, const char *argument); + void banish(Action *caller, const char *argument); + void toggleClientBarMode(Action *caller, const char *argument); + void toggleSloppyMode(Action *caller, const char *argument); + void grabMove(Action *caller, const char *argument); + void toggleTiled(Action *caller, const char *argument); + void zoomClient(Action *caller, const char *argument); +}; + +#endif // __ACTIONS_H diff --git a/atoms.cpp b/atoms.cpp @@ -0,0 +1,80 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: atoms.cpp 734 2004-09-27 18:15:45Z garbeam $ + +extern "C" { +#include "X11/Xatom.h" +} +#include <sstream> + +#include "atoms.h" + +#include "logger.h" +#include "kernel.h" +#include "wmi.h" +#include "xcore.h" + +Atom Atoms::WM_STATE = 0; +Atom Atoms::WM_CHANGE_STATE = 0; +Atom Atoms::WM_PROTOCOLS = 0; +Atom Atoms::WM_DELETE = 0; +Atom Atoms::WM_TAKE_FOCUS = 0; +Atom Atoms::WM_COLORMAPS = 0; + +Atom Atoms::MWM_HINTS = 0; + +Atom Atoms::NET_WM_DESKTOP = 0; + +Atom Atoms::WMI_ACTIONCMD = 0; +Atom Atoms::WMI_STATUSTEXT = 0; +Atom Atoms::WMI_METERTEXT = 0; +Atom Atoms::WMI_PRETTYPRINT_REQUEST = 0; +Atom Atoms::WMI_PRETTYPRINT_RESPONSE = 0; + +bool Atoms::initialized_ = false; + +void Atoms::initAtoms() +{ + if (initialized_) { + return; + } + + ostringstream oss; + + // ICCCM + WM_STATE = XCORE->internAtom("WM_STATE"); + oss << "WM_STATE: " << WM_STATE << endl; + WM_CHANGE_STATE = XCORE->internAtom("WM_CHANGE_STATE"); + oss << "WM_CHANGE_STATE: " << WM_CHANGE_STATE << endl; + WM_PROTOCOLS = XCORE->internAtom("WM_PROTOCOLS"); + oss << "WM_PROTOCOLS: " << WM_PROTOCOLS << endl; + WM_DELETE = XCORE->internAtom("WM_DELETE_WINDOW"); + oss << "WM_DELETE_WINDOW: " << WM_DELETE << endl; + WM_TAKE_FOCUS = XCORE->internAtom("WM_TAKE_FOCUS"); + oss << "WM_TAKE_FOCUS: " << WM_TAKE_FOCUS << endl; + WM_COLORMAPS = XCORE->internAtom("WM_COLORMAP_WINDOWS"); + oss << "WM_COLORMAP_WINDOWS: " << WM_COLORMAPS << endl; + oss << "XA_WM_ICON_NAME: " << XA_WM_ICON_NAME << endl; + oss << "XA_WM_NAME: " << XA_WM_NAME << endl; + oss << "XA_WM_TRANSIENT_FOR: " << XA_WM_TRANSIENT_FOR; + + LOGDEBUG(oss.str()); + + // MOTIF + MWM_HINTS = XCORE->internAtom("_MOTIF_WM_HINTS"); + + // NETWM + NET_WM_DESKTOP = XCORE->internAtom("_NET_WM_DESKTOP"); + + // WMI + WMI_ACTIONCMD = XCORE->internAtom("_WMI_ACTIONCMD"); + WMI_STATUSTEXT = XCORE->internAtom("_WMI_STATUSTEXT"); + WMI_METERTEXT = XCORE->internAtom("_WMI_METERTEXT"); + WMI_PRETTYPRINT_REQUEST = + XCORE->internAtom("_WMI_PRETTYPRINT_REQUEST"); + WMI_PRETTYPRINT_RESPONSE = + XCORE->internAtom("_WMI_PRETTYPRINT_RESPONSE"); + + initialized_ = true; +} diff --git a/atoms.h b/atoms.h @@ -0,0 +1,50 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: atoms.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __ATOMS_H +#define __ATOMS_H + +extern "C" { +#include "X11/Xlib.h" +} + +/** + * Container of all necessary X atoms used by WMI. + */ +class Atoms +{ + +public: + + /** Inits all atoms. */ + static void initAtoms(); + + /** ICCCM atoms */ + static Atom WM_STATE; + static Atom WM_CHANGE_STATE; + static Atom WM_PROTOCOLS; + static Atom WM_DELETE; + static Atom WM_TAKE_FOCUS; + static Atom WM_COLORMAPS; + + /** MOTIF atoms */ + static Atom MWM_HINTS; + + /** NETWM atoms */ + static Atom NET_WM_DESKTOP; + + /** wmi atoms */ + static Atom WMI_ACTIONCMD; + static Atom WMI_METERTEXT; + static Atom WMI_STATUSTEXT; + static Atom WMI_PRETTYPRINT_REQUEST; + static Atom WMI_PRETTYPRINT_RESPONSE; + +private: + + static bool initialized_; +}; + +#endif // __ATOMS_H diff --git a/bar.cpp b/bar.cpp @@ -0,0 +1,44 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: bar.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include "bar.h" + +#include <map> + +#include "draw.h" +#include "kernel.h" +#include "label.h" +#include "monitor.h" +#include "theme.h" +#include "util.h" +#include "xcore.h" + +Bar::Bar(Monitor *monitor, Rectangle *rect) : + Widget(monitor, rect) +{ + theme_ = this->monitor()->theme(); + isButtonVisible_ = (Util::get(KERNEL->commonSettings(), ("bar.buttons")) + == "yes"); + borderRect_ = Rectangle(0, 0, width(), height()); + + label_ = new Label(this->monitor(), window(), Label::CENTER, gc()); + label_->setX(1); + label_->setY(1); + label_->setWidth(width() - 2); + label_->setHeight(height() - 2); +} + +Bar::~Bar() { + delete label_; +} + + +void Bar::drawBorder() { + + Draw::drawRectBorder(window(), gc(), &borderRect_, + theme_->BAR_SHINE, theme_->BAR_SHADOW); + + XCORE->sync(); +} diff --git a/bar.h b/bar.h @@ -0,0 +1,47 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: bar.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __BAR_H +#define __BAR_H + +extern "C" { +#include <X11/Xlib.h> +} + +#include "widget.h" + +class Label; +class Monitor; +class Theme; + +/** Base class for status and client bars. */ +class Bar : public Widget { + +public: + + Bar(Monitor *monitor, Rectangle *rect); + virtual ~Bar(); + + virtual void illuminate() = 0; + + virtual void handleButtonPress(XButtonEvent *event) = 0; + virtual void handleButtonRelease(XButtonEvent *event) = 0; + virtual void handleMotionNotify(XMotionEvent *event) = 0; + +protected: + + Label *label_; + Theme *theme_; + + /** Draws border. */ + void drawBorder(); + bool isButtonVisible_; + +private: + + Rectangle borderRect_; +}; + +#endif // __BAR_H diff --git a/binder.cpp b/binder.cpp @@ -0,0 +1,742 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// Copyright (c) 2003 - 2004 Marcel Manthe <schneegloeckchen at gmx.li> +// See ../LICENSE.txt for license details. +// +// $Id: binder.cpp 734 2004-09-27 18:15:45Z garbeam $ + +extern "C" { +#include <assert.h> +} + +#include <sstream> +#include <string> +#include "wmi.h" + +#include "binder.h" + +#include "action.h" +#include "box.h" +#include "client.h" +#include "container.h" +#include "cursors.h" +#include "expander.h" +#include "frame.h" +#include "inputbar.h" +#include "kernel.h" +#include "logger.h" +#include "monitor.h" +#include "shortcut.h" +#include "thing.h" +#include "util.h" +#include "workspace.h" +#include "xcore.h" + + +Binder::Binder() { + actionBindings_ = KERNEL->actionBindings(); + initLockModifiers(); +#ifdef POSIX_REGEX + temp_pattern_="uninitalized"; + regex_prepare(); +#endif +} + +Binder::~Binder() { +} + +void Binder::grabShortcut(Shortcut *shortcut, Window window) { + + // update keysym definitions of the action + if (shortcut->button()) { + XCORE->grabButton(window, shortcut->modMask(), + shortcut->button()); + + if (shortcut->modMask() == AnyModifier) { + return; + } + if (numLockMask_) { + XCORE->grabButton(window, shortcut->modMask() | numLockMask_, + shortcut->button()); + XCORE->grabButton(window, shortcut->modMask() | numLockMask_ + | LockMask, shortcut->button()); + } + if (scrollLockMask_) { + XCORE->grabButton(window, shortcut->modMask() | scrollLockMask_, + shortcut->button()); + XCORE->grabButton(window, shortcut->modMask() | scrollLockMask_ + | LockMask, shortcut->button()); + } + if (numLockMask_ && scrollLockMask_) { + XCORE->grabButton(window, shortcut->modMask() | numLockMask_ + | scrollLockMask_, shortcut->button()); + XCORE->grabButton(window, shortcut->modMask() | numLockMask_ + | scrollLockMask_ | LockMask, shortcut->button()); + } + } + else if (shortcut->keyCode()) { + XCORE->grabKey(window, shortcut->modMask(), + shortcut->keyCode()); + + if (shortcut->modMask() == AnyModifier) { + return; + } + if (numLockMask_) { + XCORE->grabKey(window, shortcut->modMask() | numLockMask_, + shortcut->keyCode()); + XCORE->grabKey(window, shortcut->modMask() | numLockMask_ + | LockMask, shortcut->keyCode()); + } + if (scrollLockMask_) { + XCORE->grabKey(window, shortcut->modMask() | scrollLockMask_, + shortcut->keyCode()); + XCORE->grabKey(window, shortcut->modMask() | scrollLockMask_ + | LockMask, shortcut->keyCode()); + } + if (numLockMask_ && scrollLockMask_) { + XCORE->grabKey(window, shortcut->modMask() | numLockMask_ + | scrollLockMask_, shortcut->keyCode()); + XCORE->grabKey(window, shortcut->modMask() | numLockMask_ + | scrollLockMask_ | LockMask, shortcut->keyCode()); + } + } +} + +void Binder::ungrabShortcut(Shortcut *shortcut, Window window) { + + if (shortcut->button()) { + XCORE->ungrabButton(window, shortcut->modMask(), shortcut->button()); + + if (shortcut->modMask() == AnyModifier) { + return; + } + if (numLockMask_) { + XCORE->ungrabButton(window, shortcut->modMask() | numLockMask_, + shortcut->button()); + XCORE->ungrabButton(window, shortcut->modMask() | numLockMask_ + | LockMask, shortcut->button()); + } + if (scrollLockMask_) { + XCORE->ungrabButton(window, shortcut->modMask() | scrollLockMask_, + shortcut->button()); + XCORE->ungrabButton(window, shortcut->modMask() | scrollLockMask_ + | LockMask, shortcut->button()); + } + if (numLockMask_ && scrollLockMask_) { + XCORE->ungrabButton(window, shortcut->modMask() | numLockMask_ + | scrollLockMask_, shortcut->button()); + XCORE->ungrabButton(window, shortcut->modMask() | numLockMask_ + | scrollLockMask_ | LockMask, shortcut->button()); + } + } + else { + XCORE->ungrabKey(window, shortcut->modMask(), + shortcut->keyCode()); + + if (shortcut->modMask() == AnyModifier) { + return; + } + if (numLockMask_) { + XCORE->ungrabKey(window, shortcut->modMask() | numLockMask_, + shortcut->keyCode()); + XCORE->ungrabKey(window, shortcut->modMask() | numLockMask_ + | LockMask, shortcut->keyCode()); + } + if (scrollLockMask_) { + XCORE->ungrabKey(window, shortcut->modMask() | scrollLockMask_, + shortcut->keyCode()); + XCORE->ungrabKey(window, shortcut->modMask() | scrollLockMask_ + | LockMask, shortcut->keyCode()); + } + if (numLockMask_ && scrollLockMask_) { + XCORE->ungrabKey(window, shortcut->modMask() | numLockMask_ + | scrollLockMask_, shortcut->keyCode()); + XCORE->ungrabKey(window, shortcut->modMask() | numLockMask_ + | scrollLockMask_ | LockMask, shortcut->keyCode()); + } + } +} + +void Binder::initKeys(Window window) { + + for (MBindings::iterator it = actionBindings_->begin(); + it != actionBindings_->end(); it++) + { + Action *action = (*it).second; + LOGDEBUG("initKeys: " + action->id()); + if (action->listenOn()) { + grabShortcut(action->listenOn(), window); + } + } +} + +string Binder::prettyPrintKeyBindings() { + + ostringstream oss; + for (MBindings::iterator it = actionBindings_->begin(); + it != actionBindings_->end(); it++) + { + Action *action = (*it).second; + Shortcut *shortcut = action->shortcut(); + Shortcut *tmp = action->shortcut(); + if (shortcut) { + oss.width(35); + oss.fill(' '); + oss << action->id() << " = "; + } + while (tmp) { + oss.width(0); + if (tmp->button()) { + oss << Util::stringForModMask(tmp->modMask()) + << Util::stringForButton(tmp->button()); + } + else { + oss << Util::stringForModMask(tmp->modMask()) + << XCORE->keyCodeToString(tmp->keyCode()); + } + tmp = tmp->next(); + if (tmp) { + oss << " :: "; + } + } + if (shortcut) { + oss << "\n"; + } + } + + string result = oss.str(); + if (result == "") { + result = "no key bindings defined\n"; + } + return result; +} + +void Binder::handleButton(Window window, XButtonEvent *event) +{ + LOGDEBUG("handle button press event"); + handleShortcut(window, event->state, 0, event->button); +} + +void Binder::handleShortcut(Window window, unsigned long modMask, + KeyCode keyCode, unsigned int button) +{ + LOGDEBUG("handle shortcut event"); + LAction grabbedActions; + // only gets in here for the first part of a shortcut, thus + // create a list of all shortcuts which are listened for + for (MBindings::iterator it = actionBindings_->begin(); + it != actionBindings_->end(); it++) + { + Action *action = (*it).second; + Shortcut *shortcut = action->listenOn(); + + if (shortcut && + (modMask == shortcut->modMask()) && + (keyCode == shortcut->keyCode()) && + (button == shortcut->button())) + { + if (shortcut->next()) { + action->setListenOn(shortcut->next()); + grabbedActions.push_back(action); + } + else { + grabbedActions.clear(); + LOGDEBUG("handle shortcut performs action '" + + action->id() + "'"); + if (action->promptsCount() > 0) { + KERNEL->focusedMonitor()->inputBar()->runArgument(action); + // action will be performed by argument processing + } + else { + action->perform(); + } + break; + } + } + } + if (grabbedActions.size()) { + Shortcut shortcut(modMask, keyCode, 0, button); + // now the magic occurs + handleShortcutChains(window, &shortcut, &grabbedActions); + } + // reset listen on info + for (MBindings::iterator it = actionBindings_->begin(); + it != actionBindings_->end(); it++) + { + Action *action = (*it).second; + if (action->shortcut()) { + // already grabbed + action->setListenOn(action->shortcut()); + } + } +} + +void Binder::handleShortcutChains(Window window, Shortcut *prefix, + LAction *grabbedActions) +{ + string sequence = + " " + Util::stringForModMask(prefix->modMask()) + + XCORE->keyCodeToString(prefix->keyCode()) + " ::"; + Box *box = KERNEL->focusedMonitor()->box(); + box->setText(sequence); + box->show(); + box->illuminate(); + + XCORE->grabKeyboard(window); + + bool isDoubleShortcut = false; + unsigned long modMask; + KeyCode keyCode; + Action *action = 0; + while (grabbedActions->size()) { + // fetch new key stroke + nextKeystroke(&modMask, &keyCode); + + if ((prefix->modMask() == modMask) && + (prefix->keyCode() == keyCode)) + { + isDoubleShortcut = true; + break; + } + prefix->setModMask(modMask); + prefix->setKeyCode(keyCode); + sequence += " " + Util::stringForModMask(modMask) + + XCORE->keyCodeToString(keyCode) + " ::"; + box->setText(sequence); + box->illuminate(); + for (LAction::iterator it = grabbedActions->begin(); + it != grabbedActions->end(); ) + { + action = *it; + Shortcut *shortcut = action->listenOn(); + if (shortcut && + (modMask == shortcut->modMask()) && + (keyCode == shortcut->keyCode())) + { + // iterates next + it++; + if (shortcut->next()) { + action->setListenOn(shortcut->next()); + } + else { + grabbedActions->clear(); // escape condition + break; + } + } + else { + // iterates next + it = grabbedActions->erase(it); + } + action = 0; + } + } + XCORE->ungrabKeyboard(); + box->hide(); + if (action) { + + LOGDEBUG("handle shortcut performs action '" + + action->id() + "'"); + if (action->promptsCount() > 0) { + KERNEL->focusedMonitor()->inputBar()->runArgument(action); + // action will be performed by argument processing + } + else { + action->perform(); + } + } + else if (isDoubleShortcut) { + emulateKeyPress(modMask, keyCode); + } +} + +void Binder::emulateKeyPress(unsigned long modMask, KeyCode keyCode) { + + Monitor *monitor = KERNEL->focusedMonitor(); + Client *client = monitor->focused()->topClient(); + + if (client) { + XEvent event; + event.xkey.type = KeyPress; + event.xkey.time = CurrentTime; + event.xkey.window = client->clientWindow(); + event.xkey.display = KERNEL->display(); + event.xkey.state = modMask; + event.xkey.keycode = keyCode; + XCORE->sendEvent(client->clientWindow(), KeyPressMask, &event); + event.xkey.type = KeyRelease; + XCORE->sendEvent(client->clientWindow(), KeyReleaseMask, &event); + XCORE->sync(); + } +} + +void Binder::nextKeystroke(unsigned long *modMask, KeyCode *keyCode) { + XEvent event; + KeySym sym; + *modMask = 0; + do { + XCORE->maskEvent(KeyPressMask, &event); + *modMask |= event.xkey.state & validModMask_; + *keyCode = event.xkey.keycode; + sym = XCORE->keyCodeToKeySym(event.xkey.keycode); + } while (IsModifierKey(sym)); +} + +void Binder::handleKey(Window window, XKeyEvent *event) +{ + LOGDEBUG("handle key press event"); + handleShortcut(window, event->state, event->keycode, 0); +} + +void Binder::grabButtons(Window window, unsigned long modMask) +{ + XCORE->grabButton(window, modMask, AnyModifier); +} + +void Binder::ungrabButtons(Window window) { + XCORE->ungrabButton(window, AnyModifier, AnyButton); +} + +#ifdef POSIX_REGEX +bool Binder::regex_first_match(const string& pattern, const string& haystack, int& begin, int& end){ + regmatch_t temp_regmatch; + + begin = 0; + end = -1 ; + bool condition = false; + if (pattern == temp_pattern_ && pattern!="") { condition = true; } else + { + condition = (regcomp(&temp_regex_, pattern.c_str(), REG_EXTENDED)==0); + if (!condition) regex_prepare(); //reinitialize + } + if (condition){ + bool result = (regexec(&temp_regex_, haystack.c_str(), 1, &temp_regmatch, 0)==0); + if (result){ + begin = temp_regmatch.rm_so; + end = temp_regmatch.rm_eo; + } + temp_pattern_ = pattern; + return result; + } + return false; +} + +bool Binder::regex_match(const string& pattern, const string& haystack){ + int begin; + int end; + return(regex_first_match(pattern, haystack, begin, end)); +} +#endif + + +string Binder::absolutePattern(string pattern, Sstring *names, + unsigned int offset) +{ + + string result = pattern; +if (!(names->empty())) { + +#ifdef POSIX_REGEX + if (doRegex_) { + + /* Check whether the search-pattern contains a modifier. + If it does, simply return the pattern itself, otherwise, + perform an infix-matching-algorithm. */ + + string first = *names->begin(); + for (int direction = 0; direction <= 1; direction++){ + bool matches_all = true; + do { + LOGDEBUG("Entering do-while-infix-matching-loop"); + int begin; + int end; + + if (regex_first_match (result, first, begin, end)){ + LOGDEBUG("pattern-rule matched first member"); + int count = end - begin + 1; + if (direction == 1) begin--; + if ((begin + count <= (int)first.length()) && (begin >= 0) && (count>0)){ + pattern=first.substr(begin, count); + LOGDEBUG("trying to add a char to pattern"); + LOGDEBUG(pattern); + } else break; + } + + for (Sstring::iterator it = names->begin(); it != names->end(); it++) + if(!regex_match(pattern, (*it))) matches_all = false; + if (matches_all) result = pattern; + } while (matches_all); + } + return(result); + } +#endif + + string firstName = *names->begin(); + string lastName = *names->rbegin(); + + unsigned int firstLength = firstName.length(); + unsigned int lastLength = lastName.length(); + for (unsigned int i = offset; + (i < firstLength) && (i < lastLength); i++) + { + if (firstName[i] == lastName[i]) { + result += firstName[i]; + } + else { + break; + } + } + } + + return result; // return absolute pattern +} + +void Binder::matchPattern(string digest, string pattern, Sstring *strings, + unsigned int patternLength) +{ + bool condition; + condition = (digest.substr(0, patternLength) == pattern); + +#ifdef POSIX_REGEX + if (doRegex_) { + condition = regex_match(pattern, digest); + } +#endif + + if (condition) { + strings->insert(digest); + } +} + +void Binder::initRegex(string pattern){ +#ifdef POSIX_REGEX + doRegex_ = Util::get(KERNEL->commonSettings(), "autocompletion.mode") == "regex"; +#endif +} + +string Binder::queryFramesForPattern(string pattern, Sstring *sFrames) +{ + + Workspace *workspace = KERNEL->focusedMonitor()->focused(); + CFrame *frames = workspace->frames(); + unsigned int patternLength = pattern.length(); + string lName; + initRegex(pattern); + for (LFrame::iterator it = frames->begin(); it != frames->end(); it++) { + Frame *frame = *it; + matchPattern(frame->name(), pattern, + sFrames, patternLength); + } + return absolutePattern(pattern, sFrames, patternLength); +} + +string Binder::queryClientIdsForPattern(string pattern, Sstring *clients) +{ + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + MClient *clientMap = focusedMonitor->clients(); + unsigned int patternLength = pattern.length(); + initRegex(pattern); + for (MClient::iterator it = clientMap->begin(); + it != clientMap->end(); it++) + { + Client *client = (*it).second; + if (client->attached() +#ifdef SLOT_SUPPORT + || client->mode() == Client::SLOT +#endif // SLOT_SUPPORT + ) + { + matchPattern(client->id(), pattern, clients, patternLength); + } + } + return absolutePattern(pattern, clients, pattern.length()); +} + +string Binder::queryClientsForPattern(string pattern, Sstring *clients) +{ + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + MClient *clientMap = focusedMonitor->clients(); + unsigned int patternLength = pattern.length(); + initRegex(pattern); + for (MClient::iterator it = clientMap->begin(); + it != clientMap->end(); it++) + { + Client *client = (*it).second; + if (client->attached() +#ifdef SLOT_SUPPORT + || client->mode() == Client::SLOT +#endif + ) + { + matchPattern(client->name(), pattern, clients, patternLength); + } + } + return absolutePattern(pattern, clients, pattern.length()); +} + +string Binder::queryDetachedClientsForPattern(string pattern, Sstring *clients) +{ + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + CClient *detachedClients = focusedMonitor->detachedClients(); + unsigned int patternLength = pattern.length(); + initRegex(pattern); + for (LClient::iterator it = detachedClients->begin(); + it != detachedClients->end(); it++) + { + Client *client = *it; + matchPattern(client->name(), pattern, clients, patternLength); + } + return absolutePattern(pattern, clients, pattern.length()); +} + +string Binder::queryMonitorsForPattern(string pattern, Sstring *monitors) { + + CMonitor *ms = KERNEL->monitors(); + unsigned int patternLength = pattern.length(); + initRegex(pattern); + for (LMonitor::iterator it = ms->begin(); it != ms->end(); it++) { + matchPattern((*it)->displayString(), pattern, monitors, patternLength); + } + + return absolutePattern(pattern, monitors, patternLength); +} + +string Binder::queryWorkspacesForPattern(string pattern, + Sstring *workspaces) +{ + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + unsigned int patternLength = pattern.length(); + string wsName; + initRegex(pattern); + for (LWorkspace::iterator it = focusedMonitor->begin(); + it != focusedMonitor->end(); it++) + { + matchPattern((*it)->name(), pattern, workspaces, patternLength); + } + + return absolutePattern(pattern, workspaces, patternLength); +} + +string Binder::queryExternChainActionsForPattern( + string pattern, Sstring *actionKeys) +{ + unsigned int patternLength = pattern.length(); + string actionKey; + Action *action; + initRegex(pattern); + for (MBindings::iterator it = actionBindings_->begin(); + it != actionBindings_->end(); it++) + { + actionKey = (*it).first; + action = (*it).second; + if (action->type() == Action::INTERN) { + continue; + } + matchPattern(actionKey, pattern, actionKeys, patternLength); + } + + return absolutePattern(pattern, actionKeys, patternLength); +} + +string Binder::queryActionKeysWithoutValidationForPattern( + string pattern, Sstring *actionKeys) +{ + unsigned int patternLength = pattern.length(); + string actionKey; + initRegex(pattern); + for (MBindings::iterator it = actionBindings_->begin(); + it != actionBindings_->end(); it++) + { + actionKey = (*it).first; + matchPattern(actionKey, pattern, actionKeys, patternLength); + } + + return absolutePattern(pattern, actionKeys, patternLength); +} + +string Binder::queryActionKeysForPattern(string pattern, Sstring *actionKeys) { + + unsigned int patternLength = pattern.length(); + string actionKey; + initRegex(pattern); + for (MBindings::iterator it = actionBindings_->begin(); + it != actionBindings_->end(); it++) + { + Action *action = (*it).second; + + if (action->isValid()) { + actionKey = (*it).first; + matchPattern(actionKey, pattern, actionKeys, patternLength); + } + } + + return absolutePattern(pattern, actionKeys, patternLength); +} + +string Binder::queryCommandForPattern(string pattern, Sstring *expands) { + + Expander::instance()->queryString(pattern); + Sstring exp = Expander::instance()->expands(); + initRegex(pattern); + + + unsigned int offset = pattern.find_last_of('/'); + if (offset == string::npos) offset=0; else offset++; + +#ifdef POSIX_REGEX + doRegex_ = doRegex_ && (offset == 0); +#endif + + for (Sstring::iterator it = exp.begin(); + it != exp.end(); it++) + { + matchPattern((string)(*it), pattern.substr(offset), expands, pattern.length()-offset); + } + + return absolutePattern(pattern, expands, pattern.length() - + pattern.find_last_of('/') - 1); +} + +#define NUM_MASKS 8 + +void Binder::initLockModifiers() { + XModifierKeymap *modmap; + KeyCode numLock, scrollLock; + + // preinit + numLockMask_ = scrollLockMask_ = 0; + + // init modifier map + modmap = XCORE->modifierMapping(); + + // modifier masks we know + static int masks[NUM_MASKS] = { + ShiftMask, LockMask, ControlMask, Mod1Mask, + Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask + }; + + // temporary keysyms of evil keys + numLock = XCORE->stringToKeyCode("Num_Lock"); + scrollLock = XCORE->stringToKeyCode("Scroll_Lock"); + + if (modmap && modmap->max_keypermod > 0) { + unsigned int max = NUM_MASKS * modmap->max_keypermod; + for (unsigned int i = 0; i < max; i++) { + if (numLock && (modmap->modifiermap[i] == numLock)) { + numLockMask_ = masks[i / modmap->max_keypermod]; + } + else if (scrollLock && (modmap->modifiermap[i] == scrollLock)) { + scrollLockMask_ = masks[i / modmap->max_keypermod]; + } + } + } + + XCORE->freeModifierMapping(modmap); + validModMask_ = 255 & ~(numLockMask_ | scrollLockMask_ | LockMask); +} + +unsigned int Binder::validModMask() const { + return validModMask_; +} diff --git a/binder.h b/binder.h @@ -0,0 +1,233 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// Copyright (c) 2003 - 2004 Marcel Manthe <schneegloeckchen at gmx.li> +// See ../LICENSE.txt for license details. +// +// $Id: binder.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __BINDER_H +#define __BINDER_H + +#include "singleton.h" + +extern "C" { +#include <X11/Xlib.h> +} + +#include <list> +#include <map> +#include <set> + +#ifdef POSIX_REGEX +#include <stack> +#include "logger.h" +#include <regex.h> +#endif + +#include <string> +#include "wmi.h" + +// forward declaration +class Action; +class Binder; +class Group; +class Kernel; +class Shortcut; + +typedef set<string> Sstring; +typedef map<string, Action *, less<string> > MBindings; +typedef list<Action *> LAction; + +/** + * Main class of all key- and button-grabbing related logic. + */ +class Binder : public Singleton<Binder> +{ + +public: + + /** Constructs a new grab manager instance. */ + Binder(); + + ~Binder(); + + /** Key initialization for a specific window. */ + void initKeys(Window window); + + /** Key event handler, window is for grabbing. */ + void handleKey(Window window, XKeyEvent *e); + + /** Button event handler, window is for grabbing. */ + void handleButton(Window window, XButtonEvent *e); + + /** Grabs the shortcut. */ + void grabShortcut(Shortcut *shortcut, Window window); + + /** Ungrabs shortcut. */ + void ungrabShortcut(Shortcut *shortcut, Window window); + + /** Grabs all buttons for the modMask of the specific window. */ + void grabButtons(Window window, unsigned long modMask); + + /** Ungrabs all buttons for the specific window. */ + void ungrabButtons(Window window); + + /** Returns pretty print of current key configuration. */ + string prettyPrintKeyBindings(); + + /** + * Queries all actions for the given pattern. + * Returns absolute equal pattern of <i>all</i> entries. + * @param pattern contains the pattern. + * @param set where to put matching action keys. + */ + string queryActionKeysForPattern(string pattern, Sstring *actionKeys); + + /** Similiar to previous, except actions aren't validated. */ + string queryActionKeysWithoutValidationForPattern(string pattern, + Sstring *actionKeys); + + + /** Similiar to previous, except that internal actions are ignored. */ + string queryExternChainActionsForPattern( + string pattern, Sstring *actionKeys); + + /** + * Queries all executables for the given pattern. + * Returns absolute equal pattern of <i>all</i> executables. + * @param pattern contains the pattern. + * @param set where to put matching executables. + */ + string queryCommandForPattern(string pattern, Sstring *expands); + + /** + * Queries all workspace names of the focused monitor. + * Returns absolute equal pattern of <i>all</i> workspaces. + * @param pattern contains the pattern. + * @param set where to put matching names. + */ + string queryWorkspacesForPattern(string pattern, Sstring *workspaces); + + /** + * Queries all monitor names. + * Returns absolute equal pattern of <i>all</i> monitors. + * @param pattern contains the pattern. + * @param set where to put matching names. + */ + string queryMonitorsForPattern(string pattern, Sstring *monitors); + + /** + * Queries all client names of the focused monitor. + * Returns absolute equal pattern of <i>all</i> clients. + * @param pattern contains the pattern. + * @param set where to put matching names. + */ + string queryClientsForPattern(string pattern, Sstring *clients); + + /** + * Queries all detached client names of the focused monitor. + * Returns absolute equal pattern of <i>all</i> clients. + * @param pattern contains the pattern. + * @param set where to put matching names. + */ + string queryDetachedClientsForPattern(string pattern, Sstring *clients); + + /** Same as above, except instead of client names, client ids. */ + string queryClientIdsForPattern(string pattern, Sstring *clients); + + /** + * Queries all frame names of the focused workspace. + * Returns absolute equal pattern of <i>all</i> frame ids. + * @param pattern contains the pattern. + * @param set where to put matching names. + */ + string queryFramesForPattern(string pattern, Sstring *sFrames); + + unsigned int validModMask() const; + +#ifdef POSIX_REGEX + string popRegexPattern(){ + string result; + if (!regexPattern_.empty()) regexPattern_.pop(); + if (regexPattern_.empty()){ + result = ""; + }else{ + result = regexPattern_.top(); + } + + return result; + } + + void pushRegexPattern(string pattern){ + regexPattern_.push(pattern); + + stack<string> temp = regexPattern_; + string res; + while (!temp.empty()){ + res= res + temp.top() + " --- " ; + temp.pop(); + } + LOGDEBUG("STACK: " + res); + + } + void clearRegexPattern(){ + while (!regexPattern_.empty()) regexPattern_.pop(); + } +#endif + +private: + + /** Helper handler for handleKey and handleButton action. */ + void handleShortcut(Window window, unsigned long modMask, + KeyCode keyCode, unsigned int button); + + /** Own key press processing shortcut handler (for postfixed + shortcuts). */ + void handleShortcutChains(Window window, Shortcut *prefix, + LAction *grabbedActions); + /** Helper for handleShortcutChains. Keyboard should be grabbed. */ + void nextKeystroke(unsigned long *modMask, KeyCode *keyCode); + + /** Emulates key press for client. */ + void emulateKeyPress(unsigned long modMask, KeyCode keyCode); + + /** Inits lock modifier detection (NumLock and ScrollLock). */ + void initLockModifiers(); + + /** + * Returns absolute pattern of the given set, at least pattern. + * @param offset begin of comparisions within set. + */ + string absolutePattern(string pattern, Sstring *names, unsigned int offset); + + /** + * Matches the pattern. + * @param digest the string to check match. + * @param pattern the pattern to match. + * @param strings the container set to insert matched strings. + * @param patternLength the pattern length. + */ + void matchPattern(string digest, string pattern, Sstring *strings, + unsigned int patternLength); + + void initRegex(string); + +#ifdef POSIX_REGEX + bool regex_first_match(const string& pattern, const string& haystack, + int& begin, int& end); + bool regex_match(const string& pattern, const string& haystack); + void regex_prepare(){regcomp(&temp_regex_, "", REG_EXTENDED); temp_pattern_="";} + string temp_pattern_; + regex_t temp_regex_; + bool doRegex_; + stack<string> regexPattern_; +#endif + + + MBindings *actionBindings_; + + unsigned int numLockMask_; + unsigned int scrollLockMask_; + unsigned int validModMask_; +}; + +#endif // __BINDER_H diff --git a/box.cpp b/box.cpp @@ -0,0 +1,50 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: box.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include "box.h" + +#include "draw.h" +#include "label.h" +#include "monitor.h" +#include "theme.h" +#include "xcore.h" + +Box::Box(Monitor *monitor, Rectangle *rect, string text) : + Widget(monitor, rect) +{ + theme_ = this->monitor()->theme(); + label_ = new Label(this->monitor(), window(), Label::CENTER, gc()); + label_->setX(1); + label_->setY(1); + label_->setHeight(height() - 2); + setText(text); +} + +Box::~Box() { + delete label_; +} + +void Box::setText(string text) { + label_->setText(text); + label_->adjustWidth(); + setX(monitor()->width() / 2 - label_->width() / 2 - 1); + setWidth(label_->width() + 2); + resize(); +} + +void Box::illuminate() { + if (!isVisible()) { + return; + } + Rectangle borderRect(0, 0, width(), height()); + label_->update(theme_->TAB_BACKGROUND_ACTIVE_FOCUSSED, + theme_->TAB_TEXT_ACTIVE_FOCUSSED, + theme_->TAB_SHINE_ACTIVE_FOCUSSED, + theme_->TAB_SHADOW_ACTIVE_FOCUSSED, + true, true); + Draw::drawRectBorder(window(), gc(), &borderRect, + theme_->BAR_SHINE, theme_->BAR_SHADOW); + XCORE->sync(); +} diff --git a/box.h b/box.h @@ -0,0 +1,39 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: box.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __BOX_H +#define __BOX_H + +extern "C" { +#include <X11/Xlib.h> +} + +#include <string> + +#include "widget.h" +#include "wmi.h" + +class Label; +class Monitor; +class Theme; + +/** Basic info box. */ +class Box : public Widget { + +public: + + Box(Monitor *monitor, Rectangle *rect, string text); + ~Box(); + + void setText(string text); + void illuminate(); + +private: + + Label *label_; + Theme *theme_; +}; + +#endif // __BOX_H diff --git a/client.cpp b/client.cpp @@ -0,0 +1,884 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: client.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include <sstream> + +extern "C" { +#include <assert.h> +#include <X11/Xatom.h> +} + +#include "client.h" + +#include "atoms.h" +#include "binder.h" +#include "cursors.h" +#include "draw.h" +#include "clientbar.h" +#include "frame.h" +#include "kernel.h" +#include "label.h" +#include "logger.h" +#include "rectangle.h" +#include "statusbar.h" +#include "monitor.h" +#include "util.h" +#include "slot.h" +#include "theme.h" +#include "workspace.h" +#include "xcore.h" + +Client::Client(Monitor *monitor, Window window, XWindowAttributes *attr) + : Thing(monitor, new Rectangle(), Thing::CLIENT) +{ + clientWindow_ = window; + frame_ = 0; + state_ = WithdrawnState; + iconName_ = ""; + isCentered_ = false; + protocols_ = 0; + hasFrame_ = false; + requestsFocus_ = false; + isDestroyed_ = false; + hooked_ = ""; + workspace_ = 0; + + ostringstream oss; + oss << "<" << monitor->nextClientId() << ">"; + id_ = oss.str(); + + eventMask_ = PropertyChangeMask; + XCORE->selectEvents(clientWindow_, eventMask_); + + setX(attr->x); + setY(attr->y); + setWidth(attr->width); + setHeight(attr->height); + borderWidth_ = attr->border_width; + + oss.str(""); + oss << "constructing new client with dimensions: " << + x() << "," << y() << "," << width() << "," << height(); + LOGDEBUG(oss.str()); + + className_ = XCORE->className(clientWindow_); + instanceName_ = XCORE->instanceName(clientWindow_); + + string value; + + updateTransient(); + if (transient_) { + value = Util::get(KERNEL->sessionSettings(), + "client." + className_ + "::" + instanceName_ + ".transient-mode"); + + if ("" == value) { + value = Util::get(KERNEL->commonSettings(), + "default.transient-mode"); + + if ("" == value) { + value = "float"; + } + } + } + else { + value = Util::get(KERNEL->sessionSettings(), + "client." + className_ + "::" + instanceName_ + ".mode"); + } + + if (value == "float") { + mode_ = FLOAT; + } + else if (value == "sticky") { + mode_ = STICKY; + } + else if (value == "max") { + mode_ = MAX; + } +#ifdef SLOT_SUPPORT + else if (value == "slot") { + mode_ = SLOT; + } +#endif // SLOT_SUPPORT + // fallback, unknown yet + else if (Util::get(KERNEL->commonSettings(), "default.client-mode") + == "float") + { + mode_ = FLOAT; + } + else { + mode_ = MAX; + } + + hooked_ = Util::get(KERNEL->sessionSettings(), + "client." + className_ + "::" + instanceName_ + ".hooked"); +} + +Client::~Client() { +} + +string Client::id() { + return id_; +} + +void Client::initICCCM() { + + state_ = XCORE->state(clientWindow_); + iconName_ = XCORE->atomValue(clientWindow_, XA_WM_ICON_NAME); + setName(XCORE->atomValue(clientWindow_, XA_WM_NAME) + id_); + if (iconName_ == "") { + iconName_ = name(); + } + else { + iconName_ += id_; + } + updateSize(); + protocols_ = XCORE->protocols(clientWindow_); + if (XCORE->hasDecoration(clientWindow_) && !frameWindow()) { + hasDecoration_ = true; + } + + updateTransient(); +} + +void Client::updateSize() { + + unsigned int dummy; + // TODO: increment handling + XCORE->updateSize(clientWindow_, &dummy, &dummy, + &dummy, &dummy, &isCentered_); +} + +void Client::updateTransient() { + + Window trans = XCORE->transient(clientWindow_); + transient_ = KERNEL->clientForWindow(trans); +} + +Client *Client::transient() const { + return transient_; +} + +void Client::sendConfiguration() { + XConfigureEvent event; + + ostringstream oss; + + oss << "send configuration: " << clientAreaRect_.x() << "," + << clientAreaRect_.y() << "," << clientAreaRect_.width() + << "," << clientAreaRect_.height(); + LOGDEBUG(oss.str()); + event.type = ConfigureNotify; + event.event = clientWindow_; + event.window = clientWindow_; + if (hasFrame_) { + event.x = x() + clientAreaRect_.x(); + event.y = y() + clientAreaRect_.y(); + } + else if (frame()) { + event.x = frame()->x() + clientAreaRect_.x(); + event.y = frame()->y() + clientAreaRect_.y(); + } + else { + event.x = clientAreaRect_.x(); + event.y = clientAreaRect_.y(); + } + event.width = clientAreaRect_.width(); + event.height = clientAreaRect_.height(); + event.border_width = clientBorderWidth_; + event.above = None; + event.override_redirect = False; + + XCORE->configure(clientWindow_, &event); +} + +void Client::resize() { + + clientAreaRect_.copy(this); + + if (hasFrame_) { + ostringstream oss; + oss << "frame resize: x=" << x() << ", y=" << y() << ", w=" << + width() << ", h=" << height(); + LOGDEBUG(oss.str()); + XCORE->moveResize(frameWindow(), this); + + if (frame()) { + // maximize client window + clientAreaRect_.setX(0); + clientAreaRect_.setY(0); + clientAreaRect_.setWidth(width()); + clientAreaRect_.setHeight(height()); + } + else { + label_->setY(borderWidth_); // label fix for toggleBorder + fitClientArea(); + } + } + XCORE->moveResize(clientWindow_, &clientAreaRect_); + sendConfiguration(); + illuminate(); +} + +void Client::gravitate(bool invert) { + + int dx = 0; + int dy = 0; + int gravity = NorthWestGravity; + XSizeHints sizeHints; + + XCORE->sizeHints(clientWindow_, &sizeHints); + + if (sizeHints.flags & PWinGravity) { + gravity = sizeHints.win_gravity; + } + + switch (gravity) { + case NorthEastGravity: + case EastGravity: + case SouthEastGravity: + dx = -borderWidth_; + break; + default: + break; + } + + switch (gravity) { + case SouthWestGravity: + case SouthGravity: + case SouthEastGravity: + dy = -titleBarHeight_ - borderWidth_; + break; + default: + break; + } + + if (invert) { + dx = -dx; + dy = -dy; + } + + setX(x() + dx); + setY(y() + dy); +} + +void Client::handleConfigureRequest(XConfigureRequestEvent *event) { + + XWindowChanges wc; + + if (event->value_mask & CWStackMode) { + if (attached()) { + if (!isFocused()) { + requestsFocus_ = true; + } + if (monitor()->focused() != attached()) { + attached()->setRequestsFocus(true); + } + } + event->value_mask &= ~CWStackMode; + } + + event->value_mask &= ~CWSibling; + if (!frame() +#ifdef SLOT_SUPPORT + || (mode_ == SLOT) +#endif + ) { + + // floating client + + gravitate(true); + + if (event->value_mask & CWX) { + setX(event->x); + } + if (event->value_mask & CWY) { + setY(event->y); + } + if (event->value_mask & CWWidth) { + setWidth(event->width); + } + if (event->value_mask & CWHeight) { + setHeight(event->height); + } + if (event->value_mask & CWBorderWidth) { + clientBorderWidth_ = event->border_width; + } + ostringstream oss; + oss << "configure request: x=" << x() << ", y=" << y() + << ", w=" << width() << ", h=" << height(); + LOGDEBUG(oss.str()); + + gravitate(false); + + // applied patch by Dr. J. Pfefferl + if (hasFrame_) { + + if((event->value_mask & CWWidth)) { + setWidth(width() + 2 * borderWidth_); + } + if((event->value_mask & CWHeight)) { + setHeight(height() + titleBarHeight_ + 2 * borderWidth_ + + (titleBarHeight_ ? 1 : 0)); + } + if((event->value_mask & CWX)) { + setX(x() - borderWidth_); + } + if((event->value_mask & CWY)) { + setY(y() - titleBarHeight_ - borderWidth_); + } + + wc.x = x(); + wc.y = y(); + wc.width = width(); + wc.height = height(); + wc.border_width = 1; // event->border_width + wc.sibling = None; + wc.stack_mode = event->detail; + XCORE->configureWindow(frameWindow(), event->value_mask, &wc); + fitClientArea(); + sendConfiguration(); + } + else { + // save current dimensions to client area + clientAreaRect_.copy(this); + } + } + +#ifdef SLOT_SUPPORT + if (mode_ == SLOT) { + monitor()->slot()->manage(); + } + else +#endif // SLOT_SUPPORT + { + // If client is attached to a frame, the clientAreaRect_ has + // the size of the frames client area. + wc.x = clientAreaRect_.x(); + wc.y = clientAreaRect_.y(); + wc.width = clientAreaRect_.width(); + wc.height = clientAreaRect_.height(); + wc.border_width = 0; + wc.sibling = None; + event->value_mask |= CWBorderWidth; + + XCORE->configureWindow(clientWindow_, event->value_mask, &wc); + + illuminate(); + } +} + +void Client::handlePropertyNotify(XPropertyEvent *event) { + + if (event->state == PropertyDelete) { + return; // ignore delete properties + } + + // WM atoms + if (event->atom == Atoms::WM_PROTOCOLS) { + protocols_ = XCORE->protocols(clientWindow_); + return; + } + else if (event->atom == Atoms::MWM_HINTS) { + if (XCORE->hasDecoration(clientWindow_) && !frameWindow()) { + hasDecoration_ = true; + } + return; + } + + // default atoms + static string tmp; + ostringstream oss; + switch (event->atom) { + case XA_WM_ICON_NAME: + tmp = XCORE->atomValue(clientWindow_, XA_WM_ICON_NAME); + if (tmp.length() > 0) { + // update only if the icon name is != 0 + iconName_ = tmp + id_; + } + monitor()->clientBar()->illuminate(); + monitor()->statusBar()->illuminate(); + break; + case XA_WM_NAME: + tmp = XCORE->atomValue(clientWindow_, XA_WM_NAME); + if (tmp.length() > 0) { + // update only if the title is != 0 + setName(tmp + id_); + } + illuminate(); + monitor()->statusBar()->illuminate(); + break; + case XA_WM_TRANSIENT_FOR: + updateTransient(); + break; + case XA_WM_NORMAL_HINTS: + updateSize(); + oss << "git size: x=" << x() << ", y=" << y() << ", w=" << + width() << ", h=" << height(); + LOGDEBUG(oss.str()); + break; + } +} + +void Client::handleUnmapNotify(XUnmapEvent *event) { + + if (!isVisible_ || !event->send_event) { + LOGDEBUG("client is already unvisible"); + return; + } + + LOGDEBUG("handle unmap client: " + name()); + if (frameWindow()) { + XCORE->hide(frameWindow()); + } + isVisible_ = false; + XCORE->setState(clientWindow_, WithdrawnState); + Workspace *ws = this->attached(); + if (ws) { + LOGDEBUG("going detaching client from workspace"); + ws->detachClient(this); + } +} + +void Client::show() { + if (isDestroyed_) { + return; + } + XCORE->showRaised(clientWindow_); + if (hasFrame_) { + XCORE->showRaised(frameWindow()); + } + state_ = NormalState; + KERNEL->installCursor(Cursors::NORMAL_CURSOR, clientWindow_); + XCORE->setState(clientWindow_, state_); + isVisible_ = true; +} + +void Client::hide() { + if (isDestroyed_) { + return; + } + if (hasFrame_) { + XCORE->hide(frameWindow()); + } + XCORE->hide(clientWindow_); + state_ = WithdrawnState; + XCORE->setState(clientWindow_, state_); + isVisible_ = false; + LOGDEBUG("client state changed"); + XCORE->sync(); +} + +void Client::setMode(Client::Mode mode) { + + mode_ = mode; + string modeStr; + + switch (mode_) { + case MAX: + modeStr = "max"; + break; + case STICKY: + modeStr = "sticky"; + break; + case FLOAT: + modeStr = "float"; + break; +#ifdef SLOT_SUPPORT + case SLOT: + modeStr = "slot"; + break; +#endif // SLOT_SUPPORT + } + if (transient_) { + (*KERNEL->sessionSettings())["client." + className_ + "::" + + instanceName_ + ".transient-mode"] = modeStr; + } + else { + (*KERNEL->sessionSettings())["client." + className_ + "::" + + instanceName_ + ".mode"] = modeStr; + } +} + +long Client::eventMask() const { + return eventMask_; +} + +string Client::className() const { + return className_; +} + +string Client::instanceName() const { + return instanceName_; +} + +string Client::iconName() const { + return iconName_; +} + +int Client::protocols() const { + return protocols_; +} + +// TODO: It would be a good idea to implement an align method +// for gravitation with value VH_CENTER +bool Client::isCentered() const { + return isCentered_; +} + +Client::Mode Client::mode() const { + return mode_; +} + +int Client::state() const { + return state_; +} + +Window Client::window() { + if (hasFrame_) { + return frameWindow_; + } + else { + return clientWindow_; + } +} + +void Client::reparent(Window parentWindow, int x, int y) { + if (isDestroyed_) { + return; + } + XCORE->reparent(clientWindow_, parentWindow, x, y); + assert(parentWindow); + hasFrame_ = (parentWindow == frameWindow()); +} + +void Client::createFrame() { + initFrameWindow(); + fitClientArea(); + XCORE->sync(); +} + +bool Client::isFocused() { + + if (frame()) { + return frame()->isFocused() + && frame()->focused() == this; + } + else if (attached()) { + return attached()->topClient() == this; + } + return 0; +} + +void Client::illuminate() { + + if (!isVisible_) { + return; + } + + if (frame()) { + frame()->illuminate(); + return; + } + + if (!hasFrame_) { + return; + } + LOGDEBUG("within client illuminate"); + XCORE->sync(); + + illuminateBorder(); + + bool foc = isFocused(); + unsigned int buttonWidth = 0; + + if (foc) { + buttonWidth = monitor()->buttonWidth(); + } + + if (titleBarHeight_) { + label_->setText(name()); + label_->setX(borderWidth_); + unsigned int textWidth = label_->adjustWidth(); + unsigned long tabShine = 0; + unsigned long tabShadow = 0; + label_->setWidth(width() - label_->x() - borderWidth_); + if (foc) { + if (areButtonsVisible_) { + label_->setWidth(label_->width() - 3 * buttonWidth - 2); + } + tabShine = theme_->TAB_SHINE_ACTIVE_FOCUSSED; + tabShadow = theme_->TAB_SHADOW_ACTIVE_FOCUSSED; + label_->update(theme_->TAB_BACKGROUND_ACTIVE_FOCUSSED, + theme_->TAB_TEXT_ACTIVE_FOCUSSED, + tabShine, tabShadow, true, true); + } + else if (requestsFocus_) { + tabShine = theme_->FOCUSREQ_SHINE; + tabShadow = theme_->FOCUSREQ_SHADOW; + label_->update(theme_->FOCUSREQ_BACKGROUND, + theme_->FOCUSREQ_TEXT, + tabShine, tabShadow, true, true); + } + else if (frame() && frame()->focused() == this) { + tabShine = theme_->TAB_SHINE_ACTIVE_NORMAL; + tabShadow = theme_->TAB_SHADOW_ACTIVE_NORMAL; + label_->update(theme_->TAB_BACKGROUND_ACTIVE_NORMAL, + theme_->TAB_TEXT_ACTIVE_NORMAL, + tabShine, tabShadow, true, true); + } + else { + tabShine = theme_->TAB_SHINE_INACTIVE_NORMAL; + tabShadow = theme_->TAB_SHADOW_INACTIVE_NORMAL; + label_->update(theme_->TAB_BACKGROUND_INACTIVE_NORMAL, + theme_->TAB_TEXT_INACTIVE_NORMAL, + tabShine, tabShadow, true, true); + } + + if (mode_ == Client::STICKY) { + + Draw::drawStickyNotifier(frameWindow(), gc_, label_, + tabShine, tabShadow, textWidth); + } + } + + if (foc) { + Draw::drawFloatBorderAnchors(frameWindow(), gc_, this, + theme_->FRAME_SHINE_FOCUSSED, + theme_->FRAME_SHADOW_FOCUSSED, + titleBarHeight_ + borderWidth_ + 1, + borderWidth_); + } +} + +void Client::handleButtonPress(XButtonEvent *event) { + + LOGDEBUG("entered ClientFrame::handleButtonPress"); +#ifdef SLOT_SUPPORT + if (mode_ == SLOT) { + monitor()->slot()->focusClient(this); + return; + } +#endif + if (attached() && !isFocused()) { + attached()->focus(this); + return; + } + else { + XCORE->raise(window()); + } + + if (frame()) { + return; + } + + buttonState_ = NONE; + + if (event->button == Button1) { + + if (titleBarHeight_ && areButtonsVisible_ && + (cursor_ == Cursors::NORMAL_CURSOR)) + { + int xPosition = event->x; + unsigned int buttonWidth = titleBarHeight_ + 1; + unsigned int offsetButtonGroup = width() - borderWidth_ - 3 * buttonWidth; + if ((xPosition > (int)offsetButtonGroup) && + (xPosition < (int)(width() - borderWidth_ - 1))) + { + xPosition -= offsetButtonGroup; + unsigned int buttonNum = xPosition / buttonWidth; + switch (buttonNum) { + case 0: + buttonState_ = MINCLIENT; + break; + case 1: + buttonState_ = DEMAX; + break; + case 2: + buttonState_ = CLOSE; + break; + } + illuminate(); + return; + } + } + + if (monitor()->isThingMaximized()) { + return; + } + + Direction dir = SOUTH_EAST; + if (cursor_ == Cursors::RESIZE_LEFT_CURSOR) { + dir = LEFT; + } + else if (cursor_ == Cursors::RESIZE_RIGHT_CURSOR) { + dir = RIGHT; + } + else if (cursor_ == Cursors::RESIZE_UP_CURSOR) { + dir = UP; + } + else if (cursor_ == Cursors::RESIZE_DOWN_CURSOR) { + dir = DOWN; + } + else if (cursor_ == Cursors::RESIZE_NORTH_WEST_CURSOR) { + dir = NORTH_WEST; + } + else if (cursor_ == Cursors::RESIZE_NORTH_EAST_CURSOR) { + dir = NORTH_EAST; + } + else if (cursor_ == Cursors::RESIZE_SOUTH_WEST_CURSOR) { + dir = SOUTH_WEST; + } + else if (cursor_ == Cursors::RESIZE_SOUTH_EAST_CURSOR) { + dir = SOUTH_EAST; + } + + KERNEL->runResizeMode(this, event, dir, + cursor_ != Cursors::NORMAL_CURSOR); + } +} + +void Client::handleButtonRelease(XButtonEvent *event) { + + // TODO: make buttons customizable + if (event->button == Button1) { + + if (titleBarHeight_ && (cursor_ == Cursors::NORMAL_CURSOR) && + (buttonState_ != NONE)) + { + if (monitor()->isThingMaximized()) { + monitor()->toggleThingMaximization(); + } + switch (buttonState_) { + case MINCLIENT: + monitor()->detachClient(); + break; + case DEMAX: + attached()->toggleClientMode(); + break; + case CLOSE: + XCORE->kill(clientWindow_, protocols_); + break; + default: + break; + } + buttonState_ = NONE; + return; + } + } +} + +Cursor Client::cursorForXY(int pointerX, int pointerY) { + + if (frame() || (borderWidth_ == 0)) + { + return Cursors::NORMAL_CURSOR; + } + + // rectangle attributes of client are used + bool left = pointerX < clientAreaRect_.x(); + bool right = pointerX >= (int)(clientAreaRect_.x() + + clientAreaRect_.width()); + bool up = pointerY < (int)(clientAreaRect_.y() + - titleBarHeight_ - 1); + bool down = pointerY >= (int)(clientAreaRect_.y() + + clientAreaRect_.height()); + + bool tolLeft = pointerX < (int)(clientAreaRect_.x() + titleBarHeight_); + bool tolRight = pointerX > (int)(clientAreaRect_.x() + + clientAreaRect_.width() + - titleBarHeight_ - 1); + bool tolUp = pointerY < (int)(clientAreaRect_.y() + titleBarHeight_); + bool tolDown = pointerY > (int)(clientAreaRect_.y() + + clientAreaRect_.height() + - titleBarHeight_ - 1); + + if ((left && up) || (left && tolUp) || (up && tolLeft)) { + return Cursors::RESIZE_NORTH_WEST_CURSOR; + } + else if ((right && up) || (right && tolUp) || (up && tolRight)) { + return Cursors::RESIZE_NORTH_EAST_CURSOR; + } + else if ((left && down) || (left && tolDown) || + (down && tolLeft)) + { + return Cursors::RESIZE_SOUTH_WEST_CURSOR; + } + else if ((right && down) || (right && tolDown) || (down && + tolRight)) + { + return Cursors::RESIZE_SOUTH_EAST_CURSOR; + } + + if (left) { + return Cursors::RESIZE_LEFT_CURSOR; + } + else if (right) { + return Cursors::RESIZE_RIGHT_CURSOR; + } + else if (up) { + return Cursors::RESIZE_UP_CURSOR; + } + else if (down) { + return Cursors::RESIZE_DOWN_CURSOR; + } + + return Cursors::NORMAL_CURSOR; +} + +Frame *Client::frame() const { + return frame_; +} + +void Client::setFrame(Frame *frame) { + frame_ = frame; +} + +Workspace *Client::attached() const { + return workspace_; +} + +void Client::setAttached(Workspace *workspace) { + workspace_ = workspace; +} + +Window Client::frameWindow() const { + return frameWindow_; +} + +Window Client::clientWindow() const { + return clientWindow_; +} + +bool Client::requestsFocus() const { + return requestsFocus_; +} + +void Client::setRequestsFocus(bool requestsFocus) { + requestsFocus_ = requestsFocus; +} + +void Client::setHooked(string hooked) { + hooked_ = hooked; + if (hooked_ != "") { + (*KERNEL->sessionSettings())["client." + className_ + "::" + + instanceName_ + ".hooked"] = hooked_; + } + else { + Util::remove(KERNEL->sessionSettings(), + "client." + className_ + "::" + instanceName_ + ".hooked"); + } +} + +string Client::hooked() const { + return hooked_; +} + +void Client::setDestroyed(bool isDestroyed) { + isDestroyed_ = isDestroyed; +} + +bool Client::isDestroyed() const { + return isDestroyed_; +} diff --git a/client.h b/client.h @@ -0,0 +1,155 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: client.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __CLIENT_H +#define __CLIENT_H + +extern "C" { +#include <X11/Xlib.h> +#include <X11/Xutil.h> +} + +#include <list> +#include <string> +#include "thing.h" +#include "wmi.h" + +// forward declaration +class Client; +class Monitor; +class Workspace; + +typedef list<Client *> LClient; + +/** + * Representates an X client window. + */ +class Client : public Thing +{ + +public: + + enum Mode {FLOAT, MAX, STICKY +#ifdef SLOT_SUPPORT + , SLOT +#endif // SLOT_SUPPORT + }; + + Client(Monitor *monitor, Window window, XWindowAttributes *attr); + ~Client(); + + /** Returns if this client is transient. */ + void setTransient(Client *client); + Client *transient() const; + + long eventMask() const; + + string className() const; + + string instanceName() const; + + string iconName() const; + + void sendConfiguration(); + + virtual void resize(); + + /** event handler. */ + void handleConfigureRequest(XConfigureRequestEvent *event); + void handleMapNotify(XMapEvent *event); + void handlePropertyNotify(XPropertyEvent *event); + void handleUnmapNotify(XUnmapEvent *event); + + virtual void show(); + virtual void hide(); + + int protocols() const; + + bool isCentered() const; + + void initICCCM(); + + void setMode(Mode mode); + + Mode mode() const; + + int state() const; + + /** Illuminates this frame. */ + virtual void illuminate(); + + virtual bool isFocused(); + + virtual void handleButtonPress(XButtonEvent *event); + virtual void handleButtonRelease(XButtonEvent *event); + + virtual Cursor cursorForXY(int pointerX, int pointerY); + + virtual Window window(); + Window frameWindow() const; + Window clientWindow() const; + + void setDestroyed(bool isDestroyed); + bool isDestroyed() const; + + void createFrame(); + + void reparent(Window parentWindow, int x, int y); + + string id(); + + Frame *frame() const; + void setFrame(Frame *frame); + + Workspace *attached() const; + void setAttached(Workspace *workspace); + + bool requestsFocus() const; + void setRequestsFocus(bool requestsFocus); + + /** + * Defines where this client prefers to be attached to. + * Must be a valid workspace or slot tab name. + */ + string hooked() const; + void setHooked(string hooked); + +private: + + void gravitate(bool invert); + + /** Updates the size of this client. */ + void updateSize(); + + /** Updates transient for this client. */ + void updateTransient(); + + Window clientWindow_; + + string className_; + string instanceName_; + string iconName_; + string hooked_; + + Workspace *workspace_; + Client *transient_; + Frame *frame_; + + unsigned int clientBorderWidth_; + + int protocols_; + int state_; + long eventMask_; + + bool isCentered_; + bool hasFrame_; + bool requestsFocus_; + bool isDestroyed_; + + Mode mode_; + string id_; +}; + +#endif // __CLIENT_H diff --git a/clientbar.cpp b/clientbar.cpp @@ -0,0 +1,348 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: clientbar.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include <list> +#include <string> +#include <sstream> + +#include "clientbar.h" + +#include "client.h" +#include "cursors.h" +#include "draw.h" +#include "frame.h" +#include "label.h" +#include "logger.h" +#include "menu.h" +#include "monitor.h" +#include "theme.h" +#include "thing.h" +#include "validators.h" +#include "workspace.h" +#include "xcore.h" + +ClientBar::ClientBar(Monitor *monitor, Rectangle *rect) + : Bar(monitor, rect) +{ + isModeButtonPressed_ = isMenuButtonPressed_ = false; + mode_ = PAGER; + menu_ = new Menu(monitor); +} + +ClientBar::~ClientBar() { +} + +void ClientBar::illuminate() { + + if (!isVisible()) { + return; + } + + LOGDEBUG("going to draw border"); + drawBorder(); + + label_->setText(""); + label_->setX(1); + label_->setWidth(width() - 2); + label_->update(theme_->BAR_BACKGROUND, theme_->BAR_TEXT, + theme_->BAR_SHINE, theme_->BAR_SHADOW); + + updateMenuButton(); + if (mode_ == PAGER) { + updateClientPager(); + } + else { + updateClientInfo(); + } + updateModeButton(); +} + + +void ClientBar::updateClientPager() { + + Workspace *workspace = monitor()->focused(); + CClient *clients = workspace->floatingClients(); + if (clients->size() > 0) { + unsigned int offsetX = isButtonVisible_ ? monitor()->buttonWidth() + 3 : 1; + unsigned int clientsWidth = width() - 2; + if (isButtonVisible_) { + clientsWidth -= (2 * monitor()->buttonWidth() + 4); + } + unsigned int i = 0; + unsigned int clientWidth = clientsWidth / clients->size(); + label_->setWidth(clientWidth); + for (LClient::iterator it = clients->begin(); it != clients->end(); ) { + Client *client = *it; + it++; + + label_->setX(offsetX + i * clientWidth); + if (it == clients->end()) { + // FIX for right button irretations + label_->setWidth(width() - label_->x() + - (isButtonVisible_ ? monitor()->buttonWidth() + 3 : 1)); + } + unsigned long shine, shadow; + label_->setText(client->name()); + if (client->isFocused()) { + shine = theme_->TAB_SHINE_ACTIVE_FOCUSSED; + shadow = theme_->TAB_SHADOW_ACTIVE_FOCUSSED; + label_->update(theme_->TAB_BACKGROUND_ACTIVE_FOCUSSED, + theme_->TAB_TEXT_ACTIVE_FOCUSSED, + shine, shadow, true, true); + } + else if (client->requestsFocus()) { + shine = theme_->FOCUSREQ_SHINE; + shadow = theme_->FOCUSREQ_SHADOW; + label_->update(theme_->FOCUSREQ_BACKGROUND, + theme_->FOCUSREQ_TEXT, + shine, shadow, true, true); + } + else { + shine = theme_->TAB_SHINE_ACTIVE_NORMAL; + shadow = theme_->TAB_SHADOW_ACTIVE_NORMAL; + label_->update(theme_->TAB_BACKGROUND_ACTIVE_NORMAL, + theme_->TAB_TEXT_ACTIVE_NORMAL, + shine, shadow, true, true); + } + + if (client->mode() == Client::STICKY) { + Draw::drawStickyNotifier(window(), gc(), label_, + shine, shadow, + label_->textWidth()); + } + i++; + } + } +} + +void ClientBar::updateMenuButton() { + + // button stuff + if (!isButtonVisible_) { + return; + } + + label_->setText(""); + label_->setX(1); + label_->setWidth(monitor()->buttonWidth()); + if (isMenuButtonPressed_) { + Draw::drawMenuButton(window(), gc(), label_, + theme_->BUTTON_BACKGROUND_PRESSED, + theme_->BUTTON_SHINE_BORDER_PRESSED, + theme_->BUTTON_SHADOW_BORDER_PRESSED, + theme_->BUTTON_SHINE_FIGURE_PRESSED, + theme_->BUTTON_SHADOW_FIGURE_PRESSED); + } + else { + Draw::drawMenuButton(window(), gc(), label_, + theme_->BUTTON_BACKGROUND_NORMAL, + theme_->BUTTON_SHINE_BORDER_NORMAL, + theme_->BUTTON_SHADOW_BORDER_NORMAL, + theme_->BUTTON_SHINE_FIGURE_NORMAL, + theme_->BUTTON_SHADOW_FIGURE_NORMAL); + } +} + +void ClientBar::updateModeButton() { + + // button stuff + if (!isButtonVisible_) { + return; + } + + Workspace *workspace = monitor()->focused(); + + label_->setText(""); + label_->setX(width() - monitor()->buttonWidth() - 1); + label_->setWidth(monitor()->buttonWidth()); + if (isModeButtonPressed_) { + if (workspace->isFrameMode()) { + Draw::drawFloatButton(window(), gc(), label_, + theme_->BUTTON_BACKGROUND_PRESSED, + theme_->BUTTON_SHINE_BORDER_PRESSED, + theme_->BUTTON_SHADOW_BORDER_PRESSED, + theme_->BUTTON_SHINE_FIGURE_PRESSED, + theme_->BUTTON_SHADOW_FIGURE_PRESSED, + workspace->floatingClients()->size()); + } + else { + Draw::drawMaxButton(window(), gc(), label_, + theme_->BUTTON_BACKGROUND_PRESSED, + theme_->BUTTON_SHINE_BORDER_PRESSED, + theme_->BUTTON_SHADOW_BORDER_PRESSED, + theme_->BUTTON_SHINE_FIGURE_PRESSED, + theme_->BUTTON_SHADOW_FIGURE_PRESSED, + workspace->focusedFrame() && + workspace->focusedFrame()->size()); + } + } + else { + if (workspace->isFrameMode()) { + Draw::drawFloatButton(window(), gc(), label_, + theme_->BUTTON_BACKGROUND_NORMAL, + theme_->BUTTON_SHINE_BORDER_NORMAL, + theme_->BUTTON_SHADOW_BORDER_NORMAL, + theme_->BUTTON_SHINE_FIGURE_NORMAL, + theme_->BUTTON_SHADOW_FIGURE_NORMAL, + workspace->floatingClients()->size()); + } + else { + Draw::drawMaxButton(window(), gc(), label_, + theme_->BUTTON_BACKGROUND_NORMAL, + theme_->BUTTON_SHINE_BORDER_NORMAL, + theme_->BUTTON_SHADOW_BORDER_NORMAL, + theme_->BUTTON_SHINE_FIGURE_NORMAL, + theme_->BUTTON_SHADOW_FIGURE_NORMAL, + workspace->focusedFrame() && + workspace->focusedFrame()->size()); + } + } +} + +void ClientBar::updateClientInfo() { + + // client info stuff + Workspace *focusedWorkspace = monitor()->focused(); + Client *client = focusedWorkspace->topClient(); + unsigned int offsetX = isButtonVisible_ ? monitor()->buttonWidth() + 3 : 1; + unsigned int clientInfoWidth = width() - 2; + if (isButtonVisible_) { + clientInfoWidth -= (2 * monitor()->buttonWidth() + 4); + } + label_->setX(offsetX); + label_->setWidth(clientInfoWidth); + label_->setText(client ? client->name() : ""); + label_->update(theme_->LABEL_BACKGROUND_FOCUSSED, + theme_->LABEL_TEXT_FOCUSSED, + theme_->LABEL_SHINE_FOCUSSED, + theme_->LABEL_SHADOW_FOCUSSED, + true, true); + if (client->mode() == Client::STICKY) { + Draw::drawStickyNotifier(window(), gc(), label_, + theme_->LABEL_SHINE_FOCUSSED, + theme_->LABEL_SHADOW_FOCUSSED, + label_->textWidth()); + } +} + +void ClientBar::handleButtonRelease(XButtonEvent *event) { + + if ((event->window != window())) { + return; + } + + if (isModeButtonPressed_) { + isModeButtonPressed_ = false; + Workspace *ws = monitor()->focused(); + if ((event->button == Button1) && + Validators::instance()->validateToggleMode()) + { + ws->toggleMode(); + } + illuminate(); + } + else if (isMenuButtonPressed_) { + toggleMenuMode(); + } +} + +void ClientBar::toggleMenuMode() { + + if (menu_->isVisible()) { + menu_->hide(); + isMenuButtonPressed_ = false; + } + else { + menu_->show(); + } + illuminate(); +} + +void ClientBar::handleButtonPress(XButtonEvent *event) { + + if ((event->window != window())) { + return; + } + + XCORE->raise(window()); + + // TODO: make buttons customizable + if (event->button == Button1) { + invokeClickedThing(event->x); + } + else if (event->button == Button4) { + monitor()->focused()->cycleClientPrev(); + } + else if (event->button == Button5) { + monitor()->focused()->cycleClientNext(); + } +} + +void ClientBar::handleMotionNotify(XMotionEvent *event) { + + if (isModeButtonPressed_) { + isModeButtonPressed_ = false; + illuminate(); + } +} + +void ClientBar::invokeClickedThing(int xPosition) { + + if (isButtonVisible_) { + if (xPosition < (int)(monitor()->buttonWidth() + 1)) { + isMenuButtonPressed_ = true; + } + else if (xPosition > (int)(width() - monitor()->buttonWidth() - 2)) { + isModeButtonPressed_ = true; + } + illuminate(); + if (isModeButtonPressed_ || isMenuButtonPressed_) { + return; + } + } + + if (mode_ != PAGER) { + illuminate(); + return; + } + + Workspace *workspace = monitor()->focused(); + unsigned int clientsWidth = width() - 2; + if (isButtonVisible_) { + clientsWidth -= (2 * monitor()->buttonWidth() + 4); + xPosition -= (monitor()->buttonWidth() + 3); + } + else { + xPosition -= 1; + } + + CClient *clients = workspace->floatingClients(); + if (!clients->size()) { + return; + } + + unsigned int clientNum = xPosition / (clientsWidth / clients->size()); + unsigned i = 0; + for (LClient::iterator it = clients->begin(); it != clients->end(); it++) { + if (i == clientNum) { + workspace->focus(*it); + illuminate(); + return; + } + i++; + } +} + +Menu *ClientBar::menu() const { + return menu_; +} + +void ClientBar::setMode(ClientBar::Mode mode) { + mode_ = mode; +} + +ClientBar::Mode ClientBar::mode() const { + return mode_; +} diff --git a/clientbar.h b/clientbar.h @@ -0,0 +1,53 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: clientbar.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __CLIENTBAR_H +#define __CLIENTBAR_H + +#include "bar.h" + +class Menu; +class Monitor; + +/** + * Represents the floating app bar of WMI. + */ +class ClientBar : public Bar { + +public: + + enum Mode {PAGER, CLIENTINFO}; + + ClientBar(Monitor *monitor, Rectangle *rect); + + ~ClientBar(); + + virtual void illuminate(); + + virtual void handleMotionNotify(XMotionEvent *event); + virtual void handleButtonPress(XButtonEvent *event); + virtual void handleButtonRelease(XButtonEvent *event); + + void toggleMenuMode(); + void setMode(Mode mode); + Mode mode() const; + + Menu *menu() const; + +private: + + void updateClientInfo(); + void updateClientPager(); + void updateModeButton(); + void updateMenuButton(); + + void invokeClickedThing(int xPosition); + bool isModeButtonPressed_; + bool isMenuButtonPressed_; + Mode mode_; + Menu *menu_; +}; + +#endif // __CLIENTBAR_H diff --git a/config.h.in b/config.h.in @@ -0,0 +1,112 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if wmi is to be build with debug information. */ +#undef DEBUG + +/* Define if wmi is to be build with diamond box. */ +#undef DIAMOND_BOX + +/* Define to 1 if you have the <assert.h> header file. */ +#undef HAVE_ASSERT_H + +/* Define to 1 if you have the <ctype.h> header file. */ +#undef HAVE_CTYPE_H + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the <memory.h> header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the <regex.h> header file. */ +#undef HAVE_REGEX_H + +/* Define to 1 if you have the <stdint.h> header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the <stdio.h> header file. */ +#undef HAVE_STDIO_H + +/* Define to 1 if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the <sys/select.h> header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the <sys/wait.h> header file. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if you have the <time.h> header file. */ +#undef HAVE_TIME_H + +/* Define to 1 if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the <X11/cursorfont.h> header file. */ +#undef HAVE_X11_CURSORFONT_H + +/* Define to 1 if you have the <X11/keysym.h> header file. */ +#undef HAVE_X11_KEYSYM_H + +/* Define to 1 if you have the <X11/Xatom.h> header file. */ +#undef HAVE_X11_XATOM_H + +/* Define to 1 if you have the <X11/Xlib.h> header file. */ +#undef HAVE_X11_XLIB_H + +/* Define to 1 if you have the <X11/Xmd.h> header file. */ +#undef HAVE_X11_XMD_H + +/* Define to 1 if you have the <X11/Xproto.h> header file. */ +#undef HAVE_X11_XPROTO_H + +/* Define to 1 if you have the <X11/Xresource.h> header file. */ +#undef HAVE_X11_XRESOURCE_H + +/* Define to 1 if you have the <X11/Xutil.h> header file. */ +#undef HAVE_X11_XUTIL_H + +/* Define to 1 if you have the <X11/X.h> header file. */ +#undef HAVE_X11_X_H + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define if wmi is to be build with posix regex. */ +#undef POSIX_REGEX + +/* Define if wmi is to be build with slot support. */ +#undef SLOT_SUPPORT + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* antialias support */ +#undef XFT_SUPPORT + +/* Define to 1 if the X Window System is missing or not being used. */ +#undef X_DISPLAY_MISSING diff --git a/configure b/configure @@ -0,0 +1,8075 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.59. +# +# Copyright (C) 2003 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= + +ac_unique_file="src/main.cpp" +# Factoring default headers for most tests. +ac_includes_default="\ +#include <stdio.h> +#if HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#if HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#if STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# if HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include <memory.h> +# endif +# include <string.h> +#endif +#if HAVE_STRINGS_H +# include <strings.h> +#endif +#if HAVE_INTTYPES_H +# include <inttypes.h> +#else +# if HAVE_STDINT_H +# include <stdint.h> +# endif +#endif +#if HAVE_UNISTD_H +# include <unistd.h> +#endif" + +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO AMTAR install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CPP EGREP CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CXXCPP X_CFLAGS X_PRE_LIBS X_LIBS X_EXTRA_LIBS PKG_CONFIG LIBOBJS LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CPP_set=${CPP+set} +ac_env_CPP_value=$CPP +ac_cv_env_CPP_set=${CPP+set} +ac_cv_env_CPP_value=$CPP +ac_env_CXX_set=${CXX+set} +ac_env_CXX_value=$CXX +ac_cv_env_CXX_set=${CXX+set} +ac_cv_env_CXX_value=$CXX +ac_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_env_CXXFLAGS_value=$CXXFLAGS +ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_cv_env_CXXFLAGS_value=$CXXFLAGS +ac_env_CXXCPP_set=${CXXCPP+set} +ac_env_CXXCPP_value=$CXXCPP +ac_cv_env_CXXCPP_set=${CXXCPP+set} +ac_cv_env_CXXCPP_value=$CXXCPP + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +X features: + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-x use the X Window System + --with-debug enable debug support + --with-posix-regex enable posix regex + --without-diamond disable diamond box whily move/resize + --without-slot disable slot + --with-xft-prefix=path Prefix where Xft is installed (optional) + --with-pkg-exec-prefix=path Exec prefix where pkg-config is installed (optional) + --without-xft disable Xft support + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a + nonstandard directory <lib dir> + CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have + headers in a nonstandard directory <include dir> + CPP C preprocessor + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CXXCPP C++ preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF + +Copyright (C) 2003 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.59. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_sep= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + +am__api_version="1.8" +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 +echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} + { (exit 1); exit 1; }; } +fi +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo "$as_me:$LINENO: checking whether build environment is sane" >&5 +echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6 +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&5 +echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&2;} + { (exit 1); exit 1; }; } + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! +Check your system clock" >&5 +echo "$as_me: error: newly created file is older than distributed files! +Check your system clock" >&2;} + { (exit 1); exit 1; }; } +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +test "$program_prefix" != NONE && + program_transform_name="s,^,$program_prefix,;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$,$program_suffix,;$program_transform_name" +# Double any \ or $. echo might interpret backslashes. +# By default was `s,x,x', remove it if useless. +cat <<\_ACEOF >conftest.sed +s/[\\$]/&&/g;s/;s,x,x,$// +_ACEOF +program_transform_name=`echo $program_transform_name | sed -f conftest.sed` +rm conftest.sed + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 +echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} +fi + +if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + # Keeping the `.' argument allows $(mkdir_p) to be used without + # argument. Indeed, we sometimes output rules like + # $(mkdir_p) $(somedir) + # where $(somedir) is conditionally defined. + # (`test -n '$(somedir)' && $(mkdir_p) $(somedir)' is a more + # expensive solution, as it forces Make to start a sub-shell.) + mkdir_p='mkdir -p -- .' +else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + for d in ./-p ./--version; + do + test -d $d && rmdir $d + done + # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. + if test -f "$ac_aux_dir/mkinstalldirs"; then + mkdir_p='$(mkinstalldirs)' + else + mkdir_p='$(install_sh) -d' + fi +fi + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_AWK+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + echo "$as_me:$LINENO: result: $AWK" >&5 +echo "${ECHO_T}$AWK" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$AWK" && break +done + +echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +all: + @echo 'ac_maketemp="$(MAKE)"' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftest.make +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + SET_MAKE= +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && + test -f $srcdir/config.status; then + { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 +echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} + { (exit 1); exit 1; }; } +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE=wmi + VERSION=10 + + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + + +AMTAR=${AMTAR-"${am_missing_run}tar"} + +install_sh=${install_sh-"$am_aux_dir/install-sh"} + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + echo "$as_me:$LINENO: result: $STRIP" >&5 +echo "${ECHO_T}$STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 +echo "${ECHO_T}$ac_ct_STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + STRIP=$ac_ct_STRIP +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. + + + +# next release: AM_INIT_AUTOMAKE(wmi, 10, anselmg@t-online.de) + ac_config_headers="$ac_config_headers config.h" + +# following two AC_CHECK_HEADERS have been provided by Markus Lindorfer +# for Solaris compatibility +DEPDIR="${am__leading_dot}deps" + + ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo done +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 +echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6 +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi + + +echo "$as_me:$LINENO: result: $_am_result" >&5 +echo "${ECHO_T}$_am_result" >&6 +rm -f confinc confmf + +# Check whether --enable-dependency-tracking or --disable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then + enableval="$enable_dependency_tracking" + +fi; +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi + + +if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 + (eval $ac_compiler --version </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 + (eval $ac_compiler -v </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 + (eval $ac_compiler -V </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cc_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std1 is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std1. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include <stdlib.h> +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +depcc="$CC" am_compiler_list= + +echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 +echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 +if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 +echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6 +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + + +if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6 +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6 +if test "${ac_cv_prog_egrep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 +echo "${ECHO_T}$ac_cv_prog_egrep" >&6 + EGREP=$ac_cv_prog_egrep + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ctype.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + + + + + + + + + + + + + + +for ac_header in assert.h ctype.h stdio.h stdlib.h sys/select.h sys/stat.h sys/types.h sys/wait.h time.h unistd.h X11/cursorfont.h X11/keysym.h X11/Xatom.h X11/X.h X11/Xlib.h X11/Xmd.h X11/Xproto.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +for ac_header in X11/Xresource.h X11/Xutil.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef HAVE_X11_XLIB_H + # include <X11/Xlib.h> + #endif + + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CXX" && break +done +test -n "$ac_ct_CXX" || ac_ct_CXX="g++" + + CXX=$ac_ct_CXX +fi + + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 + (eval $ac_compiler --version </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 + (eval $ac_compiler -v </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 + (eval $ac_compiler -V </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +CXXFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cxx_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include <stdlib.h> +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +depcc="$CXX" am_compiler_list= + +echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 +echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 +if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5 +echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6 +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + + +if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then + am__fastdepCXX_TRUE= + am__fastdepCXX_FALSE='#' +else + am__fastdepCXX_TRUE='#' + am__fastdepCXX_FALSE= +fi + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 +echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6 +if test -z "$CXXCPP"; then + if test "${ac_cv_prog_CXXCPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +echo "$as_me:$LINENO: result: $CXXCPP" >&5 +echo "${ECHO_T}$CXXCPP" >&6 +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ctype.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + + +# check X headers and libs +echo "$as_me:$LINENO: checking for X" >&5 +echo $ECHO_N "checking for X... $ECHO_C" >&6 + + +# Check whether --with-x or --without-x was given. +if test "${with_x+set}" = set; then + withval="$with_x" + +fi; +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then + # Both variables are already set. + have_x=yes + else + if test "${ac_cv_have_x+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # One or both of the vars are not set, and there is no cached value. +ac_x_includes=no ac_x_libraries=no +rm -fr conftest.dir +if mkdir conftest.dir; then + cd conftest.dir + # Make sure to not put "make" in the Imakefile rules, since we grep it out. + cat >Imakefile <<'_ACEOF' +acfindx: + @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"' +_ACEOF + if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering...", which would confuse us. + eval `${MAKE-make} acfindx 2>/dev/null | grep -v make` + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl; do + if test ! -f $ac_im_usrlibdir/libX11.$ac_extension && + test -f $ac_im_libdir/libX11.$ac_extension; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case $ac_im_incroot in + /usr/include) ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; + esac + case $ac_im_usrlibdir in + /usr/lib | /lib) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; + esac + fi + cd .. + rm -fr conftest.dir +fi + +# Standard set of common directories for X headers. +# Check X11 before X11Rn because it is often a symlink to the current release. +ac_x_header_dirs=' +/usr/X11/include +/usr/X11R6/include +/usr/X11R5/include +/usr/X11R4/include + +/usr/include/X11 +/usr/include/X11R6 +/usr/include/X11R5 +/usr/include/X11R4 + +/usr/local/X11/include +/usr/local/X11R6/include +/usr/local/X11R5/include +/usr/local/X11R4/include + +/usr/local/include/X11 +/usr/local/include/X11R6 +/usr/local/include/X11R5 +/usr/local/include/X11R4 + +/usr/X386/include +/usr/x386/include +/usr/XFree86/include/X11 + +/usr/include +/usr/local/include +/usr/unsupported/include +/usr/athena/include +/usr/local/x11r5/include +/usr/lpp/Xamples/include + +/usr/openwin/include +/usr/openwin/share/include' + +if test "$ac_x_includes" = no; then + # Guess where to find include files, by looking for Intrinsic.h. + # First, try using that file with no special directory specified. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <X11/Intrinsic.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # We can compile using X headers with no special include directory. +ac_x_includes= +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + for ac_dir in $ac_x_header_dirs; do + if test -r "$ac_dir/X11/Intrinsic.h"; then + ac_x_includes=$ac_dir + break + fi +done +fi +rm -f conftest.err conftest.$ac_ext +fi # $ac_x_includes = no + +if test "$ac_x_libraries" = no; then + # Check for the libraries. + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS=$LIBS + LIBS="-lXt $LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <X11/Intrinsic.h> +int +main () +{ +XtMalloc (0) + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + LIBS=$ac_save_LIBS +# We can link X programs with no special library path. +ac_x_libraries= +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +LIBS=$ac_save_LIBS +for ac_dir in `echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` +do + # Don't even attempt the hair of trying to link an X program! + for ac_extension in a so sl; do + if test -r $ac_dir/libXt.$ac_extension; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi # $ac_x_libraries = no + +if test "$ac_x_includes" = no || test "$ac_x_libraries" = no; then + # Didn't find X anywhere. Cache the known absence of X. + ac_cv_have_x="have_x=no" +else + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes \ + ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries" +fi +fi + + fi + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + echo "$as_me:$LINENO: result: $have_x" >&5 +echo "${ECHO_T}$have_x" >&6 + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes \ + ac_x_includes=$x_includes ac_x_libraries=$x_libraries" + echo "$as_me:$LINENO: result: libraries $x_libraries, headers $x_includes" >&5 +echo "${ECHO_T}libraries $x_libraries, headers $x_includes" >&6 +fi + +if test "$no_x" = yes; then + # Not all programs may use this symbol, but it does not hurt to define it. + +cat >>confdefs.h <<\_ACEOF +#define X_DISPLAY_MISSING 1 +_ACEOF + + X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= +else + if test -n "$x_includes"; then + X_CFLAGS="$X_CFLAGS -I$x_includes" + fi + + # It would also be nice to do this for all -L options, not just this one. + if test -n "$x_libraries"; then + X_LIBS="$X_LIBS -L$x_libraries" + # For Solaris; some versions of Sun CC require a space after -R and + # others require no space. Words are not sufficient . . . . + case `(uname -sr) 2>/dev/null` in + "SunOS 5"*) + echo "$as_me:$LINENO: checking whether -R must be followed by a space" >&5 +echo $ECHO_N "checking whether -R must be followed by a space... $ECHO_C" >&6 + ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_R_nospace=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_R_nospace=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test $ac_R_nospace = yes; then + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + X_LIBS="$X_LIBS -R$x_libraries" + else + LIBS="$ac_xsave_LIBS -R $x_libraries" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_R_space=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_R_space=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test $ac_R_space = yes; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + X_LIBS="$X_LIBS -R $x_libraries" + else + echo "$as_me:$LINENO: result: neither works" >&5 +echo "${ECHO_T}neither works" >&6 + fi + fi + LIBS=$ac_xsave_LIBS + esac + fi + + # Check for system-dependent libraries X programs must link with. + # Do this before checking for the system-independent R6 libraries + # (-lICE), since we may need -lsocket or whatever for X linking. + + if test "$ISC" = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" + else + # Martyn Johnson says this is needed for Ultrix, if the X + # libraries were built with DECnet support. And Karl Berry says + # the Alpha needs dnet_stub (dnet does not exist). + ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XOpenDisplay (); +int +main () +{ +XOpenDisplay (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet" >&5 +echo $ECHO_N "checking for dnet_ntoa in -ldnet... $ECHO_C" >&6 +if test "${ac_cv_lib_dnet_dnet_ntoa+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldnet $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dnet_ntoa (); +int +main () +{ +dnet_ntoa (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dnet_dnet_ntoa=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dnet_dnet_ntoa=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_dnet_ntoa" >&5 +echo "${ECHO_T}$ac_cv_lib_dnet_dnet_ntoa" >&6 +if test $ac_cv_lib_dnet_dnet_ntoa = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" +fi + + if test $ac_cv_lib_dnet_dnet_ntoa = no; then + echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet_stub" >&5 +echo $ECHO_N "checking for dnet_ntoa in -ldnet_stub... $ECHO_C" >&6 +if test "${ac_cv_lib_dnet_stub_dnet_ntoa+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldnet_stub $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dnet_ntoa (); +int +main () +{ +dnet_ntoa (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dnet_stub_dnet_ntoa=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dnet_stub_dnet_ntoa=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5 +echo "${ECHO_T}$ac_cv_lib_dnet_stub_dnet_ntoa" >&6 +if test $ac_cv_lib_dnet_stub_dnet_ntoa = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" +fi + + fi +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$ac_xsave_LIBS" + + # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, + # to get the SysV transport functions. + # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4) + # needs -lnsl. + # The nsl library prevents programs from opening the X display + # on Irix 5.2, according to T.E. Dickey. + # The functions gethostbyname, getservbyname, and inet_addr are + # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking. + echo "$as_me:$LINENO: checking for gethostbyname" >&5 +echo $ECHO_N "checking for gethostbyname... $ECHO_C" >&6 +if test "${ac_cv_func_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define gethostbyname to an innocuous variant, in case <limits.h> declares gethostbyname. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define gethostbyname innocuous_gethostbyname + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char gethostbyname (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef gethostbyname + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_gethostbyname) || defined (__stub___gethostbyname) +choke me +#else +char (*f) () = gethostbyname; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != gethostbyname; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_func_gethostbyname" >&6 + + if test $ac_cv_func_gethostbyname = no; then + echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5 +echo $ECHO_N "checking for gethostbyname in -lnsl... $ECHO_C" >&6 +if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +int +main () +{ +gethostbyname (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_nsl_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_nsl_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_lib_nsl_gethostbyname" >&6 +if test $ac_cv_lib_nsl_gethostbyname = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" +fi + + if test $ac_cv_lib_nsl_gethostbyname = no; then + echo "$as_me:$LINENO: checking for gethostbyname in -lbsd" >&5 +echo $ECHO_N "checking for gethostbyname in -lbsd... $ECHO_C" >&6 +if test "${ac_cv_lib_bsd_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbsd $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +int +main () +{ +gethostbyname (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_bsd_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_bsd_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_bsd_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_lib_bsd_gethostbyname" >&6 +if test $ac_cv_lib_bsd_gethostbyname = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" +fi + + fi + fi + + # lieder@skyler.mavd.honeywell.com says without -lsocket, + # socket/setsockopt and other routines are undefined under SCO ODT + # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary + # on later versions), says Simon Leinen: it contains gethostby* + # variants that don't use the name server (or something). -lsocket + # must be given before -lnsl if both are needed. We assume that + # if connect needs -lnsl, so does gethostbyname. + echo "$as_me:$LINENO: checking for connect" >&5 +echo $ECHO_N "checking for connect... $ECHO_C" >&6 +if test "${ac_cv_func_connect+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define connect to an innocuous variant, in case <limits.h> declares connect. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define connect innocuous_connect + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char connect (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef connect + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char connect (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_connect) || defined (__stub___connect) +choke me +#else +char (*f) () = connect; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != connect; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_connect=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_connect=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_connect" >&5 +echo "${ECHO_T}$ac_cv_func_connect" >&6 + + if test $ac_cv_func_connect = no; then + echo "$as_me:$LINENO: checking for connect in -lsocket" >&5 +echo $ECHO_N "checking for connect in -lsocket... $ECHO_C" >&6 +if test "${ac_cv_lib_socket_connect+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $X_EXTRA_LIBS $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char connect (); +int +main () +{ +connect (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_socket_connect=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_socket_connect=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_socket_connect" >&5 +echo "${ECHO_T}$ac_cv_lib_socket_connect" >&6 +if test $ac_cv_lib_socket_connect = yes; then + X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" +fi + + fi + + # Guillermo Gomez says -lposix is necessary on A/UX. + echo "$as_me:$LINENO: checking for remove" >&5 +echo $ECHO_N "checking for remove... $ECHO_C" >&6 +if test "${ac_cv_func_remove+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define remove to an innocuous variant, in case <limits.h> declares remove. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define remove innocuous_remove + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char remove (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef remove + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char remove (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_remove) || defined (__stub___remove) +choke me +#else +char (*f) () = remove; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != remove; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_remove=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_remove=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_remove" >&5 +echo "${ECHO_T}$ac_cv_func_remove" >&6 + + if test $ac_cv_func_remove = no; then + echo "$as_me:$LINENO: checking for remove in -lposix" >&5 +echo $ECHO_N "checking for remove in -lposix... $ECHO_C" >&6 +if test "${ac_cv_lib_posix_remove+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lposix $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char remove (); +int +main () +{ +remove (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_posix_remove=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_posix_remove=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_posix_remove" >&5 +echo "${ECHO_T}$ac_cv_lib_posix_remove" >&6 +if test $ac_cv_lib_posix_remove = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" +fi + + fi + + # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. + echo "$as_me:$LINENO: checking for shmat" >&5 +echo $ECHO_N "checking for shmat... $ECHO_C" >&6 +if test "${ac_cv_func_shmat+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define shmat to an innocuous variant, in case <limits.h> declares shmat. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define shmat innocuous_shmat + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char shmat (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef shmat + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shmat (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_shmat) || defined (__stub___shmat) +choke me +#else +char (*f) () = shmat; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != shmat; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_shmat=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_shmat=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_shmat" >&5 +echo "${ECHO_T}$ac_cv_func_shmat" >&6 + + if test $ac_cv_func_shmat = no; then + echo "$as_me:$LINENO: checking for shmat in -lipc" >&5 +echo $ECHO_N "checking for shmat in -lipc... $ECHO_C" >&6 +if test "${ac_cv_lib_ipc_shmat+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lipc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shmat (); +int +main () +{ +shmat (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_ipc_shmat=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_ipc_shmat=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_ipc_shmat" >&5 +echo "${ECHO_T}$ac_cv_lib_ipc_shmat" >&6 +if test $ac_cv_lib_ipc_shmat = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" +fi + + fi + fi + + # Check for libraries that X11R6 Xt/Xaw programs need. + ac_save_LDFLAGS=$LDFLAGS + test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" + # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to + # check for ICE first), but we must link in the order -lSM -lICE or + # we get undefined symbols. So assume we have SM if we have ICE. + # These have to be linked with before -lX11, unlike the other + # libraries we check for below, so use a different variable. + # John Interrante, Karl Berry + echo "$as_me:$LINENO: checking for IceConnectionNumber in -lICE" >&5 +echo $ECHO_N "checking for IceConnectionNumber in -lICE... $ECHO_C" >&6 +if test "${ac_cv_lib_ICE_IceConnectionNumber+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lICE $X_EXTRA_LIBS $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char IceConnectionNumber (); +int +main () +{ +IceConnectionNumber (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_ICE_IceConnectionNumber=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_ICE_IceConnectionNumber=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5 +echo "${ECHO_T}$ac_cv_lib_ICE_IceConnectionNumber" >&6 +if test $ac_cv_lib_ICE_IceConnectionNumber = yes; then + X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" +fi + + LDFLAGS=$ac_save_LDFLAGS + +fi + + +test x$no_x = "xyes" && { { echo "$as_me:$LINENO: error: WMI requires the X Window + System libraries and headers." >&5 +echo "$as_me: error: WMI requires the X Window + System libraries and headers." >&2;} + { (exit 1); exit 1; }; } + +test x$x_includes = "x" && x_includes="/usr/include" +test x$x_libraries = "x" && x_libraries="/usr/lib" + +CFLAGS="" +CXXFLAGS="-Os $CXXFLAGS $X_CFLAGS" +LIBS="$LIBS $X_LIBS $X_PRE_LIBS" + +# Check for required functions in -lX11 +echo "$as_me:$LINENO: checking for XOpenDisplay in -lX11" >&5 +echo $ECHO_N "checking for XOpenDisplay in -lX11... $ECHO_C" >&6 +if test "${ac_cv_lib_X11_XOpenDisplay+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XOpenDisplay (); +int +main () +{ +XOpenDisplay (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_X11_XOpenDisplay=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_X11_XOpenDisplay=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_X11_XOpenDisplay" >&5 +echo "${ECHO_T}$ac_cv_lib_X11_XOpenDisplay" >&6 +if test $ac_cv_lib_X11_XOpenDisplay = yes; then + LIBS="$LIBS -lX11" +else + { { echo "$as_me:$LINENO: error: Could not find XOpenDisplay in -lX11." >&5 +echo "$as_me: error: Could not find XOpenDisplay in -lX11." >&2;} + { (exit 1); exit 1; }; } + +fi + + +LIBS="$LIBS $X_EXTRA_LIBS" + +# Add extra flags if in debug mode + +# Check whether --with-debug or --without-debug was given. +if test "${with_debug+set}" = set; then + withval="$with_debug" + +fi; + +if test "x$with_debug" != "x"; then + +cat >>confdefs.h <<\_ACEOF +#define DEBUG 1 +_ACEOF + + CXXFLAGS="$X_CFLAGS -g -ggdb -O0 -Wall -Wpointer-arith -Wcast-align -Winline" +fi + +# Add extra flags for posix regex feature + +# Check whether --with- or --without- was given. +if test "${with_+set}" = set; then + withval="$with_" + +fi; + +if test "x$with_posix_regex" != "x"; then + +for ac_header in regex.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +cat >>confdefs.h <<\_ACEOF +#define POSIX_REGEX 1 +_ACEOF + +fi + +# Add extra flags for posix regex feature + +# Check whether --with- or --without- was given. +if test "${with_+set}" = set; then + withval="$with_" + +fi; + +if test "x$with_posix_regex" != "x"; then + +for ac_header in regex.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +cat >>confdefs.h <<\_ACEOF +#define POSIX_REGEX 1 +_ACEOF + +fi + + +# Add extra flags for diamond box + +# Check whether --with-diamond or --without-diamond was given. +if test "${with_diamond+set}" = set; then + withval="$with_diamond" + +fi; + +if test "x$with_diamond" = "x"; then + +cat >>confdefs.h <<\_ACEOF +#define DIAMOND_BOX 1 +_ACEOF + +fi + +# Add extra flags for slot + +# Check whether --with-slot or --without-slot was given. +if test "${with_slot+set}" = set; then + withval="$with_slot" + +fi; + +if test "x$with_slot" = "x"; then + +cat >>confdefs.h <<\_ACEOF +#define SLOT_SUPPORT 1 +_ACEOF + +fi + +# Add extra flags for Xft mode checking +# Xft support, we ignore UTF-8 since WMI is not ready for i18n +TMPLIBS=$LIBS +TMPCXXFLAGS=$CXXFLAGS +echo "$as_me:$LINENO: checking whether to have Xft support" >&5 +echo $ECHO_N "checking whether to have Xft support... $ECHO_C" >&6 + + +# Check whether --with-xft-prefix or --without-xft-prefix was given. +if test "${with_xft_prefix+set}" = set; then + withval="$with_xft_prefix" + xft_prefix="$withval" +else + xft_prefix="" +fi; + +# Check whether --with-pkg-exec-prefix or --without-pkg-exec-prefix was given. +if test "${with_pkg_exec_prefix+set}" = set; then + withval="$with_pkg_exec_prefix" + pkg_exec_prefix="$withval" +else + pkg_exec_prefix="" +fi; + + + if test x$pkg_exec_prefix != x ; then + xft_args="$xft_args --exec-prefix=$pkg_exec_prefix" + if test x${PKG_CONFIG+set} != xset ; then + PKG_CONFIG=$pkg_exec_prefix/bin/pkg-config + fi +fi + +if test x$xft_prefix != x ; then + xft_args="$xft_args --prefix=$xft_prefix" + if test x${PKG_CONFIG+set} != xset ; then + PKG_CONFIG=$xft_prefix/bin/pkg-config + fi +fi + +# Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_PKG_CONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no" + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG + +if test -n "$PKG_CONFIG"; then + echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5 +echo "${ECHO_T}$PKG_CONFIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test "x$PKG_CONFIG" = "xno" ; then + # xft2 failed: try xft1 + + echo "$as_me:$LINENO: checking for XftFontOpen in -lXft" >&5 +echo $ECHO_N "checking for XftFontOpen in -lXft... $ECHO_C" >&6 +if test "${ac_cv_lib_Xft_XftFontOpen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXft $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XftFontOpen (); +int +main () +{ +XftFontOpen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_Xft_XftFontOpen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_Xft_XftFontOpen=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_Xft_XftFontOpen" >&5 +echo "${ECHO_T}$ac_cv_lib_Xft_XftFontOpen" >&6 +if test $ac_cv_lib_Xft_XftFontOpen = yes; then + XFT_LIBS="-lXft" + XFT=true +else + XFT=false + + echo "$as_me:$LINENO: result: Cant find Xft libraries! Disabling Xft" >&5 +echo "${ECHO_T}Cant find Xft libraries! Disabling Xft" >&6 + +fi + + + +else + XFT_CFLAGS=`$PKG_CONFIG $xftconf_args --cflags xft` + XFT_LIBS=`$PKG_CONFIG $xftconf_args --libs xft` + XFT=true +fi + + + +CXXFLAGS="$CXXFLAGS $XFT_CFLAGS" +LIBS="$LIBS $XFT_LIBS" + + + +XFT_LINK=false + +if test "x$XFT" = "xtrue" ; then + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #include <X11/Xft/Xft.h> + +int +main () +{ + XftFontClose(0, 0); return 1; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + XFT_LINK=true + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + +# Add extra flags for Xft feature + +# Check whether --with-xft or --without-xft was given. +if test "${with_xft+set}" = set; then + withval="$with_xft" + +fi; + +if test "x$with_xft" != "x"; then +#restore old values + LIBS=$TMPLIBS + CXXFLAGS=$TMPCXXFLAGS +else + if test "x$XFT_LINK" = "xtrue" ; then + +cat >>confdefs.h <<\_ACEOF +#define XFT_SUPPORT 1 +_ACEOF + + fi +fi + +LDFLAGS="$LDFLAGS $LIBS" + +# print summary +echo "$as_me:$LINENO: result: " >&5 +echo "${ECHO_T}" >&6 +echo "$as_me:$LINENO: result: $PACKAGE version $VERSION configured successfully." >&5 +echo "${ECHO_T} $PACKAGE version $VERSION configured successfully." >&6 +echo "$as_me:$LINENO: result: " >&5 +echo "${ECHO_T}" >&6 +echo "$as_me:$LINENO: result: Using '$prefix' for installation." >&5 +echo "${ECHO_T}Using '$prefix' for installation." >&6 +echo "$as_me:$LINENO: result: Using '$CXX' for C++ compiler." >&5 +echo "${ECHO_T}Using '$CXX' for C++ compiler." >&6 +echo "$as_me:$LINENO: result: Building with '$CXXFLAGS' for C++ compiler flags." >&5 +echo "${ECHO_T}Building with '$CXXFLAGS' for C++ compiler flags." >&6 +echo "$as_me:$LINENO: result: Building with '$LDFLAGS' for linker flags." >&5 +echo "${ECHO_T}Building with '$LDFLAGS' for linker flags." >&6 +echo "$as_me:$LINENO: result: " >&5 +echo "${ECHO_T}" >&6 + + ac_config_files="$ac_config_files Makefile version.h src/Makefile man/Makefile" +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by $as_me, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to <bug-autoconf@gnu.org>." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.59, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2003 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +INSTALL="$INSTALL" +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# +# INIT-COMMANDS section. +# + +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + +_ACEOF + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "version.h" ) CONFIG_FILES="$CONFIG_FILES version.h" ;; + "src/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "man/Makefile" ) CONFIG_FILES="$CONFIG_FILES man/Makefile" ;; + "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@CYGPATH_W@,$CYGPATH_W,;t t +s,@PACKAGE@,$PACKAGE,;t t +s,@VERSION@,$VERSION,;t t +s,@ACLOCAL@,$ACLOCAL,;t t +s,@AUTOCONF@,$AUTOCONF,;t t +s,@AUTOMAKE@,$AUTOMAKE,;t t +s,@AUTOHEADER@,$AUTOHEADER,;t t +s,@MAKEINFO@,$MAKEINFO,;t t +s,@AMTAR@,$AMTAR,;t t +s,@install_sh@,$install_sh,;t t +s,@STRIP@,$STRIP,;t t +s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t +s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t +s,@mkdir_p@,$mkdir_p,;t t +s,@AWK@,$AWK,;t t +s,@SET_MAKE@,$SET_MAKE,;t t +s,@am__leading_dot@,$am__leading_dot,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@DEPDIR@,$DEPDIR,;t t +s,@am__include@,$am__include,;t t +s,@am__quote@,$am__quote,;t t +s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t +s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t +s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t +s,@CCDEPMODE@,$CCDEPMODE,;t t +s,@am__fastdepCC_TRUE@,$am__fastdepCC_TRUE,;t t +s,@am__fastdepCC_FALSE@,$am__fastdepCC_FALSE,;t t +s,@CPP@,$CPP,;t t +s,@EGREP@,$EGREP,;t t +s,@CXX@,$CXX,;t t +s,@CXXFLAGS@,$CXXFLAGS,;t t +s,@ac_ct_CXX@,$ac_ct_CXX,;t t +s,@CXXDEPMODE@,$CXXDEPMODE,;t t +s,@am__fastdepCXX_TRUE@,$am__fastdepCXX_TRUE,;t t +s,@am__fastdepCXX_FALSE@,$am__fastdepCXX_FALSE,;t t +s,@CXXCPP@,$CXXCPP,;t t +s,@X_CFLAGS@,$X_CFLAGS,;t t +s,@X_PRE_LIBS@,$X_PRE_LIBS,;t t +s,@X_LIBS@,$X_LIBS,;t t +s,@X_EXTRA_LIBS@,$X_EXTRA_LIBS,;t t +s,@PKG_CONFIG@,$PKG_CONFIG,;t t +s,@LIBOBJS@,$LIBOBJS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_HEADER section. +# + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='[ ].*$,\1#\2' +ac_dC=' ' +ac_dD=',;t' +# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='$,\1#\2define\3' +ac_uC=' ' +ac_uD=',;t' + +for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + # Do quote $f, to prevent DOS paths from being IFS'd. + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } + # Remove the trailing spaces. + sed 's/[ ]*$//' $ac_file_inputs >$tmp/in + +_ACEOF + +# Transform confdefs.h into two sed scripts, `conftest.defines' and +# `conftest.undefs', that substitutes the proper values into +# config.h.in to produce config.h. The first handles `#define' +# templates, and the second `#undef' templates. +# And first: Protect against being on the right side of a sed subst in +# config.status. Protect against being in an unquoted here document +# in config.status. +rm -f conftest.defines conftest.undefs +# Using a here document instead of a string reduces the quoting nightmare. +# Putting comments in sed scripts is not portable. +# +# `end' is used to avoid that the second main sed command (meant for +# 0-ary CPP macros) applies to n-ary macro definitions. +# See the Autoconf documentation for `clear'. +cat >confdef2sed.sed <<\_ACEOF +s/[\\&,]/\\&/g +s,[\\$`],\\&,g +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp +t end +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp +: end +_ACEOF +# If some macros were called several times there might be several times +# the same #defines, which is useless. Nevertheless, we may not want to +# sort them, since we want the *last* AC-DEFINE to be honored. +uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines +sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs +rm -f confdef2sed.sed + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >>conftest.undefs <<\_ACEOF +s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, +_ACEOF + +# Break up conftest.defines because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS +echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS +echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS +echo ' :' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.defines >/dev/null +do + # Write a limited-size here document to $tmp/defines.sed. + echo ' cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS + # Speed up: don't consider the non `#define' lines. + echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/defines.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines +echo ' fi # grep' >>$CONFIG_STATUS +echo >>$CONFIG_STATUS + +# Break up conftest.undefs because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #undef templates' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.undefs >/dev/null +do + # Write a limited-size here document to $tmp/undefs.sed. + echo ' cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS + # Speed up: don't consider the non `#undef' + echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/undefs.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail + rm -f conftest.undefs + mv conftest.tail conftest.undefs +done +rm -f conftest.undefs + +cat >>$CONFIG_STATUS <<\_ACEOF + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + echo "/* Generated by configure. */" >$tmp/config.h + else + echo "/* $ac_file. Generated by configure. */" >$tmp/config.h + fi + cat $tmp/in >>$tmp/config.h + rm -f $tmp/in + if test x"$ac_file" != x-; then + if diff $ac_file $tmp/config.h >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + rm -f $ac_file + mv $tmp/config.h $ac_file + fi + else + cat $tmp/config.h + rm -f $tmp/config.h + fi +# Compute $ac_file's index in $config_headers. +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $ac_file | $ac_file:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $ac_file" >`(dirname $ac_file) 2>/dev/null || +$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X$ac_file : 'X\(//\)[^/]' \| \ + X$ac_file : 'X\(//\)$' \| \ + X$ac_file : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X$ac_file | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'`/stamp-h$_am_stamp_count +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_COMMANDS section. +# +for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue + ac_dest=`echo "$ac_file" | sed 's,:.*,,'` + ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_dir=`(dirname "$ac_dest") 2>/dev/null || +$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_dest" : 'X\(//\)[^/]' \| \ + X"$ac_dest" : 'X\(//\)$' \| \ + X"$ac_dest" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_dest" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 +echo "$as_me: executing $ac_dest commands" >&6;} + case $ac_dest in + depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # So let's grep whole file. + if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then + dirpart=`(dirname "$mf") 2>/dev/null || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + else + continue + fi + grep '^DEP_FILES *= *[^ #]' < "$mf" > /dev/null || continue + # Extract the definition of DEP_FILES from the Makefile without + # running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR" + # We invoke sed twice because it is the simplest approach to + # changing $(DEPDIR) to its actual value in the expansion. + for file in `sed -n ' + /^DEP_FILES = .*\\\\$/ { + s/^DEP_FILES = // + :loop + s/\\\\$// + p + n + /\\\\$/ b loop + p + } + /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`(dirname "$file") 2>/dev/null || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p $dirpart/$fdir + else + as_dir=$dirpart/$fdir + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory $dirpart/$fdir" >&5 +echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;} + { (exit 1); exit 1; }; }; } + + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done + ;; + esac +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + diff --git a/configure.ac b/configure.ac @@ -0,0 +1,130 @@ +AC_INIT(src/main.cpp) +AC_PREREQ(2.52) +AM_INIT_AUTOMAKE(wmi, 10, anselmg@t-online.de) +# next release: AM_INIT_AUTOMAKE(wmi, 10, anselmg@t-online.de) +AM_CONFIG_HEADER(config.h) +# following two AC_CHECK_HEADERS have been provided by Markus Lindorfer +# for Solaris compatibility +AC_CHECK_HEADERS([assert.h ctype.h stdio.h stdlib.h sys/select.h sys/stat.h sys/types.h sys/wait.h time.h unistd.h X11/cursorfont.h X11/keysym.h X11/Xatom.h X11/X.h X11/Xlib.h X11/Xmd.h X11/Xproto.h]) +AC_CHECK_HEADERS([X11/Xresource.h X11/Xutil.h],[],[], +[#ifdef HAVE_X11_XLIB_H + # include <X11/Xlib.h> + #endif +]) + +AC_LANG_CPLUSPLUS + +AC_PROG_CXX +AC_PROG_INSTALL +AC_HEADER_STDC + +# check X headers and libs +AC_PATH_X +AC_PATH_XTRA + +test x$no_x = "xyes" && AC_MSG_ERROR([WMI requires the X Window + System libraries and headers.]) + +test x$x_includes = "x" && x_includes="/usr/include" +test x$x_libraries = "x" && x_libraries="/usr/lib" + +CFLAGS="" +CXXFLAGS="-Os $CXXFLAGS $X_CFLAGS" +LIBS="$LIBS $X_LIBS $X_PRE_LIBS" + +# Check for required functions in -lX11 +AC_CHECK_LIB(X11, XOpenDisplay, + LIBS="$LIBS -lX11", + AC_MSG_ERROR([Could not find XOpenDisplay in -lX11.]) +) + +LIBS="$LIBS $X_EXTRA_LIBS" + +# Add extra flags if in debug mode +AC_ARG_WITH(debug, [ --with-debug enable debug support]) + +if test "x$with_debug" != "x"; then + AC_DEFINE(DEBUG, 1, [Define if wmi is to be build with debug information.]) + CXXFLAGS="$X_CFLAGS -g -ggdb -O0 -Wall -Wpointer-arith -Wcast-align -Winline" +fi + +# Add extra flags for posix regex feature +AC_ARG_WITH(, [ --with-posix-regex enable posix regex]) + +if test "x$with_posix_regex" != "x"; then + AC_CHECK_HEADERS([regex.h]) + AC_DEFINE(POSIX_REGEX, 1, [Define if wmi is to be build with posix + regex.]) +fi + +# Add extra flags for posix regex feature +AC_ARG_WITH(, [ --with-posix-regex enable posix regex]) + +if test "x$with_posix_regex" != "x"; then + AC_CHECK_HEADERS([regex.h]) + AC_DEFINE(POSIX_REGEX, 1, [Define if wmi is to be build with posix + regex.]) +fi + + +# Add extra flags for diamond box +AC_ARG_WITH(diamond, [ --without-diamond disable diamond box whily move/resize]) + +if test "x$with_diamond" = "x"; then + AC_DEFINE(DIAMOND_BOX, 1, [Define if wmi is to be build with diamond box.]) +fi + +# Add extra flags for slot +AC_ARG_WITH(slot, [ --without-slot disable slot]) + +if test "x$with_slot" = "x"; then + AC_DEFINE(SLOT_SUPPORT, 1, [Define if wmi is to be build with slot support.]) +fi + +# Add extra flags for Xft mode checking +# Xft support, we ignore UTF-8 since WMI is not ready for i18n +TMPLIBS=$LIBS +TMPCXXFLAGS=$CXXFLAGS +AC_MSG_CHECKING([whether to have Xft support]) +AM_PATH_XFT(yes, + XFT=true, + XFT=false +) + +XFT_LINK=false + +if test "x$XFT" = "xtrue" ; then + AC_TRY_LINK([ + #include <X11/Xft/Xft.h> + ], [ XftFontClose(0, 0); return 1; ], + [ + XFT_LINK=true + ]) +fi + +# Add extra flags for Xft feature +AC_ARG_WITH(xft, [ --without-xft disable Xft support]) + +if test "x$with_xft" != "x"; then +#restore old values + LIBS=$TMPLIBS + CXXFLAGS=$TMPCXXFLAGS +else + if test "x$XFT_LINK" = "xtrue" ; then + AC_DEFINE(XFT_SUPPORT, 1, antialias support) + fi +fi + +LDFLAGS="$LDFLAGS $LIBS" + +# print summary +AC_MSG_RESULT([]) +AC_MSG_RESULT([ $PACKAGE version $VERSION configured successfully.]) +AC_MSG_RESULT([]) +AC_MSG_RESULT([Using '$prefix' for installation.]) +AC_MSG_RESULT([Using '$CXX' for C++ compiler.]) +AC_MSG_RESULT([Building with '$CXXFLAGS' for C++ compiler flags.]) +AC_MSG_RESULT([Building with '$LDFLAGS' for linker flags.]) +AC_MSG_RESULT([]) + +AC_OUTPUT([Makefile version.h src/Makefile man/Makefile]) diff --git a/container.h b/container.h @@ -0,0 +1,272 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: container.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __CONTAINER_H +#define __CONTAINER_H + +#include "kernel.h" +#include "util.h" // also includes wmi.h + +/** + * A Container object keeps a parent reference and may contain a list of + * child objects. + * + * A Container is a class template that creates an object that contains a list + * of other objects and also keeps a reference to a parent object. + * A container can be configured with for stacked tabbing at compile time. + * + * @param P the parent class + * @param LT the child list class + * @param LTI the iterator class for the child list + * @param T the child class + */ +template <class P, class LT, class LTI, class T> + class Container +{ +public: + + /** + * Constructs a container with a parent and a focused child. + * + * @param parent the original parent. + * @param child the original focused child which is optional. + */ + Container(P *parent, T *child = 0) { + parent_ = parent; + child_ = child; + }; + + /** + * The destructor. + * + * When the destructor is destoryed it will also destroys + * all of the children in the container. + */ + ~Container() { + Util::destroy<LT, LTI, T *> + (&childs_, childs_.begin(), childs_.end()); + }; + + /** + * Checks if the child is contained in this container. + * + * @param child the child to search for. + */ + bool contains(T *child) { + return Util::contains<LT, LTI, T>(&childs_, child); + }; + + /** + * Get the number of children in this container. + * + * @return the the number of children + */ + unsigned int size() { + return childs_.size(); + }; + + /** + * Get the list iterator to the first child. + * + * @return the list iterator to first child. + */ + LTI begin() { + return childs_.begin(); + }; + + /** + * Get the list iterator to end of child list. + * + * @return the list iterator to the last child. + */ + LTI end() { + return childs_.end(); + }; + + /** + * Get the parent that the container is attached to. + * + * @return the parent. + */ + P *attached() const { + return parent_; + }; + + /** + * Attach the container to a new parent. + * + * @param parent the parent. + */ + void setAttached(P *parent) { + parent_ = parent; + }; + + /** + * Get the currently focused child in the container. + * + * @return the focused child, if any. + */ + T *focused() const { + return child_; + }; + + /** + * Gives a child focus. + * + * In normal mode the child simply receives focus. In stacked + * tabbing mode the currently focused child will be placed at + * the end of the list and the newly focused child will be placed + * at the front. + * + * @param child the child to receive focus. + */ + void focus(T *child) { + if (child && KERNEL->isStackedTabbing()) { + if (childs_.size()) { + T *foc = childs_.front(); + if (foc != child) { + childs_.remove(foc); + childs_.push_back(foc); + } + } + childs_.remove(child); + childs_.push_front(child); + } + child_ = child; + }; + + /** + * Attaches a child to the container. + * + * This attaches a new child to the container. + * When a child is attached it receives focus. + * <code>attach()</code> will not add a duplicate child to the container. + * + * @param child the child to attach. + */ + void attach(T *child) { + if (child && !contains(child)) { + childs_.push_back(child); + focus(child); + } + }; + + /** + * Detach a child from the container. + * + * Detaches the child from the container. If the child being detached + * currently has focus then the focus will switch to the previous child. + * If this was the last child left in the container than there will be no + * child with focus. + * + * @param child the child to detach. + * @return the current child with focus. + */ + T *detach(T *child) { + + if (child_ == child) { + // cycle to prev child + focus(prev()); + } + childs_.remove(child); + + if (childs_.size() < 1) { + child_ = 0; + } + return child_; + }; + + /** + * Get the previous child in the list. + * + * In stacked tabbing mode this is the last child. In regular + * mode this is the child before the currently focused child. + * + * @return the previous child. + */ + T *prev() { + + if (childs_.size() < 1) { + return 0; + } + else if (childs_.size() < 2) { + return child_; + } + + if (KERNEL->isStackedTabbing()) { + return childs_.back(); + } + else { + for (LTI it = childs_.begin(); + it != childs_.end(); it++) + { + if (child_ == *it) { + if (it != childs_.begin()) { + it--; + return *it; + } + else { + break; + } + } + } + return childs_.back(); + } + } + + + /** + * Get the next child in the list. + * + * In stacked tabbing mode this is the second child in the list. + * In regular mode it is the child after the currently focused child. + * + * @return the next child. + */ + T *next() { + if (childs_.size() < 1) { + return 0; + } + else if (childs_.size() < 2) { + return child_; + } + + if (KERNEL->isStackedTabbing()) { + LTI it = childs_.begin(); + it++; + return *it; + } + else { + for (LTI it = childs_.begin(); + it != childs_.end(); it++) + { + if (child_ == *it) { + it++; + if (it != childs_.end()) { + return *it; + } + else { + break; + } + } + } + return childs_.front(); + } + }; + + /** Used for direct manipulation, use with care! */ + LT *childs() { + return &childs_; + } + + +private: + + P *parent_; + T *child_; + LT childs_; +}; + +#endif // __CONTAINER_H diff --git a/cursors.cpp b/cursors.cpp @@ -0,0 +1,61 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: cursors.cpp 734 2004-09-27 18:15:45Z garbeam $ + +extern "C" { +#include <X11/cursorfont.h> +} + +#include "cursors.h" + +#include "kernel.h" +#include "wmi.h" +#include "xcore.h" + +Cursor Cursors::NORMAL_CURSOR = 0; +Cursor Cursors::RESIZE_LEFT_CURSOR = 0; +Cursor Cursors::RESIZE_RIGHT_CURSOR = 0; +Cursor Cursors::RESIZE_UP_CURSOR = 0; +Cursor Cursors::RESIZE_DOWN_CURSOR = 0; + +Cursor Cursors::RESIZE_NORTH_WEST_CURSOR = 0; +Cursor Cursors::RESIZE_NORTH_EAST_CURSOR = 0; +Cursor Cursors::RESIZE_SOUTH_EAST_CURSOR = 0; +Cursor Cursors::RESIZE_SOUTH_WEST_CURSOR = 0; + +bool Cursors::initialized_ = false; + +void Cursors::cleanup() { + + XCORE->freeCursor(NORMAL_CURSOR); + XCORE->freeCursor(RESIZE_LEFT_CURSOR); + XCORE->freeCursor(RESIZE_RIGHT_CURSOR); + XCORE->freeCursor(RESIZE_UP_CURSOR); + XCORE->freeCursor(RESIZE_DOWN_CURSOR); + + XCORE->freeCursor(RESIZE_NORTH_WEST_CURSOR); + XCORE->freeCursor(RESIZE_NORTH_EAST_CURSOR); + XCORE->freeCursor(RESIZE_SOUTH_WEST_CURSOR); + XCORE->freeCursor(RESIZE_SOUTH_EAST_CURSOR); +} + +void Cursors::initCursors() +{ + if (initialized_) { + return; + } + + NORMAL_CURSOR = XCORE->createFontCursor(XC_left_ptr); + RESIZE_LEFT_CURSOR = XCORE->createFontCursor(XC_left_side); + RESIZE_RIGHT_CURSOR = XCORE->createFontCursor(XC_right_side); + RESIZE_UP_CURSOR = XCORE->createFontCursor(XC_top_side); + RESIZE_DOWN_CURSOR = XCORE->createFontCursor(XC_bottom_side); + + RESIZE_NORTH_WEST_CURSOR = XCORE->createFontCursor(XC_top_left_corner); + RESIZE_NORTH_EAST_CURSOR = XCORE->createFontCursor(XC_top_right_corner); + RESIZE_SOUTH_WEST_CURSOR = XCORE->createFontCursor(XC_bottom_left_corner); + RESIZE_SOUTH_EAST_CURSOR = XCORE->createFontCursor(XC_bottom_right_corner); + + initialized_ = true; +} diff --git a/cursors.h b/cursors.h @@ -0,0 +1,40 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: cursors.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __CURSORS_H +#define __CURSORS_H + +extern "C" { +#include <X11/Xlib.h> +} + +/** + * Container class of all X cursors used by WMI. + */ +class Cursors { + +public: + + static void initCursors(); + + static Cursor NORMAL_CURSOR; + static Cursor RESIZE_LEFT_CURSOR; + static Cursor RESIZE_RIGHT_CURSOR; + static Cursor RESIZE_UP_CURSOR; + static Cursor RESIZE_DOWN_CURSOR; + + static Cursor RESIZE_NORTH_WEST_CURSOR; + static Cursor RESIZE_NORTH_EAST_CURSOR; + static Cursor RESIZE_SOUTH_EAST_CURSOR; + static Cursor RESIZE_SOUTH_WEST_CURSOR; + + static void cleanup(); + +private: + + static bool initialized_; +}; + +#endif // __CURSORS_H diff --git a/draw.cpp b/draw.cpp @@ -0,0 +1,535 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: draw.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include <iostream> + +#include "draw.h" + +#include "../config.h" +#include "kernel.h" +#include "rectangle.h" +#include "xcore.h" + +#define XCORE XCore::instance() +#define FIGURE_DISTANCE 3 + +void Draw::drawDetachButton(Window window, GC gc, + Rectangle *rect, unsigned long background, + unsigned long shineBorder, unsigned long shadowBorder, + unsigned long shineFigure, unsigned long shadowFigure) +{ + + XCORE->setForeground(gc, background); + XCORE->fillRectangle(window, gc, rect); + + XPoint shineButtonPoints[3]; + shineButtonPoints[0].x = rect->x() + FIGURE_DISTANCE; + shineButtonPoints[0].y = rect->y() + rect->height() - FIGURE_DISTANCE - 1; + shineButtonPoints[1].x = rect->x() + FIGURE_DISTANCE; + shineButtonPoints[1].y = rect->y() + rect->height() - 2 * FIGURE_DISTANCE - 1; + shineButtonPoints[2].x = rect->x() + rect->width() - FIGURE_DISTANCE - 1; + shineButtonPoints[2].y = rect->y() + rect->height() - 2 * FIGURE_DISTANCE - 1; + XCORE->setForeground(gc, shineFigure); + XCORE->drawLines(window, gc, shineButtonPoints, 3); + + XPoint shadowButtonPoints[3]; + shadowButtonPoints[0].x = rect->x() + rect->width() - FIGURE_DISTANCE - 1; + shadowButtonPoints[0].y = rect->y() + rect->height() - 2 * FIGURE_DISTANCE - 1; + shadowButtonPoints[1].x = rect->x() + rect->width() - FIGURE_DISTANCE - 1; + shadowButtonPoints[1].y = rect->y() + rect->height() - FIGURE_DISTANCE - 1; + shadowButtonPoints[2].x = rect->x() + FIGURE_DISTANCE; + shadowButtonPoints[2].y = rect->y() + rect->height() - FIGURE_DISTANCE - 1; + XCORE->setForeground(gc, shadowFigure); + XCORE->drawLines(window, gc, shadowButtonPoints, 3); + + drawRectBorder(window, gc, rect, shineBorder, shadowBorder); +} + +void Draw::drawMaxButton(Window window, GC gc, + Rectangle *rect, unsigned long background, + unsigned long shineBorder, unsigned long shadowBorder, + unsigned long shineFigure, unsigned long shadowFigure, + bool fill) + +{ + XCORE->setForeground(gc, background); + XCORE->fillRectangle(window, gc, rect); + + XPoint shadowButtonPoints[3]; + shadowButtonPoints[0].x = rect->x() + rect->width() - FIGURE_DISTANCE - 1; + shadowButtonPoints[0].y = rect->y() + FIGURE_DISTANCE; + shadowButtonPoints[1].x = rect->x() + rect->width() - FIGURE_DISTANCE - 1; + shadowButtonPoints[1].y = rect->y() + rect->height() - FIGURE_DISTANCE - 1; + shadowButtonPoints[2].x = rect->x() + FIGURE_DISTANCE; + shadowButtonPoints[2].y = rect->y() + rect->height() - FIGURE_DISTANCE - 1; + XCORE->setForeground(gc, shadowFigure); + XCORE->drawLines(window, gc, shadowButtonPoints, 3); + + XPoint shineButtonPoints[3]; + shineButtonPoints[0].x = rect->x() + FIGURE_DISTANCE; + shineButtonPoints[0].y = rect->y() + rect->height() - FIGURE_DISTANCE - 1; + shineButtonPoints[1].x = rect->x() + FIGURE_DISTANCE; + shineButtonPoints[1].y = rect->y() + FIGURE_DISTANCE; + shineButtonPoints[2].x = rect->x() + rect->width() - FIGURE_DISTANCE - 1; + shineButtonPoints[2].y = rect->y() + FIGURE_DISTANCE; + XCORE->setForeground(gc, shineFigure); + XCORE->drawLines(window, gc, shineButtonPoints, 3); + + if (fill) { + XCORE->setForeground(gc, shineFigure); + XCORE->fillRectangle(window, gc, + rect->x() + FIGURE_DISTANCE + 1, + rect->y() + FIGURE_DISTANCE + 1, + rect->width() - 2 * FIGURE_DISTANCE - 2, + rect->height() - 2 * FIGURE_DISTANCE - 2); + } + + drawRectBorder(window, gc, rect, shineBorder, shadowBorder); +} + +void Draw::drawMenuButton(Window window, GC gc, + Rectangle *rect, unsigned long background, + unsigned long shineBorder, unsigned long shadowBorder, + unsigned long shineFigure, unsigned long shadowFigure) +{ + XCORE->setForeground(gc, background); + XCORE->fillRectangle(window, gc, rect); + + // shine lines + XCORE->setForeground(gc, shineFigure); + XCORE->drawLine(window, gc, rect->x() + FIGURE_DISTANCE, + rect->y() + FIGURE_DISTANCE, + rect->x() + rect->width() - FIGURE_DISTANCE, + rect->y() + FIGURE_DISTANCE); + XCORE->drawLine(window, gc, rect->x() + FIGURE_DISTANCE, + rect->y() + rect->height() / 2, + rect->x() + rect->width() - FIGURE_DISTANCE, + rect->y() + rect->height() / 2); + XCORE->drawLine(window, gc, rect->x() + FIGURE_DISTANCE, + rect->y() + rect->height() - FIGURE_DISTANCE - 1, + rect->x() + rect->width() - FIGURE_DISTANCE, + rect->y() + rect->height() - FIGURE_DISTANCE - 1); + + // shadow lines + XCORE->setForeground(gc, shadowFigure); + XCORE->drawLine(window, gc, rect->x() + FIGURE_DISTANCE, + rect->y() + FIGURE_DISTANCE + 1, + rect->x() + rect->width() - FIGURE_DISTANCE, + rect->y() + FIGURE_DISTANCE + 1); + XCORE->drawLine(window, gc, rect->x() + FIGURE_DISTANCE, + rect->y() + rect->height() / 2 + 1, + rect->x() + rect->width() - FIGURE_DISTANCE, + rect->y() + rect->height() / 2 + 1); + XCORE->drawLine(window, gc, rect->x() + FIGURE_DISTANCE, + rect->y() + rect->height() - FIGURE_DISTANCE, + rect->x() + rect->width() - FIGURE_DISTANCE, + rect->y() + rect->height() - FIGURE_DISTANCE); + + drawRectBorder(window, gc, rect, shineBorder, shadowBorder); +} + +void Draw::drawFloatButton(Window window, GC gc, + Rectangle *rect, unsigned long background, + unsigned long shineBorder, unsigned long shadowBorder, + unsigned long shineFigure, unsigned long shadowFigure, + bool fill) +{ + XCORE->setForeground(gc, background); + XCORE->fillRectangle(window, gc, rect); + + XPoint shadowButtonPoints[3]; + shadowButtonPoints[0].x = rect->x() + rect->width() - 2 * FIGURE_DISTANCE - 1; + shadowButtonPoints[0].y = rect->y() + FIGURE_DISTANCE; + shadowButtonPoints[1].x = rect->x() + rect->width() - 2 * FIGURE_DISTANCE - 1; + shadowButtonPoints[1].y = rect->y() + rect->height() - 2 * FIGURE_DISTANCE - 1; + shadowButtonPoints[2].x = rect->x() + FIGURE_DISTANCE; + shadowButtonPoints[2].y = rect->y() + rect->height() - 2 * FIGURE_DISTANCE - 1; + XCORE->setForeground(gc, shadowFigure); + XCORE->drawLines(window, gc, shadowButtonPoints, 3); + + shadowButtonPoints[0].x = rect->x() + rect->width() - FIGURE_DISTANCE - 1; + shadowButtonPoints[0].y = rect->y() + 2 * FIGURE_DISTANCE; + shadowButtonPoints[1].x = rect->x() + rect->width() - FIGURE_DISTANCE - 1; + shadowButtonPoints[1].y = rect->y() + rect->height() - FIGURE_DISTANCE - 1; + shadowButtonPoints[2].x = rect->x() + 2 * FIGURE_DISTANCE; + shadowButtonPoints[2].y = rect->y() + rect->height() - FIGURE_DISTANCE - 1; + XCORE->drawLines(window, gc, shadowButtonPoints, 3); + + XPoint shineButtonPoints[3]; + shineButtonPoints[0].x = rect->x() + FIGURE_DISTANCE; + shineButtonPoints[0].y = rect->y() + rect->height() - 2 * FIGURE_DISTANCE - 1; + shineButtonPoints[1].x = rect->x() + FIGURE_DISTANCE; + shineButtonPoints[1].y = rect->y() + FIGURE_DISTANCE; + shineButtonPoints[2].x = rect->x() + rect->width() - 2 * FIGURE_DISTANCE - 1; + shineButtonPoints[2].y = rect->y() + FIGURE_DISTANCE; + XCORE->setForeground(gc, shineFigure); + XCORE->drawLines(window, gc, shineButtonPoints, 3); + + shineButtonPoints[0].x = rect->x() + 2 * FIGURE_DISTANCE; + shineButtonPoints[0].y = rect->y() + rect->height() - FIGURE_DISTANCE - 1; + shineButtonPoints[1].x = rect->x() + 2 * FIGURE_DISTANCE; + shineButtonPoints[1].y = rect->y() + 2 * FIGURE_DISTANCE; + shineButtonPoints[2].x = rect->x() + rect->width() - FIGURE_DISTANCE - 1; + shineButtonPoints[2].y = rect->y() + 2 * FIGURE_DISTANCE; + XCORE->drawLines(window, gc, shineButtonPoints, 3); + + if (fill) { + XCORE->setForeground(gc, shineFigure); + XCORE->fillRectangle(window, gc, + rect->x() + FIGURE_DISTANCE + 1, + rect->y() + FIGURE_DISTANCE + 1, + rect->width() - 3 * FIGURE_DISTANCE - 2, + rect->height() - 3 * FIGURE_DISTANCE - 2); + + XCORE->fillRectangle(window, gc, + rect->x() + 2 * FIGURE_DISTANCE + 1, + rect->y() + 2 * FIGURE_DISTANCE + 1, + rect->width() - 3 * FIGURE_DISTANCE - 2, + rect->height() - 3 * FIGURE_DISTANCE - 2); + } + + drawRectBorder(window, gc, rect, shineBorder, shadowBorder); +} + +void Draw::drawCloseButton(Window window, GC gc, + Rectangle *rect, unsigned long background, + unsigned long shineBorder, unsigned long shadowBorder, + unsigned long shineFigure, unsigned long shadowFigure) +{ + XCORE->setForeground(gc, background); + XCORE->fillRectangle(window, gc, rect); + + int mx = rect->x() + rect->width() / 2; + int my = rect->y() + rect->height() / 2; + int md = FIGURE_DISTANCE / 2 + 1; + XPoint shineButtonPoints[3]; + shineButtonPoints[0].x = mx - md; + shineButtonPoints[0].y = my + md; + shineButtonPoints[1].x = shineButtonPoints[0].x; + shineButtonPoints[1].y = my - md; + shineButtonPoints[2].x = mx + md; + shineButtonPoints[2].y = shineButtonPoints[1].y; + XCORE->setForeground(gc, shineFigure); + XCORE->drawLines(window, gc, shineButtonPoints, 3); + + XPoint shadowButtonPoints[3]; + shadowButtonPoints[0].x = mx + md; + shadowButtonPoints[0].y = my - md; + shadowButtonPoints[1].x = shadowButtonPoints[0].x; + shadowButtonPoints[1].y = my + md; + shadowButtonPoints[2].x = mx - md; + shadowButtonPoints[2].y = my + md; + XCORE->setForeground(gc, shadowFigure); + XCORE->drawLines(window, gc, shadowButtonPoints, 3); + + drawRectBorder(window, gc, rect, shineBorder, shadowBorder); +} + +void Draw::drawInputModeButton(Window window, GC gc, Rectangle *rect, + unsigned long background, + unsigned long shineBorder, unsigned long shadowBorder, + unsigned long shineFigure, unsigned long shadowFigure) +{ + XCORE->setForeground(gc, background); + XCORE->fillRectangle(window, gc, rect); + + XPoint shadowButtonPoints[2]; + shadowButtonPoints[0].x = rect->x() + 2 * FIGURE_DISTANCE; + shadowButtonPoints[0].y = rect->y() + FIGURE_DISTANCE; + shadowButtonPoints[1].x = rect->x() + 2 * FIGURE_DISTANCE; + shadowButtonPoints[1].y = rect->y() + rect->height() - FIGURE_DISTANCE - 1; + shadowButtonPoints[2].x = rect->x() + FIGURE_DISTANCE; + shadowButtonPoints[2].y = rect->y() + rect->height() - FIGURE_DISTANCE - 1; + XCORE->setForeground(gc, shadowFigure); + XCORE->drawLines(window, gc, shadowButtonPoints, 3); + + shadowButtonPoints[0].x = rect->x() + rect->width() - FIGURE_DISTANCE - 1; + shadowButtonPoints[0].y = rect->y() + FIGURE_DISTANCE; + shadowButtonPoints[1].x = rect->x() + rect->width() - FIGURE_DISTANCE - 1; + shadowButtonPoints[1].y = rect->y() + rect->height() - FIGURE_DISTANCE - 1; + shadowButtonPoints[2].x = rect->x() + rect->width() - 2 * FIGURE_DISTANCE - 1; + shadowButtonPoints[2].y = rect->y() + rect->height() - FIGURE_DISTANCE - 1; + XCORE->drawLines(window, gc, shadowButtonPoints, 3); + + XPoint shineButtonPoints[3]; + shineButtonPoints[0].x = rect->x() + FIGURE_DISTANCE; + shineButtonPoints[0].y = rect->y() + rect->height() - FIGURE_DISTANCE - 1; + shineButtonPoints[1].x = rect->x() + FIGURE_DISTANCE; + shineButtonPoints[1].y = rect->y() + FIGURE_DISTANCE; + shineButtonPoints[2].x = rect->x() + 2 * FIGURE_DISTANCE; + shineButtonPoints[2].y = rect->y() + FIGURE_DISTANCE; + XCORE->setForeground(gc, shineFigure); + XCORE->drawLines(window, gc, shineButtonPoints, 3); + + shineButtonPoints[0].x = rect->x() + rect->width() - 2 * FIGURE_DISTANCE - 1; + shineButtonPoints[0].y = rect->y() + rect->height() - FIGURE_DISTANCE - 1; + shineButtonPoints[1].x = rect->x() + rect->width() - 2 * FIGURE_DISTANCE - 1; + shineButtonPoints[1].y = rect->y() + FIGURE_DISTANCE; + shineButtonPoints[2].x = rect->x() + rect->width() - FIGURE_DISTANCE - 1; + shineButtonPoints[2].y = rect->y() + FIGURE_DISTANCE; + XCORE->drawLines(window, gc, shineButtonPoints, 3); + + drawRectBorder(window, gc, rect, shineBorder, shadowBorder); +} + +void Draw::drawMeter(Window window, GC gc, Rectangle *rect, + unsigned int percentage, unsigned long background, + unsigned long highFigure, unsigned long normalFigure, + unsigned long lowFigure, unsigned long shineBorder, + unsigned long shadowBorder) +{ + XCORE->setForeground(gc, background); + XCORE->fillRectangle(window, gc, rect); + + unsigned int pHeight = (rect->height() * percentage) / 100; + unsigned long figure = lowFigure; + if (percentage > 66) { + figure = highFigure; + } + else if (percentage > 33) { + figure = normalFigure; + } + XCORE->setForeground(gc, figure); + XCORE->fillRectangle(window, gc, + rect->x() + 1, rect->y() + (rect->height() - 1 - pHeight), + rect->width() - 2, pHeight); + + drawRectBorder(window, gc, rect, shineBorder, shadowBorder); +} + +void Draw::drawBorder(Window window, GC commonGC, + GC borderGC, Rectangle *rect, + unsigned long background, unsigned long shine, + unsigned long shadow, unsigned int titleBarHeight, + unsigned int borderWidth) +{ + // titlebar 1px separator + XCORE->setForeground(commonGC, background); + if (titleBarHeight > 0 && borderWidth > 0) { + XPoint titleBorderPoints[2]; + titleBorderPoints[0].x = borderWidth; + titleBorderPoints[0].y = titleBarHeight; + titleBorderPoints[1].x = rect->width() - borderWidth; + titleBorderPoints[1].y = titleBarHeight; + XCORE->drawLines(window, commonGC, titleBorderPoints, 2); + } + + if (borderWidth == 0) { + return; + } + + // background border + XCORE->setForeground(borderGC, background); + XCORE->drawRectangle(window, borderGC, + borderWidth / 2, borderWidth / 2, + rect->width() - borderWidth, + rect->height() - borderWidth); + + // shadow border + XPoint shadowBorderPoints[3]; + shadowBorderPoints[0].x = rect->width() - 1; + shadowBorderPoints[0].y = 0; + shadowBorderPoints[1].x = rect->width() - 1; + shadowBorderPoints[1].y = rect->height() - 1; + shadowBorderPoints[2].x = 0; + shadowBorderPoints[2].y = rect->height() - 1; + + XCORE->setForeground(commonGC, shadow); + XCORE->drawLines(window, commonGC, shadowBorderPoints, 3); + + // shine border + XPoint shineBorderPoints[3]; + shineBorderPoints[0].x = 0; + shineBorderPoints[0].y = rect->height() - 1; + shineBorderPoints[1].x = 0; + shineBorderPoints[1].y = 0; + shineBorderPoints[2].x = rect->width() - 1; + shineBorderPoints[2].y = 0; + + XCORE->setForeground(commonGC, shine); + XCORE->drawLines(window, commonGC, shineBorderPoints, 3); +} + +void Draw::drawFloatBorderAnchors(Window window, GC gc, Rectangle *rect, + unsigned long shine, unsigned long shadow, + unsigned int titleBarHeight, unsigned int borderWidth) +{ + XCORE->setForeground(gc, shadow); + XCORE->drawLine(window, gc, titleBarHeight, 0, titleBarHeight, borderWidth); + XCORE->drawLine(window, gc, 0, titleBarHeight, borderWidth, titleBarHeight); + XCORE->drawLine(window, gc, 0, rect->height() - titleBarHeight - 1, + borderWidth, rect->height() - titleBarHeight); + XCORE->drawLine(window, gc, titleBarHeight, rect->height() - borderWidth, + titleBarHeight, rect->height()); + XCORE->drawLine(window, gc, rect->width() - titleBarHeight - 1, 0, + rect->width() - titleBarHeight - 1, borderWidth); + XCORE->drawLine(window, gc, rect->width() - borderWidth, titleBarHeight, + rect->width(), titleBarHeight); + XCORE->drawLine(window, gc, rect->width() - borderWidth, rect->height() + - titleBarHeight - 1, rect->width(), rect->height() + - titleBarHeight - 1); + XCORE->drawLine(window, gc, rect->width() - titleBarHeight - 1, + rect->height() - borderWidth, + rect->width() - titleBarHeight - 1, + rect->height()); + + XCORE->setForeground(gc, shine); + XCORE->drawLine(window, gc, titleBarHeight + 1, 0, + titleBarHeight + 1, borderWidth); + XCORE->drawLine(window, gc, 0, titleBarHeight + 1, borderWidth, + titleBarHeight + 1); + XCORE->drawLine(window, gc, 0, rect->height() - titleBarHeight, + borderWidth, rect->height() - titleBarHeight); + XCORE->drawLine(window, gc, titleBarHeight + 1, + rect->height() - borderWidth, + titleBarHeight + 1, rect->height()); + XCORE->drawLine(window, gc, rect->width() - titleBarHeight, 0, + rect->width() - titleBarHeight, borderWidth); + XCORE->drawLine(window, gc, rect->width() - borderWidth, + titleBarHeight + 1, + rect->width(), titleBarHeight + 1); + XCORE->drawLine(window, gc, rect->width() - borderWidth, + rect->height() - titleBarHeight, + rect->width(), rect->height() - titleBarHeight); + XCORE->drawLine(window, gc, rect->width() - titleBarHeight, + rect->height() - borderWidth, + rect->width() - titleBarHeight, + rect->height()); +} + +void Draw::drawShineBorder(Window window, GC gc, Rectangle *rect, + unsigned long shine) +{ + XPoint shineBorderPoints[3]; + shineBorderPoints[0].x = rect->x(); + shineBorderPoints[0].y = rect->y() + rect->height() - 1; + shineBorderPoints[1].x = rect->x(); + shineBorderPoints[1].y = rect->y(); + shineBorderPoints[2].x = rect->x() + rect->width() - 1; + shineBorderPoints[2].y = rect->y(); + + XCORE->setForeground(gc, shine); + XCORE->drawLines(window, gc, shineBorderPoints, 3); +} + +void Draw::drawShadowBorder(Window window, GC gc, Rectangle *rect, + unsigned long shadow) +{ + XPoint shadowBorderPoints[3]; + shadowBorderPoints[0].x = rect->x() + rect->width() - 1; + shadowBorderPoints[0].y = rect->y(); + shadowBorderPoints[1].x = rect->x() + rect->width() - 1; + shadowBorderPoints[1].y = rect->y() + rect->height() - 1; + shadowBorderPoints[2].x = rect->x(); + shadowBorderPoints[2].y = rect->y() + rect->height() - 1; + + XCORE->setForeground(gc, shadow); + XCORE->drawLines(window, gc, shadowBorderPoints, 3); +} + +void Draw::drawRectBorder(Window window, GC gc, Rectangle *rect, + unsigned long shine, unsigned long shadow) +{ + drawShadowBorder(window, gc, rect, shadow); + drawShineBorder(window, gc, rect, shine); +} + +void Draw::drawStickyNotifier(Window window, GC gc, Rectangle *rect, + unsigned long shine, unsigned long shadow, + unsigned int textWidth) +{ + // We assume that the text is centered! + XCORE->setForeground(gc, shadow); + XCORE->drawLine(window, gc, + rect->x() + FIGURE_DISTANCE + 1, + rect->y() + FIGURE_DISTANCE + 2, + rect->x() + rect->width() / 2 - textWidth / 2 - FIGURE_DISTANCE - 1, + rect->y() + FIGURE_DISTANCE + 2); + + XCORE->drawLine(window, gc, + rect->x() + FIGURE_DISTANCE + rect->width() / 2 + textWidth / 2 + FIGURE_DISTANCE, + rect->y() + FIGURE_DISTANCE + 2, + rect->x() + rect->width() - FIGURE_DISTANCE - 1, + rect->y() + FIGURE_DISTANCE + 2); + + XCORE->drawLine(window, gc, + rect->x() + FIGURE_DISTANCE + 1, + rect->y() + rect->height() - FIGURE_DISTANCE - 1, + rect->x() + rect->width() / 2 - textWidth / 2 - FIGURE_DISTANCE - 1, + rect->y() + rect->height() - FIGURE_DISTANCE - 1); + + XCORE->drawLine(window, gc, + rect->x() + FIGURE_DISTANCE + rect->width() / 2 + textWidth / 2 + FIGURE_DISTANCE, + rect->y() + rect->height() - FIGURE_DISTANCE - 1, + rect->x() + rect->width() - FIGURE_DISTANCE - 1, + rect->y() + rect->height() - FIGURE_DISTANCE - 1); + + XCORE->setForeground(gc, shine); + XCORE->drawLine(window, gc, + rect->x() + FIGURE_DISTANCE + 1, + rect->y() + FIGURE_DISTANCE + 1, + rect->x() + rect->width() / 2 - textWidth / 2 - FIGURE_DISTANCE - 1, + rect->y() + FIGURE_DISTANCE + 1); + + XCORE->drawLine(window, gc, + rect->x() + FIGURE_DISTANCE + rect->width() / 2 + textWidth / 2 + FIGURE_DISTANCE, + rect->y() + FIGURE_DISTANCE + 1, + rect->x() + rect->width() - FIGURE_DISTANCE - 1, + rect->y() + FIGURE_DISTANCE + 1); + + XCORE->drawLine(window, gc, + rect->x() + FIGURE_DISTANCE + 1, + rect->y() + rect->height() - FIGURE_DISTANCE - 2, + rect->x() + rect->width() / 2 - textWidth / 2 - FIGURE_DISTANCE - 1, + rect->y() + rect->height() - FIGURE_DISTANCE - 2); + + XCORE->drawLine(window, gc, + rect->x() + FIGURE_DISTANCE + rect->width() / 2 + textWidth / 2 + FIGURE_DISTANCE, + rect->y() + rect->height() - FIGURE_DISTANCE - 2, + rect->x() + rect->width() - FIGURE_DISTANCE - 1, + rect->y() + rect->height() - FIGURE_DISTANCE - 2); +} + +void Draw::drawTransRectangle(Window window, GC gc, + Rectangle *rect, unsigned int barHeight, + unsigned int borderWidth) +{ + XCORE->drawRectangle(window, gc, + rect->x(), rect->y(), + rect->width(), rect->height()); + + unsigned int offsetY = borderWidth; + if (barHeight > 0) { + XCORE->drawLine(window, gc, + rect->x() + borderWidth / 2, + rect->y() + barHeight + + borderWidth, + rect->x() + rect->width() - + borderWidth / 2, + rect->y() + barHeight + + borderWidth); + offsetY += barHeight + borderWidth; + } +#if DIAMOND_BOX + XPoint orthRectPoints[3]; + + orthRectPoints[0].x = rect->x() + rect->width() / 3; + orthRectPoints[0].y = rect->y() + rect->height() - borderWidth; + orthRectPoints[1].x = rect->x() + borderWidth; + orthRectPoints[1].y = rect->y() + rect->height() / 2 + offsetY / 2; + orthRectPoints[2].x = orthRectPoints[0].x; + orthRectPoints[2].y = rect->y() + offsetY; + XCORE->drawLines(window, gc, orthRectPoints, 3); + + orthRectPoints[0].x = rect->x() + (2 * rect->width()) / 3; + orthRectPoints[0].y = rect->y() + offsetY; + orthRectPoints[1].x = rect->x() + rect->width() - borderWidth; + // same as above + //orthRectPoints[1].y = rect->y() + rect->height() / 2 + offsetY / 2; + orthRectPoints[2].x = orthRectPoints[0].x; + orthRectPoints[2].y = rect->y() + rect->height() - borderWidth; + XCORE->drawLines(window, gc, orthRectPoints, 3); +#endif +} diff --git a/draw.h b/draw.h @@ -0,0 +1,88 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: draw.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __DRAW_H +#define __DRAW_H + +extern "C" { +#include <X11/Xlib.h> +} + +class Light; +class Rectangle; + +/** + * Main class of all low-level drawing methods used by WMI. + */ +class Draw { + +public: + + static void drawMenuButton(Window window, GC gc, Rectangle *rect, + unsigned long background, unsigned long shineBorder, + unsigned long shadowBorder, unsigned long shineFigure, + unsigned long shadowFigure); + + static void drawDetachButton(Window window, GC gc, Rectangle *rect, + unsigned long background, + unsigned long shineBorder, unsigned long shadowBorder, + unsigned long shineFigure, unsigned long shadowFigure); + + static void drawMaxButton(Window window, GC gc, Rectangle *rect, + unsigned long background, + unsigned long shineBorder, unsigned long shadowBorder, + unsigned long shineFigure, unsigned long shadowFigure, + bool fill = false); + + static void drawFloatButton(Window window, GC gc, Rectangle *rect, + unsigned long background, + unsigned long shineBorder, unsigned long shadowBorder, + unsigned long shineFigure, unsigned long shadowFigure, + bool fill = false); + + static void drawCloseButton(Window window, GC gc, Rectangle *rect, + unsigned long background, + unsigned long shineBorder, unsigned long shadowBorder, + unsigned long shineFigure, unsigned long shadowFigure); + + static void drawInputModeButton(Window window, GC gc, Rectangle *rect, + unsigned long background, + unsigned long shineBorder, unsigned long shadowBorder, + unsigned long shineFigure, unsigned long shadowFigure); + + static void drawMeter(Window window, GC gc, Rectangle *rect, + unsigned int percentage, unsigned long background, + unsigned long highFigure, unsigned long normalFigure, + unsigned long lowFigure, unsigned long shineBorder, + unsigned long shadowBorder); + + static void drawBorder(Window window, GC commonGC, GC borderGC, Rectangle *rect, + unsigned long background, unsigned long shine, + unsigned long shadow, unsigned int titleBarHeight, + unsigned int borderWidth); + + static void drawFloatBorderAnchors(Window window, GC gc, Rectangle *rect, + unsigned long shine, unsigned long shadow, + unsigned int titleBarHeight, unsigned int borderWidth); + + static void drawShineBorder(Window window, GC gc, Rectangle *rect, + unsigned long shine); + + static void drawShadowBorder(Window window, GC gc, Rectangle *rect, + unsigned long shadow); + + static void drawRectBorder(Window window, GC gc, Rectangle *rect, + unsigned long shine, unsigned long shadow); + + static void drawStickyNotifier(Window window, GC gc, Rectangle *rect, + unsigned long shine, unsigned long shadow, + unsigned int textWidth); + + static void drawTransRectangle(Window window, GC gc, + Rectangle *rect, unsigned int barHeight, + unsigned int borderWidth); +}; + +#endif // __DRAW_H diff --git a/examples/session-managers/kdm-entry b/examples/session-managers/kdm-entry @@ -0,0 +1,14 @@ +Katryn Anderson proposed following entry to +/usr/share/apps/kdm/sessions if you're using the +KDM login manager: +---------------------------------------------------------- +[Desktop Entry] +Encoding=UTF-8 +Type=XSession +Exec=wmi +TryExec=wmi +Name=WMI +Name[xx]=xxWMIxx +Comment=Window-Manager Improved +Comment[xx]=xxWindow-Manager Improvedxxxxxxxxxxxxxxxxxxx +---------------------------------------------------------- diff --git a/examples/statustext-deleuze.sh b/examples/statustext-deleuze.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +# Deleuze proposed following statustext.sh + +# Just add following line to your .xinitrc to launch this status text: +# +# exec <patch-to-this-dir>/statustext.sh& +# (or whatever file name you prefer) +# + +# set statusbar to +# .wmi/common.conf:statusbar.status-width=60 + +# time format +TFORMAT="%d.%m., %H:%M" + +while sleep 8 +do + UP=`uptime |awk '{ print $1 " " $2 $3 $4 " " $5 " " $6 " " $7 " "$9 + +$10 $11 +}'` + TAIL=`tail -n 1 /var/log/messages` + + wmiremote -t "[$TAIL] " + sleep 8 + wmiremote -t "[$UP] " +done diff --git a/examples/statustext-gavin.sh b/examples/statustext-gavin.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +# Gavin McCullagh proposed following change to the original +# statustext.sh (only works under GNU/Linux): + +########################## +# time format +TFORMAT="%d.%m.%Y, %H:%M" +# give wmi time to start. +sleep 2 + +while pgrep wmi &>/dev/null +do + MSG=`date "+${TFORMAT}"` + APM=`cat /proc/apm| awk '{ print $7 }'` + + wmiremote -t "[$APM] [$MSG]" + # launched every 10 seconds, wait until wmi is up. + sleep 10 +done + +# Additionally just uncomment and add following lines to +# your .xinitrc or .xsession file: + +############################################## +# if ! pgrep statustext.sh; then +# exec ~/bin/statustext.sh & +# fi +############################################## diff --git a/examples/statustext.sh b/examples/statustext.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +# Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# +# $Id: statustext.sh 140 2004-05-05 22:29:34Z garbeam $ + +# statustext.sh - shows date/time and APM status on the status bar. +# +# Just add following line to your .xinitrc to launch this status text: +# +# exec <patch-to-this-dir>/statustext.sh& +# (or whatever file name you prefer) +# + +# time format +TFORMAT="%d.%m., %H:%M" + +while true +do + MSG=`date "+${TFORMAT}"` + APM=`cat /proc/apm| awk '{ print $7 }'` + + wmiremote -t "[$APM] [$MSG]" + +# launched every 10 seconds + sleep 10 +done diff --git a/examples/themes/accent-theme.conf b/examples/themes/accent-theme.conf @@ -0,0 +1,48 @@ +color.bar.background=grey30 +color.bar.shadow=grey30 +color.bar.shine=grey30 +color.bar.text=black +color.button.background.normal=grey55 +color.button.background.pressed=grey30 +color.button.border.shadow.normal=grey55 +color.button.border.shadow.pressed=grey55 +color.button.border.shine.normal=grey55 +color.button.border.shine.pressed=grey55 +color.button.figure.shadow.normal=black +color.button.figure.shadow.pressed=grey55 +color.button.figure.shine.normal=black +color.button.figure.shine.pressed=grey55 +color.frame.background.focussed=grey55 +color.frame.pseudo=grey55 +color.frame.background.normal=grey30 +color.frame.shadow.focussed=grey55 +color.frame.shadow.normal=black +color.frame.shine.focussed=grey55 +color.frame.shine.normal=black +color.label.background.focussed=khaki4 +color.label.background.normal=grey30 +color.label.shadow.focussed=black +color.label.shadow.normal=grey30 +color.label.shine.focussed=black +color.label.shine.normal=grey30 +color.label.text.focussed=black +color.label.text.normal=grey55 +color.tab.background.active.focussed=khaki4 +color.tab.background.active.normal=gray30 +color.tab.background.inactive.focussed=grey55 +color.tab.background.inactive.normal=grey30 +color.tab.shadow.active.focussed=black +color.tab.shadow.active.normal=black +color.tab.shadow.inactive.focussed=grey55 +color.tab.shadow.inactive.normal=grey30 +color.tab.shine.active.focussed=black +color.tab.shine.active.normal=black +color.tab.shine.inactive.focussed=grey55 +color.tab.shine.inactive.normal=grey30 +color.tab.text.active.focussed=black +color.tab.text.active.normal=grey80 +color.tab.text.inactive.focussed=black +color.tab.text.inactive.normal=grey45 +exec="xsetroot -solid grey10" +font="fixed" + diff --git a/examples/themes/flat-cyan-theme.conf b/examples/themes/flat-cyan-theme.conf @@ -0,0 +1,47 @@ +color.bar.background=\#888888 +color.bar.shadow=\#333333 +color.bar.shine=\#AAAAAA +color.bar.text=\#000000 +color.button.background.normal=\#BBBBBB +color.button.background.pressed=\#777777 +color.button.border.shadow.normal=\#BBBBBB +color.button.border.shadow.pressed=\#777777 +color.button.border.shine.normal=\#BBBBBB +color.button.border.shine.pressed=\#777777 +color.button.figure.shadow.normal=\#336699 +color.button.figure.shadow.pressed=\#AAAAAA +color.button.figure.shine.normal=\#6699AA +color.button.figure.shine.pressed=\#AAAAAA +color.frame.background.focussed=\#888888 +color.frame.pseudo=\#888888 +color.frame.background.normal=\#505050 +color.frame.shadow.focussed=\#333333 +color.frame.shadow.normal=\#111111 +color.frame.shine.focussed=\#AAAAAA +color.frame.shine.normal=\#828282 +color.label.background.focussed=\#505050 +color.label.background.normal=\#333333 +color.label.shadow.focussed=\#111111 +color.label.shadow.normal=\#111111 +color.label.shine.focussed=\#828282 +color.label.shine.normal=\#828282 +color.label.text.focussed=\#BBBBBB +color.label.text.normal=\#999999 +color.tab.background.active.focussed=\#6699AA +color.tab.background.active.normal=\#336699 +color.tab.background.inactive.focussed=\#707070 +color.tab.background.inactive.normal=\#333333 +color.tab.shadow.active.focussed=\#333333 +color.tab.shadow.active.normal=\#111111 +color.tab.shadow.inactive.focussed=\#333333 +color.tab.shadow.inactive.normal=\#111111 +color.tab.shine.active.focussed=\#AAAAAA +color.tab.shine.active.normal=\#828282 +color.tab.shine.inactive.focussed=\#AAAAAA +color.tab.shine.inactive.normal=\#828282 +color.tab.text.active.focussed=\#000000 +color.tab.text.active.normal=\#222222 +color.tab.text.inactive.focussed=\#AAAAAA +color.tab.text.inactive.normal=\#777777 +exec="xsetroot -mod 20 20 -fg \#333333 -bg \#111111" +font=anorexia diff --git a/examples/themes/flat-grey-theme.conf b/examples/themes/flat-grey-theme.conf @@ -0,0 +1,47 @@ +color.bar.background=\#888888 +color.bar.shadow=\#333333 +color.bar.shine=\#AAAAAA +color.bar.text=\#000000 +color.button.background.normal=\#BBBBBB +color.button.background.pressed=\#777777 +color.button.border.shadow.normal=\#BBBBBB +color.button.border.shadow.pressed=\#777777 +color.button.border.shine.normal=\#BBBBBB +color.button.border.shine.pressed=\#777777 +color.button.figure.shadow.normal=\#888888 +color.button.figure.shadow.pressed=\#AAAAAA +color.button.figure.shine.normal=\#888888 +color.button.figure.shine.pressed=\#AAAAAA +color.frame.background.focussed=\#888888 +color.frame.pseudo=\#888888 +color.frame.background.normal=\#505050 +color.frame.shadow.focussed=\#333333 +color.frame.shadow.normal=\#111111 +color.frame.shine.focussed=\#AAAAAA +color.frame.shine.normal=\#828282 +color.label.background.focussed=\#505050 +color.label.background.normal=\#333333 +color.label.shadow.focussed=\#111111 +color.label.shadow.normal=\#111111 +color.label.shine.focussed=\#828282 +color.label.shine.normal=\#828282 +color.label.text.focussed=\#BBBBBB +color.label.text.normal=\#999999 +color.tab.background.active.focussed=\#888888 +color.tab.background.active.normal=\#505050 +color.tab.background.inactive.focussed=\#707070 +color.tab.background.inactive.normal=\#333333 +color.tab.shadow.active.focussed=\#333333 +color.tab.shadow.active.normal=\#111111 +color.tab.shadow.inactive.focussed=\#333333 +color.tab.shadow.inactive.normal=\#111111 +color.tab.shine.active.focussed=\#AAAAAA +color.tab.shine.active.normal=\#828282 +color.tab.shine.inactive.focussed=\#AAAAAA +color.tab.shine.inactive.normal=\#828282 +color.tab.text.active.focussed=\#000000 +color.tab.text.active.normal=\#999999 +color.tab.text.inactive.focussed=\#AAAAAA +color.tab.text.inactive.normal=\#777777 +exec="xsetroot -mod 20 20 -fg \#333333 -bg \#111111" +font=anorexia diff --git a/examples/themes/gold-theme.conf b/examples/themes/gold-theme.conf @@ -0,0 +1,48 @@ +# Gold theme by Kathryn Andersen +color.bar.background=gold3 +color.bar.shadow=gold4 +color.bar.shine=gold2 +color.bar.text=black +color.label.background.focussed=DarkGoldenrod4 +color.label.shadow.focussed=wheat4 +color.label.shine.focussed=DarkGoldenrod2 +color.label.text.focussed=wheat2 +color.label.background.normal=gold3 +color.label.shadow.normal=gold4 +color.label.shine.normal=gold2 +color.label.text.normal=gold4 +color.button.background.normal=gold3 +color.button.background.pressed=gold1 +color.button.border.shadow.normal=gold4 +color.button.border.shadow.pressed=gold2 +color.button.border.shine.normal=gold2 +color.button.border.shine.pressed=gold4 +color.button.figure.shadow.normal=gold4 +color.button.figure.shadow.pressed=gold2 +color.button.figure.shine.normal=gold2 +color.button.figure.shine.pressed=gold4 +color.frame.background.focussed=DarkGoldenrod3 +color.frame.pseudo=DarkGoldenrod3 +color.frame.shadow.focussed=DarkGoldenrod4 +color.frame.shine.focussed=DarkGoldenrod2 +color.frame.background.normal=wheat3 +color.frame.shadow.normal=wheat4 +color.frame.shine.normal=wheat2 +color.tab.background.active.focussed=DarkGoldenrod3 +color.tab.shadow.active.focussed=DarkGoldenrod4 +color.tab.shine.active.focussed=DarkGoldenrod2 +color.tab.text.active.focussed=black +color.tab.background.active.normal=wheat3 +color.tab.shadow.active.normal=wheat4 +color.tab.shine.active.normal=wheat2 +color.tab.text.active.normal=black +color.tab.background.inactive.focussed=gold3 +color.tab.shadow.inactive.focussed=gold4 +color.tab.shine.inactive.focussed=gold2 +color.tab.text.inactive.focussed=gold1 +color.tab.background.inactive.normal=wheat3 +color.tab.shadow.inactive.normal=wheat4 +color.tab.shine.inactive.normal=wheat2 +color.tab.text.inactive.normal=wheat1 +exec="xsetroot -mod 20 20 -fg gold2 -bg gold4" +font=fixed diff --git a/examples/themes/laotse-theme.conf b/examples/themes/laotse-theme.conf @@ -0,0 +1,47 @@ +color.bar.background=\#D3D3D3 +color.bar.shadow=\#D3D3D3 +color.bar.shine=\#D3D3D3 +color.bar.text=black +color.button.background.normal=\#D3D3D3 +color.button.background.pressed=\#D3D3D3 +color.button.border.shadow.normal=\#D3D3D3 +color.button.border.shadow.pressed=\#D3D3D3 +color.button.border.shine.normal=\#D3D3D3 +color.button.border.shine.pressed=\#D3D3D3 +color.button.figure.shadow.normal=black +color.button.figure.shadow.pressed=\#D3D3D3 +color.button.figure.shine.normal=black +color.button.figure.shine.pressed=\#D3D3D3 +color.frame.background.focussed=\#D3D3D3 +color.frame.pseudo=\#D3D3D3 +color.frame.background.normal=\#D3D3D3 +color.frame.shadow.focussed=\#D3D3D3 +color.frame.shadow.normal=black +color.frame.shine.focussed=\#D3D3D3 +color.frame.shine.normal=black +color.label.background.focussed=\#68858E +color.label.background.normal=\#D3D3D3 +color.label.shadow.focussed=black +color.label.shadow.normal=\#D3D3D3 +color.label.shine.focussed=black +color.label.shine.normal=\#D3D3D3 +color.label.text.focussed=black +color.label.text.normal=black +color.tab.background.active.focussed=\#68858E +color.tab.background.active.normal=gray30 +color.tab.background.inactive.focussed=\#D3D3D3 +color.tab.background.inactive.normal=\#D3D3D3 +color.tab.shadow.active.focussed=black +color.tab.shadow.active.normal=black +color.tab.shadow.inactive.focussed=\#D3D3D3 +color.tab.shadow.inactive.normal=\#D3D3D3 +color.tab.shine.active.focussed=black +color.tab.shine.active.normal=black +color.tab.shine.inactive.focussed=\#D3D3D3 +color.tab.shine.inactive.normal=\#D3D3D3 +color.tab.text.active.focussed=black +color.tab.text.active.normal=black +color.tab.text.inactive.focussed=black +color.tab.text.inactive.normal=black +exec="xsetroot -solid black" +font="anorexia" diff --git a/examples/themes/lunatic-theme.conf b/examples/themes/lunatic-theme.conf @@ -0,0 +1,47 @@ +color.bar.background=\#547EE6 +color.bar.shadow=\#506CAF +color.bar.shine=\#82BDFF +color.bar.text=\#FFFFFF +color.button.background.normal=\#CC484D +color.button.background.pressed=\#69DA56 +color.button.border.shadow.normal=\#BBBBBB +color.button.border.shadow.pressed=\#777777 +color.button.border.shine.normal=\#BBBBBB +color.button.border.shine.pressed=\#777777 +color.button.figure.shadow.normal=\#EDE5D0 +color.button.figure.shadow.pressed=\#AAAAAA +color.button.figure.shine.normal=\#EDE5D0 +color.button.figure.shine.pressed=\#AAAAAA +color.frame.background.focussed=\#547EE6 +color.frame.pseudo=\#547EE6 +color.frame.background.normal=\#54A2E6 +color.frame.shadow.focussed=\#506CAF +color.frame.shadow.normal=\#506CAF +color.frame.shine.focussed=\#82BDFF +color.frame.shine.normal=\#82BDFF +color.label.background.focussed=\#547EE6 +color.label.background.normal=\#54A2E6 +color.label.shadow.focussed=\#506CAF +color.label.shadow.normal=\#506CAF +color.label.shine.focussed=\#82BDFF +color.label.shine.normal=\#82BDFF +color.label.text.focussed=\#FFFFFF +color.label.text.normal=\#FFFFFF +color.tab.background.active.focussed=\#547EE6 +color.tab.background.active.normal=\#54A2E6 +color.tab.background.inactive.focussed=\#FFBA7B +color.tab.background.inactive.normal=\#FFBA7B +color.tab.shadow.active.focussed=\#506CAF +color.tab.shadow.active.normal=\#506CAF +color.tab.shadow.inactive.focussed=\#F68D2B +color.tab.shadow.inactive.normal=\#F68D2B +color.tab.shine.active.focussed=\#AAAAAA +color.tab.shine.active.normal=\#828282 +color.tab.shine.inactive.focussed=\#FFD1A7 +color.tab.shine.inactive.normal=\#FFD1A7 +color.tab.text.active.focussed=\#FFFFFF +color.tab.text.active.normal=\#FFFFFF +color.tab.text.inactive.focussed=\#FFFFFF +color.tab.text.inactive.normal=\#FFFFFF +exec="xsetroot -mod 20 20 -fg \#333333 -bg \#111111" +font=anorexia diff --git a/examples/themes/peacock-theme.conf b/examples/themes/peacock-theme.conf @@ -0,0 +1,48 @@ +# "Peacock" by Kathryn Andersen +color.bar.background=\#0F59990F5 +color.bar.shadow=\#0A36660A3 +color.bar.shine=\#51ECCC51E +color.bar.text=\#000000000 +color.button.background.normal=\#0F59990F5 +color.button.background.pressed=\#0F59990F5 +color.button.border.shadow.normal=\#0A36660A3 +color.button.border.shadow.pressed=\#51ECCC51E +color.button.border.shine.normal=\#51ECCC51E +color.button.border.shine.pressed=\#0A36660A3 +color.button.figure.shadow.normal=\#0A36660A3 +color.button.figure.shadow.pressed=\#51ECCC51E +color.button.figure.shine.normal=\#51ECCC51E +color.button.figure.shine.pressed=\#0A36660A3 +color.label.background.focussed=\#0F50F5666 +color.label.shadow.focussed=\#000000333 +color.label.shine.focussed=\#555555CCC +color.label.text.focussed=\#CF5DAEE66 +color.label.background.normal=\#0F59990F5 +color.label.shadow.normal=\#0A36660A3 +color.label.shine.normal=\#51ECCC51E +color.label.text.normal=\#CF5E66CF5 +color.frame.background.focussed=\#0F50F5666 +color.frame.pseudo=\#0F50F5666 +color.frame.shadow.focussed=\#000000333 +color.frame.shine.focussed=\#555555CCC +color.frame.background.normal=\#0A36660A3 +color.frame.shadow.normal=\#000333000 +color.frame.shine.normal=\#51ECCC51E +color.tab.background.active.focussed=\#0F50F5666 +color.tab.shadow.active.focussed=\#000000333 +color.tab.shine.active.focussed=\#555555CCC +color.tab.text.active.focussed=\#CF5DAEE66 +color.tab.background.active.normal=\#0A36660A3 +color.tab.shadow.active.normal=\#000333000 +color.tab.shine.active.normal=\#51ECCC51E +color.tab.text.active.normal=\#CCCDDDCCC +color.tab.background.inactive.focussed=\#0A3666666 +color.tab.shadow.inactive.focussed=\#000333333 +color.tab.shine.inactive.focussed=\#51ECCCCCC +color.tab.text.inactive.focussed=\#999E66E66 +color.tab.background.inactive.normal=\#0A36660A3 +color.tab.shadow.inactive.normal=\#000333000 +color.tab.shine.inactive.normal=\#51ECCC51E +color.tab.text.inactive.normal=black +exec="xsetroot -mod 20 20 -bg \#0A36660A3 -fg \#51ECCC51E" +font=fixed diff --git a/expander.cpp b/expander.cpp @@ -0,0 +1,118 @@ +// Copyright (c) 2003 - 2004 Marcel Manthe <schneegloeckchen at gmx.li> +// See ../LICENSE.txt for license details. +// +// $Id: expander.cpp 734 2004-09-27 18:15:45Z garbeam $ + +extern "C" { +#include <unistd.h> +#include <stdlib.h> + +#include <sys/types.h> +#include <dirent.h> +#include <sys/stat.h> +} + +#include "expander.h" +#include "util.h" + + +Expander::Expander(){ + this->key_ = ""; + this->path_ = ""; + this->rehash(); +} + +bool Expander::rehash(){ + string path_env; + char *p_c = getenv("PATH"); + if (p_c != NULL) { + path_env = (string)p_c; + } + else{ + return(false); + } + paths_ = Util::stringSplit(path_env, ":"); + pathExpands_ = this->read(); + return true; +} + +bool Expander::queryString (string s){ + paths_.clear(); + if ((s.find('/') == string::npos) || (Util::trimL(s).substr(0,1) == ".")) { + //so performing on PATH + key_ = s; + pathSearch_=true; + } + else{ + //we're using the given string as search-base + + path_ = s.substr(0, s.find_last_of('/')+1); + key_= s.substr(s.find_last_of('/')+1); + + paths_.insert(path_); + pathSearch_=false; + } + return(true); +} + +set<string> Expander::expands (){ + + set<string> *target; + if (pathSearch_) { + target = &pathExpands_; + } + else + { + target = &expands_; + *target = this->read(); + } + + return *target; +} + +set<string> Expander::read(){ + set<string> expands; + DIR *dir; + dirent *entry; + + for (set<string>::iterator iter = paths_.begin(); iter != paths_.end(); iter++){ + dir=opendir(iter->c_str()); + if (dir != NULL) { + do { + entry=readdir(dir); + if (entry != NULL) { + bool expand = false; + string filename = (string)(*iter) + "/" + + (string)(entry->d_name); + + /* if we're dealing with a directory, its + sufficient to have read-permission (bash + acts like this) */ + + struct stat Buf; + if (stat(filename.c_str(), &Buf) == 0) + { + if (S_ISDIR(Buf.st_mode)) { + expand = true; + } + } + /* this test for executability uses the real + ids (see man 2 access) and thats why may + be incorrect if wmi is s(u/g)id'd */ + + if (0 == access(filename.c_str(), X_OK)) { + expand = true; + } + + if (expand == true) { + expands.insert((string)(entry->d_name)); + } + } + } while (entry != NULL); + closedir(dir); + } + } + expands.erase("."); + expands.erase(".."); + return(expands); +} diff --git a/expander.h b/expander.h @@ -0,0 +1,37 @@ +// Copyright (c) 2003 - 2004 Marcel Manthe <schneegloeckchen at gmx.li> +// See ../LICENSE.txt for license details. +// +// $Id: expander.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __EXPANDER_H +#define __EXPANDER_H + +#include <string> +#include <set> + +#include "singleton.h" + +using namespace std; + + +/** + * Provides PATH executable expansion. + */ +class Expander : public Singleton<Expander>{ + public: + Expander(); + bool queryString (string s); + bool rehash(); + set<string> expands(); + + private: + set<string> read(); + bool pathSearch_; + string key_; + string path_; + set<string> paths_; + set<string> expands_; + set<string> pathExpands_; +}; + +#endif // __EXPANDER_H diff --git a/float.cpp b/float.cpp @@ -0,0 +1,75 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: float.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include "float.h" + +#include "rectangle.h" + +// applied patch by Dr. J. Pfefferl +void Float::resize(Rectangle *rect, Direction dir, int stepW, int stepH) +{ + int newW, newH; + + switch (dir) { + case NORTH_WEST: + case SOUTH_WEST: + case LEFT: + newW = rect->width() - stepW; + if (0 < newW) { + rect->setX(rect->x() + stepW); + rect->setWidth(newW); + } + break; + case NORTH_EAST: + case SOUTH_EAST: + case RIGHT: + newW = rect->width() + stepW; + if (0 < newW) { + rect->setWidth(newW); + } + break; + default: + break; + } + + switch (dir) { + case NORTH_WEST: + case NORTH_EAST: + case UP: + newH = rect->height() - stepH; + if (0 < newH) { + rect->setY(rect->y() + stepH); + rect->setHeight(newH); + } + break; + case SOUTH_WEST: + case SOUTH_EAST: + case DOWN: + newH = rect->height() + stepH; + if (0 < newH) { + rect->setHeight(newH); + } + break; + default: + break; + } +} + +void Float::move(Rectangle *rect, int stepW, int stepH) { + rect->setX(rect->x() + stepW); + rect->setY(rect->y() + stepH); +} + +void Float::center(Rectangle *rect, Rectangle *parentRect) { + + unsigned int clientCenterX = (rect->x() + rect->width()) / 2; + unsigned int clientCenterY = (rect->y() + rect->height()) / 2; + unsigned int parentCenterX = (parentRect->x() + parentRect->width()) / 2; + unsigned int parentCenterY = (parentRect->y() + parentRect->height()) / 2; + int dx = parentCenterX - clientCenterX; + int dy = parentCenterY - clientCenterY; + rect->setX(rect->x() + dx); + rect->setY(rect->y() + dy); +} diff --git a/float.h b/float.h @@ -0,0 +1,30 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: float.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __FLOAT_H +#define __FLOAT_H + +#include "wmi.h" + +class Rectangle; + +/** + * Provides base algorithms for moving and resizing rectangles + * in a floating manner. + */ +class Float { + +public: + + /** Used for resizing. */ + static void resize(Rectangle *rect, Direction dir, + int stepW, int stepH); + + static void move(Rectangle *rect, int stepW, int stepH); + + static void center(Rectangle *rect, Rectangle *parentRect); + +}; +#endif // __FLOAT_H diff --git a/font.cpp b/font.cpp @@ -0,0 +1,34 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: font.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include "font.h" + +#include "xcore.h" +#include "xfont.h" +#include "xftfont.h" + +WFont::WFont(Monitor *monitor) { + monitor_ = monitor; +} + +WFont::~WFont() { +} + +WFont *WFont::load(Monitor *monitor, string name) { + + WFont *font = XFont::load(monitor, name); +#ifdef XFT_SUPPORT + if (!font) { + // fallback if XFT_SUPPORT enabled + font = WXftFont::load(monitor, name); + } +#endif + return font; +} + + +WFont::Type WFont::type() const{ + return type_; +} diff --git a/font.h b/font.h @@ -0,0 +1,52 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: font.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __FONT_H +#define __FONT_H + +extern "C" { +#include <X11/Xlib.h> +} + +#include <string> + +#include "wmi.h" + +class Monitor; + +/** Base class for fonts (currently default XFonts and XftFonts). */ +class WFont { + +public: + + enum Type {NORMAL, XFT}; + + WFont(Monitor *monitor); + virtual ~WFont(); + + Type type() const; + + static WFont *load(Monitor *monitor, string name); + + virtual void drawText(Window window, GC gc, int x, int y, string text) = 0; + + virtual int textWidth(string text) = 0; + + virtual unsigned int height() = 0; + + virtual void setHeight(unsigned int height) = 0; + + virtual int ascent() = 0; + + virtual int descent() = 0; + +protected: + + Monitor *monitor_; + Type type_; + +}; + +#endif // __FONT_H diff --git a/frame.cpp b/frame.cpp @@ -0,0 +1,458 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: frame.cpp 734 2004-09-27 18:15:45Z garbeam $ + +extern "C" { +#include <assert.h> +} + +#include <sstream> + +#include "frame.h" + +#include "client.h" +#include "cursors.h" +#include "draw.h" +#include "frame.h" +#include "kernel.h" +#include "label.h" +#include "logger.h" +#include "monitor.h" +#include "split.h" +#include "theme.h" +#include "tree.h" +#include "util.h" +#include "workspace.h" +#include "xcore.h" + +Frame::Frame(Workspace *workspace, Rectangle *rect) + : Thing(workspace->attached(), rect, Thing::FRAME), + Container<Workspace, LClient, LClient::iterator, Client>(workspace) +{ + ostringstream oss; + oss << "<" << workspace->nextFrameId() << ">"; + setName(oss.str()); + isTiled_ = Util::get(KERNEL->commonSettings(), "frame.mode") == "tiled"; +} + +Frame::~Frame() { +} + +bool Frame::isFocused() { + bool result = attached() && attached()->focusedFrame() == this; + if (focused()) { + result = result && (focused() == attached()->topClient()); + } + return result; +} + +void Frame::focus(Client *client) { + + Container<Workspace, LClient, LClient::iterator, Client> + ::focus(client); + XCORE->raise(client->clientWindow()); +} + +void Frame::illuminate() { + + if (!isVisible()) { + return; + } + + illuminateBorder(); + + bool foc = this->isFocused(); + + if (titleBarHeight_) { + + unsigned int buttonWidth = 0; + unsigned int labelsWidth = width() - 2 * borderWidth_; + unsigned int offsetX = borderWidth_; + if (foc && areButtonsVisible_) { + buttonWidth = monitor()->buttonWidth(); + labelsWidth -= (3 * buttonWidth) - 3; + } + + unsigned int labelWidth = size() ? labelsWidth / size() : labelsWidth; + + unsigned int i = 0; + label_->setWidth(labelWidth); + for (LClient::iterator it = begin(); it != end(); ) { + + Client *client = *it; + it++; + + label_->setText(client->name()); + label_->setX(offsetX + i * labelWidth); + if (it == end()) { + // FIX for right button panel irretations + label_->setWidth( + width() - label_->x() - 3 * buttonWidth - + ((foc && areButtonsVisible_) ? 3 + borderWidth_ : borderWidth_)); + } + i++; + if (foc) { // FOCUSSED + if (client == focused()) { + label_->update(theme_->TAB_BACKGROUND_ACTIVE_FOCUSSED, + theme_->TAB_TEXT_ACTIVE_FOCUSSED, + theme_->TAB_SHINE_ACTIVE_FOCUSSED, + theme_->TAB_SHADOW_ACTIVE_FOCUSSED, + true, true); + } + else if (client->requestsFocus()) { + label_->update(theme_->FOCUSREQ_BACKGROUND, + theme_->FOCUSREQ_TEXT, + theme_->FOCUSREQ_SHINE, + theme_->FOCUSREQ_SHADOW, + true, true); + } + else { + label_->update(theme_->TAB_BACKGROUND_INACTIVE_FOCUSSED, + theme_->TAB_TEXT_INACTIVE_FOCUSSED, + theme_->TAB_SHINE_INACTIVE_FOCUSSED, + theme_->TAB_SHADOW_INACTIVE_FOCUSSED, + true, true); + } + } + else { // NORMAL + if (client == focused()) { + label_->update(theme_->TAB_BACKGROUND_ACTIVE_NORMAL, + theme_->TAB_TEXT_ACTIVE_NORMAL, + theme_->TAB_SHINE_ACTIVE_NORMAL, + theme_->TAB_SHADOW_ACTIVE_NORMAL, + true, true); + } + else if (client->requestsFocus()) { + label_->update(theme_->FOCUSREQ_BACKGROUND, + theme_->FOCUSREQ_TEXT, + theme_->FOCUSREQ_SHINE, + theme_->FOCUSREQ_SHADOW, + true, true); + } + else { + label_->update(theme_->TAB_BACKGROUND_INACTIVE_NORMAL, + theme_->TAB_TEXT_INACTIVE_NORMAL, + theme_->TAB_SHINE_INACTIVE_NORMAL, + theme_->TAB_SHADOW_INACTIVE_NORMAL, + true, true); + } + } + } + if (!size()) { + label_->setText("<empty>" + name()); + if (foc) { // FOCUSSED + label_->update(theme_->TAB_BACKGROUND_ACTIVE_FOCUSSED, + theme_->TAB_TEXT_ACTIVE_FOCUSSED, + theme_->TAB_SHINE_ACTIVE_FOCUSSED, + theme_->TAB_SHADOW_ACTIVE_FOCUSSED, + true, true); + } + else { // NORMAL + label_->update(theme_->TAB_BACKGROUND_ACTIVE_NORMAL, + theme_->TAB_TEXT_ACTIVE_NORMAL, + theme_->TAB_SHINE_ACTIVE_NORMAL, + theme_->TAB_SHADOW_ACTIVE_NORMAL, + true, true); + } + } + } + if (isTiled_) { + unsigned shine, shadow; + for (LClient::iterator it = begin(); it != end(); it++) { + Client *client = *it; + if (foc && client == focused()) { + shine = theme_->TILED_SHINE_FOCUSSED; + shadow = theme_->TILED_SHADOW_FOCUSSED; + } + else { + shine = theme_->TILED_SHINE_NORMAL; + shadow = theme_->TILED_SHADOW_NORMAL; + } + Rectangle rect; + rect.setX(client->x() - 1); + rect.setY(client->y() - 1); + rect.setWidth(client->width() + 2); + rect.setHeight(client->height() + 2); + Draw::drawRectBorder(frameWindow_, gc_, &rect, shine, shadow); + } + } +} + +void Frame::resize() { + + label_->setY(borderWidth_); + XCORE->clearWindow(window()); + XCORE->moveResize(window(), this); + + fitClientArea(); + if (isTiled_ && size() > 1) { + unsigned int colWidth = + Util::strToUInt(Util::get(KERNEL->commonSettings(), "frame.colwidth")); + + colWidth = (clientAreaRect_.width() * colWidth) / 100; + unsigned int stackHeight = clientAreaRect_.height() / (size() - 1); + unsigned int i = 0; + + for (LClient::iterator it = begin(); it != end(); it++) { + Client *client = *it; + if (it == begin()) { + // left column + client->copy(&clientAreaRect_); + client->setX(clientAreaRect_.x() + 1); + client->setY(clientAreaRect_.y() + 1); + client->setWidth(colWidth - 2); + client->setHeight(clientAreaRect_.height() - 2); + } + else { + // right column + client->setX(clientAreaRect_.x() + colWidth + 1); + client->setY(i * stackHeight + clientAreaRect_.y() + 1); + client->setHeight(stackHeight - 2); + client->setWidth(clientAreaRect_.width() - colWidth - 2); + i++; + } + client->resize(); + } + } + else { + for (LClient::iterator it = begin(); it != end(); it++) { + Client *client = *it; + matchClientSize(client); + } + } + illuminate(); +} + +void Frame::matchClientSize(Client *client) +{ + client->copy(&clientAreaRect_); + client->resize(); +} + +void Frame::attach(Client *client) { + + if (client->frame() == this) { + LOGWARN("frame already attached."); + return; + } + Container<Workspace, LClient, LClient::iterator, Client> + ::attach(client); + client->setFrame(this); + client->prevRectangle()->copy(client); + client->reparent(window(), clientAreaRect_.x(), clientAreaRect_.y()); + XCORE->sync(); + if (isVisible()) { + client->show(); + } + childs()->remove(client); + childs()->push_front(client); + resize(); + LOGDEBUG("attached client to frame"); +} + +Client *Frame::detach(Client *client) { + + assert(size() > 0); + XCORE->sync(); + LOGDEBUG("detaching clientframe"); + Client *next = Container<Workspace, LClient, LClient::iterator, Client> + ::detach(client); + if (client->isVisible()) { + client->hide(); + } + if (size() > 0) { + assert(next); + } + client->reparent(monitor()->rootWindow(), client->x(), client->y()); + client->copy(client->prevRectangle()); + client->setFrame(0); + if (next) { + resize(); + } + return next; +} + +void Frame::handleButtonPress(XButtonEvent *event) { + + // TODO: make buttons customizable + if (event->button == Button1) { + + if (!isFocused()) { + attached()->focus(focused()); + return; + } + else { + XCORE->raise(window()); + } + + buttonState_ = NONE; + if (titleBarHeight_ && (cursor_ == Cursors::NORMAL_CURSOR) && size()) { + LOGDEBUG("normal cursor / switching client"); + int xPosition = event->x; + unsigned int buttonWidth = titleBarHeight_ + 1; + if (areButtonsVisible_) { + unsigned int offsetButtonGroup = width() - borderWidth_ - 3 * buttonWidth; + if ((xPosition > (int)offsetButtonGroup) && + (xPosition < (int)(width() - borderWidth_ - 1))) + { + xPosition -= offsetButtonGroup; + unsigned int buttonNum = xPosition / buttonWidth; + switch (buttonNum) { + case 0: + buttonState_ = MINCLIENT; + break; + case 1: + buttonState_ = DEMAX; + break; + case 2: + buttonState_ = CLOSE; + break; + } + illuminate(); + return; + } + } + + // handle label click + xPosition -= borderWidth_; + unsigned int labelsWidth = width() - 2 * borderWidth_ + - (areButtonsVisible_ ? (3 * buttonWidth) - 2 : 0); + unsigned int labelWidth = labelsWidth / size(); + + unsigned int clientNum = xPosition / labelWidth; + unsigned int i = 0; + + for (LClient::iterator it = begin(); it != end(); it++) { + + if (i == clientNum) { + attached()->focus(*it); + return; + } + i++; + } + } + + if (monitor()->isThingMaximized()) { + return; + } + + Direction dir = DOWN; + if (cursor_ == Cursors::RESIZE_LEFT_CURSOR) { + dir = LEFT; + } + else if (cursor_ == Cursors::RESIZE_RIGHT_CURSOR) { + dir = RIGHT; + } + else if (cursor_ == Cursors::RESIZE_UP_CURSOR) { + dir = UP; + } + else if (cursor_ == Cursors::RESIZE_DOWN_CURSOR) { + dir = DOWN; + } + + // Patch applied by Christof Musik + if (cursor_ != Cursors::NORMAL_CURSOR) { + + if (Split::neighbor(attached()->root(), tree_, dir)) { + Kernel::instance()->runResizeMode(this, event, dir); + } + else if (event->button == Button4) { + monitor()->focused()->cycleClientPrev(); + } else if (event->button == Button5) { + monitor()->focused()->cycleClientNext(); + } + } + } +} + +void Frame::handleButtonRelease(XButtonEvent *event) { + + if (titleBarHeight_ && (event->button == Button1)) + { + if ((buttonState_ != NONE) && monitor()->isThingMaximized()) { + monitor()->toggleThingMaximization(); + } + InvertButton state = buttonState_; + buttonState_ = NONE; + switch (state) { + case MINCLIENT: + monitor()->detachClient(); + break; + case DEMAX: + attached()->toggleClientMode(); + break; + case CLOSE: + XCORE->kill(focused()->clientWindow(), focused()->protocols()); + break; + case NONE: + break; + } + } + +} + +Cursor Frame::cursorForXY(int pointerX, int pointerY) { + + if (borderWidth_ == 0) { + return Cursors::NORMAL_CURSOR; + } + bool left = pointerX < clientAreaRect_.x(); + bool right = pointerX >= + (int)(clientAreaRect_.x() + clientAreaRect_.width()); + bool up; + if (titleBarHeight_) { + up = pointerY < + (int)(clientAreaRect_.y() - titleBarHeight_ - 1); + } + else { + up = pointerY < clientAreaRect_.y(); + } + bool down = pointerY >= + (int)(clientAreaRect_.y() + clientAreaRect_.height()); + + if (left && Split::neighbor(attached()->root(), tree_, LEFT)) { + return Cursors::RESIZE_LEFT_CURSOR; + } + else if (right && Split::neighbor(attached()->root(), tree_, RIGHT)) { + return Cursors::RESIZE_RIGHT_CURSOR; + } + else if (up && Split::neighbor(attached()->root(), tree_, UP)) { + return Cursors::RESIZE_UP_CURSOR; + } + else if (down && Split::neighbor(attached()->root(), tree_, DOWN)) { + return Cursors::RESIZE_DOWN_CURSOR; + } + + return Cursors::NORMAL_CURSOR; +} + +Tree *Frame::tree() const { + return tree_; +} + +void Frame::setTree(Tree *t) { + tree_ = t; +} + +Window Frame::window() { + return frameWindow_; +} + +void Frame::toggleTiled() { + isTiled_ = !isTiled_; + resize(); +} + +void Frame::zoomClient() { + if (focused() && size() > 1) { + if (focused() == *begin()) { + attached()->focus(next()); + } + Client *client = focused(); + childs()->remove(client); + childs()->push_front(client); + resize(); + } +} + diff --git a/frame.h b/frame.h @@ -0,0 +1,71 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: frame.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __FRAME_H +#define __FRAME_H + +#include "container.h" +#include "thing.h" +#include "wmi.h" + +// forward declaration +class Client; +class Tree; +class Workspace; + +typedef list<Client *> LClient; + +/** + * Represents a frame of WMI. Frames are container for clients in + * non-overlapping configurations. + */ +class Frame + : public Thing, + public Container<Workspace, LClient, LClient::iterator, Client> +{ + +public: + + Frame(Workspace *workspace, Rectangle *rect); + + ~Frame(); + + void focus(Client *client); + + void attach(Client *client); + Client *detach(Client *client); + + virtual Window window(); + + /** Resizes all clients of this frame. */ + virtual void resize(); + + /** Illuminates this frame. */ + virtual void illuminate(); + + virtual bool isFocused(); + + virtual void handleButtonPress(XButtonEvent *event); + virtual void handleButtonRelease(XButtonEvent *event); + + virtual Cursor cursorForXY(int pointerX, int pointerY); + + /** Matches client size. */ + void matchClientSize(Client *client); + + void setTree(Tree *t); + + Tree *tree() const; + + void toggleTiled(); + void zoomClient(); + +private: + + bool isTiled_; + Tree *tree_; +}; + +#endif // __FRAME_H diff --git a/inputbar.cpp b/inputbar.cpp @@ -0,0 +1,463 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: inputbar.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include "inputbar.h" + +extern "C" { +#include <assert.h> +#include <stdlib.h> +} + +#include "action.h" +#include "actions.h" +#include "binder.h" +#include "kernel.h" +#include "label.h" +#include "logger.h" +#include "monitor.h" +#include "prompt.h" +#include "theme.h" +#include "workspace.h" +#include "xcore.h" + +InputBar::InputBar(Monitor *monitor, Rectangle *rect) + : Bar(monitor, rect) +{ + + LOGDEBUG("initializing input"); + currAction_ = 0; + prompt_ = 0; + promptCounter_ = 0; + isArgument_ = false; + partitionBegin_ = selected_ = entryBegin_; + args_ = ""; + LOGDEBUG("creating input"); +} + +InputBar::~InputBar() { +} + +void InputBar::selectPrevEntry() { + + if (entryBegin_ == entryEnd_) { + // nothing to select, empty list + return; + } + + if (selected_ != partitionBegin_) { + selected_--; + } + else { + + if (partitionBegin_ != entryBegin_) { + + selected_ = --partitionBegin_; + partitionBegin_ = prevPartitions_.top(); + prevPartitions_.pop(); + } + else { + clearPrevPartitionsStack(); + } + } +} + +void InputBar::selectNextEntry() { + + if (entryBegin_ == entryEnd_) { + // nothing to select, empty list + return; + } + + Sstring::iterator tmp = selected_; + selected_++; + + if (selected_ == entryEnd_) { + selected_ = partitionBegin_ = entryBegin_; + clearPrevPartitionsStack(); + return; + } + + if (tmp == partitionEnd_) { + prevPartitions_.push(partitionBegin_); + partitionBegin_ = selected_; + } +} + +void InputBar::illuminate() { + + if (!isVisible()) { + return; + } + + drawBorder(); + LOGDEBUG("input update"); + + // draw background + label_->setAlignment(Label::CENTER); + label_->setText(""); + label_->setX(1); + label_->setWidth(width() - 2); + label_->update(theme_->BAR_BACKGROUND, theme_->BAR_TEXT, + theme_->BAR_SHINE, theme_->BAR_SHADOW); + + // draw prompt + label_->setText(prompt_ ? prompt_->prompt() : ""); + label_->adjustWidth(); + label_->update(theme_->BAR_BACKGROUND, theme_->BAR_TEXT, + theme_->BAR_SHINE, theme_->BAR_SHADOW); + label_->setX(label_->x() + label_->width()); + + // draw text + label_->setText(text_); + label_->adjustWidth(); + label_->update(theme_->BAR_BACKGROUND, theme_->BAR_TEXT, + theme_->BAR_SHINE, theme_->BAR_SHADOW); + label_->setX(label_->x() + label_->width()); + + if (partitionBegin_ != entryBegin_) { + label_->setText("<<"); + label_->adjustWidth(); + label_->update(theme_->BAR_BACKGROUND, theme_->BAR_TEXT, + theme_->BAR_SHINE, theme_->BAR_SHADOW); + label_->setX(label_->x() + label_->width()); + } + + label_->setText(">>"); + unsigned int nextWidth = label_->adjustWidth(); + + for (Sstring::iterator it = partitionBegin_; it != entryEnd_; it++) + { + string currStr = *it; + label_->setText(currStr); + label_->adjustWidth(); + + // draw entry + if (label_->x() + label_->width() < (width() - nextWidth)) { + + if (selected_ != it) { + label_->update(theme_->LABEL_BACKGROUND_NORMAL, + theme_->LABEL_TEXT_NORMAL, + theme_->LABEL_SHINE_NORMAL, + theme_->LABEL_SHADOW_NORMAL); + } + else { + label_->update(theme_->LABEL_BACKGROUND_FOCUSSED, + theme_->LABEL_TEXT_FOCUSSED, + theme_->LABEL_SHINE_FOCUSSED, + theme_->LABEL_SHADOW_FOCUSSED, + true, true); + } + } + else { + partitionEnd_ = --it; + label_->setText(">>"); + label_->adjustWidth(); + label_->update(theme_->BAR_BACKGROUND, theme_->BAR_TEXT, + theme_->BAR_SHINE, theme_->BAR_SHADOW); + break; + } + label_->setX(label_->x() + label_->width()); + } +} + +string InputBar::text(bool onExecEnter) { + + if ((selected_ == entryBegin_) && (entryBegin_ == entryEnd_)) { + return text_; + } + else { + // If an input begins with '/' character we use also the prefix path + if (onExecEnter && (text_.length() > 0) && (text_[0] == '/')) { + text_ = text_.substr(0, text_.find_last_of('/') + 1); + return text_ + *selected_; + } + return *selected_; + } +} + +void InputBar::clearPrevPartitionsStack() { + while (!prevPartitions_.empty()) { + prevPartitions_.pop(); + } +} + +void InputBar::removeChar() { + + if (!isVisible() || !prompt_) { + return; + } + + int textLength = text_.length(); + if (textLength < 1) { + return; + } + + if (prompt_->toQuery() && names_.size()>0) { + unsigned int numNames = names_.size(); + for (; (numNames == names_.size()) && (textLength >= 0); + textLength--) + { +#ifdef POSIX_REGEX + string s = Binder::instance()->popRegexPattern(); + LOGDEBUG("popping from STACK: " + s); + queryText(s); + textLength=s.length(); +#else + queryText(text_.substr(0, textLength)); +#endif + } + } + else { + queryText(text_.substr(0, textLength - 1)); + } + illuminate(); +} + +void InputBar::queryText(string text) { + + if (!isVisible() || !prompt_) { + return; + } + + QueryNamesForPrefix toQuery = prompt_->toQuery(); + names_.clear(); + + if (toQuery) { + text_ = ((*Binder::instance()).*toQuery)(text, &names_); + entryBegin_ = names_.begin(); + entryEnd_ = names_.end();; + selected_ = partitionBegin_ = entryBegin_; + clearPrevPartitionsStack(); + } + else { + partitionBegin_ = selected_ = entryBegin_; + text_ = text; + } +} + +void InputBar::handleInput(XKeyEvent *event) { + + static const char *home = getenv("HOME"); + static bool isNext = false; + char buffer[32]; + int count; + + if (!isVisible()) { + return; + } + static KeySym sym; + // patch contributed by Marcin Pawlik + sym = XCORE->lookupNextKeySym(event, &count, buffer); + if (IsFunctionKey(sym) || IsKeypadKey(sym) || + IsMiscFunctionKey(sym) || IsPFKey(sym) || + IsPrivateKeypadKey(sym)) + { + return; // ignore + } + + bool reset = false; + if (event->state & ControlMask) { + switch (sym) { + case XK_H: + case XK_h: + sym = XK_BackSpace; + break; + case XK_J: + case XK_j: + sym = XK_Return; + break; + case XK_G: + case XK_g: + sym = XK_Escape; + break; + case XK_U: + case XK_u: + reset = true; + break; + } + } + + switch (sym) { + case XK_BackSpace: + removeChar(); + break; + case XK_Right: + selectNextEntry(); + break; + case XK_Left: + selectPrevEntry(); + break; + case XK_Return: + handlePressedReturn(); + break; + case XK_Escape: + escape(); + break; + case XK_Num_Lock: + break; + default: + if (reset) { + text_ = ""; + queryText(text_); + } + else if ((count == 1) && !iscntrl(buffer[0])) { + buffer[count] = 0; + string text = ""; + if (home && (buffer[0] == '~')) { + text = text_ + home; + } + else { + text = text_ + buffer; + } + queryText(text); + text_ = text; + } + else if (sym == XK_Tab) { + string text = text_; + if (!isNext) { + queryText(text_); + } + isNext = (text == text_); + if (isNext) { + selectNextEntry(); + } + } +#ifdef POSIX_REGEX + if (text_=="") {Binder::instance()->clearRegexPattern();}else{ + if (!names_.empty()) Binder::instance()->pushRegexPattern(text_);} + +#endif + break; + } + if (sym != XK_Tab) { + isNext = false; + } + illuminate(); +} + +void InputBar::escape() { + + promptCounter_ = 0; + args_ = ""; + prompt_ = 0; + currAction_ = 0; +#ifdef POSIX_REGEX + Binder::instance()->clearRegexPattern(); +#endif + XCORE->ungrabKeyboard(); + hide(); +} + +void InputBar::handlePressedReturn() { + + string actionKey; + bool isDirectInvocation = false; + + LOGDEBUG("fetching selection"); + actionKey = text(); + unsigned int pos = actionKey.find_first_of('+'); + if (!isArgument_ && (pos != string::npos)) { + args_ = actionKey.substr(pos + 1); + actionKey = actionKey.substr(0, pos); + isDirectInvocation = true; + } + LOGDEBUG("selection fetched"); + if (isArgument_ || (actionKey != "") || isDirectInvocation) { + + if (!isArgument_ || isDirectInvocation) + { // fetch action + LOGDEBUG("fetching action: " + actionKey ); + currAction_ = Util::get(KERNEL->actionBindings(), actionKey); + } + + if (currAction_) { + + if (!isArgument_ && + (currAction_->promptsCount() > 0) && !isDirectInvocation) + { + // set prompt of first argument + prompt_ = currAction_->prompt(0); + isArgument_ = true; + queryText(""); + } + else if (isArgument_) { + + // fetch args + if (args_.length() > 0) { + args_ += '+'; + } + args_ += text((currAction_->getToPerform() == &Actions::execute) || + (currAction_->getToPerform() == &Actions::executeTerm)); + + promptCounter_++; + if (promptCounter_ < currAction_->promptsCount()) { + prompt_ = currAction_->prompt(promptCounter_); + } + queryText(""); // keyboard is already grabbed + } + illuminate(); + + if ((promptCounter_ == currAction_->promptsCount()) || + isDirectInvocation) + { + LOGDEBUG("going to perform action"); + if (isArgument_ || isDirectInvocation) { + LOGDEBUG("got args: " + args_); + currAction_->setArgument((char *)args_.c_str()); + } + // otherwise default invocation + currAction_->perform(); + escape(); + } + else { + return; + } + } + } +} + +void InputBar::runKey(Prompt *prompt) { + if (!isVisible()) { + show(); + } + XCORE->grabKeyboard(window()); + currAction_ = 0; + prompt_ = prompt; + isArgument_ = false; + queryText(""); + illuminate(); +} + +void InputBar::runArgument(Action *action) { + if (!action->isValid()) { + return; + } + if (!isVisible()) { + show(); + } + XCORE->grabKeyboard(window()); + currAction_ = action; + // set prompt of first argument + prompt_ = currAction_->prompt(0); + isArgument_ = true; + queryText(""); + illuminate(); +} + +void InputBar::handleMotionNotify(XMotionEvent *event) { + // nothing todo +} + +void InputBar::handleButtonPress(XButtonEvent *event) { + escape(); +} + +void InputBar::handleButtonRelease(XButtonEvent *event) { + // nothing todo +} + +bool InputBar::isArgument() const { + return isArgument_; +} diff --git a/inputbar.h b/inputbar.h @@ -0,0 +1,82 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: inputbar.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __INPUTBAR_H +#define __INPUTBAR_H + +#include <set> +#include <stack> +#include <string> +#include "wmi.h" + +#include "bar.h" + +class Action; +class Monitor; +class Prompt; +class Theme; + +typedef set<string> Sstring; +typedef stack<Sstring::iterator> SSstringIter; + +/** + * Represents the input bar and input mode of WMI. + */ +class InputBar: public Bar +{ + +public: + + InputBar(Monitor *monitor, Rectangle *rect); + + ~InputBar(); + + virtual void illuminate(); + + virtual void handleMotionNotify(XMotionEvent *event); + virtual void handleButtonPress(XButtonEvent *event); + virtual void handleButtonRelease(XButtonEvent *event); + + /** Handler for input key events. */ + void handleInput(XKeyEvent *event); + void handlePressedReturn(); + + void runKey(Prompt *prompt); + void runArgument(Action *action); + +private: + + bool isArgument() const; + + string text(bool onExecEnter = false); + + void queryText(string text); + void removeChar(); + void clearPrevPartitionsStack(); + + void selectNextEntry(); + void selectPrevEntry(); + + void escape(); + + /** Provides argument processing. */ + Action *currAction_; + + Sstring names_; + + bool isArgument_; + Sstring::iterator entryBegin_; + Sstring::iterator entryEnd_; + Sstring::iterator partitionBegin_; + Sstring::iterator partitionEnd_; + Sstring::iterator selected_; + SSstringIter prevPartitions_; + Prompt *prompt_; + string text_; + string args_; + unsigned int promptCounter_; +}; + +#endif // __INPUTBAR_H diff --git a/install-sh b/install-sh @@ -0,0 +1,325 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2004-04-01.17 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename= +transform_arg= +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd= +chgrpcmd= +stripcmd= +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src= +dst= +dir_arg= + +usage="Usage: $0 [OPTION]... SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 -d DIRECTORIES... + +In the first form, install SRCFILE to DSTFILE, removing SRCFILE by default. +In the second, create the directory path DIR. + +Options: +-b=TRANSFORMBASENAME +-c copy source (using $cpprog) instead of moving (using $mvprog). +-d create directories instead of installing files. +-g GROUP $chgrp installed files to GROUP. +-m MODE $chmod installed files to MODE. +-o USER $chown installed files to USER. +-s strip installed files (using $stripprog). +-t=TRANSFORM +--help display this help and exit. +--version display version info and exit. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG +" + +while test -n "$1"; do + case $1 in + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + -c) instcmd=$cpprog + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + --help) echo "$usage"; exit 0;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + --version) echo "$0 $scriptversion"; exit 0;; + + *) # When -d is used, all remaining arguments are directories to create. + test -n "$dir_arg" && break + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dstarg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dstarg" + shift # fnord + fi + shift # arg + dstarg=$arg + done + break;; + esac +done + +if test -z "$1"; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + instcmd=: + chmodcmd= + else + instcmd=$mkdirprog + fi + else + # Waiting for this to be detected by the "$instcmd $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" || lasterr=$? + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test ! -d "$pathcomp" && { (exit ${lasterr-1}); exit; } + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $instcmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + # If we're going to rename the final executable, determine the name now. + if test -z "$transformarg"; then + dstfile=`basename "$dst"` + else + dstfile=`basename "$dst" $transformbasename \ + | sed $transformarg`$transformbasename + fi + + # don't allow the sed command to completely eliminate the filename. + test -z "$dstfile" && dstfile=`basename "$dst"` + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 + trap '(exit $?); exit' 1 2 13 15 + + # Move or copy the file name to the temp name + $doit $instcmd "$src" "$dsttmp" && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $instcmd $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ + || { + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + } + } + fi || { (exit 1); exit; } +done + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit +} + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/kernel.cpp b/kernel.cpp @@ -0,0 +1,1294 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: kernel.cpp 734 2004-09-27 18:15:45Z garbeam $ + +extern "C" { +#include <assert.h> +#include <stdlib.h> // getenv stuff +#include <string.h> +#include <unistd.h> +#include <X11/Xlib.h> +#include <X11/Xatom.h> +#include <X11/Xutil.h> +} + +#include <sstream> + +#include "kernel.h" + +#include "action.h" +#include "actions.h" +#include "atoms.h" +#include "binder.h" +#include "box.h" +#include "client.h" +#include "clientbar.h" +#include "cursors.h" +#include "container.h" +#include "draw.h" +#include "expander.h" +#include "float.h" +#include "frame.h" +#include "inputbar.h" +#include "launcher.h" +#include "loader.h" +#include "logger.h" +#include "menu.h" +#include "monitor.h" +#include "prompt.h" +#include "shortcut.h" +#include "slot.h" +#include "split.h" +#include "statusbar.h" +#include "thing.h" +#include "util.h" +#include "validators.h" +#include "workspace.h" +#include "xcore.h" + +Kernel::Kernel() { +} + +void Kernel::initMonitors() { + + unsigned int monitorCount = ScreenCount(display_); + + for (unsigned int i = 0; i < monitorCount; i++) { + Monitor *monitor = new Monitor(display_, i); + monitors_->attach(monitor); + } +} + +int Kernel::start(char *argv[], Display *display, MSettings *themeSettings, + MSettings *commonSettings, MSettings *actionSettings, + MSettings *sessionSettings, bool isFirstRun) +{ + + runlevel_ = START; + + // init, order is very important + display_ = display; + monitors_ = new CMonitor(this); + themeSettings_ = themeSettings; + commonSettings_ = commonSettings; + actionSettings_ = actionSettings; + sessionSettings_ = sessionSettings; + actionBindings_ = new MBindings(); + isRecording_ = false; + isMenuMode_ = false; + isSloppyMode_ = true; + isStackedTabbing_ = Util::get(commonSettings_, "cycle.mode") != "default"; + borderWidth_ = Util::strToUInt(Util::get(commonSettings_, "border.width")); + + LOGDEBUG("--- begin of new WMI session ---"); + XSetErrorHandler(XCore::handleErrors); + LOGDEBUG("error handler installed"); + XCORE->setDisplay(display_); + LOGDEBUG("xcore initialized"); + Atoms::initAtoms(); + LOGDEBUG("atoms initialized"); + Cursors::initCursors(); + LOGDEBUG("cursors initialized"); + Actions::instance()->initInternActions(actionBindings_); + LOGDEBUG("intern actions initialized"); + initActionBindings(); + LOGDEBUG("action bindings initialized"); + initMonitors(); + LOGDEBUG("monitors initialized"); + initKeys(); + LOGDEBUG("keys initialized"); + Launcher::instance()->exec( + Util::get(themeSettings_, "exec")); + if (isFirstRun) { + Actions::instance()->executeTerm(0, "man wmi"); + } + // Sync all X buffers and wait until all events has been + // processed + XCORE->sync(); + initWindows(); + LOGDEBUG("windows initialized"); + + defaultPrompt_ = new Prompt(": ", &Binder::queryActionKeysForPattern); + + Action* startupAction = new Action("startup", &Actions::sequence, + &Validators::isAlwaysPossible, + Action::SEQUENCE, + strdup(Util::get(commonSettings_, + "startup.chain").c_str())); + startupAction->perform(); + delete startupAction; + Expander::instance(); // rehash expander + + // Launch main event loop + runlevel_ = RUN; + int result = run(); + + serialize(); + LOGDEBUG("current state serialized"); + LOGDEBUG("--- end of WMI session ---"); + + cleanup(); + + if (runlevel_ == RESTART) { + saveSettings(); + execvp(argv[0], argv); + LOGERROR("restart failed", false); + exit(1); + } + + return result; +} + +Kernel::~Kernel() { +} + +Prompt *Kernel::defaultPrompt() const { + return defaultPrompt_; +} + +Window Kernel::defaultRootWindow() { + return DefaultRootWindow(display_); +} + +Window Kernel::rootWindow() { + return focusedMonitor()->rootWindow(); +} + +Client *Kernel::focusedClient() { + + assert(focusedMonitor() != 0); // always, while running + Workspace *focusedWorkspace = focusedMonitor()->focused(); + assert(focusedWorkspace != 0); + + return focusedWorkspace->topClient(); +} + +void Kernel::killClient(Client *client) { + if (client) { + XCORE->kill(client->clientWindow(), client->protocols()); + } +} + +void Kernel::updateBars() { + + for (LMonitor::iterator it = monitors_->begin(); + it != monitors_->end(); it++) + { + Monitor *monitor = (Monitor *)*it; + monitor->statusBar()->illuminate(); + monitor->clientBar()->illuminate(); + } +} + +void Kernel::initWindows() { + + for (LMonitor::iterator it = monitors_->begin(); + it != monitors_->end(); it++) + { + Monitor *monitor = (Monitor *)*it; + monitor->scanWindows(); + } +} + +void Kernel::initKeys() { + + XCORE->ungrabKeyboard(); + Binder *bm = Binder::instance(); + + for (LMonitor::iterator it = monitors_->begin(); + it != monitors_->end(); it++) + { + Monitor *monitor = (Monitor *)*it; + bm->initKeys(monitor->rootWindow()); + } +} + +void Kernel::initActionBindings() { + + Action::Type type = Action::UNKNOWN; + + string settingsKey, bind, postfix, spec, keys; + spec = ""; + Action *action = 0; + + // extract all extern actions and chain sequences + for (MSettings::iterator it = actionSettings_->begin(); + it != actionSettings_->end(); it++) + { + settingsKey = (*it).first; + if (settingsKey.substr(0, 6) == "extern") { + type = Action::EXTERN; + } + else if (settingsKey.substr(0, 5) == "chain") { + type = Action::SEQUENCE; + } + else { + type = Action::UNKNOWN; + } + + if (type != Action::UNKNOWN) { // settingsKey has a valid action prefix + bind = Util::nthToken(settingsKey, '.', 2); + LOGDEBUG("found " + bind); + postfix = Util::nthToken(settingsKey, '.', 3); + + if ((type == Action::EXTERN) && (postfix == "cmd")) { + spec = (*it).second; + } + else if ((type == Action::SEQUENCE) && (postfix == "seq")) { + spec = (*it).second; + } + + if (spec != "") { + + if (type == Action::EXTERN) { + action = new Action(bind, &Actions::execute, + &Validators::isWorkspaceFocused, type, + (char *)spec.c_str()); + } + else if (type == Action::SEQUENCE) { + + // We determine the first sequential action and use + // its possibility method (or if it's user defined we + // allow sequential performing under all + // circumstances). + string firstActionKey = Util::nthToken(spec, ',', 1); + IsValid isValid = 0; + Action *firstAction = + Util::get(actionBindings_, firstActionKey); + if (firstAction) { + isValid = firstAction->getIsValid(); + } + else { + isValid = &Validators::isAlwaysPossible; + } + action = new Action(bind, &Actions::sequence, + isValid, type, (char *)spec.c_str()); + } + } + + if (action != 0) { + + LOGDEBUG("creating action: " + bind); + (*actionBindings_)[bind] = action; + action = 0; + spec = ""; + } + } + } + + // extract all key bindings, if they're defined + for (MSettings::iterator it = actionSettings_->begin(); + it != actionSettings_->end(); it++) + { + settingsKey = (*it).first; + if (settingsKey.substr(0, 6) == "extern") { + type = Action::EXTERN; + } + else if (settingsKey.substr(0, 6) == "intern") { + type = Action::INTERN; + } + else if (settingsKey.substr(0, 5) == "chain") { + type = Action::SEQUENCE; + } + else { + type = Action::UNKNOWN; + } + + if (type != Action::UNKNOWN) { + + bind = Util::nthToken(settingsKey, '.', 2); + LOGDEBUG("found " + bind); + postfix = Util::nthToken(settingsKey, '.', 3); + + // settingsKey has a valid action prefix + if (postfix == "keys") { + keys = (*it).second; + + if (keys != "") { + + // fetch action + action = Util::get(actionBindings_, bind); + if (action) { + action->setShortcut(Shortcut::shortcut(keys)); + } + + keys = ""; + } + } + } + } +} + +bool Kernel::isWMIWindow(Window window) { + + return isRootWindow(window) || +#ifdef SLOT_SUPPORT + slotWindow(window) || +#endif // SLOT_SUPPORT + menuWindow(window) || + barWindow(window) || + boxWindow(window) || + thingWindow(window); +} + +bool Kernel::isRootWindow(Window window) { + + for (LMonitor::iterator it = monitors_->begin(); + it != monitors_->end(); it++) + { + Monitor *monitor = (Monitor *)*it; + if (monitor->rootWindow() == window) { + monitors_->focus(monitor); + return true; + } + } + + return false; +} + +Menu *Kernel::menuWindow(Window window) { + + for (LMonitor::iterator it = monitors_->begin(); + it != monitors_->end(); it++) + { + Monitor *monitor = (Monitor *)*it; + Menu *menu = monitor->menuWindow(window); + if (menu) { + monitors_->focus(monitor); + return menu; + } + } + + return 0; +} + +#ifdef SLOT_SUPPORT +Slot *Kernel::slotWindow(Window window) { + + for (LMonitor::iterator it = monitors_->begin(); + it != monitors_->end(); it++) + { + Monitor *monitor = (Monitor *)*it; + Slot *slot = monitor->slotWindow(window); + if (slot) { + monitors_->focus(monitor); + return slot; + } + } + + return 0; +} +#endif // SLOT_SUPPORT + +Thing *Kernel::thingWindow(Window window) { + + for (LMonitor::iterator it = monitors_->begin(); + it != monitors_->end(); it++) + { + Monitor *monitor = (Monitor *)*it; + Thing *thing = monitor->thingWindow(window); + if (thing) { + monitors_->focus(monitor); + return thing; + } + } + + return 0; +} + +Box *Kernel::boxWindow(Window window) { + + for (LMonitor::iterator it = monitors_->begin(); + it != monitors_->end(); it++) + { + Monitor *monitor = (Monitor *)*it; + Box *box = monitor->box(); + if (box->window() == window) { + return box; + } + } + return 0; +} + +Bar *Kernel::barWindow(Window window) { + + for (LMonitor::iterator it = monitors_->begin(); + it != monitors_->end(); it++) + { + Monitor *monitor = (Monitor *)*it; + Bar *bar = monitor->barWindow(window); + if (bar) { + monitors_->focus(monitor); + return bar; + } + } + + return 0; +} + +Client *Kernel::clientForWindow(Window window) { + + for (LMonitor::iterator it = monitors_->begin(); + it != monitors_->end(); it++) + { + Monitor *monitor = (Monitor *)*it; + Client *client = monitor->clientForWindow(window); + if (client != 0) { + monitors_->focus(monitor); + return client; + } + } + return 0; +} + +bool Kernel::isInputMode() { + return focusedMonitor()->inputBar()->isVisible(); +} + +void Kernel::ungrabShortcutOnAllMonitors(Shortcut *shortcut) { + + Binder *bm = Binder::instance(); + + for (LMonitor::iterator it = monitors_->begin(); + it != monitors_->end(); it++) + { + Monitor *monitor = (Monitor *)*it; + bm->ungrabShortcut(shortcut, monitor->rootWindow()); + } +} + +void Kernel::grabShortcutOnAllMonitors(Shortcut *shortcut) { + + Binder *bm = Binder::instance(); + + for (LMonitor::iterator it = monitors_->begin(); + it != monitors_->end(); it++) + { + Monitor *monitor = (Monitor *)*it; + bm->grabShortcut(shortcut, monitor->rootWindow()); + } +} + +void Kernel::toggleShortcuts() { + + static bool isGrabbed = false; + + isGrabbed = !isGrabbed; + for (MBindings::iterator it = actionBindings_->begin(); + it != actionBindings_->end(); it++) + { + Action *action = (*it).second; + Shortcut *shortcut = action->listenOn(); + if (shortcut + && (action->getToPerform() != &Actions::inputMode) + && (action->getToPerform() != &Actions::toggleShortcuts)) + { + if (isGrabbed) { + ungrabShortcutOnAllMonitors(shortcut); + } + else { + grabShortcutOnAllMonitors(shortcut); + } + } + } +} + +void Kernel::bindShortcut(string argument) { + + unsigned int argDelim = argument.find_first_of('+'); + if (argDelim == string::npos) { + return; + } + string bind = argument.substr(0, argDelim); + string keys = argument.substr(argDelim + 1); + + Action *action = Util::get(actionBindings_, bind); + + if (action) { + Shortcut *oldShortcut = action->shortcut(); + if (oldShortcut) { + bool doUngrab = true; + for (MBindings::iterator it = actionBindings_->begin(); + it != actionBindings_->end(); it++) + { + Action *action = (*it).second; + Shortcut *s = action->listenOn(); + if (s && + (s->modMask() == oldShortcut->modMask()) && + (s->keyCode() == oldShortcut->keyCode()) && + (s->button() == oldShortcut->button())) + { + doUngrab = false; + break; + } + } + if (doUngrab) { + ungrabShortcutOnAllMonitors(oldShortcut); + } + delete oldShortcut; + } + + string prefix; + switch (action->type()) { + case Action::INTERN: + prefix = "intern."; + break; + case Action::EXTERN: + prefix = "extern."; + break; + case Action::SEQUENCE: + prefix = "chain."; + break; + case Action::UNKNOWN: + prefix = "unknown."; + break; + } + + if (keys == "") { + Util::remove(actionSettings_, prefix + bind + ".keys"); + return; + } + action->setShortcut(Shortcut::shortcut(keys)); + + (*actionSettings_)[prefix + bind + ".keys"] = keys; + if (action->listenOn()) { + grabShortcutOnAllMonitors(action->listenOn()); + } + } +} + +void Kernel::serialize() { + + for (LMonitor::iterator it = monitors_->begin(); + it != monitors_->end(); it++) + { + Monitor *monitor = *it; + monitor->serialize(); + } +} + +void Kernel::installCursor(Cursor cursor, Window window) { + XSetWindowAttributes attr; + attr.cursor = cursor; + XCORE->setWindowAttributes(window, CWCursor, &attr); +} + + +void Kernel::addClient(Client *client) { + + focusedMonitor()->addClient(client); +} + +void Kernel::saveSettings() { + + // actions and session will be safed under any circumstances saved + // comments will be lost in these files + const char *home = getenv("HOME"); + + Loader::saveSettings(actionSettings_, (string)home + + "/.wmi/actions.session"); + Loader::saveSettings(sessionSettings_, (string)home + + "/.wmi/wmi.session"); +} + +void Kernel::cleanup() { + + for (LMonitor::iterator it = monitors_->begin(); + it != monitors_->end(); it++) + { + Monitor *monitor = *it; + monitor->cleanup(); + } + XCORE->setInputFocus(PointerRoot); + Cursors::cleanup(); + delete monitors_; + // TODO: theme, etc. + XCloseDisplay(display_); +} + +//////// EVENT HANDLING ////////////// + +void Kernel::handleButtonRelease(XButtonEvent *event) { + + event->state &= Binder::instance()->validModMask(); + + Bar *bar = barWindow(event->window); + if (bar) { + bar->handleButtonRelease(event); + return; + } + + Thing *thing = thingWindow(event->window); + if (thing) { + thing->handleButtonRelease(event); + } +} + +void Kernel::handleButtonPress(XButtonEvent *event) { + + event->state &= Binder::instance()->validModMask(); + + if (event->state != 0) { + // no AnyModifier, so this seems to be shortcut + Binder::instance()->handleButton(event->root, event); + return; + } + + Menu *menu = menuWindow(event->window); + if (menu) { + menu->handleButtonPress(event); + return; + } + + Bar *bar = barWindow(event->window); + if (bar) { + bar->handleButtonPress(event); + return; + } + +#ifdef SLOT_SUPPORT + Slot *slot = slotWindow(event->window); + if (slot) { + slot->handleButtonPress(event); + return; + } +#endif + + Thing *thing = thingWindow(event->window); + + if (thing) { + thing->handleButtonPress(event); + } + + Client *client = clientForWindow(event->window); + if (client) { + client->handleButtonPress(event); + } +} + +void Kernel::handleConfigureRequest(XConfigureRequestEvent *event) { + + Client *client = clientForWindow(event->window); + + if (client) { + client->handleConfigureRequest(event); + } + else { + XWindowChanges wc; + + wc.x = event->x; + wc.y = event->y; + wc.width = event->width; + wc.height = event->height; + wc.border_width = 0; + wc.sibling = None; + wc.stack_mode = Above; + event->value_mask &= ~CWStackMode; + event->value_mask |= CWBorderWidth; + + XCORE->configureWindow(event->window, event->value_mask, &wc); + } +} + +void Kernel::handleDestroyNotify(XDestroyWindowEvent *event) { + + Client *client = clientForWindow(event->window); + + if (client) { + if (event->window == client->clientWindow()) { + client->setDestroyed(true); + client->monitor()->removeClient(client); + delete client; + } + } +} + +void Kernel::handleExpose(XExposeEvent *event) { + + Bar *bar = barWindow(event->window); + if (bar) { + bar->illuminate(); + return; + } + +#ifdef SLOT_SUPPORT + Slot *slot = slotWindow(event->window); + if (slot) { + slot->illuminate(); + return; + } +#endif // SLOT_SUPPORT + + Thing *thing = thingWindow(event->window); + if (thing) { + thing->illuminate(); + } +} + +void Kernel::handleKeyPress(XKeyEvent *event) { + + event->state &= Binder::instance()->validModMask(); + + if (isInputMode()) { + focusedMonitor()->inputBar()->handleInput(event); + } + else { + Binder::instance()->handleKey(event->root, event); + updateBars(); + } +} + +void Kernel::handleMapRequest(XMapRequestEvent *event) { + + if (isWMIWindow(event->window)) { + return; + } + + XWindowAttributes attr; + XCORE->windowAttributes(event->window, &attr); + + if (attr.override_redirect) { + LOGDEBUG("override redirect!"); + return; + } + + Client *client = clientForWindow(event->window); + + if (!client) { + client = new Client(focusedMonitor(), event->window, &attr); + focusedMonitor()->addClient(client); + LOGDEBUG("client created"); + } + else if (client->attached()) { + client->setRequestsFocus(true); + client->attached()->setRequestsFocus(true); + return; // we ignore Map Requests from those clients + } + + ostringstream oss; + oss << "client dims: " << client->x() << "," << + client->y() << "," << client->width() << "," << + client->height(); + LOGDEBUG(oss.str()); + + /** Initialize names. */ + focusedMonitor()->attachClient(client); +} + +void Kernel::handleMotionNotify(XMotionEvent *event) { + + Menu *menu = menuWindow(event->window); + if (menu) { + menu->handleMotionNotify(event); + } + + Bar *bar = barWindow(event->window); + if (bar) { + bar->handleMotionNotify(event); + return; + } + + Thing *thing = thingWindow(event->window); + if (thing) { + if (!thing->isFocused() && isSloppyMode_) { + Workspace *workspace = focusedMonitor()->focused(); + workspace->focus(thing, false); + } + thing->handleMotionNotify(event); + } + + // focusses the monitor if multihead + isRootWindow(event->root); +} + +void Kernel::handlePropertyNotify(XPropertyEvent *event) { + + if (!isRootWindow(event->window)) { + + Client *client = clientForWindow(event->window); + ostringstream oss; + oss << "property atom: " << XCORE->atomName(event->atom); + LOGDEBUG(oss.str()); + + if (client) { + client->handlePropertyNotify(event); + } + return; + } + + // check if status text has been changed + if (event->atom == Atoms::WMI_STATUSTEXT || + event->atom == Atoms::WMI_METERTEXT) + { + focusedMonitor()->updateBars(); + return; + } + else if (event->atom == Atoms::WMI_ACTIONCMD) { + + // TODO + // action[+arg1[...]] + string actionCmd; + if (XCORE->textProperty(defaultRootWindow(), + Atoms::WMI_ACTIONCMD, &actionCmd)) + { + string bind, arg; + unsigned int pos = actionCmd.find_first_of('+'); + if (pos != string::npos) { + bind = actionCmd.substr(0, pos); + arg = actionCmd.substr(pos + 1); + } + else { + bind = actionCmd; + } + + // query action + Action *action = Util::get(actionBindings_, bind); + if (action && pos != string::npos) { + action->setArgument((char *)arg.c_str()); + } + + if (action) { + if ((action->promptsCount() > 0) && !action->argument()) { + focusedMonitor()->inputBar()->runArgument(action); + // action will be performed by argument processing + } + else { + action->perform(); + } + } + + } + return; + } + else if (event->atom == Atoms::WMI_PRETTYPRINT_REQUEST) { + + XTextProperty property; + XCORE->stringListToTextProperty( + Binder::instance()->prettyPrintKeyBindings(), &property); + XCORE->setTextProperty(display_, defaultRootWindow(), + &property, Atoms::WMI_PRETTYPRINT_RESPONSE); + } +} + +void Kernel::handleUnmapNotify(XUnmapEvent *event) { + LOGDEBUG("handle unmap notify"); + Client *client = clientForWindow(event->window); + + if (client) { + LOGDEBUG("got unmap client"); + client->handleUnmapNotify(event); + } +} + +void Kernel::handleClientMessage(XClientMessageEvent *event) { + + LOGDEBUG("handle client message"); + if (event->message_type == Atoms::WM_CHANGE_STATE) { + Client *client = clientForWindow(event->window); + + if (client && client->monitor() + && (event->format == 32) + && (event->data.l[0] == IconicState)) + { + client->monitor()->detachClient(client); + } + } +} + +int Kernel::run() { + XEvent event; + + LOGDEBUG("main event loop launched"); + ostringstream oss; + while (runlevel_ == Kernel::RUN) { + + XCORE->nextEvent(&event); + switch (event.type) { + case ButtonPress: + LOGDEBUG("button press event"); + handleButtonPress(&event.xbutton); + break; + case ButtonRelease: + LOGDEBUG("button release event"); + handleButtonRelease(&event.xbutton); + break; + case ClientMessage: + LOGDEBUG("client message event"); + handleClientMessage(&event.xclient); + break; + case ConfigureRequest: + LOGDEBUG("configure request event"); + handleConfigureRequest(&event.xconfigurerequest); + break; + case DestroyNotify: + LOGDEBUG("destroy window event"); + handleDestroyNotify(&event.xdestroywindow); + break; + case Expose: + LOGDEBUG("expose event"); + handleExpose(&event.xexpose); + break; + case KeyPress: + LOGDEBUG("keypress event"); + handleKeyPress(&event.xkey); + break; + case MapRequest: + LOGDEBUG("map request event"); + handleMapRequest(&event.xmaprequest); + break; + case MotionNotify: + LOGDEBUG("motion event"); + handleMotionNotify(&event.xmotion); + break; + case PropertyNotify: + LOGDEBUG("property event"); + handlePropertyNotify(&event.xproperty); + break; + case UnmapNotify: + LOGDEBUG("unmap event"); + handleUnmapNotify(&event.xunmap); + break; + } + + } + return 0; +} + +void Kernel::runResizeMode(Thing *thing, XButtonEvent *buttonEvent, + Direction dir, bool resize) +{ + Window window = thing->window(); + if (!window) { + return; + } + + Monitor *monitor = thing->monitor(); + Window rootWindow = monitor->rootWindow(); + Thing::Type type = thing->type(); + Workspace *workspace = (type == Thing::CLIENT) ? + ((Client *)thing)->attached() : ((Frame *)thing)->attached(); + + if (!workspace) { + return; + } + + int origX, origY, lastX, lastY, newX, newY, dx, dy; + Rectangle rect(*thing); + + XCORE->translateCoordinates(window, rootWindow, + buttonEvent->x, buttonEvent->y, + &lastX, &lastY); + newX = newY = 0; + origX = lastX; + origY = lastY; + + XCORE->grabPointer(window, + ButtonMotionMask | ButtonReleaseMask, + buttonEvent->time); + + XEvent event; + bool done = false, found = false, firstMotion = true; + + XCORE->grabServer(); + while (!done) { + found = false; + + while (XCORE->checkMaskEvent( + ButtonReleaseMask | ButtonMotionMask, &event)) + { + found = true; + + if (event.type != MotionNotify) { + break; + } + } + + if (!found) { + usleep(20000); + continue; + } + + switch (event.type) { + case ButtonRelease: + if (!firstMotion) { + monitor->illuminateTransRect(&rect, thing->titleBarHeight()); + + dx = newX - origX; + dy = newY - origY; + + if ((dir == LEFT) || (dir == UP)) { + // normalization + dx *= -1; + dy *= -1; + } + + if (type == Thing::FRAME) { + Split::resize(workspace->root(), + ((Frame *)thing)->tree(), + dir, dx, dy); + } + else { + thing->copy(&rect); + thing->resize(); + thing->illuminate(); + } + XCORE->sync(); + } + XCORE->ungrabPointer(event.xbutton.time); + XCORE->ungrabServer(); + done = true; + break; // ButtonRelease + case MotionNotify: + XCORE->translateCoordinates(event.xmotion.window, + rootWindow, event.xmotion.x, event.xmotion.y, + &newX, &newY); + + dx = newX - lastX; + dy = newY - lastY; + + lastX = newX; + lastY = newY; + + if (firstMotion) { + firstMotion = false; + } + else { + monitor->illuminateTransRect(&rect, thing->titleBarHeight()); + } + + if (type == Thing::FRAME) { + switch (dir) { + case LEFT: + rect.setX(rect.x() + dx); + rect.setWidth(rect.width() - dx); + break; + case RIGHT: + rect.setWidth(rect.width() + dx); + break; + case UP: + rect.setY(rect.y() + dy); + rect.setHeight(rect.height() - dy); + break; + case DOWN: + rect.setHeight(rect.height() + dy); + break; + default: + break; + } + } + else { + + if (resize) { + Float::resize(&rect, dir, dx, dy); + } + else { + Float::move(&rect, dx, dy); + } + } + monitor->illuminateTransRect(&rect, thing->titleBarHeight()); + break; // MotionNotify + } + } +} + +void Kernel::beginRecording() { + isRecording_ = true; + assert(recordedActions_.size() == 0); +} + +void Kernel::endChainRecording(string name) { + isRecording_ = false; + if (recordedActions_.size() == 0) { + return; + } + + string chain = ""; + Action *firstAction = 0; + for (LAction::iterator it = recordedActions_.begin(); + it != recordedActions_.end(); ) + { + Action *action = *it; + + it++; + if (action->argument()) { + chain += action->id() + "+" + action->argument(); + } + else { + chain += action->id(); + } + if (it != recordedActions_.end()) { + chain += ","; + } + + if (it == recordedActions_.begin()) { + firstAction = action; + } + else { + delete action; + } + } + // clean up + recordedActions_.clear(); + + IsValid isValid = 0; + if (firstAction) { + isValid = firstAction->getIsValid(); + } + else { + isValid = &Validators::isAlwaysPossible; + } + delete firstAction; + + (*actionSettings_)["chain." + name + ".seq"] = chain; + Action *action = new Action(name, &Actions::sequence, isValid, + Action::SEQUENCE, (char *)chain.c_str()); + (*actionBindings_)[name] = action; +} + +void Kernel::cancelRecording() { + isRecording_ = false; + if (recordedActions_.size() == 0) { + return; + } + // clean up + recordedActions_.clear(); +} + + +void Kernel::endScriptRecording(string name) { + isRecording_ = false; + if (recordedActions_.size() == 0) { + return; + } + + string script = "#!/bin/sh\n"; + for (LAction::iterator it = recordedActions_.begin(); + it != recordedActions_.end(); ) + { + Action *action = *it; + + it++; + script += "wmiremote -a \""; + if (action->argument()) { + script += action->id() + "+" + action->argument(); + } + else { + script += action->id(); + } + script += "\"\n"; + + delete action; + } + // clean up + recordedActions_.clear(); + + + Loader::saveFile(name, script); +} + + +MSettings *Kernel::themeSettings() { + return themeSettings_; +} + +MSettings *Kernel::commonSettings() { + return commonSettings_; +} + +MSettings *Kernel::actionSettings() { + return actionSettings_; +} + +MSettings *Kernel::sessionSettings() { + return sessionSettings_; +} + +Display *Kernel::display() const { + return display_; +} + +Monitor *Kernel::focusedMonitor() const { + return monitors_->focused(); +} + +Kernel::Runlevel Kernel::runlevel() const { + return runlevel_; +} + +void Kernel::restart() { + runlevel_ = RESTART; +} + +void Kernel::stop() { + runlevel_ = STOP; +} + +MBindings *Kernel::actionBindings() const { + return actionBindings_; +} + + +bool Kernel::isRecording() const { + return isRecording_; +} + +LAction *Kernel::recordedActions() { + return &recordedActions_; +} + +unsigned int Kernel::borderWidth() const { + return borderWidth_; +} + +void Kernel::setMenuMode(bool isMenuMode) { + isMenuMode_ = isMenuMode; +} + +void Kernel::toggleSloppyMode() { + isSloppyMode_ = !isSloppyMode_; +} + +bool Kernel::isStackedTabbing() const { + return isStackedTabbing_; +} + +CMonitor *Kernel::monitors() const { + return monitors_; +} + +void Kernel::selectMonitor(string displayString) { + + for (LMonitor::iterator it = monitors_->begin(); + it != monitors_->end(); it++) + { + Monitor *monitor = *it; + if (monitor->displayString() == displayString) { + if (monitors_->focused() != monitor) { + XCORE->warpPointer(monitor->rootWindow(), + monitor->width() / 2, + monitor->height() / 2); + monitors_->focus(monitor); + Workspace *ws = monitor->focused(); + ws->focus(ws->topClient()); + } + return; + } + } +} + +void Kernel::grabMove() { + + Client *client = focusedClient(); + if (!client || client->frame()) { + return; + } + XCORE->warpPointer(client->window(), + client->width() / 2, + client->height() / 2); + XButtonEvent event; + event.x = client->width() / 2; + event.y = client->height() / 2; + event.time = CurrentTime; + runResizeMode(client, &event, LEFT, false); +} diff --git a/kernel.h b/kernel.h @@ -0,0 +1,253 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: kernel.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __KERNEL_H +#define __KERNEL_H + +#include "singleton.h" + +extern "C" { +#include <X11/Xlib.h> +} + +// STL list +#include <list> +#include <string> +#include <map> + +#include "wmi.h" + +// forward declaration +class Action; +class Bar; +class Box; +class Client; +template <class P, class LT, class LTI, class T> class Container; +class Frame; +class Kernel; +class Menu; +class Monitor; +class Prompt; +class Rectangle; +class Shortcut; +#ifdef SLOT_SUPPORT +class Slot; +#endif // SLOT_SUPPORT +class Thing; +class Workspace; + +typedef list<Action *> LAction; +typedef list<Monitor *> LMonitor; +typedef map<string, string, less<string> > MSettings; +typedef map<string, Action *, less<string> > MBindings; +typedef Container<Kernel, LMonitor, LMonitor::iterator, Monitor> CMonitor; + +/** + * Main controller of WMI. Contains all base functionality + * of a window manager. + */ +class Kernel : public Singleton<Kernel> +{ + +public: + + /** Constructs a new window manager instance. */ + Kernel(); + + ~Kernel(); + + /** Returns settings. */ + MSettings *themeSettings(); + + MSettings *commonSettings(); + + MSettings *actionSettings(); + + MSettings *sessionSettings(); + + /** Returns the display. */ + Display *display() const; + + /** Returns the currently focused monitor. */ + Monitor *focusedMonitor() const; + + /** Returns wether input mode is active. */ + bool isInputMode(); + + /** Returns focused client. */ + Client *focusedClient(); + + void killClient(Client *client); + + /** Returns the root window. */ + Window rootWindow(); + + /** Returns the default root window (of deafault monitor). */ + Window defaultRootWindow(); + + /** Runlevel enum. */ + enum Runlevel {START, RUN, STOP, RESTART}; + + Runlevel runlevel() const; + + /** Start method. */ + int start(char *argv[], + Display *display, + MSettings *themeSettings, + MSettings *commonSettings, + MSettings *actionSettings, + MSettings *sessionSettings, + bool isFirstRun = false); + + void stop(); + void restart(); + + /** Updates all bars.*/ + void updateBars(); + + /** Saves session settings. */ + void saveSettings(); + + MBindings *actionBindings() const; + + /** Returns <code>true</code> if window is a root window. */ + bool isRootWindow(Window window); + + /** Returns bar if window is a barwindow. */ + Bar *barWindow(Window window); + + /** Returns box if window is a boxwindow. */ + Box *boxWindow(Window window); + + /** Returns menu if window is a menu window. */ + Menu *menuWindow(Window window); + +#ifdef SLOT_SUPPORT + /** Returns slot if window is a slot window. */ + Slot *slotWindow(Window window); +#endif // SLOT_SUPPORT + + /** Returns frame if window is a frame window. */ + Thing *thingWindow(Window window); + + /** Returns <code>true</code> if window is a WMI window. */ + bool isWMIWindow(Window window); + + /** Returns client for this window. */ + Client *clientForWindow(Window window); + + /** Binds the shortcut for the given <action id>=<key> pair. */ + void bindShortcut(string argument); + + void installCursor(Cursor cursor, Window window); + + /** Adds client. */ + void addClient(Client *client); + + /** Main event loop. */ + int run(); + + /** Resize event loop. */ + void runResizeMode(Thing *thing, XButtonEvent *buttonEvent, + Direction dir, bool resize = false); + + bool isRecording() const; + + LAction *recordedActions(); + + void beginRecording(); + void endChainRecording(string name); + void endScriptRecording(string name); + void cancelRecording(); + + + unsigned int borderWidth() const; + + void cleanup(); + + Prompt *defaultPrompt() const; + + void setMenuMode(bool isMenuMode); + + void toggleSloppyMode(); + + bool isStackedTabbing() const; + + void toggleShortcuts(); + + CMonitor *monitors() const; + void selectMonitor(string displayString); + + /** Enters runResizeMode for moving focussed clients with a + faked XButtonEvent. */ + void grabMove(); + +private: + + /** event handler. */ + void handleButtonPress(XButtonEvent *event); + void handleButtonRelease(XButtonEvent *event); + void handleConfigureRequest(XConfigureRequestEvent *event); + void handleClientMessage(XClientMessageEvent *event); + void handleCreateNotify(XCreateWindowEvent *event); + void handleDestroyNotify(XDestroyWindowEvent *event); + void handleExpose(XExposeEvent *event); + void handleKeyPress(XKeyEvent *event); + void handleMapRequest(XMapRequestEvent *event); + void handleMotionNotify(XMotionEvent *event); + void handlePropertyNotify(XPropertyEvent *event); + void handleUnmapNotify(XUnmapEvent *event); + + /** Atom initialization. */ + void initAtoms(); + + /** Inits all monitors. */ + void initMonitors(); + + /** Inits all existing windows. */ + void initWindows(); + + /** Inits the bind map for all actions. */ + void initActionBindings(); + + /** Inits keys on all monitors. */ + void initKeys(); + + /** Grabs shortcut on all monitors. */ + void grabShortcutOnAllMonitors(Shortcut *shortcut); + + /** Ungrabs shortcut on all monitors. */ + void ungrabShortcutOnAllMonitors(Shortcut *shortcut); + + /** + * Serializes and updates all settings. + */ + void serialize(); + + bool isSloppyMode_; + bool isRecording_; + LAction recordedActions_; + Display *display_; + CMonitor *monitors_; + + unsigned int borderWidth_; + bool isMenuMode_; + bool isStackedTabbing_; + + // default rc settings + MSettings *themeSettings_; + MSettings *commonSettings_; + MSettings *actionSettings_; + MSettings *sessionSettings_; + + // bind map + MBindings *actionBindings_; + + Runlevel runlevel_; + Prompt *defaultPrompt_; + +}; + +#endif // __KERNEL_H diff --git a/label.cpp b/label.cpp @@ -0,0 +1,110 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: label.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include <sstream> + +#include "label.h" + +#include "draw.h" +#include "font.h" +#include "logger.h" +#include "kernel.h" +#include "monitor.h" +#include "xcore.h" + +Label::Label(Monitor *monitor, Window window, Alignment align, GC gc) + : Rectangle() +{ + + LOGDEBUG("initializing label"); + align_ = align; + font_ = monitor->font(); + monitor_ = monitor; + gc_ = gc; + window_ = window; +} + +Label::~Label() { +} + +unsigned int Label::adjustWidth() { + setWidth(textWidth()); + return width(); +} + +unsigned int Label::textWidth() { + return font_->textWidth(text_) + 2 * font_->height(); +} + +void Label::update(unsigned long background, unsigned long text, + unsigned long shine, unsigned long shadow, + bool shineBorder, bool shadowBorder) + +{ + + LOGDEBUG("label update"); + + // draw background + XCORE->setForeground(gc_, background); + XCORE->fillRectangle(window_, gc_, this); + + // draw border if neccessary + if (shadowBorder) { + Draw::drawShadowBorder(window_, gc_, this, shadow); + } + + if (shineBorder) { + + Draw::drawShineBorder(window_, gc_, this, shine); + } + + // draw text + if (text_ == "") { + return; // nothing to draw + } + XCORE->setForeground(gc_, text); + int textWidth = this->textWidth(); + + if (textWidth > (int)width()) { + int matchLength = (int)((text_.length() * width() / textWidth) - 3); + if (matchLength < 0) { + matchLength = 0; + } + text_ = Util::shortenString(text_, matchLength); + textWidth = this->textWidth(); + } + + unsigned int fontBaseLine = 0; + fontBaseLine = font_->ascent(); + unsigned int fontY = y() + height() / 2 - font_->height() / 2 + fontBaseLine; + + unsigned int fontX = 0; + switch (align_) { + case LEFT: + fontX = x() + font_->height(); + break; + case CENTER: + fontX = x() + (width() / 2 - (textWidth - 2 * font_->height()) / 2); + break; + case RIGHT: + fontX = x() + width() - textWidth + font_->height(); + break; + } + + font_->drawText(window_, gc_, fontX, fontY, text_); +} + + +void Label::setText(string text) { + text_ = text; +} + +string Label::text() const { + return text_; +} + +void Label::setAlignment(const Alignment align) { + align_ = align; +} diff --git a/label.h b/label.h @@ -0,0 +1,77 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: label.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __LABEL_H +#define __LABEL_H + +extern "C" { +#include <X11/Xlib.h> +} + +#include <string> +#include "wmi.h" + +#include "rectangle.h" + +class Monitor; +class WFont; + +/** + * Represents a low-level label widget implementation with alignment + * handling. + * + * This widget is capable of using old style PCF fonts and new style + * XFT fonts. + */ +class Label : public Rectangle +{ + +public: + + enum Alignment {LEFT, CENTER, RIGHT}; + + Label(Monitor *monitor, Window window, Alignment align, GC gc); + + ~Label(); + + void setText(string text); + + string text() const; + + /** + * Updates this label. + * @param leftBorder if <code>true</code> a left border + * will be drawn. + * @param rightBorder if <code>true</code> a right border + * will be drawn. + */ + void update(unsigned long background, unsigned long text, + unsigned long shine, unsigned long shadow, + bool shineBorder = false, bool shadowBorder = false); + + void setAlignment(const Alignment align); + + /** + * Adjusts label width with the currently set text. + * Returns the adjusted width. + */ + unsigned int adjustWidth(); + + /** + * Helper method for adjustWidth, also useful for menu and bar stuff. + */ + unsigned int textWidth(); + +private: + + Alignment align_; + GC gc_; + Monitor *monitor_; + string text_; + Window window_; + WFont *font_; +}; + +#endif // __LABEL_H diff --git a/launcher.cpp b/launcher.cpp @@ -0,0 +1,114 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: launcher.cpp 734 2004-09-27 18:15:45Z garbeam $ + +extern "C" { +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#include <X11/Xlib.h> +} + +#include <map> + +#include "launcher.h" + +#include "action.h" +#include "logger.h" +#include "kernel.h" +#include "monitor.h" + +Launcher::Launcher() {} +Launcher::~Launcher() {} + +void Launcher::exec(string command) { + + Monitor *focusedMonitor = Kernel::instance()->focusedMonitor(); + + if (fork() == 0) { + if (fork() == 0) { + setsid(); + + close(ConnectionNumber(Kernel::instance()->display())); + + putenv((char *)focusedMonitor->displayString().c_str()); + + char **cmdArgs = Util::arguments(command); + + LOGDEBUG("executing '" + command + "'"); + execvp(cmdArgs[0], cmdArgs); + LOGERROR("cannot execute '" + command + "'", true); + // exits WMI + } + exit(0); + } + wait(0); +} + +void Launcher::execSeq(Action *caller, string command) { + + MBindings *actionBindings = KERNEL->actionBindings(); + + string cmd = command; + string actionName = ""; + string arguments = ""; + + LOGDEBUG("sequence: got: " + cmd); + bool proceed = true; + for (string::iterator it = cmd.begin(); proceed; it++) { + + proceed = it != cmd.end(); + if (!proceed || (*it == ',') ) { // proceed action + if (caller->id() == actionName) { // recursion detected + Logger::instance()->warning( + "sequence '" + actionName + + "' was called recursivly, stopped"); + return; + + } + // argument fetching + unsigned int argCount = 0; + unsigned int argDelim = actionName.find_first_of('+'); + + if (argDelim != string::npos) { + argCount++; // at least 1 argument + arguments = actionName.substr(argDelim + 1); + LOGDEBUG("sequence: got arguments: " + arguments); + actionName = actionName.substr(0, argDelim); + LOGDEBUG("sequence: found arguments: " + arguments); + LOGDEBUG("sequence: for action: " + actionName); + } + + Action *action = Util::get(actionBindings, actionName); + if (!action) { + LOGWARN("unknown action '" + actionName + + "' cannot be performed sequentially"); + return; + } + if (action->promptsCount() != argCount) { + LOGWARN("action '" + actionName + + "' cannot be performed sequentially, because " + "to much or less given arguments."); + return; + } + if (!action->isValid()) { + LOGWARN("action '" + actionName + + "' cannot be performed because it" + " won't have any effect"); + return; + } + if (argCount) { + action->setArgument((char *)arguments.c_str()); + } + action->perform(); + actionName = ""; + } + else { + actionName += *it; + } + } +} diff --git a/launcher.h b/launcher.h @@ -0,0 +1,42 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: launcher.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __LAUNCHER_H +#define __LAUNCHER_H + +#include <string> + +#include "wmi.h" + +#include "singleton.h" + +// forward declaration +class Action; +class Launcher; + +/** + * Launches external processes and is capable to process chain + * invocations. + * + * Determines recursion in chain invocation. + */ +class Launcher : public Singleton<Launcher> +{ + +public: + + /** Constructs a new process manager instance. */ + Launcher(); + + ~Launcher(); + + /** Execs the given command. */ + void exec(string command); + + /** Execs a chain. */ + void execSeq(Action *caller, string command); +}; + +#endif // __LAUNCHER_H diff --git a/loader.cpp b/loader.cpp @@ -0,0 +1,195 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: loader.cpp 734 2004-09-27 18:15:45Z garbeam $ + +extern "C" { +#include <sys/stat.h> +#include <sys/types.h> +} + +#include <fstream> +#include <iostream> +#include <sstream> + +#include "loader.h" +#include "util.h" + +Loader::Loader() { +} + +Loader::~Loader() { +} + +bool Loader::load(MSettings *settings, string path, + bool suppressWarning, bool caseSensitive) +{ + + ifstream is(path.c_str()); + + if (!is) { + if (!suppressWarning) { + cerr << "wmi[W " << Util::timestamp() + << "]: cannot open/read configuration file '" + << path << "', skipping" << endl; + } + return false; + } + + string key = ""; + string value = ""; + string buf = ""; + bool comment = false; + bool ignoreWhitespaces = true; + bool escape = false; // provides using {#, ", =, \n} characters + int c; + + while (!is.eof()) { + + c = is.get(); + + switch (c) { + case ' ': + case '\t': + if (!comment && !ignoreWhitespaces) { + buf += c; + } + escape = false; + break; + case '"': // toggle ignore whitespace/or escape this character + if (!comment) { + if (escape) { + buf += c; + } + else { + ignoreWhitespaces = !ignoreWhitespaces; + } + } + escape = false; + break; + case '\\': // escape + if (!comment) { + if (escape) { + buf += c; + escape = false; + } + else { + escape = true; + } + } + break; + case '#': // comment + if (escape) { + buf += c; + } + else { + comment = true; + } + escape = false; + break; + case '=': + if (!comment) { + if (escape) { + buf += c; + } + else { + key = buf; + buf = ""; + } + } + escape = false; + break; + case '\n': + +#define ENDLINE \ + if (!escape) { \ + comment = false; \ + ignoreWhitespaces = true; \ + value = buf; \ + if ((key != "") && (value != "")) { \ + value = buf; \ + if (caseSensitive) { \ + (*settings)[key] = value; \ + } \ + else { \ + (*settings)[Util::lowerCase(key)] = value; \ + } \ + } \ + buf = key = value = ""; \ + } \ + escape = false; \ + break; \ + + ENDLINE + case EOF : + ENDLINE + default: + if (!comment) { + buf += c; + } + escape = false; + break; + } + } + is.close(); + + return true; +} + +bool Loader::saveSettings(MSettings *settings, string path) { + + ostringstream content; + + for (MSettings::iterator it = settings->begin(); + it != settings->end(); it++) + { + string value = Util::encodeEscapes((*it).second); + if (Util::containsWhitespaces(value)) { + content << (*it).first << "=\"" << value << "\"" << endl; + } + else { + content << (*it).first << "=" << value << endl; + } + } + + return saveFile(path, content.str()); +} + +bool Loader::saveFile(string path, string content) { + + string dir = Util::canonicalDir(path); + if (!Util::exists(dir.c_str())) { + + mode_t mode = umask(0); + mode = (mode ^ (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IWUSR | S_IXUSR; + if (mkdir(dir.c_str(), mode) != 0) { + cerr << "wmi[W " << Util::timestamp() + << "]: cannot create non-existing directory '" + << dir << "', skipping" << endl; + } + } + + ofstream os(path.c_str()); + + if (!os) { + cerr << "wmi[W " << Util::timestamp() + << "]: cannot open/write configuration file '" + << path << "', skipping" << endl; + return false; + } + + os << content; + os.close(); + + return true; + +} + +void Loader::print(MSettings *settings) { + + MSettings::iterator it = settings->begin(); + while (it != settings->end()) { + cout << (*it).first << "=" << (*it).second << endl; + it++; + } +} diff --git a/loader.h b/loader.h @@ -0,0 +1,57 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: loader.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __LOADER_H +#define __LOADER_H + +#include "wmi.h" + +#include <list> +#include <string> +#include <map> + +typedef map<string, string, less<string> > MSettings; + +/** + * Loads and saves settings. + */ +class Loader +{ + +public: + + /** Constructs a new settings manager instance. */ + Loader(); + + ~Loader(); + + /** + * (Re)loads settings. Returns <code>true</code> on success. + * The settings file has following grammar: + * <key>=<value> + * whitespaces (' ', '\t') are ignored by default (escape using "...") + * '\' is escape character for escaping from '"', '=', '#', '\n', '\' + * @param settings the settings to set + * @param filename the filename to load from + * @param suppressWarning suppresses warn messages to stderr + * @param caseSensitive reads keys case sensitive + * if file couldn't be loaded + */ + static bool load(MSettings *settings, string path, + bool suppressWarning = false, + bool caseSensitive = false); + + /** Saves settings. Returns <code>true</code> on success. */ + static bool saveSettings(MSettings *settings, string path); + + /** Saves content to the file specified by path. */ + static bool saveFile(string path, string content); + + /** Prints all settings to stdout. */ + static void print(MSettings *settings); + +}; + +#endif // __LOADER_H diff --git a/logger.cpp b/logger.cpp @@ -0,0 +1,39 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: logger.cpp 734 2004-09-27 18:15:45Z garbeam $ + +extern "C" { +#include <stdlib.h> +} + +#include <iostream> + +#include "logger.h" +#include "util.h" + +Logger::Logger() { + +} + +Logger::~Logger() { + +} + +void Logger::error(string message, bool fatal) { + cerr << "wmi[E " << Util::timestamp() << "]: " << message; + if (fatal) { + cerr << ", giving up" << endl; + exit(1); + } + cerr << endl; +} + +void Logger::warning(string message) { + cerr << "wmi[W " << Util::timestamp() << "]: " << message << endl; +} + +void Logger::debug(string message) { + cout << "wmi[D " << Util::timestamp() << "]: " + << message << endl; +} diff --git a/logger.h b/logger.h @@ -0,0 +1,36 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: logger.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __LOGGER_H +#define __LOGGER_H + +#include <fstream> +#include <string> + +#include "singleton.h" +#include "wmi.h" + +// forward declaration +class Logger; + +/** + * Basic logger which distinguishes error, warning and debug logging. + */ +class Logger : public Singleton<Logger> +{ + +public: + + Logger(); + ~Logger(); + + /** If fatal <code>true</code> then exit(1) occurs */ + void error(string message, bool fatal = false); // will be logged always + void warning(string message); + void debug(string message); + +}; + +#endif // __LOGGER_H diff --git a/main.cpp b/main.cpp @@ -0,0 +1,343 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: main.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include "../config.h" + +extern "C" { +#include <assert.h> +#include <unistd.h> // getopt stuff +#include <stdlib.h> // getenv stuff +#include <string.h> +#include <X11/Xlib.h> +} + +#include <iostream> +#include <string> +#include <sstream> +#include <map> + +#include "wmi.h" + +#include "loader.h" +#include "util.h" +#include "kernel.h" + + +static void version() { + cout << "wmi - window manager improved - " << __WMI_VERSION + << endl << " (C)opyright 2003 - 2004 by Anselm R. Garbe" + << endl; +} + +static void usage() { + cout << "usage: " << endl << endl + << " wmi [-d <display>] [-h] [-v]" << endl + << endl + << " -d display specifies the display to use" << endl + << " -h prints out this help" << endl + << " -v prints out above version info" << endl; +} + +Display *openDisplay(const char *displayName) { + + Display *display = XOpenDisplay(displayName); + if (!display) { + if (displayName != 0) { + cerr << "wmi[E " << Util::timestamp() + << "]: cannot open display \'" + << displayName << "\', giving up" << endl; + } + else { + cerr << "wmi[E " << Util::timestamp() + << "]: cannot open default display" + << ", giving up" << endl; + } + exit(1); + } + + return display; +} + +static bool loadSettings(MSettings *settings, string filename, + const char *home, bool suppressWarning = false, + bool caseSensitive = false) +{ + // check global conf + Loader::load(settings, (string)CONFPATH + "/" + filename, true); + + // check local conf + string localConf = (string)home + "/.wmi/" + filename; + bool result = Loader::load(settings, localConf, + suppressWarning, caseSensitive); + if (!suppressWarning && !result) { + cerr << "wmi[W " << Util::timestamp() + << "]: cannot load settings from '" + << localConf << "', using defaults" << endl; + } + return result; +} + +static MSettings *initThemeSettings() { + + MSettings *themeSettings = new MSettings(); + + // init default values + // new default 24Bit grey color schema + (*themeSettings)["color.bar.background"] = "#F6F6F6"; + (*themeSettings)["color.bar.text"] = "black"; + (*themeSettings)["color.bar.shine"] = "#999999"; + (*themeSettings)["color.bar.shadow"] = "#999999"; + (*themeSettings)["color.meter.background"] = "#F6F6F6"; + (*themeSettings)["color.meter.figure.high"] = "red"; + (*themeSettings)["color.meter.figure.normal"] = "#253446"; + (*themeSettings)["color.meter.figure.low"] = "green"; + (*themeSettings)["color.meter.border.shine"] = "#7AA4D9"; + (*themeSettings)["color.meter.border.shadow"] = "#7AA4D9"; + (*themeSettings)["color.focusreq.background"] = "#FF4000"; + (*themeSettings)["color.focusreq.text"] = "black"; + (*themeSettings)["color.focusreq.shine"] = "#FFD900"; + (*themeSettings)["color.focusreq.shadow"] = "#FFD900"; + (*themeSettings)["color.tiled.shine.focussed"] = "#FFD900"; + (*themeSettings)["color.tiled.shadow.focussed"] = "#FFD900"; + (*themeSettings)["color.tiled.shine.normal"] = "black"; + (*themeSettings)["color.tiled.shadow.normal"] = "black"; + (*themeSettings)["color.button.background.normal"] = "#3A5D8A"; + (*themeSettings)["color.button.background.pressed"] = "#253446"; + (*themeSettings)["color.button.border.shine.normal"] = "#7AA4D9"; + (*themeSettings)["color.button.border.shine.pressed"] = "#7AA4D9"; + (*themeSettings)["color.button.border.shadow.normal"] = "#7AA4D9"; + (*themeSettings)["color.button.border.shadow.pressed"] = "#7AA4D9"; + (*themeSettings)["color.button.figure.shine.normal"] = "white"; + (*themeSettings)["color.button.figure.shine.pressed"] = "#BDBDBD"; + (*themeSettings)["color.button.figure.shadow.normal"] = "white"; + (*themeSettings)["color.button.figure.shadow.pressed"] = "#BDBDBD"; + (*themeSettings)["color.frame.background.normal"] = "#F6F6F6"; + (*themeSettings)["color.frame.background.focussed"] = "#3E71AA"; + (*themeSettings)["color.frame.pseudo"] = "#D9D9D9"; + (*themeSettings)["color.frame.shine.normal"] = "black"; + (*themeSettings)["color.frame.shine.focussed"] = "#26476A"; + (*themeSettings)["color.frame.shadow.normal"] = "black"; + (*themeSettings)["color.frame.shadow.focussed"] = "#26476A"; + (*themeSettings)["color.label.background.normal"] = "#F6F6F6"; + (*themeSettings)["color.label.background.focussed"] = "#D9D9D9"; + (*themeSettings)["color.label.text.normal"] = "black"; + (*themeSettings)["color.label.text.focussed"] = "black"; + (*themeSettings)["color.label.shine.normal"] = "#999999"; + (*themeSettings)["color.label.shine.focussed"] = "#848484"; + (*themeSettings)["color.label.shadow.normal"] = "#999999"; + (*themeSettings)["color.label.shadow.focussed"] = "#848484"; + (*themeSettings)["color.tab.background.active.normal"] = "#F6F6F6"; + (*themeSettings)["color.tab.background.inactive.normal"] = "#D9D9D9"; + (*themeSettings)["color.tab.background.active.focussed"] = "#3E71AA"; + (*themeSettings)["color.tab.background.inactive.focussed"] = "#F6F6F6"; + (*themeSettings)["color.tab.text.active.normal"] = "#ADADAD"; + (*themeSettings)["color.tab.text.inactive.normal"] = "#ADADAD"; + (*themeSettings)["color.tab.text.active.focussed"] = "white"; + (*themeSettings)["color.tab.text.inactive.focussed"] = "#ADADAD"; + (*themeSettings)["color.tab.shine.active.normal"] = "#F6F6F6"; + (*themeSettings)["color.tab.shine.inactive.normal"] = "#F6F6F6"; + (*themeSettings)["color.tab.shine.active.focussed"] = "#3E71AA"; + (*themeSettings)["color.tab.shine.inactive.focussed"] = "#F6F6F6"; + (*themeSettings)["color.tab.shadow.active.normal"] = "#F6F6F6"; + (*themeSettings)["color.tab.shadow.inactive.normal"] = "#F6F6F6"; + (*themeSettings)["color.tab.shadow.active.focussed"] = "#3E71AA"; + (*themeSettings)["color.tab.shadow.inactive.focussed"] = "#F6F6F6"; + (*themeSettings)["font"] = "fixed"; + (*themeSettings)["exec"] = "xsetroot -solid #7B96AC"; + + return themeSettings; +} + +static MSettings *initCommonSettings() { + + MSettings *commonSettings = new MSettings(); + + // init common settings + (*commonSettings)["resize-move.factor"] = "10"; + (*commonSettings)["terminal"] = "xterm -e"; + (*commonSettings)["statusbar.alignment"] = "bottom"; +#ifdef SLOT_SUPPORT + (*commonSettings)["slot.alignment"] = "right"; // left + (*commonSettings)["slot.style"] = "transparent"; // solid + (*commonSettings)["slot.tabs"] = "default"; // name1,name2,... + (*commonSettings)["slot.mode"] = "non-overlap"; // overlap +#endif + (*commonSettings)["bar.buttons"] = "yes"; // no + (*commonSettings)["frame.buttons"] = "yes"; // no + (*commonSettings)["frame.colwidth"] = "60"; + (*commonSettings)["frame.autodestroy"] = "yes"; // no + (*commonSettings)["frame.mode"] = "tabbed"; // tiled + (*commonSettings)["border.width"] = "3"; + (*commonSettings)["default.client-mode"] = "float"; + (*commonSettings)["default.transient-mode"] = "float"; + (*commonSettings)["default.bar-mode"] = "show"; // hide + (*commonSettings)["default.border-mode"] = "show"; // hide + (*commonSettings)["startup.chain"] = ""; + (*commonSettings)["menu.actions"] = "xterm,restart,quit"; + (*commonSettings)["autocompletion.mode"] = "default"; // regex + (*commonSettings)["cycle.mode"] = "default"; // stackedtabbing + + return commonSettings; +} + + +static MSettings *initActionSettings() { + + MSettings *actionSettings = new MSettings(); + + // intern action bindings + (*actionSettings)["intern.quit.keys"] = "ctrl+alt+q"; + (*actionSettings)["intern.grow-left.keys"] = "alt+r::h"; + (*actionSettings)["intern.grow-right.keys"] = "alt+r::l"; + (*actionSettings)["intern.grow-up.keys"] = "alt+r::k"; + (*actionSettings)["intern.grow-down.keys"] = "alt+r::j"; + (*actionSettings)["intern.shrink-left.keys"] = "shift+alt+r::h"; + (*actionSettings)["intern.shrink-right.keys"] = "shift+alt+r::l"; + (*actionSettings)["intern.shrink-up.keys"] = "shift+alt+r::k"; + (*actionSettings)["intern.shrink-down.keys"] = "shift+alt+r::j"; + (*actionSettings)["intern.move-client-left.keys"] = "shift+alt+h"; + (*actionSettings)["intern.move-client-right.keys"] = "shift+alt+l"; + (*actionSettings)["intern.move-client-up.keys"] = "shift+alt+k"; + (*actionSettings)["intern.move-client-down.keys"] = "shift+alt+j"; + (*actionSettings)["intern.select-frame-left.keys"] = "alt+h"; + (*actionSettings)["intern.select-frame-right.keys"] = "alt+l"; + (*actionSettings)["intern.select-frame-up.keys"] = "alt+k"; + (*actionSettings)["intern.select-frame-down.keys"] = "alt+j"; + (*actionSettings)["intern.kill-client.keys"] = "ctrl+alt+c"; + (*actionSettings)["intern.cycle-client-next.keys"] = "alt+Tab"; + (*actionSettings)["intern.cycle-client-prev.keys"] = "shift+alt+Tab"; + (*actionSettings)["intern.cycle-workspace-next.keys"] = "ctrl+alt+Right"; + (*actionSettings)["intern.cycle-workspace-prev.keys"] = "ctrl+alt+Left"; + (*actionSettings)["intern.split-frame-left.keys"] = "alt+s::h"; + (*actionSettings)["intern.split-frame-right.keys"] = "alt+s::l"; + (*actionSettings)["intern.split-frame-up.keys"] = "alt+s::k"; + (*actionSettings)["intern.split-frame-down.keys"] = "alt+s::j"; + (*actionSettings)["intern.join-frame-left.keys"] = "shift+alt+s::h"; + (*actionSettings)["intern.join-frame-right.keys"] = "shift+alt+s::l"; + (*actionSettings)["intern.join-frame-up.keys"] = "shift+alt+s::k"; + (*actionSettings)["intern.join-frame-down.keys"] = "shift+alt+s::j"; + (*actionSettings)["intern.detach-client.keys"] = "alt+d"; + (*actionSettings)["intern.attach-last-client.keys"] = "alt+a"; + (*actionSettings)["intern.toggle-client-mode.keys"] = "alt+m"; + (*actionSettings)["intern.toggle-mode.keys"] = "alt+f"; + (*actionSettings)["intern.inputmode.keys"] = "alt+i"; + (*actionSettings)["intern.exec.keys"] = "alt+e"; + (*actionSettings)["intern.grab-move.keys"] = "mod1+Button1"; + (*actionSettings)["intern.zoom-client.keys"] = "mod1+z"; + + // sample extern commands + (*actionSettings)["extern.xterm.cmd"] = "xterm"; + (*actionSettings)["extern.xterm.keys"] = "alt+x"; + + // sample chains + (*actionSettings)["chain.grow-full.seq"] = + "grow-left,grow-right,grow-up,grow-down"; + (*actionSettings)["chain.grow-full.keys"] = "alt+r::f"; + (*actionSettings)["chain.shrink-full.seq"] = + "shrink-left,shrink-right,shrink-up,shrink-down"; + (*actionSettings)["chain.shrink-full.keys"] = "shift+alt+r::f"; + + return actionSettings; +} + +static MSettings *initSessionSettings(Display *display) +{ + MSettings *sessionSettings = new MSettings(); + + unsigned int monitorCount = ScreenCount(display); + + ostringstream prefix; + + for (unsigned int i = 0; i < monitorCount; i++) { + prefix.str(""); + prefix << "monitor[" << i << "]"; + + (*sessionSettings)[prefix.str() + ".workspaces"] = "2"; + (*sessionSettings)[prefix.str() + ".focused"] = "0"; + (*sessionSettings)[prefix.str() + ".workspace[0].name"] = "workspace 1"; + (*sessionSettings)[prefix.str() + ".workspace[0].clientbar"] = "yes"; + (*sessionSettings)[prefix.str() + ".workspace[0].statusbar"] = "yes"; + (*sessionSettings)[prefix.str() + ".workspace[1].name"] = "workspace 2"; + (*sessionSettings)[prefix.str() + ".workspace[1].clientbar"] = "yes"; + (*sessionSettings)[prefix.str() + ".workspace[1].statusbar"] = "yes"; +#ifdef SLOT_SUPPORT + (*sessionSettings)[prefix.str() + ".workspace[0].slot"] = "default"; + (*sessionSettings)[prefix.str() + ".workspace[1].slot"] = "default"; +#endif + } + + return sessionSettings; +} + +//////////////////////////////////////////////////////////// +// Here WMI's life begins +int main(int argc, char *argv[]) +{ + string *displayName = 0; + int c; + unsigned int size; + + // command line args + while ((c = getopt(argc, argv, "vhd:")) != -1) { + switch (c) { + case 'd': + size = strlen(optarg); + displayName = new string(optarg); + break; + case 'v': + version(); + exit(0); + break; + case '?': + case 'h': + usage(); + exit(1); + break; + } + } + + const char *home = getenv("HOME"); + if (!home) { + cerr << "wmi[E " << Util::timestamp() + << "]: cannot determine your $HOME directory," + << " giving up" << endl; + exit(1); + } + + Display *display = openDisplay((displayName != 0) ? + displayName->c_str() : 0); + + // settings + MSettings *themeSettings = initThemeSettings(); + bool existsThemeConf = loadSettings(themeSettings, "theme.conf", home); + MSettings *commonSettings = initCommonSettings(); + bool existsCommonConf = loadSettings(commonSettings, "common.conf", home); + MSettings *actionSettings = initActionSettings(); + loadSettings(actionSettings, "actions.session", home); + loadSettings(actionSettings, "actions.conf", home, true); + MSettings *sessionSettings = initSessionSettings(display); + loadSettings(sessionSettings, "wmi.session", home, false, true); + loadSettings(sessionSettings, "session.conf", home, true, true); + + // only one Kernel instance is needed + int result = Kernel::instance()->start(argv, display, + themeSettings, commonSettings, actionSettings, + sessionSettings, !existsCommonConf); + + // Check if we should safe all current settings to the rc file + if (result == 0) { + if (!existsThemeConf) { + Loader::saveSettings(themeSettings, (string)home + + "/.wmi/theme.conf"); + } + if (!existsCommonConf) { + Loader::saveSettings(commonSettings, (string)home + + "/.wmi/common.conf"); + } + Kernel::instance()->saveSettings(); + } + + return result; +} diff --git a/man/Makefile.am b/man/Makefile.am @@ -0,0 +1,2 @@ +man_MANS = actions.conf.5 common.conf.5 session.conf.5 theme.conf.5 wmi.1 wmiremote.1 +EXTRA_DIST = actions.conf.5 common.conf.5 session.conf.5 theme.conf.5 wmi.1 wmiremote.1 diff --git a/man/Makefile.in b/man/Makefile.in @@ -0,0 +1,387 @@ +# Makefile.in generated by automake 1.8.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = man +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/./xft.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(mkdir_p) +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +depcomp = +am__depfiles_maybe = +SOURCES = +DIST_SOURCES = +man1dir = $(mandir)/man1 +am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" +man5dir = $(mandir)/man5 +NROFF = nroff +MANS = $(man_MANS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build_alias = @build_alias@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +man_MANS = actions.conf.5 common.conf.5 session.conf.5 theme.conf.5 wmi.1 wmiremote.1 +EXTRA_DIST = actions.conf.5 common.conf.5 session.conf.5 theme.conf.5 wmi.1 wmiremote.1 +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps man/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps man/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +uninstall-info-am: +install-man1: $(man1_MANS) $(man_MANS) + @$(NORMAL_INSTALL) + test -z "$(man1dir)" || $(mkdir_p) "$(DESTDIR)$(man1dir)" + @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 1*) ;; \ + *) ext='1' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst"; \ + done +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 1*) ;; \ + *) ext='1' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \ + rm -f "$(DESTDIR)$(man1dir)/$$inst"; \ + done +install-man5: $(man5_MANS) $(man_MANS) + @$(NORMAL_INSTALL) + test -z "$(man5dir)" || $(mkdir_p) "$(DESTDIR)$(man5dir)" + @list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.5*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 5*) ;; \ + *) ext='5' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst"; \ + done +uninstall-man5: + @$(NORMAL_UNINSTALL) + @list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.5*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 5*) ;; \ + *) ext='5' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f '$(DESTDIR)$(man5dir)/$$inst'"; \ + rm -f "$(DESTDIR)$(man5dir)/$$inst"; \ + done +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(MANS) +installdirs: + for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-man + +install-exec-am: + +install-info: install-info-am + +install-man: install-man1 install-man5 + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-man + +uninstall-man: uninstall-man1 uninstall-man5 + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-man1 install-man5 install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am uninstall uninstall-am uninstall-info-am \ + uninstall-man uninstall-man1 uninstall-man5 + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/man/actions.conf.5 b/man/actions.conf.5 @@ -0,0 +1,366 @@ +.TH WMI 5 User Manuals +.SH NAME +WMI \- Window Manager Improved, a X11 window manager for hackers +.SH DESCRIPTION +The file \fIactions.conf\f1 is used to define actions manually. Three types of actions are supported: external (extern), internal (intern) and sequential (chain) actions. The internal actions are described in the following section. +.SH INTERN ACTIONS +Note, most actions are context-sensitive, this means that they are only available, if they would have any effect. +.TP +\fBattach-all-clients: \f1 +Attaches all detached clients. +.TP +\fBattach-client: \f1 +Attaches an detached client to the workspace. If the client has been detached as floating client, it'll be attached as floating client again, otherwise if will be attached to the focussed frame, or to a new frame, if there does not exist a frame yet. +.TP +\fBbanish: \f1 +Banishes the pointer to bottom-right corner. +.TP +\fBbegin-record: \f1 +Begins recording all WMI specific actions until end-record-* or cancel-record will be invoked, except entering interactive mode and end-record-*. +.TP +\fBbind-keys: \f1 +Creates a shortcut for a specific action. +.TP +\fBcancel-record: \f1 +Cancels the recording of actions immediately. +.TP +\fBcreate-action: \f1 +Creates a new action alias for an external application. +.TP +\fBcreate-workspace: \f1 +Creates a new workspace on the focussed monitor. +.TP +\fBcycle-client-next: \f1 +Focusses next client within a frame. +.TP +\fBcycle-client-prev: \f1 +Focusses previous client within a frame. +.TP +\fBcycle-slot-tab-next: \f1 +Focusses next slot tab of the slot. +.TP +\fBcycle-slot-tab-prev: \f1 +Focussed previous slot tab of the slot. +.TP +\fBcycle-workspace-next: \f1 +Focusses next workspace on the monitor. +.TP +\fBcycle-workspace-prev: \f1 +Focusses previous workspace on the monitor. +.TP +\fBdestroy-action: \f1 +Destroys a selected extern- or chain-action. Always valid. +.TP +\fBdestroy-workspace: \f1 +Destroys the focussed workspace. Only valid if no clients or frames are attached to this workspace and at least another workspace exists. +.TP +\fBdetach-all-clients: \f1 +Detaches all clients from focussed frame or all floating clients. +.TP +\fBdetach-client: \f1 +Detaches the focused client. +.TP +\fBend-record-chain: \f1 +Ends recording actions and provides to create a chain action, which will invoke all recorded actions sequentially through only one alias name. +.TP +\fBend-record-script: \f1 +Ends recording actions and provides to save all recorded actions to a shell script which uses wmiremote for remote invocation of the actions. This enables flexible pseudo session management. +.TP +\fBexec: \f1 +Provides a list of all executables in the \fI$PATH\f1 environment, which can be executed. You can also use the '/' character to browse through your directories and choose an executable which isn't available through the \fI$PATH\f1 environment. You can also smuggle additional command arguments behind the executable name, as you know it from the command line. But note that this is not as powerful as you use the shell. Note, that exec executes the choosen application directly. +.TP +\fBexec-term: \f1 +Same as exec, except that the action will be executed within the defined (see common.conf) default terminal. +.TP +\fBgrow-down: \f1 +Grows the focussed floating client or frame in south direction. This action is not valid for borderless clients. +.TP +\fBfit-client: \f1 +Fits the client size to workspace area. +.TP +\fBgrow-left: \f1 +Grows the focussed floating client or frame in west direction. This action is not valid for borderless clients. +.TP +\fBgrow-right: \f1 +Grows the focussed floating client or frame in east direction. This action is not valid fo borderless clients. +.TP +\fBgrow-up: \f1 +Grows the focussed floating client or frame in north direction. This action is not valid for borderless clients. +.TP +\fBhide-bars: \f1 +Hides all bars of all frames/clients on the workspace. +.TP +\fBhide-borders: \f1 +Hides all borders of all frames/clients on the workspace. +.TP +\fBhook-client: \f1 +Hooks a client to a specific workspace. Thus the specific clients class::instance will be attached automatically to the hooked workspace afterwards all the time. +.TP +\fBjoin-frame-down: \f1 +Joins the focussed frame with its neighbor frame in south direction. +.TP +\fBjoin-frame-left: \f1 +Joins the focussed frame with its neighbor frame in west direction. +.TP +\fBjoin-frame-right: \f1 +Joins the focussed frame with its neighbor frame in east direction. +.TP +\fBjoin-frame-up: \f1 +Joins the focussed frame with its neighbor frame in north direction. +.TP +\fBkill-client: \f1 +Kills the focussed client. First WMI will try to let the client close itself, if the client ignores this request, it'll be killed. +.TP +\fBkill-slot-client: \f1 +Kills the slotted client. +.TP +\fBlower: \f1 +Lowers the focussed client or frame. +.TP +\fBmax-client-to-screen: \f1 +Maximizes the focussed floating client to the whole screen. +.TP +\fBmove-client-down: \f1 +Moves the focussed floating client in south direction. +.TP +\fBmove-client-left: \f1 +Moves the focussed floating client in west direction. +.TP +\fBmove-client-right: \f1 +Moves the focussed floating client in east direction. +.TP +\fBmove-client-up: \f1 +Moves the focussed floating client in north direction. +.TP +\fBquit: \f1 +Exits WMI and saves all settings. +.TP +\fBraise: \f1 +Raises the focussed client or frame. +.TP +\fBrehash: \f1 +Rereads the \fI$PATH\f1 environment for exec actions, this is useful after having installed new apps. It's pretty similiar to the (t)csh or zsh way of life. +.TP +\fBrename-workspace: \f1 +Renames the focussed workspace. Note, that WMI doesn't cares about the names, they may be equal or not. +.TP +\fBsave-settings: \f1 +Manually saves session settings (shortcuts, workspace configuration). +.TP +\fBselect-client: \f1 +Selects a client from a list of all clients. +.TP +\fBselect-client-id: \f1 +Selects a client from a list of all client ids. +.TP +\fBselect-frame-down: \f1 +Focusses the downward neighbor frame of the focussed frame. +.TP +\fBselect-frame-left: \f1 +Focusses the leftward neighbor frame of the focussed frame. +.TP +\fBselect-frame-right: \f1 +Focusses the rightward neighbor frame of the focussed frame. +.TP +\fBselect-frame-up: \f1 +Focusses the upward neighbor frame of the focussed frame. +.TP +\fBselect-workspace: \f1 +Provides the names of all workspaces of this monitor and focusses the selected workspace afterwards. +.TP +\fBshow-bars: \f1 +Shows all bars of all frames/clients on the workspace. +.TP +\fBshow-borders: \f1 +Shows all borders of all frames/clients on the workspace. +.TP +\fBshrink-down: \f1 +Shrinks the focussed floating client or frame in south direction. +.TP +\fBshrink-left: \f1 +Shrinks the focussed floating client or frame in west direction. +.TP +\fBshrink-right: \f1 +Shrinks the focussed floating client or frame in east direction. +.TP +\fBshrink-up: \f1 +Shrinks the focussed floating client or frame in north direction. +.TP +\fBsend-client-down: \f1 +Sends the focussed client to its neighbor frame in south direction. +.TP +\fBsend-client-left: \f1 +Sends the focussed client from the focussed frame to its neighbor frame in west direction. +.TP +\fBsend-client-right: \f1 +Sends the focussed client from the focussed frame to its neighbor frame in east direction. +.TP +\fBsend-client-up: \f1 +Sends the focussed client from the focussed frame to its neighbor frame in north direction. +.TP +\fBslot-client: \f1 +Attaches the running client to the slot if WMI was build with slot support. +.TP +\fBsplit-frame-down: \f1 +Splits the focussed frame in south direction. Only valid if at least two clients are attached to the focussed frame. +.TP +\fBsplit-frame-left: \f1 +Splits the focussed frame in west direction. Only valid if at least two clients are attached to the focussed frame. +.TP +\fBsplit-frame-right: \f1 +Splits the focussed frame in east direction. Only valid if at least two clients are attached to the focussed frame. +.TP +\fBsplit-frame-up: \f1 +Splits the focussed frame in north direction. Only valid if at least two clients are attached to the focussed frame. +.TP +\fBsticky-client: \f1 +Makes the focussed client sticky. Sticky means that the client will be visible on all workspaces and always on top. +.TP +\fBstartup-action.name: \f1 +Starts an action after WMI is up and running on each start. +.TP +\fBswap-client-down: \f1 +Swaps the focussed client in the focussed frame with the focussed client of the downward neighbor frame. +.TP +\fBswap-client-left: \f1 +Swaps the focussed client in the focussed frame with the focussed client of the leftward neighbor frame. +.TP +\fBswap-client-right: \f1 +Swaps the focussed client in the focussed frame with the focussed client of the rightward neighbor frame. +.TP +\fBswap-client-up: \f1 +Swaps the focussed client in the focussed frame with the focussed client of the upward neighbor frame. +.TP +\fBswap-frame-down: \f1 +Swaps the focussed frame with the downward neighbor frame. +.TP +\fBswap-frame-left: \f1 +Swaps the focussed frame with the leftward neighbor frame. +.TP +\fBswap-frame-right: \f1 +Swaps the focussed frame with the rightward neighbor frame. +.TP +\fBswap-frame-up: \f1 +Swaps the focussed frame with the upward neighbor frame. +.TP +\fBtoggle-bar: \f1 +Toggles the visibility of the clients or frames titlebar. +.TP +\fBtoggle-border: \f1 +Toggles the visibility of the frame or client border. +.TP +\fBtoggle-client-mode: \f1 +Toggles between floating mode of a client with border and maximized mode. +.TP +\fBtoggle-client-sticky: \f1 +Toggles the focussed client between sticky and floating mode. +.TP +\fBtoggle-float-bar: \f1 +Toggles the visibility of the floating bar. +.TP +\fBtoggle-focus-mode: \f1 +Toggles the focus between frames and floating clients. +.TP +\fBtoggle-inputmode: \f1 +Enters input mode, which will appear in the status bar. +.TP +\fBtoggle-slot: \f1 +Toggles the visibility of the slot. +.TP +\fBtoggle-sloppy-mode: \f1 +Toggles the sloppy focus mode. +.TP +\fBtoggle-status-bar: \f1 +Toggles the visibility of the status bar. +.TP +\fBtoggle-tiled: \f1 +Toggles tiled mode of a frame. +.TP +\fBunslot-client: \f1 +Detaches the last client which has been attached to the slot again. +.TP +\fBunhook-client: \f1 +Unhooks a client from the hooked workspace. +.TP +\fBzoom-client: \f1 +Zooms the focussed client to the tiled (left) column. +.SH CONFIGURATION +If you prefer using WMI actions for configuration of the WMI, you can use create-action, begin/end-record-* and bind-keys from input mode. Such a configuration will be saved to \fIactions.session\f1 + +Experienced users may use a manually created configuration described in the following. + +Note that the \fIactions.conf\f1 will override all definitions made (automatically by WMI) in \fIactions.session\f1. Both files are syntactically equal and you can rename an existing \fIactions.session\f1 to \fIactions.conf\f1 for fine tuning or further manually configuration. +.SH FORMAT +The basic format of all \fI.conf\f1 and \fI.session\f1 files is as follows: + +key=value + +# comment + +key=\\#value # '\\' escapes special characters + +# special characters are: ", =, \\ and # + +If you've whitespaces within values, you've to quote them with '"' characters. You're free to let empty lines or whitespaces before and after keys, the '=' operator and the value. If you need a special character, you've to escape it using the '\\' character, e.g. \\=. +.SH TYPES OF ACTIONS +.TP +\fBextern:\f1 +External actions are aliases to external programs, e.g. mozilla, with following syntax: + +extern.< alias name >.cmd="< the command, maybe with arguments >" + +extern.< alias name >.keys=< modifier[+modifier]+(key|button) > + +The first line defines the command which will be executed if the action defined by < alias name > is invoked. Note that the command needs to be quoted, if it contains whitespaces. The second line defines the shortcut of the action. Note that the second line is optional. +.TP +\fBintern:\f1 +Internal actions are such actions defined in \fBwmi(1)\f1. It's forbidden to define external or sequential actions with the same alias name as an internal action has. If you ignore this advice, don't wonder if WMI isn't able to invoke the specific internal action anymore. + +Since internal actions have a fixed semantic you can only define a shortcut for them: + +intern.< action name >.keys=< modifier[+modifier]+(key|button) > + +The line defines the shortcut of the action. +.TP +\fBchain:\f1 +The chain mechanism, which represents the ability for user defined sequential action invoking is a special feature of WMI never seen before in other window managers. + +Regardless of which type an action within a chain is, everything is possible, except recursion. Recursion means that the chain is calling itself, which would lead to an endless loop. WMI detects such recursion and will stop the invocation of recursive chains immediatly. + +Everything is possible means, that you're free to invoke internal, external and sequential actions within one chain arbitrarily. + +One scenario which may occur is the invocation of several external applications and afterwards automatic arrangement of them (e.g. split actions or whatever WMI provides) through internal actions. But you'll have problems achieving this, since WMI doesn't waits while chain processing until an external application will be ready and proceed afterwards, because this would be indecisable. So take care yourself, that all actions after an external action within a chain are independently from any client window. + +If you want to achieve something like this, you can use \fBwmiremote(1)\f1 with the \fI-a\f1 argument within a script and between external and internal actions you may define some sleep or wait timeouts. + +Through chains it's also possible to define aliases for internal actions, one chain with only one internal action could be an alias for it - sometimes this may useful. + +The syntax for chains looks as follows: + +chain.< alias name >.seq=< action[+arg[+arg ...]] >[,< action ... >] ... + +chain.< alias name >.keys=< modifier[+modifier]+(key|button) > + +The first line defines the chain. As you can see, all actions of a chain are comma separated and for actions which may need arguments it's optional to smuggle some arguments to these actions with the '+' operator. Note that it's only possible to run defined actions within a chain. If you want to invoke an application from a chain without having defined an external action for it, you could use the following example: + +chain.cxterm.seq=exec+xterm + +This will use the exec action and smuggle xterm as command to it. +.SH SHORTCUTS +The basic format of all shortcuts is: + +[modifier*]+(key|button)[::[modifier*]+(key|button)]* + +A modifier is one of the following strings: none, mod1, mod2, mod3, ..., ctrl, shift + +A key is a key on your keyboard, note that keys have to be case sensitive to the definitions in \fI< X11/keysymdef.h >\f1, but without the 'XK_' prefix. This means for example, that 'f1' is invalid, you have to use 'F1' instead (same to Left, Right, Up, Down, etc.). + +A button is a mouse button, if you've a three-button mouse following buttons are valid: Button1, Button2, Button3. +.SH AUTHOR +WMI was written by Anselm R. Garbe < anselmg@t-online.de > and others (see AUTHORS or the WMI site for further information) + +You will find the newest version of WMI at \fBhttp://wmi.berlios.de/\f1. There is also a mailing list. +.SH BUGS +You should report them to the mailing list. +.SH SEE ALSO +\fBwmi(1)\f1, \fBwmiremote(1)\f1, \fBcommon.conf(5)\f1, \fBsession.conf(5)\f1, \fBtheme.conf(5)\f1 diff --git a/man/common.conf.5 b/man/common.conf.5 @@ -0,0 +1,87 @@ +.TH WMI 5 User Manuals +.SH NAME +WMI \- Window Manager Improved, a X11 window manager for hackers +.SH DESCRIPTION +The file \fIcommon.conf\f1 is used to fine adjust the common options of WMI. +.SH FORMAT +The basic format of all \fI.conf\f1 and \fI.session\f1 files is as follows: + +key=value + +# comment + +key=\\#value # '\\' escapes special characters + +# special characters are: ", =, \\ and # + +If you've whitespaces within values, you've to quote them with '"' characters. You're free to let empty lines or whitespaces before and after keys, the '=' operator and the value. If you need a special character, you've to escape it using the '\\' character, e.g. \\=. +.SH OPTIONS +Following option keys are defined: +.TP +\fBautocompletion.mode=\f1 +Defines how to autocomplete in input mode. Valid values are 'regex' and 'default'. +.TP +\fBbar.buttons=\f1 +Defines wether the buttons of the float bar or statusbar are visible ('yes') or not visible ('no'), default is 'yes'. +.TP +\fBborder.width=\f1 +Defines the width of frame and client borders. Default is 3 pixels. +.TP +\fBdefault.bar-mode=\f1 +Defines if bars are visible by default or not. Values are 'show' and 'hide'. +.TP +\fBdefault.border-mode=\f1 +Defines if borders are visible by default or not. Values are 'show' and 'hide'. +.TP +\fBdefault.client-mode=\f1 +Defines if unknown clients are attached maxmized ('max') or floating ('float'). Default is 'float'. +.TP +\fBdefault.transient-mode=\f1 +Defines if unknown transient windows are attached maxmized ('max') or floating ('float'). Default is 'float'. +.TP +\fBframe.autodestroy=\f1 +Defines wether frames are automatically destroyed when empty or not. Valid values are 'yes' and 'no'. +.TP +\fBframe.buttons=\f1 +Defines wether the buttons of frames/clients are visible ('yes') or not ('no'), default is 'yes'. +.TP +\fBframe.colwidth=\f1 +Defines how much percentage is used for the left client in tiled mode of the frame width. Default is '66', valid values vary between 1 and 99. +.TP +\fBframe.mode=\f1 +Defines wether frames are tiled or tabbed by default. Valid values are 'tiled' and 'tabbed'. +.TP +\fBmenu.actions=\f1 +Defines which actions appear in the menu of the clientbar. The value is a comma-separated list of action names. +.TP +\fBresize-factor=\f1 +Defines the relative resize factor for keyboard driven resize or move operations. Relative means relative to the screen dimension. Useful values are between 1 and 30, default is 10. +.TP +\fBresize-info=\f1 +Defines where the resize information should be located. You can choose 'center' or 'bar' here, default is 'center'. +.TP +\fBslot.alignment=\f1 +Defines wether the slot appears 'right' or 'left', default is 'right'. +.TP +\fBslot.style=\f1 +Defines wether the slot should appear 'transparent' or 'solid'. Default is 'transparent'. Solid means fill with bar.background color. +.TP +\fBslot.tabs=\f1 +Defines the tabs of the slot. Values are a comma-seprated list of tab names. +.TP +\fBstatusbar.alignment=\f1 +Defines the alignment of the status bar, allowed are 'top' and 'bottom', default is 'bottom'. +.TP +\fBstatusbar.status-width=\f1 +Defines the relative (to monitor width) width of the space for user defined status information set by \fBwmiremote(1)\f1. Default is 30 (percent). +.TP +\fBterminal=\f1 +Defines the terminal command to use for the exec-term action, default is "xterm -e". +.SH AUTHOR +WMI was written by Anselm R. Garbe < anselmg@t-online.de > and others (see AUTHORS or the WMI site for further information) + +You will find the newest version of WMI at \fBhttp://wmi.berlios.de/\f1. There is also a mailing list. +.SH BUGS +You should report them to the mailing list. +.SH SEE ALSO +\fBwmi(1)\f1, \fBwmiremote(1)\f1, \fBactions.conf(5)\f1, \fBsession.conf(5)\f1, \fBtheme.conf(5)\f1 diff --git a/man/session.conf.5 b/man/session.conf.5 @@ -0,0 +1,37 @@ +.TH WMI 5 User Manuals +.SH NAME +WMI \- Window Manager Improved, a X11 window manager for hackers +.SH DESCRIPTION +The file \fIsession.conf\f1 is for experts only. Here special client class/instance hints can be set and a user defined layout (workspace, layer and frame configuration) can be adjusted. Normally this is the job of WMI, but maybe there're people who want adjust everything by hand. + +If so, you may ask questions concerning session.conf on the wmi-devel mailinglist. This manual page only covers the basic class/instance syntax for client hints. + +Note that \fIsession.conf\f1 is syntactically equal to \fIwmi.session\f1 which can be used as starting point for understanding the expert syntax, which is quiet easy to understand - I think :) +.SH FORMAT +The basic format of all \fI.conf\f1 and \fI.session\f1 files is as follows: + +key=value + +# comment + +key=\\#value # '\\' escapes special characters + +# special characters are: ", =, \\ and # + +If you've whitespaces within values, you've to quote them with '"' characters. You're free to let empty lines or whitespaces before and after keys, the '=' operator and the value. If you need a special character, you've to escape it using the '\\' character, e.g. \\=. +.SH BASIC SYNTAX +The basic syntax for setting client class/instance hints is as follows: + +client.< class >::< instance >.mode=(float|max) + +This setting gives WMI the hint, if an application should be running in maximized mode (default) or run as floating application. + +Note that borderless applications will never be maximized whatever you may define. +.SH AUTHOR +WMI was written by Anselm R. Garbe < anselmg@t-online.de > and others (see AUTHORS or the WMI site for further information) + +You will find the newest version of WMI at \fBhttp://wmi.berlios.de/\f1. There is also a mailing list. +.SH BUGS +You should report them to the mailing list. +.SH SEE ALSO +\fBwmi(1)\f1, \fBwmiremote(1)\f1, \fBactions.conf(5)\f1, \fBcommon.conf(5)\f1, \fBtheme.conf(5)\f1 diff --git a/man/theme.conf.5 b/man/theme.conf.5 @@ -0,0 +1,237 @@ +.TH WMI 5 User Manuals +.SH NAME +WMI \- Window Manager Improved, a X11 window manager for hackers +.SH DESCRIPTION +The file \fItheme.conf\f1 is used to define the look and feel of WMI. +.SH FORMAT +The basic format of all \fI.conf\f1 and \fI.session\f1 files is as follows: + +key=value + +# comment + +key=\\#value # '\\' escapes special characters + +# special characters are: ", =, \\ and # + +If you've whitespaces within values, you've to quote them with '"' characters. You're free to let empty lines or whitespaces before and after keys, the '=' operator and the value. If you need a special character, you've to escape it using the '\\' character, e.g. \\=. +.SH COLOR FORMAT +Note that you can vary the syntax for color triplet definitions as follows: + +key=\\#nnnnnn + +or + +key="#nnnnnn" + +or + +key=blue + +This shows different escaping possibilities, the last case is useful for predefined X11 colors. + +The syntax: key=rgb:/nn/nn/nn +is NOT supported. +.SH TERMINOLOGY +All color definitions begin with prefix 'color.', afterwards the object is appended to this prefix, e.g. 'label', 'button'. + +There are four types of colors per object (note that some have only three colors): 'background', 'text', 'shine' and 'shadow'. Background means the background filling color of the object, text means the color of text, if any, shine and shadow means the color of the objects border, where top-left border is the shine border and bottom-right is the shadow border. + +If an object is distinguished into active and inactive it may have the focus, like frames or tabs. +.SH FORMAT +Following look and feel option keys are defined: +.SH OPTIONS +.TP +\fBcolor.bar.background=\f1 +Background color of float and status bar and input mode. +.TP +\fBcolor.bar.shadow=\f1 +Shadow border of the float and status bar. +.TP +\fBcolor.bar.shine=\f1 +Shine border of the float and status bar. +.TP +\fBcolor.bar.text=\f1 +Text color of the status text within status bar and the input mode prompt. +.TP +\fBcolor.button.background.normal=\f1 +Background color of not pressed buttons. +.TP +\fBcolor.button.background.pressed=\f1 +Background color of pressed buttons. +.TP +\fBcolor.button.border.shadow.normal=\f1 +Border shadow color of not pressed buttons. +.TP +\fBcolor.button.border.shadow.pressed=\f1 +Border shadow color of pressed buttons. +.TP +\fBcolor.button.border.shine.normal=\f1 +Border shine color of not pressed buttons. +.TP +\fBcolor.button.border.shine.pressed=\f1 +Border shine color of pressed buttons. +.TP +\fBcolor.button.figure.shadow.normal=\f1 +Figure shadow color of not pressed buttons. +.TP +\fBcolor.button.figure.shadow.pressed=\f1 +Figure shadow color of pressed buttons. +.TP +\fBcolor.button.figure.shine.normal=\f1 +Figure shine color of not pressed buttons. +.TP +\fBcolor.focusreq.background=\f1 +Background color of an item which requests for focus. +.TP +\fBcolor.focusreq.text=\f1 +Text color of an item which requests for focus. +.TP +\fBcolor.focusreq.shine=\f1 +Shine border color of an item which requests for focus. +.TP +\fBcolor.focusreq.shadow=\f1 +Shadow border color of an item which requests for focus. +.TP +\fBcolor.button.figure.shine.pressed=\f1 +Figure shine color of pressed buttons. +.TP +\fBcolor.frame.background.focussed=\f1 +Background color of the focussed frame. +.TP +\fBcolor.frame.background.normal=\f1 +Background color of not focussed frames. +.TP +\fBcolor.frame.pseudo=\f1 +XORed color of frame/client movements. +.TP +\fBcolor.frame.shadow.focussed=\f1 +Shadow color of the focussed frame. +.TP +\fBcolor.frame.shadow.normal=\f1 +Shadow color of not focussed frames. +.TP +\fBcolor.frame.shine.focussed=\f1 +Shine color of the focussed frame. +.TP +\fBcolor.frame.shine.normal=\f1 +Shine color of not focussed frames. +.TP +\fBcolor.label.background.focussed=\f1 +Background color of focussed labels (workspace and group pager labels or focussed entry within input mode). +.TP +\fBcolor.label.background.normal=\f1 +Background color of not focussed labels (workspace and group pager labels or focussed entry within input mode). +.TP +\fBcolor.label.shadow.focussed=\f1 +Shadow border color of focussed labels (workspace and group pager labels or focussed entry within input mode). +.TP +\fBcolor.label.shadow.normal=\f1 +Shadow border color of not focussed labels (workspace and group pager labels or focussed entry within input mode). +.TP +\fBcolor.label.shine.focussed=\f1 +Shine border color of focussed labels (workspace and group pager labels or focussed entry within input mode). +.TP +\fBcolor.label.shine.normal=\f1 +Shine border color of not focussed labels (workspace and group pager labels or focussed entry within input mode). +.TP +\fBcolor.label.text.focussed=\f1 +Text color of focussed labels (workspace and group pager labels or focussed entry within input mode). +.TP +\fBcolor.label.text.normal=\f1 +Text color of not focussed labels (workspace and group pager labels or focussed entry within input mode). +.TP +\fBcolor.meter.background=\f1 +Background color of a meter. +.TP +\fBcolor.meter.figure.high=\f1 +High color of a meter. +.TP +\fBcolor.meter.figure.normal=\f1 +Normal color of a meter. +.TP +\fBcolor.meter.figure.low=\f1 +Low color of a meter. +.TP +\fBcolor.meter.border.shine=\f1 +Shine border color of a meter. +.TP +\fBcolor.meter.border.shadow=\f1 +Shadow border color of a meter. +.TP +\fBcolor.meter.text=\f1 +Text color of a meter. +.TP +\fBcolor.tab.background.active.focussed=\f1 +Background color of active tab within focussed frame. +.TP +\fBcolor.tab.background.active.normal=\f1 +Background color of active tab within not focussed frame. +.TP +\fBcolor.tab.background.inactive.focussed=\f1 +Background color of inactive tab within focussed frame. +.TP +\fBcolor.tab.background.inactive.normal=\f1 +Background color of inactive tab within not focussed frame. +.TP +\fBcolor.tab.shadow.active.focussed=\f1 +Shadow color of active tab within focussed frame. +.TP +\fBcolor.tab.shadow.active.normal=\f1 +Shadow color of active tab within not focussed frame. +.TP +\fBcolor.tab.shadow.inactive.focussed=\f1 +Shadow color of inactive tab within focussed frame. +.TP +\fBcolor.tab.shadow.inactive.normal=\f1 +Shadow color of inactive tab within not focussed frame. +.TP +\fBcolor.tab.shine.active.focussed=\f1 +Shine color of active tab within focussed frame. +.TP +\fBcolor.tab.shine.active.normal=\f1 +Shine color of active tab within not focussed frame. +.TP +\fBcolor.tab.shine.inactive.focussed=\f1 +Shine color of inactive tab within focussed frame. +.TP +\fBcolor.tab.shine.inactive.normal=\f1 +Shine color of inactive tab within not focussed frame. +.TP +\fBcolor.tab.text.active.focussed=\f1 +Text color of active tab within focussed frame. +.TP +\fBcolor.tab.text.active.normal=\f1 +Text color of active tab within not focussed frame. +.TP +\fBcolor.tab.text.inactive.focussed=\f1 +Text color of inactive tab within focussed frame. +.TP +\fBcolor.tab.text.inactive.normal=\f1 +Text color of inactive tab within not focussed frame. +.TP +\fBcolor.tiled.shine.focussed=\f1 +Shine border color of focussed tiled clients. +.TP +\fBcolor.tiled.shadow.focussed=\f1 +Shadow border color of focussed tiled clients. +.TP +\fBcolor.tiled.shine.normal=\f1 +Shine border color of unfocussed tiled clients. +.TP +\fBcolor.tiled.shadow.normal=\f1 +Shine border color of unfocussed tiled clients. +.TP +\fBexec=\f1 +Execution of a command, e.g. setting the background wallpaper which is invoked while loading the theme (while startup of WMI). +.TP +\fBfont=\f1 +The font of labels, tabs and bars. Note that the height of buttons and bars is scaled to match with the font size of the defined font. If you want to have bigger or smaller bars and buttons simply choose a bigger or smaller font. +.SH AUTHOR +WMI was written by Anselm R. Garbe < anselmg@t-online.de > and others (see AUTHORS or the WMI site for further information) + +You will find the newest version of WMI at \fBhttp://wmi.berlios.de/\f1. There is also a mailing list. +.SH BUGS +You should report them to the mailing list. +.SH SEE ALSO +\fBwmi(1)\f1, \fBwmiremote(1)\f1, \fBactions.conf(5)\f1, \fBcommon.conf(5)\f1 \fBsession.conf(5)\f1, diff --git a/man/wmi.1 b/man/wmi.1 @@ -0,0 +1,109 @@ +.TH WMI 1 User Manuals +.SH NAME +WMI \- Window Manager Improved, a X11 window manager for hackers +.SH SYNOPSIS +\fBwmi [-d \fIdisplay\fB] [-h] [-v] +\f1 +.SH DESCRIPTION +WMI is a new window manager for X11, which attempts to combine the best features of LarsWM (\fBhttp://home.earthlink.net/~lab1701/larswm/\f1), Ion (\fBhttp://modeemi.cs.tut.fi/~tuomov/ion/\f1), TrsWM (\fBhttp://www.relex.ru/~yarick/trswm/\f1), evilwm (\fBhttp://evilwm.sf.net\f1) and ratpoison (\fBhttp://ratpoison.sf.net\f1) into one window manager. The basic user interaction interface is pretty much oriented on the two modes of the widespread vi editor. +.SH OPTIONS +Since WMI is a window manager most options are customized within configuration files, but there are following command line options: +.TP +\fB-d \fIdisplay\fB\f1 +Specifies the X display to use. Normally WMI uses the display provided by the \fI$DISPLAY\f1 environment variable. But if you want to use another display, e.g. a display provided by a remote host, just use this option. +.TP +\fB-h\f1 +Prints short usage information about WMI. +.TP +\fB-v\f1 +Prints the version of WMI. +.SH WELCOME +If you're a newbie user and want getting started with WMI, it's recommended to read this manual page and at least \fBactions.conf(5)\f1. Alternativly you can also read the tutorial at the WMI website \fBhttp://wmi.berlios.de/\f1 or following brief introduction. + +It's assumed that you've already installed WMI successfully and started it already. If it's the first time you've started WMI, you'll see this manual page automatically within a xterm. + +The next thing you can do is to toggle the client mode of the running xterm using alt+m shortcut. If your client was small, it'll be maximized afterwards. Make sure that the terminal is maximized before proceeding with next steps. + +Next step is to examine the input mode. WMI comes with two modes, the input mode and the normal mode. By default you're in the normal mode. To enter the input mode just press alt+i. + +Before we proceed keep in mind that you can cycle back to this window using alt+Tab. + +Within input mode you'll see all internal actions which would have currently any effect. You can press some keys to notice how the input mode autocompletes the actions. Press backspace for deleting all characters you entered until next match. + +First we're going to exec a new xterm. So enter 'e' and the exec action will be focussed. Now press RETURN to invoke the 'exec' action. Afterwards you'll see all binaries which are in your PATH environment. + +Now enter 'xt' to select 'xterm' and press RETURN. Afterwards a new xterm has been started. + +In this xterm we call wmiremote now to determine current default key bindings. Just enter 'wmiremote -p' in your terminal. Afterwards you'll get all currently used key bindings. + +Key bindings which have a '::' within are sequential key bindings, e.g. alt+s::l means pressing alt+s and afterwards l to invoke the specific action. + +Now we will try to split the current two xterms into two frames. So press the key binding for the action 'split-frame-left' which is alt+s::l by default. Note that splitting frames is only possible, if there're at least two clients attached to the specific frame you're going to split. The opposite action is 'join-frame-right' which is used to join splitted frames together again. + +We're now going to make the focussed xterm floating again. Press alt+m again. You'll notice that the floating xterm is attached to a group on the top bar. + +If you now toggle the floating xterm back to maximized mode, it'll be attached to the previous frame again. You can cycle between the clients using alt+Tab as you know it from conventional window managers. + +To getting further started, just read further in this manual page. +.SH TERMINOLOGY +To use WMI successfully you've to understand some often used words which have a special meaning and are described in the following. +.TP +\fBAction: \f1 +all internal functions, userdefined aliases to such functions, userdefined aliases to external applications and userdefined aliases for sequences of internal functions or aliases are called actions. Three types of actions are distinguished: internal (intern), external (extern) and sequential (chain). +.TP +\fBClient: \f1 +each window is called a client, regardless if it has a border (like most X clients) or not (like XMMS). Clients can be attached to frames (see below) in a maximized manner or attached in a floating manner. +.TP +\fBDirection: \f1 +all actions concerning non-overlapping frame handling are used in a directional manner. WMI distinguished the four base directions: west (left), east (right), north (up), south (down). +.TP +\fBFloating bar: \f1 +a bar in the opposite position of the status bar which contains a group pager and displays all clients attached to the focussed group. If the status bar has been configured to appear at bottom (default), the floating bar will appear at top, and vice versa. +.TP +\fBFrame: \f1 +frames are special container windows which are arranged in a non-overlapping manner on the workspace (see below). Frames may contain an arbitrary number of maximized clients. Frames can be split in several frames or merged together in a directional manner. Frames of WMI are pretty similiar to frames of the Ion window manager. There's no limit of numbers of frames per workspace. +.TP +\fBMode: \f1 +since WMI is strongly oriented on the vi-alike usage, it comes with two modes: input mode and normal mode. The input mode is used for invoking WMI specific actions, the normal mode is used for the allday work with your clients. In vi the input mode is the command mode, where ex commands are invoked and the normal mode of WMI is comparable to the editing mode in vi. +.TP +\fBMonitor: \f1 +in multi-head X configurations WMI is able to handle several screens. One screen in X terminology is a monitor in WMI terminology. Note: future versions of WMI will have built-in Xinerama support. +.TP +\fBShortcut: \f1 +a shortcut is a user defined key combination for an action, consisting of modifiers (or none) and a key or mouse button identifier. +.TP +\fBSlot: \f1 +the slot is a special area on the monitor visible on all workspaces which is used for withdrawn apps such as gkrellm or NeXTish dockapps from AfterStep or WindowMaker. +.TP +\fBStatus bar: \f1 +a bar which contains a workspace pager, some space for user defined status information using the wmiremote tool and which displays all (monitor-wide) detached clients. +.TP +\fBSticky clients: \f1 +Sticky clients are clients which are always on top and visible on all workspaces. Commonly sticky clients are applications providing status information or your favorite video media player. Note that sticky clients aren't visible at floating or statusbar because they're always on top. +.TP +\fBWorkspace: \f1 +a (virtual) workspace is used as virtual container of frames and floating clients on a specific screen (monitor), which can be used as virtual desktop. There's no limit of workspaces on a monitor. +.SH ACTIONS +WMI comes with many built-in actions, which are described in \fBactions.conf(5)\f1. +.SH CONFIGURATION +WMI is mainly configured through several files which should be located in \fI$ETCDIR/wmi/\f1 or in \fI$HOME/.wmi/\f1. + +Files are distinguished by their name and extension. In any circumstances don't touch \fI*.session\f1 files in your \fI$HOME/.wmi/\f1 directory, since they contain automatically saved stuff and any change would only take effect until next save-settings or quit action. Only edit \fI*.conf\f1 files manually. If they're located in \fI$ETCDIR/wmi/\f1 their properties will be valid for all users, otherwise if they're located in \fI$HOME/.wmi/\f1 their properties will be valid only for the specific user. Note, that changes made to files within \fI$HOME/.wmi/\f1 may override properties from \fI$ETCDIR/wmi/\f1. + +Following files are valid configuration files: + +\fBactions.conf(5)\f1: This file contains manually configured actions and shortcuts for actions. + +\fBcommon.conf(5)\f1: This file contains some common options. + +\fBsession.conf(5)\f1: This file contains properties which should override properties in \fIwmi.session\f1. + +\fBtheme.conf(5)\f1: This file contains all properties which influence the look and feel of the WMI. +.SH AUTHOR +WMI was written by Anselm R. Garbe < anselmg@t-online.de > and others (see AUTHORS or the WMI site for further information) + +You will find the newest version of WMI at \fBhttp://wmi.berlios.de/\f1. There is also a mailing list. +.SH BUGS +You should report them to the mailing list. +.SH SEE ALSO +\fBwmiremote(1)\f1, \fBactions.conf(5)\f1, \fBcommon.conf(5)\f1, \fBsession.conf(5)\f1, \fBtheme.conf(5)\f1 diff --git a/man/wmiremote.1 b/man/wmiremote.1 @@ -0,0 +1,41 @@ +.TH WMI 1 User Manuals +.SH NAME +WMI \- Window Manager Improved, a X11 window manager for hackers and real programmers +.SH SYNOPSIS +\fBwmiremote [-d \fIdisplay\fB] [-t \fItext\fB] [-a \fIaction\fB\fI[+arg[+arg ...]]\fB] [-m \fINN%text[,NN%text,...]\fB] [-p] [-v] +\f1 +.SH DESCRIPTION +Remote tool for WMI which is capable to set user defined status text to the WMI status bar, to pretty print current WMI key bindings (shortcuts) or to invoke WMI actions remotely. +.SH OPTIONS +.TP +\fB-d \fIdisplay\fB\f1 +Specifies the X display to use. Normally the display provided by the \fI$DISPLAY\f1 environment variable is used. But if you want to use another display, e.g. a display provided by a remote host, just use this option. +.TP +\fB-m \fINN%text[,NN%text,...]\fB\f1 +Sets user defined status meters to the status bar. NN stands for a number between 1 and 99 to define the percentage of the meter. The text is a definition what the meter stands for. The text is optional. The usage of a ! before NN reverts the meaning of high and low. Example: '99%high,66%normal,33%low,!99%highrevert' +.TP +\fB-t \fItext\fB\f1 +Sets user defined status text to the status bar of the WMI. Note that the \fItext\f1 string must be quoted if it contains whitespaces. This option is useful if you've running some status scripts which provide time/date information or maybe some other info to the status bar. See \fIexamples\f1 directory of the WMI distribution tarball which contains a \fIstatustext.sh\f1 example script, which sets time/date and APM information to the WMI status bar using wmiremote with the discussed option. +.TP +\fB-a \fIaction\fB\fI[+arg[+arg ...]]\fB\f1 +Invokes the specified action within WMI remotely, e.g. split-frame-down. If the action needs some arguments you can smuggle them with following syntax: + +wmiremote -a create-workspace+cool + +This will create a new workspace with the name "cool" remotely. As you can see the '+' character is used to introduce an argument. + +To get further informations about the actions you can invoke, see \fBwmi(1)\f1. +.TP +\fB-p\f1 +Prints current key bindings of WMI. +.TP +\fB-v\f1 +Prints the version of WMI. +.SH AUTHOR +WMI was written by Anselm R. Garbe < anselmg@t-online.de > and others (see AUTHORS or the WMI site for further information) + +You will find the newest version of WMI at \fBhttp://wmi.berlios.de/\f1. There is also a mailing list. +.SH BUGS +You should report them to the mailing list. +.SH SEE ALSO +\fBwmi(1)\f1 diff --git a/menu.cpp b/menu.cpp @@ -0,0 +1,408 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: menu.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include "menu.h" + +#include <sstream> + +#include "action.h" +#include "clientbar.h" +#include "cursors.h" +#include "draw.h" +#include "font.h" +#include "kernel.h" +#include "label.h" +#include "logger.h" +#include "monitor.h" +#include "theme.h" +#include "util.h" +#include "workspace.h" +#include "xcore.h" +#include "xfont.h" + +/// Item class implementation + +Item::Item(string name, void *data, Type type) { + data_ = data; + type_ = type; + + switch (type_) { + case WORKSPACE: + { + Workspace *workspace = (Workspace *)data; + Monitor *monitor = workspace->attached(); + if (workspace->clients()->size() + || monitor->detachedClients()->size() + || monitor->stickyClients()->size()) + { + addItem(new Item(name, 0, ROOTITEM)); + addItem(new Item("", 0, SEPARATOR)); + name_ = name + " >>"; + } + else { + name_ = name; + } + if (workspace == monitor->focused()) { + name_ = "* " + name_; + } + else { + name_ = " " + name_; + } + } + break; + case DCLIENT: + name_ = "+ " + name; + break; + case ROOTITEM: + name_ = "<< " + name; + break; + case SEPARATOR: + name_ = " -----------------------"; + break; + default: + name_ = " " + name; + break; + } +} + +Item::~Item() { + // clean up subitems + while (items_.size()) { + Item *item = items_.front(); + items_.erase(items_.begin()); + delete item; + } +} + +LItem *Item::items() { + return &items_; +} + +void Item::addItem(Item *item) { + item->setParent(this); + items_.push_back(item); +} + +void Item::removeItem(Item *item) { + item->setParent(0); + items_.remove(item); +} + +Item::Type Item::type() const { + return type_; +} + +string Item::name() const { + return name_; +} + +unsigned int Item::size() { + return items_.size(); +} + +Item *Item::parent() const { + return parent_; +} + +void Item::setParent(Item *parent) { + parent_ = parent; +} + +void *Item::data() const { + return data_; +} + +/// Menu class implementation + +Menu::Menu(Monitor *monitor) + : Widget(monitor, new Rectangle(0, 0, 1, 1)) +{ + theme_ = this->monitor()->theme(); + root_ = subRoot_ = selected_ = 0; + + label_ = new Label(this->monitor(), window(), Label::LEFT, gc()); + label_->setX(1); + label_->setY(1); + label_->setWidth(1); + label_->setHeight(this->monitor()->font()->height() + 2); + + initActions(); +} + +Menu::~Menu() { + +} + +void Menu::initActions() { + + MBindings *actionBindings = KERNEL->actionBindings(); + string actions = Util::get(KERNEL->commonSettings(), "menu.actions"); + + string actionName = ""; + bool proceed = actions.size(); + for (string::iterator it = actions.begin(); proceed; it++) { + + if ((*it != ',') && (it != actions.end())) { + actionName += *it; + } + else { + Action *action = Util::get(actionBindings, actionName); + if (action) { + actions_.push_back(action); + } + else { + LOGWARN("unknown action '" + actionName + "' in menu setup"); + } + actionName = ""; + } + proceed = it != actions.end(); + } + +} + +void Menu::updateItemTree() { + + if (root_) { + delete root_; + } + root_ = new Item("", 0, Item::ROOT); + subRoot_ = root_; + + // now build up the item tree + for (LAction::iterator it = actions_.begin(); it != actions_.end(); it++) { + Action *action = *it; + if (action->isValid()) { + root_->addItem(new Item(action->id(), action, Item::ACTION)); + } + } + if (root_->items()->size()) { + root_->addItem(new Item("", 0, Item::SEPARATOR)); + } + + // now add all workspaces + for (LWorkspace::iterator it = monitor()->begin(); + it != monitor()->end(); it++) + { + Workspace *workspace = *it; + Item *wsItem = new Item(workspace->name(), workspace, Item::WORKSPACE); + LClient *clients = workspace->clients(); + for (LClient::iterator it = clients->begin(); it != clients->end(); it++) { + Client *client = *it; + if (client->mode() != Client::STICKY) { + wsItem->addItem(new Item(client->name(), client, Item::CLIENT)); + } + } + CClient *stickyClients = monitor()->stickyClients(); + for (LClient::iterator it = stickyClients->begin(); + it != stickyClients->end(); it++) + { + Client *client = *it; + wsItem->addItem(new Item(client->name(), client, Item::CLIENT)); + } + CClient *detachedClients = monitor()->detachedClients(); + if (detachedClients->size()) { + if (workspace->clients()->size() || clients->size()) { + wsItem->addItem(new Item("", 0, Item::SEPARATOR)); + } + for (LClient::iterator it = detachedClients->begin(); + it != detachedClients->end(); it++) + { + Client *client = *it; + wsItem->addItem(new Item(client->name(), client, Item::DCLIENT)); + } + } + root_->addItem(wsItem); + } +} + +void Menu::show() { + KERNEL->setMenuMode(true); + isVisible_ = true; + XCORE->showRaised(window()); + updateItemTree(); + manage(); +} + +void Menu::hide() { + KERNEL->setMenuMode(false); + isVisible_ = false; + XCORE->hide(window()); +} + +void Menu::illuminate() { + + Rectangle rect(*this); + rect.setX(0); + rect.setY(0); + LOGDEBUG("drawing solid background"); + // draw solid background + XCORE->raise(window()); + XCORE->setForeground(gc(), theme_->BAR_BACKGROUND); + XCORE->fillRectangle(window(), gc(), &rect); + LItem *items = subRoot_->items(); + + unsigned int offsetY = 1; + unsigned int i = 0; + for (LItem::iterator it = items->begin(); it != items->end(); it++) { + Item *item = *it; + label_->setY(offsetY + i * label_->height()); + label_->setText(item->name()); + if ((item == selected_) && (item->type() != Item::SEPARATOR)) { + label_->update(theme_->LABEL_BACKGROUND_FOCUSSED, + theme_->LABEL_TEXT_FOCUSSED, + theme_->LABEL_SHINE_FOCUSSED, + theme_->LABEL_SHADOW_FOCUSSED, + true, true); + } + else { + label_->update(theme_->LABEL_BACKGROUND_NORMAL, + theme_->LABEL_TEXT_NORMAL, + theme_->LABEL_SHINE_NORMAL, + theme_->LABEL_SHADOW_NORMAL); + } + i++; + } + + Draw::drawRectBorder(window(), gc(), &rect, + theme_->BAR_SHINE, theme_->BAR_SHADOW); +} + +void Menu::manage() { + + if (!isVisible()) { + return; + } + + unsigned int maxWidth = 0; + LItem *items = subRoot_->items(); + for (LItem::iterator it = items->begin(); it != items->end(); it++) { + Item *item = *it; + label_->setText(item->name()); + if (label_->textWidth() > maxWidth) { + maxWidth = label_->textWidth() + 10; + } + } + label_->setWidth(maxWidth); + setWidth(maxWidth + 2); + setHeight(items->size() * label_->height() + 2); + + if (monitor()->clientBar()->y()) { + setY(monitor()->height() - monitor()->clientBar()->height() - height()); + } + else { + setY(monitor()->clientBar()->height()); + } + + // time to illuminate menu + resize(); + illuminate(); +} + +void Menu::handleButtonPress(XButtonEvent *event) { + XCORE->raise(window()); + if (selected_) { + switch (selected_->type()) { + case Item::WORKSPACE: + { + Workspace *workspace = (Workspace *)selected_->data(); + if (event->button == Button1) { + if (selected_->items()->size()) { + subRoot_ = selected_; + manage(); + } + else { // focus workspace + monitor()->focus(workspace); + escape(); + } + } + else if (event->button == Button3) { + monitor()->focus(workspace); + updateItemTree(); + manage(); + } + } + break; + case Item::ROOTITEM: + subRoot_ = subRoot_->parent(); + manage(); + break; + case Item::ACTION: + { + Action *action = (Action *)selected_->data(); + if (action->isValid()) { + action->perform(); + escape(); + } + } + break; + case Item::CLIENT: + { + Workspace *workspace = (Workspace *)subRoot_->data(); + Client *client = (Client *)selected_->data(); + if (event->button == Button3) { + monitor()->detachClient(client); + if (monitor()->focused() != workspace) { + monitor()->attachLastClient(); + } + } + else { + monitor()->focus(workspace); + workspace->focus(client); + if (event->button == Button2) { + XCORE->warpPointer(client->clientWindow(), + client->width() / 2, + client->height() / 2); + } + } + escape(); + } + break; + case Item::DCLIENT: + { + Client *client = (Client *)selected_->data(); + monitor()->attachDetachedClient((Workspace *)subRoot_->data(), + client); + if (event->button == Button2) { + XCORE->warpPointer(client->clientWindow(), + client->x() + client->width() / 2, + client->y() + client->height() / 2); + } + escape(); + } + break; + default: + break; + } + } +} + +void Menu::escape() { + monitor()->clientBar()->toggleMenuMode(); +} + +void Menu::handleMotionNotify(XMotionEvent *event) { + + unsigned int selItem = event->y / label_->height(); + ostringstream oss; + oss << "eventY=" << event->y << " selItem=" << selItem; + LOGDEBUG(oss.str()); + + unsigned int i = 0; + LItem *items = subRoot_->items(); + for (LItem::iterator it = items->begin(); it != items->end(); it++) { + Item *item = *it; + if (selItem == i) { + if (item == selected_) { + LOGDEBUG("no redraw"); + return; + } + selected_ = item; + illuminate(); + return; + } + i++; + } + selected_ = 0; +} diff --git a/menu.h b/menu.h @@ -0,0 +1,113 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: menu.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __MENU_H +#define __MENU_H + +#include "wmi.h" + +extern "C" { +#include <X11/Xlib.h> +} + +#include <list> +#include <string> + +#include "widget.h" + +class Action; +class Client; +class Item; +class Label; +class Monitor; +class Theme; + +typedef list<Action *> LAction; +typedef list<Item *> LItem; + +/** + * Items for menu. + */ +class Item { + +public: + + // The type of this items is related to the data_ pointer which must + // of following type if the specific type has been choosen: + // ACTION -> Action * + // CLIENT -> Client * (attached client) + // DCLIENT -> Client * (detached client) + // WORKSPACE -> Workspace * + // ROOT -> 0 + // ROOTITEM -> 0 + // SEPARATOR -> 0 + enum Type {ACTION, CLIENT, DCLIENT, WORKSPACE, ROOT, + ROOTITEM, SEPARATOR}; + + Item(string name, void *data, Type type); + ~Item(); + + LItem *items(); + + void addItem(Item *item); + void removeItem(Item *item); + + Type type() const; + string name() const; + Item *parent() const; + void setParent(Item *parent); + void *data() const; + + unsigned int size(); + +private: + + string name_; + void *data_; + LItem items_; + Type type_; + Item *parent_; + +}; + + +/** + * Basic menu for action, cut'n'paste and re-attach stuff. + */ +class Menu : public Widget { + +public: + + Menu(Monitor *monitor); + + ~Menu(); + + void manage(); + void updateItemTree(); + + /** called on Expose by Kernel. */ + void illuminate(); + + void handleButtonPress(XButtonEvent *event); + void handleMotionNotify(XMotionEvent *event); + + virtual void show(); + virtual void hide(); + +private: + + void initActions(); + + void escape(); + + Theme *theme_; + Label *label_; + LAction actions_; + Item *root_; + Item *subRoot_; + Item *selected_; +}; + +#endif // __MENU_H diff --git a/missing b/missing @@ -0,0 +1,360 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2003-09-02.23 + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003 +# Free Software Foundation, Inc. +# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996. + +# 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, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Send bug reports to <bug-automake@gnu.org>." + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + + aclocal*) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` + test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then + # We have makeinfo, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + tar) + shift + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + fi + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/monitor.cpp b/monitor.cpp @@ -0,0 +1,1040 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: monitor.cpp 734 2004-09-27 18:15:45Z garbeam $ + +extern "C" { +#include <assert.h> +#include <X11/keysym.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +} + +#include <iostream> +#include <sstream> + +#include "monitor.h" + +#include "action.h" +#include "actions.h" +#include "atoms.h" +#include "binder.h" +#include "box.h" +#include "client.h" +#include "clientbar.h" +#include "cursors.h" +#include "draw.h" +#include "font.h" +#include "frame.h" +#include "inputbar.h" +#include "logger.h" +#include "menu.h" +#include "rectangle.h" +#include "slot.h" +#include "statusbar.h" +#include "theme.h" +#include "thing.h" +#include "util.h" +#include "kernel.h" +#include "workspace.h" +#include "xcore.h" +#include "xfont.h" + +Monitor::Monitor(Display *display, unsigned int id) + : Container<Display, LWorkspace, LWorkspace::iterator, Workspace>(display), + Rectangle(), detachedClients_(this), stickyClients_(this) +{ + + ostringstream oss; + oss << "monitor[" << id << "]"; + prefix_ = oss.str(); + id_ = id; + themeSettings_ = KERNEL->themeSettings(); + commonSettings_ = KERNEL->commonSettings(); + sessionSettings_ = KERNEL->sessionSettings(); + setWidth(DisplayWidth(attached(), id_)); + setHeight(DisplayHeight(attached(), id_)); + rootWindow_ = RootWindow(attached(), id_); + + resizeFactor_ = Util::strToUInt( + Util::get(commonSettings_, "resize-move.factor")); + + theme_ = new Theme(); + maxThing_ = 0; + clientIds_ = 0; + fixed_ = 0; + + initFonts(); + LOGDEBUG("font initialized"); + initDisplayString(); + LOGDEBUG("display string '" + displayString_ + "' initialized"); + theme_->initTheme(themeSettings_, XCORE->defaultColormap(id_)); + LOGDEBUG("colors initialized"); + initGC(); + LOGDEBUG("GC initialized"); + initBars(); + LOGDEBUG("bars initialized"); + XCORE->sync(); +#ifdef SLOT_SUPPORT + initSlot(); + LOGDEBUG("slot initialized"); +#endif // SLOT_SUPPORT + initWorkspaces(); + LOGDEBUG("workspaces initialized"); + + XCORE->selectEvents(rootWindow_, + SubstructureRedirectMask | SubstructureNotifyMask + | PropertyChangeMask); + + KERNEL->installCursor(Cursors::NORMAL_CURSOR, rootWindow_); + + XCORE->sync(); +} + +void Monitor::initFonts() { + + string fontName = Util::get(KERNEL->themeSettings(), "font"); + font_ = WFont::load(this, fontName); + if (!font_) { + // fallback, trying to load "fixed" + LOGWARN("cannot load font '" + fontName + + "', trying loading default font 'fixed'"); + font_ = WFont::load(this, "fixed"); + if (!font_) { + LOGERROR("cannot load any font", true); + // exits WMI + } + } + if (font_->height() < MINIMAL_BARHEIGHT) { + font_->setHeight(MINIMAL_BARHEIGHT); + } + if (font_->type() == WFont::XFT) { + fixed_ = XFont::load(this, "fixed"); + if (!fixed_) { + LOGERROR("cannot load any font", true); + // exits WMI + } + } +} + +void Monitor::initBars() { + + Rectangle rect(0, 0, width(), titleBarHeight() + 2); + + if (Util::get(commonSettings_, "statusbar.alignment") != "bottom") { + statusBar_ = new StatusBar(this, &rect); + inputBar_ = new InputBar(this, &rect); + rect.setY(height() - rect.height()); + clientBar_ = new ClientBar(this, &rect); + } + else { + clientBar_ = new ClientBar(this, &rect); + rect.setY(height() - rect.height()); + statusBar_ = new StatusBar(this, &rect); + inputBar_ = new InputBar(this, &rect); + } + + rect.setY(height() / 2 - rect.height() / 2); + box_ = new Box(this, &rect, ""); +} + +void Monitor::initGC() { + + unsigned long mask = + GCForeground | GCGraphicsExposures + | GCFunction | GCSubwindowMode | GCLineWidth + | GCPlaneMask; + XGCValues gcv; + gcv.subwindow_mode=IncludeInferiors; + gcv.function=GXxor; + gcv.foreground = theme_->FRAME_PSEUDO; + gcv.fill_style=FillSolid; + gcv.line_width = Util::strToUInt( + Util::get(KERNEL->commonSettings(), "border.width")); + gcv.plane_mask = AllPlanes; + gcv.graphics_exposures = False; + if (font_->type() == WFont::NORMAL) { + gcv.font = ((XFont *)font_)->font()->fid; + mask |= GCFont; + } + + pseudoBorderGC_ = XCORE->createGC(rootWindow_, mask, &gcv); + + gcv.function=GXcopy; + borderGC_ = XCORE->createGC(rootWindow_, mask, &gcv); +} + +Monitor::~Monitor() { + for (MClient::iterator it = clients_.begin(); + it != clients_.end(); it++) + { + Client *client = (*it).second; + clients_.erase(it); + delete client; + } + delete statusBar_; + delete clientBar_; +#ifdef SLOT_SUPPORT + delete slot_; +#endif // SLOT_SUPPORT +} + +void Monitor::rectForWorkspace(Workspace *workspace) { + + bool isClientBarVisible = workspace->isClientBarVisible(); + bool isStatusBarVisible = workspace->isStatusBarVisible(); + + // bar dimensions + if (Util::get(commonSettings_, "statusbar.alignment") != "bottom") { + workspace->setY((isStatusBarVisible ? statusBar_->height() : 0)); + } + else { + workspace->setY((isClientBarVisible ? clientBar_->height() : 0)); + } + workspace->setHeight(height() + - (isStatusBarVisible ? statusBar_->height() : 0) + - (isClientBarVisible ? clientBar_->height() : 0)); + +#ifdef SLOT_SUPPORT + static bool isSlotOverlap = + Util::get(commonSettings_, "slot.mode") == "overlap"; + // slot dimensions + if (workspace->isSlotVisible() && !isSlotOverlap + && slot_->hasClients()) + { + if (slot_->alignment() == LEFT) { + workspace->setX(slot_->width()); + } + else { + workspace->setX(x()); + } + workspace->setWidth(width() - slot_->width()); + } + else +#endif // SLOT_SUPPORT + { + workspace->setX(x()); + workspace->setWidth(width()); + } +} + +void Monitor::initWorkspaces() { + + string key = prefix_ + ".workspaces"; + + unsigned int workspaceCount = + Util::strToUInt(Util::get(sessionSettings_, key)); + string id = + Util::get(KERNEL->sessionSettings(), prefix_ + ".focused"); + unsigned int focusedWSNum = (id != "") ? Util::strToUInt(id) : 0; + + Rectangle rect; + Workspace *toFocus = 0; + for (unsigned int i = 0; i < workspaceCount; i++) { + Workspace *workspace = new Workspace(this, i, &rect); + matchWorkspace(workspace, LEFT); + attach(workspace); + if (i == focusedWSNum) { + toFocus = workspace; + } + } + LOGDEBUG("workspaces created"); + XCORE->sync(); + focus(toFocus); +} + +void Monitor::initDisplayString() { + + ostringstream oss; + + displayString_ = DisplayString(attached()); + unsigned int dot = displayString_.rfind('.'); + + LOGDEBUG("initializing display string '" + displayString_ + "'"); + oss << "DISPLAY="; + LOGDEBUG("ok displayString_"); + if (dot > 0) { + oss << displayString_.substr(0, dot + 1) << id_; + } + else { + oss << displayString_; + } + + displayString_ = oss.str(); +} + +void Monitor::scanWindows() { + + unsigned int numWindows = 0; + Window *windows; + XWindowAttributes attr; + + // Queries only the tree of this monitor + XCORE->queryTree(rootWindow_, &windows, &numWindows); + + ostringstream oss; + oss << "scanning " << numWindows << " windows"; + LOGDEBUG(oss.str()); + for (unsigned int i = 0; i < numWindows; i++) { + XCORE->windowAttributes(windows[i], &attr); + + // ignore default windows + if (attr.override_redirect || + menuWindow(windows[i]) || + (box_->window() == windows[i]) || + barWindow(windows[i]) || +#ifdef SLOT_SUPPORT + slotWindow(windows[i]) || +#endif // SLOT_SUPPORT + (windows[i] == rootWindow_)) + { + LOGDEBUG("ignoring scanned window (override redirect)"); + continue; + } + + if (XCORE->transient(windows[i])) { + LOGDEBUG("ignoring scanned window (transient)"); + continue; + } + + // determine client + Client *client; + if ((client = clientForWindow(windows[i])) == 0) { + if (attr.map_state == IsViewable) { + client = new Client(this, windows[i], &attr); + addClient(client); + attachClient(client); + } + } + } + if (windows) { + XCORE->free((void *)windows); + } +} + +Thing *Monitor::thingWindow(Window window) { + + for (LWorkspace::iterator it = begin(); it != end(); it++) { + Workspace *workspace = *it; + Thing *thing = workspace->thingWindow(window); + if (thing) { + return thing; + } + } + return 0; +} + + +Bar *Monitor::barWindow(Window window) { + + if (statusBar_->window() == window) { + return statusBar_; + } + if (clientBar_->window() == window) { + return clientBar_; + } + if (inputBar_->window() == window) { + return inputBar_; + } + return 0; +} + +Menu *Monitor::menuWindow(Window window) { + Menu *menu = clientBar_->menu(); + if (clientBar_->menu()->window() == window) { + return menu; + } + + return 0; +} + +#ifdef SLOT_SUPPORT +void Monitor::initSlot() { + + Direction align; + string valueAlign = Util::get(commonSettings_, "slot.alignment"); + Rectangle rect; + + int offsetX = 0; + if (valueAlign == "right") { + align = RIGHT; + offsetX = width() - 1; // initial offset :) + } + else { + align = LEFT; + } + rect = Rectangle(offsetX, titleBarHeight(), 1, + height() - 2 * titleBarHeight()); + + slot_ = new Slot(this, &rect, align); +} + + +Slot *Monitor::slotWindow(Window window) { + + if (slot_->window() == window) { + return slot_; + } + + return 0; +} + +Slot *Monitor::slot() const { + return slot_; +} + +void Monitor::unslotClient() { + + Client *client = slot_->focused()->focused(); + if (client) { + slot_->detachClient(client); + client->setMode(Client::FLOAT); + attachClient(client); + } +} + +void Monitor::slotClient() { + + Client *client = focusedClient(); + if (client) { + // HACK: removeClient also removes it from clients + // TODO: thus it would be useful to distinguish removeClient + // with detachClient -> overwork around wmi-10 + removeClient(client); + addClient(client); // we've to add it again, because it was removed + client->setMode(Client::SLOT); + attachClient(client); + } +} + +void Monitor::toggleSlot() { + + if (slot_->isVisible()) { + focused()->setSlotVisible(false); + slot_->hide(); + } + else { + focused()->setSlotVisible(true); + slot_->show(focused()->slotTabName()); + slot_->manage(); + } + + focused()->setSlotVisible(slot_->isVisible()); +} + +void Monitor::cycleSlotTabPrev() { + slot_->focused()->hide(); + slot_->focus(slot_->prev()); + slot_->focused()->show(); + slot_->manage(); +} + +void Monitor::cycleSlotTabNext() { + slot_->focused()->hide(); + slot_->focus(slot_->next()); + slot_->focused()->show(); + slot_->manage(); +} +#endif // SLOT_SUPPORT + +Client *Monitor::clientForWindow(Window window) { + + if (window == 0 || window == rootWindow_) { + return 0; + } + + MClient::iterator it = clients_.find((long)window); + + if (it != clients_.end()) { + return (*it).second; + } + + // client does not exist + return 0; +} + +void Monitor::addClient(Client *client) { + + clients_[(long)client->clientWindow()] = client; +} + +void Monitor::cleanup() { + while (clients_.size()) { + MClient::iterator it = clients_.begin(); + Client *client = (*it).second; + removeClient(client); + if (!client->transient()) { + XCORE->addToSaveSet(client->clientWindow()); + } + delete client; + } +} + +Client *Monitor::focusedClient() { + return focused()->topClient(); +} + +void Monitor::removeClient(Client *client) { + + XCORE->sync(); + LOGDEBUG("removing client"); + + Workspace *workspace = client->attached(); + if (workspace) { + workspace->detachClient(client); + LOGDEBUG("client removed from workspace"); + } +#ifdef SLOT_SUPPORT + else if (client->mode() == Client::SLOT) { + LOGDEBUG("removing slot client"); + slot_->detachClient(client); + matchWorkspace(focused(), slot_->alignment()); + } +#endif + else if (!client->isVisible()) { + // seems to be an detached client + detachedClients_.detach(client); + XCORE->sync(); + LOGDEBUG("removing detached client"); + statusBar_->illuminate(); + } + // else already detached + XCORE->sync(); + clients_.erase((long)client->clientWindow()); + LOGDEBUG("client removed"); +} + +void Monitor::matchWorkspace(Workspace *workspace, Direction dir) { + + rectForWorkspace(workspace); + workspace->matchBarNeighbors(dir); +#ifdef SLOT_SUPPORT + // slot fix + slot_->setY(workspace->y()); +#endif // SLOT_SUPPORT +} + +void Monitor::toggleClientBar() { + + if (clientBar_->isVisible()) { + clientBar_->hide(); + } + else { + clientBar_->show(); + } + + focused()->setClientBarVisible(clientBar_->isVisible()); + Direction dir = + (Util::get(commonSettings_, "statusbar.alignment") == "bottom") ? UP : DOWN; + matchWorkspace(focused(), dir); +#ifdef SLOT_SUPPORT + slot_->manage(); +#endif // SLOT_SUPPORT +} + +void Monitor::toggleStatusBar() { + + if (statusBar_->isVisible()) { + statusBar_->hide(); + } + else { + statusBar_->show(); + } + + focused()->setStatusBarVisible(statusBar_->isVisible()); + Direction dir = + (Util::get(commonSettings_, "statusbar.alignment") != "bottom") ? UP : DOWN; + matchWorkspace(focused(), dir); +#ifdef SLOT_SUPPORT + slot_->manage(); +#endif // SLOT_SUPPORT +} + +void Monitor::toggleAllClientStates() { + + Workspace *workspace = focused(); + assert(workspace); + Thing *thing = workspace->focusedThing(); + + if (!thing || (thing->type() != Thing::FRAME)) { + return; + } + Frame *frame = (Frame *)thing; + + unsigned int num = frame->size(); + for (unsigned int i = 0; (i < num) && (frame->size() != 0); i++) { + workspace->changeClientMode(frame->focused(), Client::FLOAT); + } + statusBar_->illuminate(); +} + +void Monitor::attachAllClients() { + + while (detachedClients_.size()) { + Client *client = *detachedClients_.begin(); + detachedClients_.detach(client); + attachClient(client); + } +} + +void Monitor::detachAllClients() { + + Workspace *workspace = focused(); + assert(workspace); + + if (workspace->isFrameMode()) { + Frame *frame = workspace->focusedFrame(); + unsigned int i = frame->size(); + while (i) { + detachClient(*frame->begin()); + i--; + } + } + else { + CClient *floatingClients = workspace->floatingClients(); + unsigned int i = floatingClients->size(); + while (i) { + detachClient(*floatingClients->begin()); + i--; + } + } + statusBar_->illuminate(); +} + +void Monitor::detachClient(Client *client) { + + if (!client) { + return; + } + + Workspace *workspace = client->attached(); + + if (workspace) { + workspace->detachClient(client); + detachedClients_.attach(client); + } +} + +void Monitor::detachClient() { + detachClient(focused()->topClient()); +} + +void Monitor::attachClientByName(string name) { + + for (LClient::iterator it = detachedClients_.begin(); + it != detachedClients_.end(); it++) + { + Client *client = *it; + if (client->name() == name) { + detachedClients_.detach(client); + attachClient(client); + return; + } + } +} + +void Monitor::attachLastClient() { + + Client *client = detachedClients_.focused(); + if (client) { + detachedClients_.detach(client); + attachClient(client); + } +} + +void Monitor::attachClient(Client *client) { + + // first we've to init all necessary info + client->initICCCM(); + + if (client->state() == IconicState) { + assert(!client->attached()); + detachedClients_.attach(client); + return; + } + + // first transient handling + Client *transient = client->transient(); + + if (transient && !transient->attached() +#ifdef SLOT_SUPPORT + && (transient->mode() != Client::SLOT) +#endif // SLOT_SUPPORT + ) + { + // attach also the transient, if some + detachedClients_.detach(transient); + attachClient(transient); + } + +#ifdef SLOT_SUPPORT + if (client->mode() == Client::SLOT) { + // will be handled by the slot + LOGDEBUG("new slot client"); + slot_->attachClient(client); + } + else +#endif // SLOT_SUPPORT + { + Workspace *hooked = workspaceForName(client->hooked()); + if (hooked && contains(hooked)) { + focus(hooked); + } + focused()->attachClient(client); + } +} + +void Monitor::attachDetachedClient(Workspace *workspace, Client *client) { + + focus(workspace); + detachedClients_.detach(client); + attachClient(client); +} + +void Monitor::createNewWorkspace(string name) { + + static Rectangle rect; + unsigned int id = size(); + + ostringstream key; + key << prefix_ << ".workspace[" << id << "]"; + + (*sessionSettings_)[key.str() + ".name"] = name; + (*sessionSettings_)[key.str() + ".clientbar"] = "yes"; + (*sessionSettings_)[key.str() + ".statusbar"] = "yes"; +#ifdef SLOT_SUPPORT + (*sessionSettings_)[key.str() + ".slot"] = slot_->tabName(); +#endif // SLOT_SUPPORT + (*sessionSettings_)[key.str() + ".focused"] = "0"; + + if (focused()) { + focused()->hide(); + } + Workspace *workspace = new Workspace(this , id, this); + matchWorkspace(workspace, LEFT); + attach(workspace); + focused()->show(); + + ostringstream value; + value << size(); + (*sessionSettings_)[prefix_ + ".workspaces"] = value.str(); +} + +void Monitor::serialize() { + + ostringstream value; + value << size(); + (*sessionSettings_)[prefix_ + ".workspaces"] = value.str(); + + for (LWorkspace::iterator it = begin(); it != end(); it++) { + Workspace *workspace = *it; + workspace->serialize(); + } + + value.str(""); + value << focused()->id(); + (*sessionSettings_)[prefix_ + ".focused"] = value.str(); +} + +void Monitor::focus(Workspace *workspace) { + + workspace->setRequestsFocus(false); + if (focused() != workspace) { + focused()->hide(); + LOGDEBUG("focussing workspace"); + XCORE->sync(); + Container<Display, LWorkspace, LWorkspace::iterator, + Workspace>::focus(workspace); + } + focused()->show(); + updateBars(); +} + +void Monitor::focusClient(Client *client) { + + Workspace *workspace = client->attached(); + if (workspace) { + focus(workspace); + workspace->focus(client); + } +} + +void Monitor::focusClientById(string id) { + + for (MClient::iterator it = clients_.begin(); + it != clients_.end(); it++) + { + Client *client = (*it).second; + + if (client->id() == id) { + focusClient(client); + } + } +} + +void Monitor::focusClientByName(string name) { + + for (MClient::iterator it = clients_.begin(); + it != clients_.end(); it++) + { + Client *client = (*it).second; + + if (client->name() == name) { + focusClient(client); + } + } +} + +Workspace *Monitor::workspaceForName(string name) { + + for (LWorkspace::iterator it = begin(); it != end(); it++) { + if ((*it)->name() == name) { + return (Workspace *)*it; + } + } + return 0; +} + +void Monitor::focusWorkspaceNum(unsigned int workspaceNum) { + + unsigned int i = 0; + for (LWorkspace::iterator it = begin(); it != end(); it++) { + if (i == workspaceNum) { + focus(*it); + return; + } + i++; + } +} + +void Monitor::destroyWorkspace(Workspace *workspace) { + + assert(workspace); + if (size() > 1) { + LClient *clients = workspace->clients(); + while (clients->size()) { + Client *client = *clients->begin(); + detachClient(client); + KERNEL->killClient(client); + } + detach(workspace); + Util::remove(sessionSettings_, workspace->prefix()); + delete workspace; + focused()->show(); + updateBars(); + } +} + +void Monitor::renameWorkspace(Workspace *workspace, string newName) { + workspace->setName(newName); + (*sessionSettings_)[workspace->prefix() + ".name"] = newName; +} + +void Monitor::updateBars() { + + static string value; + + if (XCORE->textProperty(rootWindow_, Atoms::WMI_STATUSTEXT, &value)) { + statusBar_->setText(value); + } + if (XCORE->textProperty(rootWindow_, Atoms::WMI_METERTEXT, &value)) { + statusBar_->setMeterText(value); + } + + LOGDEBUG("update status"); + statusBar_->illuminate(); + clientBar_->illuminate(); + XCORE->sync(); +} + +void Monitor::toggleThingMaximization() { + + if (!focused()) { + return; + } + + if (maxThing_) { + + maxThing_->copy(maxThing_->prevRectangle()); + maxThing_->resize(); + focused()->illuminate(); + maxThing_ = 0; // reset + + } + else { + + Workspace *workspace = focused(); + maxThing_ = workspace->focusedThing(); + + if (!maxThing_) { + return; + } + + maxThing_->prevRectangle()->copy(maxThing_); + maxThing_->setX(x()); + maxThing_->setY(y()); + maxThing_->setWidth(width()); + maxThing_->setHeight(height()); + maxThing_->resize(); + XCORE->raise(maxThing_->window()); + maxThing_->illuminate(); + } +} + +void Monitor::illuminateTransRect(Rectangle *rect, unsigned int barHeight) +{ + Draw::drawTransRectangle(rootWindow_, pseudoBorderGC_, rect, barHeight, + KERNEL->borderWidth()); + + // additional size info + ostringstream oss; + oss << "x=" << rect->x() << ", y=" << rect->y() + << ": " << rect->width() << "x" << rect->height(); + + illuminateTransText(rect, oss.str()); +} + +unsigned int Monitor::nextClientId() { + ++clientIds_; + return clientIds_; +} + +void Monitor::illuminateTransText(Rectangle *rect, string text) +{ + WFont *font = (font_->type() == WFont::NORMAL) ? + font_ : fixed_; + + // additional size info + int textWidth = font->textWidth(text); + unsigned int fontBaseLine = font->ascent(); + unsigned int fontY = rect->y() + rect->height() / 2 + - font->height() / 2 + fontBaseLine; + + unsigned int fontX = rect->x() + + (rect->width() / 2 - textWidth / 2); + font->drawText(rootWindow_, pseudoBorderGC_, + fontX, fontY, text); +} + + +unsigned int Monitor::id() const { + return id_; +} + +Window Monitor::rootWindow() const { + return rootWindow_; +} + +string Monitor::displayString() const { + return displayString_; +} + +Theme *Monitor::theme() const { + return theme_; +} + +unsigned int Monitor::resizeFactor() const { + return resizeFactor_; +} + +string Monitor::prefix() const { + return prefix_; +} + +Box *Monitor::box() const { + return box_; +} + +StatusBar *Monitor::statusBar() const { + return statusBar_; +} + +ClientBar *Monitor::clientBar() const { + return clientBar_; +} + +CClient *Monitor::detachedClients() { + return &detachedClients_; +} + +bool Monitor::isThingMaximized() { + return maxThing_ != 0; +} + +GC Monitor::borderGC() { + return borderGC_; +} + +CClient *Monitor::stickyClients() { + return &stickyClients_; +} + +WFont *Monitor::font() const { + return font_; +} + +unsigned int Monitor::titleBarHeight() const { + return font_->height() + 2; +} + +MClient *Monitor::clients() { + return &clients_; +} + +InputBar *Monitor::inputBar() const { + return inputBar_; +} + +void Monitor::banish() { + XCORE->warpPointer(rootWindow_, width(), height()); +} + +unsigned int Monitor::buttonWidth() const { + return font_->height() + 4; +} + +void Monitor::hookClient() { + + Client *client = 0; +#ifdef SLOT_SUPPORT + if (slot_->isGrabFocus() || + (!focused()->clients()->size() && slot_->focused()->focused())) + { + client = slot_->focused()->focused(); + if (client) { + client->setHooked(slot_->tabName()); + return; + } + } + else +#endif // SLOT_SUPPORT + { + client = focused()->topClient(); + if (client) { + client->setHooked(focused()->name()); + } + } +} + +void Monitor::unhookClient() { + + Client *client = 0; +#ifdef SLOT_SUPPORT + if (slot_->isGrabFocus() || + (!focused()->clients()->size() && slot_->focused()->focused())) + { + client = slot_->focused()->focused(); + if (client) { + client->setHooked(""); + return; + } + } + else +#endif // SLOT_SUPPORT + { + client = focused()->topClient(); + if (client) { + client->setHooked(""); + } + } +} diff --git a/monitor.h b/monitor.h @@ -0,0 +1,270 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: monitor.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __MONITOR_H +#define __MONITOR_H + +extern "C" { +#include <X11/Xlib.h> +} + +#include <list> +#include <map> +#include <string> +#include "wmi.h" + +#include "container.h" +#include "rectangle.h" + +class Action; +class Box; +class Client; +class ClientBar; +class Frame; +class InputBar; +class Manager; +class MultiFrame; +#ifdef SLOT_SUPPORT +class Slot; +#endif // SLOT_SUPPORT +class StatusBar; +class Theme; +class Thing; +class WFont; +class Workspace; +class XFont; + +typedef list<Client *> LClient; +typedef list<Thing *> LThing; +typedef list<Workspace *> LWorkspace; +typedef map<long, Client *, less<long> > MClient; +typedef map<string, string, less<string> > MSettings; +typedef Container<Monitor, LClient, LClient::iterator, Client> CClient; + +/** + * Represents a physical monitor in multi-head or single-head + * configurations not using Xinerama or a Xinerama monitor in + * configurations using Xinerama of WMI. + */ +class Monitor : + public Container<Display, LWorkspace, LWorkspace::iterator, Workspace>, + public Rectangle +{ + +public: + + //////////////////////////////////////////////////////////// + // Monitor stuff + Monitor(Display *display, unsigned int id); + ~Monitor(); + + unsigned int id() const; + + /** Returns the root window of this monitor. */ + Window rootWindow() const; + + string displayString() const; + + Theme *theme() const; + + unsigned int resizeFactor() const; + + string prefix() const; + + void serialize(); + + //////////////////////////////////////////////////////////// + // Bar stuff + StatusBar *statusBar() const; + + ClientBar *clientBar() const; + + InputBar *inputBar() const; + + void toggleStatusBar(); + + void toggleClientBar(); + + void scanWindows(); + void updateBars(); + + //////////////////////////////////////////////////////////// + // Client stuff + + Client *focusedClient(); + + /** + * Returns the client for the given window if it exists, + * otherwise <code>0</code>. + * If the window is the root window or <code>0</code> + * then <code>0</code> will be returned. + */ + Client *clientForWindow(Window window); + + /** Adds client. */ + void addClient(Client *client); + + /** Removes the specified client. */ + void removeClient(Client *client); + + void detachClient(); // hide + void detachClient(Client *client); + void attachLastClient(); // show + void attachClientByName(string name); // show + // with transient handling + void attachClient(Client *client); + + /** Attaches all detached clients. */ + void attachAllClients(); + void detachAllClients(); + void toggleAllClientStates(); + + CClient *detachedClients(); + + /** Maximization handling. */ + void toggleThingMaximization(); + + bool isThingMaximized(); + + /** Attaches detached client to workspace. */ + void attachDetachedClient(Workspace *workspace, Client *client); + + unsigned int titleBarHeight() const; + unsigned int buttonWidth() const; + + //////////////////////////////////////////////////////////// + // Workspace stuff + void createNewWorkspace(string name); + + void focus(Workspace *workspace); + void focusWorkspaceNum(unsigned int workspaceNum); + void focusWorkspaceByName(string name); + void focusClientByName(string name); + void focusClientById(string id); + + void destroyWorkspace(Workspace *workspace); + + /** Rename methods. */ + void renameWorkspace(Workspace *workspace, string newName); + + void matchWorkspace(Workspace *workspace, Direction dir); + void illuminateTransRect(Rectangle *rect, unsigned int barHeight = 0); + void illuminateTransText(Rectangle *rect, string text); + + Thing *thingWindow(Window window); + + Bar *barWindow(Window window); + + Menu *menuWindow(Window window); + +#ifdef SLOT_SUPPORT + Slot *slotWindow(Window window); + Slot *slot() const; + void unslotClient(); + void slotClient(); + void toggleSlot(); + void cycleSlotTabPrev(); + void cycleSlotTabNext(); +#endif // SLOT_SUPPORT + + /** + * Used for differentiation of clients, each client has an + * unique id. + */ + unsigned int nextClientId(); + + void resetClientId() { + clientIds_ = 0; + }; + + GC borderGC(); + + CClient *stickyClients(); + + WFont *font() const; + + /** + * Reparents all client windows to the root window, destroys all + * frames and WMI related items of clients. + */ + void cleanup(); + + MClient *clients(); + void banish(); + + Workspace *workspaceForName(string name); + + Box *box() const; + + void hookClient(); + void unhookClient(); + +private: + + /** Inits all fonts. */ + void initFonts(); + + /** Inits display string. */ + void initDisplayString(); + + /** Inits workspaces. */ + void initWorkspaces(); + + /** Inits the bar. */ + void initBars(); + + /** Inits gc. */ + void initGC(); + + /** Initializes rectangle with workspace size. */ + void rectForWorkspace(Workspace *workspace); + + void focusClient(Client *client); + + GC pseudoBorderGC_; + GC borderGC_; + Window rootWindow_; + WFont *font_; + XFont *fixed_; // default font for pseudo border, if XFT + // font is used + + + Box *box_; + StatusBar *statusBar_; + ClientBar *clientBar_; + InputBar *inputBar_; + +#ifdef SLOT_SUPPORT + /** Inits slot. */ + void initSlot(); + + Slot *slot_; +#endif // SLOT_SUPPORT + + + unsigned int resizeFactor_; + + unsigned int id_; + + string displayString_; + + Theme *theme_; + + MClient clients_; + + CClient detachedClients_; + CClient stickyClients_; + + MSettings *themeSettings_; + MSettings *sessionSettings_; + MSettings *commonSettings_; + string prefix_; + + Thing *maxThing_; + + unsigned int clientIds_; +}; + +#endif // __MONITOR_H diff --git a/prompt.cpp b/prompt.cpp @@ -0,0 +1,22 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: prompt.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include "prompt.h" + +#include "binder.h" + +Prompt::Prompt(string prompt, QueryNamesForPrefix toQuery) +{ + prompt_ = prompt; + toQuery_ = toQuery; +} + +string Prompt::prompt() const { + return prompt_; +} + +QueryNamesForPrefix Prompt::toQuery() const { + return toQuery_; +} diff --git a/prompt.h b/prompt.h @@ -0,0 +1,39 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: prompt.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __PROMPT_H +#define __PROMPT_H + +#include <set> +#include <string> +#include "wmi.h" + +class Binder; + +typedef set<string> Sstring; +typedef string (Binder::*QueryNamesForPrefix) + (string prefix, Sstring *nameSet); + +/** + * Represents a prompt in input mode. A prompt may also contain a + * query method pointer for dynamic menu support. + */ +class Prompt { + +public: + + Prompt(string prompt, QueryNamesForPrefix toQuery); + + string prompt() const; + + QueryNamesForPrefix toQuery() const; + +private: + + string prompt_; + QueryNamesForPrefix toQuery_; +}; + +#endif // __PROMPT_H diff --git a/rectangle.cpp b/rectangle.cpp @@ -0,0 +1,52 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: rectangle.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include "rectangle.h" + +Rectangle::Rectangle() +{ + x_ = 0; + y_ = 0; + w_ = 0; + h_ = 0; +} + +Rectangle::Rectangle(int x, int y, unsigned int w, unsigned int h) { + x_ = x; + y_ = y; + w_ = w; + h_ = h; +} + +void Rectangle::copy(Rectangle *source) { + x_ = source->x(); + y_ = source->y(); + w_ = source->width(); + h_ = source->height(); +} + +bool Rectangle::fitsInto(Rectangle *rect) { + return ((x_ >= rect->x()) && + (y_ >= rect->y()) && + (w_ <= rect->width()) && + (h_ <= rect->height()) && + (x_ + w_ <= rect->x() + rect->width()) && + (y_ + h_ <= rect->y() + rect->height())); +} + + +Rectangle::~Rectangle() {} + +int Rectangle::x() const { return x_; } +void Rectangle::setX(int x) { x_ = x; } + +int Rectangle::y() const { return y_; } +void Rectangle::setY(int y) { y_ = y; } + +unsigned int Rectangle::width() const { return w_; } +void Rectangle::setWidth(unsigned int w) { w_ = w; } + +unsigned int Rectangle::height() const { return h_; } +void Rectangle::setHeight(unsigned int h) { h_ = h; } diff --git a/rectangle.h b/rectangle.h @@ -0,0 +1,45 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: rectangle.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __RECTANGLE_H +#define __RECTANGLE_H + +/** + * Basic rectangle used by all viewable items of WMI. + */ +class Rectangle +{ + +public: + + Rectangle(); + + Rectangle(int x, int y, unsigned int w, unsigned int h); + + ~Rectangle(); + + int x() const; + void setX(int x); + + int y() const; + void setY(int y); + + unsigned int width() const; + void setWidth(unsigned int w); + + unsigned int height() const; + void setHeight(unsigned int h); + + void copy(Rectangle *source); + + bool fitsInto(Rectangle *rect); + +private: + + int x_, y_; + unsigned int w_, h_; +}; + +#endif // __RECTANGLE_H diff --git a/shortcut.cpp b/shortcut.cpp @@ -0,0 +1,103 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: shortcut.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include "shortcut.h" + +#include "logger.h" +#include "util.h" +#include "xcore.h" + +Shortcut::Shortcut(unsigned long modMask, KeyCode keyCode, + Shortcut *next, unsigned int button) +{ + modMask_ = modMask; + button_ = button; + keyCode_ = keyCode; + next_ = next; +} + +Shortcut::~Shortcut() { + if (next_) { + delete next_; + } +} + + +Shortcut *Shortcut::shortcut(string keys) { + + if (keys == "") { + return 0; + } + + LOGDEBUG("entered shortcut construction"); + // shortcut handling + Shortcut *root = 0; + Shortcut *tmp = 0; + keys = Util::truncate(keys, ' '); + unsigned int length = keys.length(); + bool sep; + string subkeys = ""; + for (int i = 0; i < (int)length; i++) { + sep = keys[i] == ':'; + if (!sep) { + subkeys += keys[i]; + } + else { + i++; // ignore next ':' + } + + if (sep || (i == (int)(length - 1))) { + LOGDEBUG("next shortcut: " + subkeys); + // if no modifier is given, none is assumed + if (subkeys.find('+') == string::npos) { + subkeys = "none+" + subkeys; + } + string key = Util::lastToken(subkeys, '+'); + // check if the key sequence contains a Button identifier + unsigned int button = Util::buttonForString(key); + Shortcut *shortcut = new Shortcut( + Util::modMaskForString(subkeys), + XCORE->stringToKeyCode(key), 0, button); + if (!root) { + root = shortcut; + } + else { + tmp->setNext(shortcut); + } + tmp = shortcut; + subkeys = ""; + } + } + return root; +} + + +KeyCode Shortcut::keyCode() { + return keyCode_; +} + +unsigned long Shortcut::modMask() const { + return modMask_; +} + +unsigned int Shortcut::button() const { + return button_; +} + +Shortcut *Shortcut::next() const { + return next_; +} + +void Shortcut::setNext(Shortcut *next) { + next_ = next; +} + +void Shortcut::setKeyCode(KeyCode keyCode) { + keyCode_ = keyCode; +} + +void Shortcut::setModMask(unsigned long modMask) { + modMask_ = modMask; +} diff --git a/shortcut.h b/shortcut.h @@ -0,0 +1,50 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: shortcut.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __SHORTCUT_H +#define __SHORTCUT_H + +extern "C" { +#include <X11/Xlib.h> +} + +#include <string> +#include "wmi.h" + +/** + * Represents a shortcut. If this shortcut has a postdecessor the next + * pointer may point to it. + */ +class Shortcut { + +public: + + Shortcut(unsigned long modMask, KeyCode keyCode, Shortcut *next, + unsigned int button = 0); + ~Shortcut(); + + KeyCode keyCode(); + void setKeyCode(KeyCode keyCode); + + unsigned long modMask() const; + void setModMask(unsigned long modMask); + + unsigned int button() const; + + Shortcut *next() const; + + void setNext(Shortcut *next); + + static Shortcut *shortcut(string keys); + +private: + + Shortcut *next_; + KeyCode keyCode_; + unsigned long modMask_; + unsigned int button_; +}; + +#endif // __SHORTCUT_H diff --git a/singleton.h b/singleton.h @@ -0,0 +1,33 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: singleton.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __SINGLETON_H +#define __SINGLETON_H + +/** + * Basic singleton template used by various controller classes of WMI. + */ +template <class T> class Singleton +{ + +public: + + static T *instance() { + if (instance_ == 0) { + // use default constructor + instance_ = new T; + } + return instance_; + } + +private: + + // the singleton instance + static T *instance_; +}; + +template <class T> T* Singleton<T>::instance_ = 0; + +#endif // __SINGLETON_H diff --git a/slot.cpp b/slot.cpp @@ -0,0 +1,477 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: slot.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include "slot.h" + +#ifdef SLOT_SUPPORT + +#include <map> +#include <string> +#include <sstream> + +#include "binder.h" +#include "client.h" +#include "cursors.h" +#include "draw.h" +#include "kernel.h" +#include "label.h" +#include "logger.h" +#include "monitor.h" +#include "theme.h" +#include "util.h" +#include "workspace.h" +#include "xcore.h" +#include "xfont.h" + +/// slot tab +Tab::Tab(const string name) { + name_ = name; + focused_ = 0; +} + +Tab::~Tab() { +} + +string Tab::name() const { + return name_; +} + +LClient *Tab::clients() { + return &clients_; +} + +void Tab::addClient(Client *client) { + focused_ = client; + clients_.push_back(client); +} + +void Tab::removeClient(Client *client) { + clients_.remove(client); + if (focused_ == client) { + if (clients_.size()) { + focused_ = clients_.front(); + } + else { + focused_ = 0; + } + } +} + +bool Tab::isVisible() const { + return isVisible_; +} + +void Tab::show() { + isVisible_ = true; + for (LClient::iterator it = clients_.begin(); + it != clients_.end(); it++) + { + Client *client = *it; + client->show(); + } +} + +void Tab::hide() { + isVisible_ = false; + for (LClient::iterator it = clients_.begin(); + it != clients_.end(); it++) + { + Client *client = *it; + client->hide(); + } +} + +Client *Tab::focused() const { + return focused_; +} + +void Tab::focus(Client *client) { + focused_ = client; +} + +/// Slot implementation + +Slot::Slot(Monitor *monitor, Rectangle *rect, Direction align) + : Widget(monitor, rect), + Container<Monitor, LTab, LTab::iterator, Tab>(monitor) +{ + align_ = align; + theme_ = this->monitor()->theme(); + isGrabFocus_ = false; + + isSolid_ = (Util::get(KERNEL->commonSettings(), "slot.style") == "solid"); + initTabs(); + + label_ = new Label(this->monitor(), window(), Label::CENTER, gc()); + label_->setX(1); + label_->setY(1); + label_->setWidth(width() - 2); + label_->setHeight(this->monitor()->titleBarHeight()); +} + +Slot::~Slot() { +} + +void Slot::initTabs() { + + string tabs = Util::get(KERNEL->commonSettings(), "slot.tabs"); + + string name = ""; + for (string::iterator it = tabs.begin(); it != tabs.end(); ) { + + char c = *it; + it++; + bool isEndReached = it == tabs.end(); + + if ((c == ',') || isEndReached) { + if (isEndReached) { + name += c; + } + if (name != "") { + attach(new Tab(name)); + name = ""; + } + } + else { + name += c; + } + } + + if (!size()) { + attach(new Tab("default")); + } +} + +void Slot::show(string tabName) { + + if (isVisible() + && tabName == this->tabName() + && hasClients()) + { + illuminate(); + return; + } + isVisible_ = true; + for (LTab::iterator it = begin(); it != end(); it++) { + Tab *tab = *it; + tab->hide(); + if (tab->name() == tabName) { + focus(tab); + } + } + focused()->show(); + XCORE->show(window()); +} + +void Slot::hide() { + isVisible_ = false; + focused()->hide(); + XCORE->hide(window()); + monitor()->matchWorkspace(monitor()->focused(), align_); +} + +Direction Slot::alignment() const { + return align_; +} + +void Slot::illuminate() { + + if (!isVisible() || width() == 1) { + return; + } + + if (isSolid_) { + Rectangle rect(*this); + rect.setX(0); + rect.setY(0); + LOGDEBUG("drawing solid background"); + // draw solid background + XCORE->setForeground(gc(), theme_->BAR_BACKGROUND); + XCORE->fillRectangle(window(), gc(), &rect); + Draw::drawRectBorder(window(), gc(), &rect, + theme_->BAR_SHINE, theme_->BAR_BACKGROUND); + } + else { + XCORE->clearWindow(window()); + } + + label_->setWidth(width() - 2); + unsigned int offsetY = 1; + unsigned int i = 0; + for (LTab::iterator it = begin(); it != end(); it++) { + Tab *tab = *it; + label_->setY(offsetY + (i * label_->height())); + label_->setText(tab->name()); + if (tab == focused()) { + label_->update(theme_->LABEL_BACKGROUND_FOCUSSED, + theme_->LABEL_TEXT_FOCUSSED, + theme_->LABEL_SHINE_FOCUSSED, + theme_->LABEL_SHADOW_FOCUSSED, + true, true); + } + else { + label_->update(theme_->LABEL_BACKGROUND_NORMAL, + theme_->LABEL_TEXT_NORMAL, + theme_->LABEL_SHINE_NORMAL, + theme_->LABEL_SHADOW_NORMAL, + true, true); + } + i++; + } + + LClient *clients = focused()->clients(); + for (LClient::iterator it = clients->begin(); + it != clients->end(); it++) + { + Client *client = *it; + Rectangle rect(*client); + rect.setX(rect.x() - 1); + rect.setY(rect.y() - 1); + rect.setWidth(rect.width() + 2); + rect.setHeight(rect.height() + 2); + + if (client == focused()->focused()) { + Draw::drawRectBorder(window(), gc(), &rect, + theme_->TAB_SHINE_ACTIVE_FOCUSSED, + theme_->TAB_SHADOW_ACTIVE_FOCUSSED); + } + else { + Draw::drawRectBorder(window(), gc(), &rect, + theme_->TAB_SHINE_ACTIVE_NORMAL, + theme_->TAB_SHADOW_ACTIVE_NORMAL); + } + } +} + +bool Slot::hasClients() { + + for (LTab::iterator it = begin(); it != end(); it++) { + Tab *tab = *it; + if (tab->clients()->size()) { + return true; + } + } + return false; +} + +void Slot::manage() { + + if (!isVisible()) { + return; + } + + static bool isSlotOverlap = + Util::get(KERNEL->commonSettings(), "slot.mode") == "overlap"; + unsigned int cHeight = 0; + unsigned int maxWidth = 1; + LClient *clients = focused()->clients(); + if (!clients->size() && hasClients()) { + maxWidth = width(); + } + for (LClient::iterator it = clients->begin(); + it != clients->end(); it++) + { + Client *client = *it; + cHeight += client->height(); + if (maxWidth < client->width()) { + maxWidth = client->width() + 2; + } + } + + if (align_ == RIGHT) { + setX(monitor()->width() - maxWidth); + } + setWidth(maxWidth); + + // apps are centered + unsigned int tabPagerHeight = (size() * label_->height()) + 3; + int offsetY = tabPagerHeight; + + for (LClient::iterator it = clients->begin(); + it != clients->end(); it++) + { + Client *client = *it; + client->setY(offsetY); + client->setX((width() - client->width()) / 2); + client->resize(); + offsetY += client->height() + 2; + } + + if (isSolid_ && !isSlotOverlap) { + setHeight(monitor()->focused()->height()); + } + else { + setHeight(offsetY); + } + monitor()->matchWorkspace(monitor()->focused(), align_); + XCORE->moveResize(window(), this); + illuminate(); +} + +Tab *Slot::tabForName(string name) { + + for (LTab::iterator it = begin(); it != end(); it++) { + Tab *tab = *it; + if (tab->name() == name) { + return tab; + } + } + + return 0; +} + +void Slot::attachClient(Client *client) { + + if (width() < client->width()) { + setWidth(client->width()); + } + + Binder::instance()->ungrabButtons(client->clientWindow()); + Binder::instance()->grabButtons(client->clientWindow(), AnyModifier); + + if (client->hooked() != "") { + Tab *tab = tabForName(client->hooked()); + if (tab && (tab != focused())) { + focused()->hide(); + focus(tab); + tab->show(); + } + } + + focused()->addClient(client); + client->reparent(window(), 0, 0); + + if (isVisible()) { + client->show(); + } + manage(); +} + +void Slot::detachClient(Client *client) { + + for (LTab::iterator it = begin(); it != end(); it++) { + Tab *tab = *it; + LClient *clients = tab->clients(); + bool found = false; + for (LClient::iterator cit = clients->begin(); + cit != clients->end(); cit++) + { + found = (client == *cit); + if (found) { + break; + } + } + if (found) { + tab->removeClient(client); + break; + } + } + if (!client->isDestroyed()) { + if (client->isVisible()) { + client->hide(); + } + client->reparent(monitor()->rootWindow(), 0, 0); + } + manage(); +} + +void Slot::handleButtonPress(XButtonEvent *event) { + + if (event->button == Button1) { + unsigned int tabPagerHeight = (size() * label_->height()) + 3; + + XCORE->raise(window()); + if (event->y < (int)tabPagerHeight) { + unsigned int selTab = event->y / label_->height(); + ostringstream oss; + oss << "select tab #" << selTab << " of " << size() << " tabs "; + LOGDEBUG(oss.str()); + unsigned int i = 0; + for (LTab::iterator it = begin(); it != end(); it++) { + if (selTab == i) { + if (focused() != *it) { + focused()->hide(); + focus(*it); + focused()->show(); + manage(); + } + return; + } + i++; + } + } + } + else if (event->button == Button4) { + monitor()->cycleSlotTabPrev(); + } + else if (event->button == Button5) { + monitor()->cycleSlotTabNext(); + } +} + +void Slot::handleMotionNotify(XMotionEvent *event) { +} + +string Slot::tabName() { + return focused()->name(); +} + +bool Slot::isGrabFocus() const { + return isGrabFocus_; +} + +void Slot::setGrabFocus(bool grabFocus) { + Client *client = focused()->focused(); + if (isGrabFocus_ && !grabFocus) { + // workspace grabs back the focus + if (client) { + Binder::instance()->ungrabButtons(client->clientWindow()); + Binder::instance()->grabButtons(client->clientWindow(), AnyModifier); + } + } + isGrabFocus_ = grabFocus; +} + +void Slot::focusClient(Client *client) { + + for (LTab::iterator it = begin(); it != end(); it++) { + Tab *tab = *it; + LClient *clients = tab->clients(); + for (LClient::iterator cit = clients->begin(); + cit != clients->end(); cit++) + { + if (*cit == client) { + if (tab != focused()) { + focused()->hide(); + focus(tab); + tab->show(); + manage(); + } + Client *old = focused()->focused(); + if (old != client) { + Binder::instance()->ungrabButtons(old->clientWindow()); + Binder::instance()->grabButtons(old->clientWindow(), + AnyModifier); + } + Client *tc = monitor()->focused()->topClient(); + isGrabFocus_ = true; + if (tc) { + // unfocus topClient() of workspace, because the + // slot grabs focus control now + Binder::instance()->ungrabButtons(tc->clientWindow()); + Binder::instance()->grabButtons(tc->clientWindow(), + AnyModifier); + monitor()->focused()->illuminate(); + } + focused()->focus(client); + Binder::instance()->ungrabButtons(client->clientWindow()); + XCORE->setInputFocus(client->clientWindow()); + illuminate(); + return; + } + } + } +} +#endif // SLOT_SUPPORT diff --git a/slot.h b/slot.h @@ -0,0 +1,109 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: slot.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __SLOT_H +#define __SLOT_H + +#include "wmi.h" + +#ifdef SLOT_SUPPORT + +extern "C" { +#include <X11/Xlib.h> +} + +#include <list> +#include <string> +#include "container.h" +#include "widget.h" + +class Client; +class Label; +class Monitor; +class Theme; + +typedef list<Client *> LClient; + +/** + * Class for slot tabs. + */ +class Tab { + +public: + + Tab(const string name); + ~Tab(); + + string name() const; + LClient *clients(); + void addClient(Client *client); + void removeClient(Client *client); + + void show(); + void hide(); + bool isVisible() const; + + Client *focused() const; + void focus(Client *client); + +private: + + Client *focused_; + bool isVisible_; + string name_; + LClient clients_; +}; + +typedef list<Tab *> LTab; + +/** + * Base class of the slot which is capable to handle all kinds + * of X clients in a dockapp manner. + */ +class Slot : public Widget, + public Container<Monitor, LTab, LTab::iterator, Tab> +{ + +public: + + Slot(Monitor *monitor, Rectangle *rect, Direction align); + + virtual ~Slot(); + + Direction alignment() const; + + void show(string tabName); + virtual void hide(); + bool hasClients(); + bool isGrabFocus() const; + void setGrabFocus(bool grabFocus); + void focusClient(Client *client); + + void attachClient(Client *client); + void detachClient(Client *client); + void manage(); + + /** called on Expose by Kernel. */ + void illuminate(); + + void handleButtonPress(XButtonEvent *event); + void handleMotionNotify(XMotionEvent *event); + + string tabName(); + +private: + + void initTabs(); + Tab *tabForName(string name); + + Direction align_; + Label *label_; + bool isSolid_; + bool isGrabFocus_; + Theme *theme_; +}; + +#endif // SLOT_SUPPORT +#endif // __SLOT_H diff --git a/split.cpp b/split.cpp @@ -0,0 +1,382 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: split.cpp 734 2004-09-27 18:15:45Z garbeam $ + +extern "C" { +#include <assert.h> +} + +#include <cmath> + +#include "split.h" + +#include "frame.h" +#include "logger.h" +#include "rectangle.h" +#include "tree.h" +#include "util.h" + +Tree *Split::topMostRoot(Tree *first, Tree *last) { + + assert(first); + assert(last); + + Tree *tmp = first; + while (tmp->parent()) { + tmp = tmp->parent(); + tmp->setVisit(tmp->visits() + 1); + } + + tmp = last; + while (tmp->parent()) { + tmp = tmp->parent(); + tmp->setVisit(tmp->visits() + 1); + } + + // now all tree nodes have been marked, let's + // search for the first tree node with two visits, + // this is the topmost root of first an last + + Tree *result = first; + while (result->visits() < 2) { + result = result->parent(); + } + + // we got the result, now cleanup on both paths + tmp = first; + while (tmp->parent()) { + tmp = tmp->parent(); + tmp->setVisit(0); + } + + tmp = last; + while (tmp->parent()) { + tmp = tmp->parent(); + tmp->setVisit(0); + } + + return result; +} + +// applied patch by Dr. J. Pfefferl +void Split::resize(Tree *root, Tree *origin, + Direction dir, int stepW, int stepH) +{ + int newW, newH; + + if (!origin->frame()) { + return; + } + + Tree *neighbor = Split::neighbor(root, origin, dir); + if (!neighbor|| !neighbor->parent()) { + return; + } + + // Normalize stepH/W to positive numbers + // This is necessary to guarantee that the boundary checks + // for newW/newH later on work under all circumstances! + if(0 > stepH || 0 > stepW) { + stepH *= -1; + stepW *= -1; + // Reverse the grow/shrink directions accordingly + switch(dir) { + case LEFT: dir = RIGHT; break; + case RIGHT: dir = LEFT; break; + case UP: dir = DOWN; break; + case DOWN: dir = UP; break; + default: break; // Should not happen + } + } + + // neighbor is the nearest neighbor, but this can be + // a subtree of the top-level neighbor, so we've to + // determine the top-level neighbor + Tree *parent = topMostRoot(origin, neighbor); + + // determine the correct root for resizing and if we + // should grow or shrink the origin + Tree *growTree, *shrinkTree; + if ((dir == LEFT) || (dir == UP)) { + // shrink + growTree = parent->last(); + shrinkTree = parent->first(); + } + else { + // grow + growTree = parent->first(); + shrinkTree = parent->last(); + } + + switch (dir) { + case LEFT: + newW = shrinkTree->width() - stepW; + if (0 >= newW) { + return; + } + growTree->setX(growTree->x() - stepW); + growTree->setWidth(growTree->width() + stepW); + shrinkTree->setWidth(newW); + break; + case RIGHT: + newW = shrinkTree->width() - stepW; + if (0 >= newW) { + return; + } + growTree->setWidth(growTree->width() + stepW); + shrinkTree->setX(shrinkTree->x() + stepW); + shrinkTree->setWidth(newW); + break; + case UP: + newH = shrinkTree->height() - stepH; + if (0 >= newH) { + return; + } + growTree->setY(growTree->y() - stepH); + growTree->setHeight(growTree->height() + stepH); + shrinkTree->setHeight(newH); + break; + case DOWN: + newH = shrinkTree->height() - stepH; + if(0 >= newH) { + return; + } + growTree->setHeight(growTree->height() + stepH); + shrinkTree->setY(shrinkTree->y() + stepH); + shrinkTree->setHeight(newH); + break; + default: + break; + } + adjustSize(growTree, ((dir == LEFT) || (dir == RIGHT))); + adjustSize(shrinkTree, ((dir == LEFT) || (dir == RIGHT))); +} + +int Split::distance(Tree *origin, Tree *target) { + + int ox = origin->x() + origin->width() / 2; + int oy = origin->y() + origin->height() / 2; + int tx = target->x() + target->width() / 2; + int ty = target->y() + target->height() / 2; + + return (int)sqrt((double)(((ox - tx) * (ox - tx)) + + ((oy - ty) * (oy - ty)))); +} + +bool Split::isNeighbor(Tree *origin, Tree *target, Direction dir) { + + switch (dir) { + case LEFT: + return origin->x() >= (int)(target->x() + target->width()); + break; + case RIGHT: + return (int)(origin->x() + origin->width()) <= target->x(); + break; + case UP: + return origin->y() >= (int)(target->y() + target->height()); + break; + case DOWN: + return (int)(origin->y() + origin->height()) <= target->y(); + break; + default: + return false; + break; + } +} + +Tree *Split::neighbor(Tree *root, Tree *origin, Direction dir) { + + if (root == 0) { + return 0; + } + + Tree *result1 = neighbor(root->first(), origin, dir); + if (!result1 && root->first()) { + result1 = root->first(); + } + + Tree *result2 = neighbor(root->last(), origin, dir); + if (!result2 && root->last()) { + result2 = root->last(); + } + + bool res1 = result1 && (result1 != origin) + && isNeighbor(origin, result1, dir); + bool res2 = result2 && (result2 != origin) + && isNeighbor(origin, result2, dir); + + if (res1 && res2) { + + if (distance(origin, result1) + < distance(origin, result2)) + { + return result1; + } + else { + return result2; + } + } + else if (res1) { + return result1; + } + else if (res2) { + return result2; + } + + return 0; +} + +void Split::adjustSize(Tree *tree, bool ignoreVert) { + + Tree *first = tree->first(); + Tree *last = tree->last(); + if (first) { + assert(last); + if (tree->isHoriz()) { + // horizontal split + if (ignoreVert) { + first->copy(tree); + first->setWidth(tree->width() / 2); + last->copy(first); + last->setX(first->x() + first->width()); + } + else { + // beware horiz order + first->setY(tree->y()); + first->setHeight(tree->height()); + last->setY(tree->y()); + last->setHeight(tree->height()); + } + } + else { + // vertical split + if (!ignoreVert) { + first->copy(tree); + first->setHeight(tree->height() / 2); + last->copy(first); + last->setY(first->y() + first->height()); + } + else { + // beware vert order + first->setX(tree->x()); + first->setWidth(tree->width()); + last->setX(tree->x()); + last->setWidth(tree->width()); + } + } + adjustSize(first, ignoreVert); + adjustSize(last, ignoreVert); + } + else { + Frame *frame = tree->frame(); + if (frame) { + frame->copy(tree); + frame->resize(); + } + } +} + +void Split::detach(Tree *root, Tree *origin) { + + Tree *parent = origin->parent(); + + if (parent) { + Tree *child = (parent->first() != origin) + ? parent->first() : parent->last(); + delete origin; + assert(child); + if (child->first()) { + assert(child->last()); + assert(!child->frame()); + parent->setChilds(child->first(), child->last()); + parent->setHoriz(child->isHoriz()); + adjustSize(parent, parent->isHoriz()); + delete child; + } + else { + Frame *frame = child->frame(); + assert(frame); + parent->setFrame(frame); + parent->setChilds(0, 0); + frame->resize(); + delete child; + } + } + else { + assert(origin == root); + root->setFrame(0); + } +} + +Frame *Split::firstLeaf(Tree *tree) { + + if (tree->frame()) { + return tree->frame(); + } + if (tree->first() && tree->first()->frame()) { + return tree->first()->frame(); + } + if (tree->last() && tree->last()->frame()) { + return tree->last()->frame(); + } + if (tree->first()) { + return firstLeaf(tree->first()); + } + else if (tree->last()) { + return firstLeaf(tree->last()); + } + return 0; +} + +void Split::attach(Tree *root, Frame *frame, Direction dir) { + + Rectangle rect; + assert(root->first() == 0); + + Frame *oldFrame = root->frame(); + if (!oldFrame) { + root->setFrame(frame); + } + else { + root->setFrame(0); + rect.copy(root); + + if ((dir == LEFT) || (dir == RIGHT)) { + root->setHoriz(true); + rect.setWidth(rect.width() / 2); + } + else { + root->setHoriz(false); + rect.setHeight(rect.height() / 2); + } + + Tree *first = new Tree(root, &rect); + Tree *last; + if ((dir == LEFT) || (dir == UP)) { + first->setFrame(frame); + if (dir == LEFT) { + rect.setX(rect.x() + rect.width()); + } + else { // UP + rect.setY(rect.y() + rect.height()); + } + last = new Tree(root, &rect); + last->setFrame(oldFrame); + } + else { // RIGHT || DOWN + first->setFrame(oldFrame); + if (dir == RIGHT) { + rect.setX(rect.x() + rect.width()); + } + else { // DOWN + rect.setY(rect.y() + rect.height()); + } + last = new Tree(root, &rect); + last->setFrame(frame); + } + root->setChilds(first, last); + oldFrame->resize(); + } + frame->resize(); +} diff --git a/split.h b/split.h @@ -0,0 +1,46 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: split.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __SPLIT_H +#define __SPLIT_H + +#include "wmi.h" + +class Frame; +class Tree; + +/** + * This class contains all necessary splitting algorithm for managing + * windows in a non-overlapping manner. + */ +class Split { + +public: + + static void resize(Tree *root, Tree *origin, + Direction dir, int stepW, int stepH); + + static Tree *neighbor(Tree *root, Tree *origin, Direction dir); + static bool isNeighbor(Tree *origin, Tree *target, Direction dir); + + static void adjustSize(Tree *tree, bool ignoreVert); + + static void detach(Tree *root, Tree *origin); + + static Frame *firstLeaf(Tree *tree); + + static void attach(Tree *root, Frame *frame, Direction dir); + +private: + + /** Helper for neighbor stuff. */ + static int distance(Tree *origin, Tree *target); + + /** Helper for resize stuff. */ + static Tree *topMostRoot(Tree *first, Tree *last); + +}; + +#endif // __SPLIT_H diff --git a/src/Makefile.am b/src/Makefile.am @@ -0,0 +1,84 @@ +bin_PROGRAMS = wmi wmiremote +wmiremote_SOURCES = wmiremote.cpp +wmi_SOURCES = action.h \ +action.cpp \ +actions.h \ +actions.cpp \ +atoms.h \ +atoms.cpp \ +bar.h \ +bar.cpp \ +binder.h \ +binder.cpp \ +box.h \ +box.cpp \ +client.h \ +client.cpp \ +container.h \ +cursors.h \ +cursors.cpp \ +draw.h \ +draw.cpp \ +expander.cpp \ +expander.h \ +float.h \ +float.cpp \ +clientbar.h \ +clientbar.cpp \ +font.h \ +font.cpp \ +frame.h \ +frame.cpp \ +inputbar.h \ +inputbar.cpp \ +kernel.h \ +kernel.cpp \ +label.h \ +label.cpp \ +launcher.h \ +launcher.cpp \ +loader.h \ +loader.cpp \ +logger.h \ +logger.cpp \ +main.cpp \ +menu.h \ +menu.cpp \ +monitor.h \ +monitor.cpp \ +prompt.h \ +prompt.cpp \ +rectangle.h \ +rectangle.cpp \ +shortcut.h \ +shortcut.cpp \ +singleton.h \ +slot.cpp \ +slot.h \ +split.h \ +split.cpp \ +statusbar.h \ +statusbar.cpp \ +theme.h \ +theme.cpp \ +thing.h \ +thing.cpp \ +tree.h \ +tree.cpp \ +util.h \ +util.cpp \ +wmi.h \ +validators.h \ +validators.cpp \ +widget.h \ +widget.cpp \ +workspace.h \ +workspace.cpp \ +xcore.h \ +xcore.cpp \ +xfont.h \ +xfont.cpp \ +xftfont.h \ +xftfont.cpp +wmi_LDADD = @LDFLAGS@ +wmiremote_LDADD = @LDFLAGS@ diff --git a/src/Makefile.in b/src/Makefile.in @@ -0,0 +1,495 @@ +# Makefile.in generated by automake 1.8.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +SOURCES = $(wmi_SOURCES) $(wmiremote_SOURCES) + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +bin_PROGRAMS = wmi$(EXEEXT) wmiremote$(EXEEXT) +subdir = src +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/./xft.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(mkdir_p) +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) +am_wmi_OBJECTS = action.$(OBJEXT) actions.$(OBJEXT) atoms.$(OBJEXT) \ + bar.$(OBJEXT) binder.$(OBJEXT) box.$(OBJEXT) client.$(OBJEXT) \ + cursors.$(OBJEXT) draw.$(OBJEXT) expander.$(OBJEXT) \ + float.$(OBJEXT) clientbar.$(OBJEXT) font.$(OBJEXT) \ + frame.$(OBJEXT) inputbar.$(OBJEXT) kernel.$(OBJEXT) \ + label.$(OBJEXT) launcher.$(OBJEXT) loader.$(OBJEXT) \ + logger.$(OBJEXT) main.$(OBJEXT) menu.$(OBJEXT) \ + monitor.$(OBJEXT) prompt.$(OBJEXT) rectangle.$(OBJEXT) \ + shortcut.$(OBJEXT) slot.$(OBJEXT) split.$(OBJEXT) \ + statusbar.$(OBJEXT) theme.$(OBJEXT) thing.$(OBJEXT) \ + tree.$(OBJEXT) util.$(OBJEXT) validators.$(OBJEXT) \ + widget.$(OBJEXT) workspace.$(OBJEXT) xcore.$(OBJEXT) \ + xfont.$(OBJEXT) xftfont.$(OBJEXT) +wmi_OBJECTS = $(am_wmi_OBJECTS) +wmi_DEPENDENCIES = +am_wmiremote_OBJECTS = wmiremote.$(OBJEXT) +wmiremote_OBJECTS = $(am_wmiremote_OBJECTS) +wmiremote_DEPENDENCIES = +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = +am__depfiles_maybe = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(wmi_SOURCES) $(wmiremote_SOURCES) +DIST_SOURCES = $(wmi_SOURCES) $(wmiremote_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build_alias = @build_alias@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +wmiremote_SOURCES = wmiremote.cpp +wmi_SOURCES = action.h \ +action.cpp \ +actions.h \ +actions.cpp \ +atoms.h \ +atoms.cpp \ +bar.h \ +bar.cpp \ +binder.h \ +binder.cpp \ +box.h \ +box.cpp \ +client.h \ +client.cpp \ +container.h \ +cursors.h \ +cursors.cpp \ +draw.h \ +draw.cpp \ +expander.cpp \ +expander.h \ +float.h \ +float.cpp \ +clientbar.h \ +clientbar.cpp \ +font.h \ +font.cpp \ +frame.h \ +frame.cpp \ +inputbar.h \ +inputbar.cpp \ +kernel.h \ +kernel.cpp \ +label.h \ +label.cpp \ +launcher.h \ +launcher.cpp \ +loader.h \ +loader.cpp \ +logger.h \ +logger.cpp \ +main.cpp \ +menu.h \ +menu.cpp \ +monitor.h \ +monitor.cpp \ +prompt.h \ +prompt.cpp \ +rectangle.h \ +rectangle.cpp \ +shortcut.h \ +shortcut.cpp \ +singleton.h \ +slot.cpp \ +slot.h \ +split.h \ +split.cpp \ +statusbar.h \ +statusbar.cpp \ +theme.h \ +theme.cpp \ +thing.h \ +thing.cpp \ +tree.h \ +tree.cpp \ +util.h \ +util.cpp \ +wmi.h \ +validators.h \ +validators.cpp \ +widget.h \ +widget.cpp \ +workspace.h \ +workspace.cpp \ +xcore.h \ +xcore.cpp \ +xfont.h \ +xfont.cpp \ +xftfont.h \ +xftfont.cpp + +wmi_LDADD = @LDFLAGS@ +wmiremote_LDADD = @LDFLAGS@ +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps src/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) +wmi$(EXEEXT): $(wmi_OBJECTS) $(wmi_DEPENDENCIES) + @rm -f wmi$(EXEEXT) + $(CXXLINK) $(wmi_LDFLAGS) $(wmi_OBJECTS) $(wmi_LDADD) $(LIBS) +wmiremote$(EXEEXT): $(wmiremote_OBJECTS) $(wmiremote_DEPENDENCIES) + @rm -f wmiremote$(EXEEXT) + $(CXXLINK) $(wmiremote_LDFLAGS) $(wmiremote_OBJECTS) $(wmiremote_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.cpp.o: + $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -z "$$unique" && unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: install-binPROGRAMS + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-exec install-exec-am \ + install-info install-info-am install-man install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-binPROGRAMS uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/statusbar.cpp b/statusbar.cpp @@ -0,0 +1,353 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: statusbar.cpp 734 2004-09-27 18:15:45Z garbeam $ + +extern "C" { +#include <assert.h> +} + +#include "statusbar.h" + +#include "binder.h" +#include "client.h" +#include "cursors.h" +#include "draw.h" +#include "kernel.h" +#include "inputbar.h" +#include "label.h" +#include "logger.h" +#include "rectangle.h" +#include "workspace.h" +#include "monitor.h" +#include "theme.h" +#include "util.h" +#include "xcore.h" + +StatusBar::StatusBar(Monitor *monitor, Rectangle *rect) + : Bar(monitor, rect) +{ + text_ = "window manager improved - " + string(__WMI_VERSION); + buttonPressed_ = false; +} + +void StatusBar::illuminate() { + + if (!isVisible()) { + return; + } + + LOGDEBUG("going to draw border"); + drawBorder(); + + unsigned int offsetX = 1; + + label_->setAlignment(Label::CENTER); + label_->setText(""); + label_->setX(offsetX); + label_->setWidth(width() - 2); + label_->update(theme_->BAR_BACKGROUND, theme_->BAR_TEXT, + theme_->BAR_SHINE, theme_->BAR_SHADOW); + + updateInputModeButton(&offsetX); + updateWorkspacePager(&offsetX); + updateStatus(&offsetX); + updateMeters(offsetX); + + XCORE->sync(); +} + +StatusBar::~StatusBar() { +} + +void StatusBar::updateInputModeButton(unsigned int *offsetX) { + + if (!isButtonVisible_) { + return; + } + + // input mode button + label_->setX(*offsetX); + label_->setText(""); + label_->setWidth(monitor()->buttonWidth()); + if (!buttonPressed_) { + + Draw::drawInputModeButton(window(), gc(), label_, + theme_->BUTTON_BACKGROUND_NORMAL, + theme_->BUTTON_SHINE_BORDER_NORMAL, + theme_->BUTTON_SHADOW_BORDER_NORMAL, + theme_->BUTTON_SHINE_FIGURE_NORMAL, + theme_->BUTTON_SHADOW_FIGURE_NORMAL); + } + else { + + Draw::drawInputModeButton(window(), gc(), label_, + theme_->BUTTON_BACKGROUND_PRESSED, + theme_->BUTTON_SHINE_BORDER_PRESSED, + theme_->BUTTON_SHADOW_BORDER_PRESSED, + theme_->BUTTON_SHINE_FIGURE_PRESSED, + theme_->BUTTON_SHADOW_FIGURE_PRESSED); + } + *offsetX += monitor()->buttonWidth() + 2; +} + +unsigned int StatusBar::calculateWorkspaceWidth() { + + // workspace pager stuff + Workspace *focusedWorkspace = monitor()->focused(); + assert(focusedWorkspace); + + // first determine maximum workspace label width + unsigned int workspaceWidth = 0; + for (LWorkspace::iterator it = monitor()->begin(); + it != monitor()->end(); it++) + { + Workspace *workspace = *it; + label_->setText(workspace->name()); + label_->adjustWidth(); + if (label_->width() > workspaceWidth) { + workspaceWidth = label_->width(); + } + } + + return workspaceWidth; +} + +void StatusBar::updateWorkspacePager(unsigned int *offsetX) { + + // workspace pager stuff + Workspace *focusedWorkspace = monitor()->focused(); + assert(focusedWorkspace); + unsigned int workspaceWidth = calculateWorkspaceWidth(); + unsigned int i = 0; + label_->setWidth(workspaceWidth); + for (LWorkspace::iterator it = monitor()->begin(); + it != monitor()->end(); it++) + { + Workspace *workspace = *it; + label_->setX(i * workspaceWidth + *offsetX); + label_->setText(workspace->name()); + if (workspace == focusedWorkspace) { + label_->update(theme_->LABEL_BACKGROUND_FOCUSSED, + theme_->LABEL_TEXT_FOCUSSED, + theme_->LABEL_SHINE_FOCUSSED, + theme_->LABEL_SHADOW_FOCUSSED, + true, true); + } + else if (workspace->requestsFocus()) { + label_->update(theme_->FOCUSREQ_BACKGROUND, + theme_->FOCUSREQ_TEXT, + theme_->FOCUSREQ_SHINE, + theme_->FOCUSREQ_SHADOW, + true, true); + } + else { + label_->update(theme_->LABEL_BACKGROUND_NORMAL, + theme_->LABEL_TEXT_NORMAL, + theme_->LABEL_SHINE_NORMAL, + theme_->LABEL_SHADOW_NORMAL, + true, true); + } + i++; + } + *offsetX += i * workspaceWidth + 2; +} + +unsigned int StatusBar::calculateMetersWidth() { + + unsigned int result = 0; + if (meterText_ != "") { + string percentage = ""; + string text = ""; + bool isPercentage = true; + unsigned int meterWidth = monitor()->buttonWidth() / 2; + for (string::iterator it = meterText_.begin(); + it != meterText_.end(); ) + { + + char c = *it; + it++; + bool isEndreached = it == meterText_.end(); + if (c == '%') { + isPercentage = false; + } + if ((c == ',') || isEndreached) { + if (isEndreached && (c != '%')) { + text += c; + } + isPercentage = true; + result += 2 + meterWidth; + if (text != "") { + label_->setAlignment(Label::LEFT); + label_->setText(text); + result += label_->textWidth(); + } + text = ""; + percentage = ""; + } + else if (isPercentage && (c == '!')) { + // do nothing here + } + else if (c != '%') { + if (isPercentage) { + percentage += c; + } + else { + text += c; + } + } + } + } + return result; +} + +void StatusBar::updateMeters(unsigned int offsetX) { + + if (meterText_ != "") { + + string percentage = ""; + string text = ""; + bool isPercentage = true; + bool isNegotiated = false; + unsigned int meterWidth = monitor()->buttonWidth() / 2; + label_->setX(offsetX); + label_->setWidth(0); + for (string::iterator it = meterText_.begin(); + it != meterText_.end(); ) + { + + char c = *it; + it++; + bool isEndreached = it == meterText_.end(); + if (c == '%') { + isPercentage = false; + } + if ((c == ',') || isEndreached) { + if (isEndreached && (c != '%')) { + text += c; + } + label_->setX(label_->x() + label_->width() + 2); + label_->setWidth(meterWidth); + int percent = Util::strToUInt(percentage); + if (percent < 0) { + percent = 0; + } + else if (percent > 99) { + percent = 99; + } + Draw::drawMeter(window(), gc(), label_, percent, + theme_->METER_BACKGROUND, + isNegotiated ? theme_->METER_FIGURE_LOW : theme_->METER_FIGURE_HIGH, + theme_->METER_FIGURE_NORMAL, + isNegotiated ? theme_->METER_FIGURE_HIGH : theme_->METER_FIGURE_LOW, + theme_->METER_BORDER_SHINE, + theme_->METER_BORDER_SHADOW); + if (text != "") { + label_->setAlignment(Label::LEFT); + label_->setX(label_->x() + label_->width()); + label_->setText(text); + label_->adjustWidth(); + label_->update(theme_->BAR_BACKGROUND, theme_->BAR_TEXT, + theme_->BAR_SHINE, theme_->BAR_SHADOW); + } + text = ""; + percentage = ""; + isPercentage = true; + isNegotiated = false; + } + else if (isPercentage && (c == '!')) { + isNegotiated = true; + } + else if (c != '%') { + + if (isPercentage) { + percentage += c; + } + else { + text += c; + } + } + } + } +} + +void StatusBar::updateStatus(unsigned int *offsetX) { + + unsigned int metersWidth = calculateMetersWidth(); + + // user defined status text + label_->setAlignment(Label::RIGHT); + label_->setX(*offsetX); + label_->setWidth(width() - *offsetX - metersWidth - 5); + label_->setText(text_); + label_->update(theme_->BAR_BACKGROUND, theme_->BAR_TEXT, + theme_->BAR_SHINE, theme_->BAR_SHADOW); + + *offsetX = label_->x() + label_->width() + 2; +} + +void StatusBar::handleButtonRelease(XButtonEvent *event) { + + // TODO: make buttons customizable + if (buttonPressed_) { + if (event->button == Button1) { + LOGDEBUG("toggling interactive mode"); + monitor()->inputBar()->runKey(KERNEL->defaultPrompt()); + buttonPressed_ = false; + } + } +} + +void StatusBar::handleButtonPress(XButtonEvent *event) { + + if ((event->window != window())) { + return; + } + + XCORE->raise(window()); + + // TODO: make buttons customizable + if (event->button == Button1) { + invokeClickedThing(event->x); + } + else if (event->button == Button4) { + monitor()->focus(monitor()->prev()); + } + else if (event->button == Button5) { + monitor()->focus(monitor()->next()); + } +} + +void StatusBar::handleMotionNotify(XMotionEvent *event) { + + if (buttonPressed_) { + buttonPressed_ = false; + illuminate(); + } +} + +void StatusBar::invokeClickedThing(int xPosition) { + + if (isButtonVisible_) { + if (xPosition < (int)monitor()->buttonWidth() + 1) { + buttonPressed_ = true; + illuminate(); + return; + } + xPosition -= (monitor()->buttonWidth() + 3); + } + + unsigned int workspaceNum = xPosition / calculateWorkspaceWidth(); + if (workspaceNum < monitor()->size()) { + monitor()->focusWorkspaceNum(workspaceNum); + } + illuminate(); +} + +void StatusBar::setText(const string text) { + text_ = text; +} + +void StatusBar::setMeterText(const string meterText) { + meterText_ = meterText; +} diff --git a/statusbar.h b/statusbar.h @@ -0,0 +1,55 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: statusbar.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __STATUSBAR_H +#define __STATUSBAR_H + +#include "bar.h" + +#include <set> +#include <string> +#include "wmi.h" + +class Kernel; +class Monitor; + +/** + * Represents the statusbar of WMI. + */ +class StatusBar : public Bar { + +public: + + StatusBar(Monitor *monitor, Rectangle *rect); + + ~StatusBar(); + + virtual void illuminate(); + + virtual void handleMotionNotify(XMotionEvent *event); + virtual void handleButtonPress(XButtonEvent *event); + virtual void handleButtonRelease(XButtonEvent *event); + + void setText(const string text); + void setMeterText(const string meterText); + +private: + + unsigned int calculateMetersWidth(); + unsigned int calculateWorkspaceWidth(); + void invokeClickedThing(int xPosition); + + void updateInputModeButton(unsigned int *offsetX); + void updateWorkspacePager(unsigned int *offsetX); + void updateDetachedClients(unsigned int *offsetX); + void updateStatus(unsigned int *offsetX); + void updateMeters(unsigned int offsetX); + + string meterText_; + string text_; + bool buttonPressed_; +}; + +#endif // __STATUSBAR_H diff --git a/theme.cpp b/theme.cpp @@ -0,0 +1,141 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: theme.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include "theme.h" + +#include "logger.h" +#include "monitor.h" +#include "xcore.h" + +Theme::Theme() { +} + +Theme::~Theme() { +} + +unsigned long Theme::allocateColor(string name, Colormap cmap) { + + XColor color; + + if (!XCORE->allocNamedColor(cmap, name, &color)) + { + Logger::instance()->error("cannot allocate color '" + + name + "'", true); + // exits WMI + } + + return color.pixel; +} + +void Theme::initTheme(MSettings *ts, Colormap cmap) { + + BAR_BACKGROUND = allocateColor(Util::get(ts, "color.bar.background"), cmap); + BAR_TEXT = allocateColor(Util::get(ts, "color.bar.text"), cmap); + BAR_SHINE = allocateColor(Util::get(ts, "color.bar.shine"), cmap); + BAR_SHADOW = allocateColor(Util::get(ts, "color.bar.shadow"), cmap); + + METER_BACKGROUND = allocateColor(Util::get(ts, "color.meter.background"), cmap); + METER_FIGURE_HIGH = allocateColor(Util::get(ts, "color.meter.figure.high"), cmap); + METER_FIGURE_NORMAL = allocateColor(Util::get(ts, "color.meter.figure.normal"), cmap); + METER_FIGURE_LOW = allocateColor(Util::get(ts, "color.meter.figure.low"), cmap); + METER_BORDER_SHINE= allocateColor(Util::get(ts, "color.meter.border.shine"), cmap); + METER_BORDER_SHADOW= allocateColor(Util::get(ts, "color.meter.border.shadow"), cmap); + + FOCUSREQ_BACKGROUND = allocateColor(Util::get(ts, "color.focusreq.background"), cmap); + FOCUSREQ_TEXT = allocateColor(Util::get(ts, "color.focusreq.text"), cmap); + FOCUSREQ_SHINE = allocateColor(Util::get(ts, "color.focusreq.shine"), cmap); + FOCUSREQ_SHADOW = allocateColor(Util::get(ts, "color.focusreq.shadow"), cmap); + + TILED_SHINE_FOCUSSED = allocateColor(Util::get(ts, "color.tiled.shine.focussed"), cmap); + TILED_SHADOW_FOCUSSED = allocateColor(Util::get(ts, "color.tiled.shadow.focussed"), cmap); + TILED_SHINE_NORMAL = allocateColor(Util::get(ts, "color.tiled.shine.normal"), cmap); + TILED_SHADOW_NORMAL = allocateColor(Util::get(ts, "color.tiled.shadow.normal"), cmap); + + BUTTON_BACKGROUND_NORMAL = + allocateColor(Util::get(ts, "color.button.background.normal"), cmap); + BUTTON_BACKGROUND_PRESSED = + allocateColor(Util::get(ts, "color.button.background.pressed"), cmap); + BUTTON_SHINE_BORDER_NORMAL = + allocateColor(Util::get(ts, "color.button.border.shine.normal"), cmap); + BUTTON_SHINE_BORDER_PRESSED = + allocateColor(Util::get(ts, "color.button.border.shine.pressed"), cmap); + BUTTON_SHADOW_BORDER_NORMAL = + allocateColor(Util::get(ts, "color.button.border.shadow.normal"), cmap); + BUTTON_SHADOW_BORDER_PRESSED = + allocateColor(Util::get(ts, "color.button.border.shadow.pressed"), cmap); + BUTTON_SHINE_FIGURE_NORMAL = + allocateColor(Util::get(ts, "color.button.figure.shine.normal"), cmap); + BUTTON_SHINE_FIGURE_PRESSED = + allocateColor(Util::get(ts, "color.button.figure.shine.pressed"), cmap); + BUTTON_SHADOW_FIGURE_NORMAL = + allocateColor(Util::get(ts, "color.button.figure.shadow.normal"), cmap); + BUTTON_SHADOW_FIGURE_PRESSED = + allocateColor(Util::get(ts, "color.button.figure.shadow.pressed"), cmap); + + FRAME_BACKGROUND_NORMAL = + allocateColor(Util::get(ts, "color.frame.background.normal"), cmap); + FRAME_BACKGROUND_FOCUSSED = + allocateColor(Util::get(ts, "color.frame.background.focussed"), cmap); + FRAME_SHINE_NORMAL = + allocateColor(Util::get(ts, "color.frame.shine.normal"), cmap); + FRAME_SHINE_FOCUSSED = + allocateColor(Util::get(ts, "color.frame.shine.focussed"), cmap); + FRAME_SHADOW_NORMAL = + allocateColor(Util::get(ts, "color.frame.shadow.normal"), cmap); + FRAME_SHADOW_FOCUSSED = + allocateColor(Util::get(ts, "color.frame.shadow.focussed"), cmap); + FRAME_PSEUDO = + allocateColor(Util::get(ts, "color.frame.pseudo"), cmap); + + LABEL_BACKGROUND_NORMAL = + allocateColor(Util::get(ts, "color.label.background.normal"), cmap); + LABEL_BACKGROUND_FOCUSSED = + allocateColor(Util::get(ts, "color.label.background.focussed"), cmap); + LABEL_TEXT_NORMAL = + allocateColor(Util::get(ts, "color.label.text.normal"), cmap); + LABEL_TEXT_FOCUSSED = + allocateColor(Util::get(ts, "color.label.text.focussed"), cmap); + LABEL_SHINE_NORMAL = + allocateColor(Util::get(ts, "color.label.shine.normal"), cmap); + LABEL_SHINE_FOCUSSED = + allocateColor(Util::get(ts, "color.label.shine.focussed"), cmap); + LABEL_SHADOW_NORMAL = + allocateColor(Util::get(ts, "color.label.shadow.normal"), cmap); + LABEL_SHADOW_FOCUSSED = + allocateColor(Util::get(ts, "color.label.shadow.focussed"), cmap); + + TAB_BACKGROUND_ACTIVE_NORMAL = + allocateColor(Util::get(ts, "color.tab.background.active.normal"), cmap); + TAB_BACKGROUND_INACTIVE_NORMAL = + allocateColor(Util::get(ts, "color.tab.background.inactive.normal"), cmap); + TAB_BACKGROUND_ACTIVE_FOCUSSED = + allocateColor(Util::get(ts, "color.tab.background.active.focussed"), cmap); + TAB_BACKGROUND_INACTIVE_FOCUSSED = + allocateColor(Util::get(ts, "color.tab.background.inactive.focussed"), cmap); + TAB_TEXT_ACTIVE_NORMAL = + allocateColor(Util::get(ts, "color.tab.text.active.normal"), cmap); + TAB_TEXT_INACTIVE_NORMAL = + allocateColor(Util::get(ts, "color.tab.text.inactive.normal"), cmap); + TAB_TEXT_ACTIVE_FOCUSSED = + allocateColor(Util::get(ts, "color.tab.text.active.focussed"), cmap); + TAB_TEXT_INACTIVE_FOCUSSED = + allocateColor(Util::get(ts, "color.tab.text.inactive.focussed"), cmap); + TAB_SHINE_ACTIVE_NORMAL = + allocateColor(Util::get(ts, "color.tab.shine.active.normal"), cmap); + TAB_SHINE_INACTIVE_NORMAL = + allocateColor(Util::get(ts, "color.tab.shine.inactive.normal"), cmap); + TAB_SHINE_ACTIVE_FOCUSSED = + allocateColor(Util::get(ts, "color.tab.shine.active.focussed"), cmap); + TAB_SHINE_INACTIVE_FOCUSSED = + allocateColor(Util::get(ts, "color.tab.shine.inactive.focussed"), cmap); + TAB_SHADOW_ACTIVE_NORMAL = + allocateColor(Util::get(ts, "color.tab.shadow.active.normal"), cmap); + TAB_SHADOW_INACTIVE_NORMAL = + allocateColor(Util::get(ts, "color.tab.shadow.inactive.normal"), cmap); + TAB_SHADOW_ACTIVE_FOCUSSED = + allocateColor(Util::get(ts, "color.tab.shadow.active.focussed"), cmap); + TAB_SHADOW_INACTIVE_FOCUSSED = + allocateColor(Util::get(ts, "color.tab.shadow.inactive.focussed"), cmap); +} diff --git a/theme.h b/theme.h @@ -0,0 +1,105 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: theme.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __THEME_H +#define __THEME_H + +extern "C" { +#include <X11/Xlib.h> +} + +#include <map> +#include <string> + +#include "wmi.h" + +typedef map<string, string, less<string> > MSettings; + +/** + * Represents a theme of WMI. + */ +class Theme +{ + +public: + + Theme(); + ~Theme(); + + void initTheme(MSettings *settings, Colormap cmap); + + unsigned long BAR_BACKGROUND; + unsigned long BAR_TEXT; + unsigned long BAR_SHINE; + unsigned long BAR_SHADOW; + + unsigned long METER_BACKGROUND; + unsigned long METER_FIGURE_HIGH; + unsigned long METER_FIGURE_NORMAL; + unsigned long METER_FIGURE_LOW; + unsigned long METER_BORDER_SHINE; + unsigned long METER_BORDER_SHADOW; + + unsigned long FOCUSREQ_BACKGROUND; + unsigned long FOCUSREQ_TEXT; + unsigned long FOCUSREQ_SHINE; + unsigned long FOCUSREQ_SHADOW; + + unsigned long TILED_SHINE_FOCUSSED; + unsigned long TILED_SHADOW_FOCUSSED; + unsigned long TILED_SHINE_NORMAL; + unsigned long TILED_SHADOW_NORMAL; + + unsigned long BUTTON_BACKGROUND_NORMAL; + unsigned long BUTTON_BACKGROUND_PRESSED; + unsigned long BUTTON_SHINE_BORDER_NORMAL; + unsigned long BUTTON_SHINE_BORDER_PRESSED; + unsigned long BUTTON_SHADOW_BORDER_NORMAL; + unsigned long BUTTON_SHADOW_BORDER_PRESSED; + unsigned long BUTTON_SHINE_FIGURE_NORMAL; + unsigned long BUTTON_SHINE_FIGURE_PRESSED; + unsigned long BUTTON_SHADOW_FIGURE_NORMAL; + unsigned long BUTTON_SHADOW_FIGURE_PRESSED; + + unsigned long FRAME_BACKGROUND_NORMAL; + unsigned long FRAME_BACKGROUND_FOCUSSED; + unsigned long FRAME_SHINE_NORMAL; + unsigned long FRAME_SHINE_FOCUSSED; + unsigned long FRAME_SHADOW_NORMAL; + unsigned long FRAME_SHADOW_FOCUSSED; + unsigned long FRAME_PSEUDO; + + unsigned long LABEL_BACKGROUND_NORMAL; + unsigned long LABEL_BACKGROUND_FOCUSSED; + unsigned long LABEL_TEXT_NORMAL; + unsigned long LABEL_TEXT_FOCUSSED; + unsigned long LABEL_SHINE_NORMAL; + unsigned long LABEL_SHINE_FOCUSSED; + unsigned long LABEL_SHADOW_NORMAL; + unsigned long LABEL_SHADOW_FOCUSSED; + + unsigned long TAB_BACKGROUND_ACTIVE_NORMAL; + unsigned long TAB_BACKGROUND_INACTIVE_NORMAL; + unsigned long TAB_BACKGROUND_ACTIVE_FOCUSSED; + unsigned long TAB_BACKGROUND_INACTIVE_FOCUSSED; + unsigned long TAB_TEXT_ACTIVE_NORMAL; + unsigned long TAB_TEXT_INACTIVE_NORMAL; + unsigned long TAB_TEXT_ACTIVE_FOCUSSED; + unsigned long TAB_TEXT_INACTIVE_FOCUSSED; + unsigned long TAB_SHINE_ACTIVE_NORMAL; + unsigned long TAB_SHINE_INACTIVE_NORMAL; + unsigned long TAB_SHINE_ACTIVE_FOCUSSED; + unsigned long TAB_SHINE_INACTIVE_FOCUSSED; + unsigned long TAB_SHADOW_ACTIVE_NORMAL; + unsigned long TAB_SHADOW_INACTIVE_NORMAL; + unsigned long TAB_SHADOW_ACTIVE_FOCUSSED; + unsigned long TAB_SHADOW_INACTIVE_FOCUSSED; + +private: + unsigned long allocateColor(string name, Colormap cmap); + +}; + +#endif // __THEME_H diff --git a/thing.cpp b/thing.cpp @@ -0,0 +1,361 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: thing.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include "thing.h" + +#include "client.h" +#include "cursors.h" +#include "draw.h" +#include "font.h" +#include "frame.h" +#include "kernel.h" +#include "label.h" +#include "logger.h" +#include "monitor.h" +#include "theme.h" +#include "workspace.h" +#include "xcore.h" +#include "xfont.h" + +Thing::Thing(Monitor *monitor, Rectangle *rect, Type type) + : Rectangle(*rect) +{ + monitor_ = monitor; + type_ = type; + isVisible_ = false; + hasDecoration_ = false; + clientAreaRect_ = Rectangle(*rect); + name_ = ""; + + // view + theme_ = monitor_->theme(); + + areButtonsVisible_ = + (Util::get(KERNEL->commonSettings(), "frame.buttons") == "yes"); + + cursor_ = Cursors::NORMAL_CURSOR; + prevRect_ = new Rectangle(*rect); + buttonState_ = NONE; + + // creates frame window + if (type == FRAME) { + initFrameWindow(); + fitClientArea(); + } + else { + frameWindow_ = 0; + gc_ = 0; + label_ = 0; + titleBarHeight_ = 0; + borderWidth_ = 0; + } +} + +Thing::~Thing() { + delete prevRect_; + + if (frameWindow_) { + delete label_; + XCORE->free(gc_); + XCORE->destroy(frameWindow_); + LOGDEBUG("frame destroyed"); + } +} + +void Thing::initFrameWindow() { + + titleBarHeight_ = + (Util::get(KERNEL->commonSettings(), "default.bar-mode") + == "show") ? monitor_->titleBarHeight() : 0; + borderWidth_ = + (Util::get(KERNEL->commonSettings(), "default.border-mode") + == "show") ? KERNEL->borderWidth() : 0; + + if (type_ == CLIENT) { + setX(x() - borderWidth_); + setY(y() - titleBarHeight_ - borderWidth_ - 1); + setWidth(width() + 2 * borderWidth_); + setHeight(height() + titleBarHeight_ + 2 * borderWidth_ + 1); + } + + XSetWindowAttributes attr; + attr.background_pixmap = ParentRelative; + attr.override_redirect = 1; + frameWindow_ = XCORE->createWindow(this->monitor()->rootWindow(), &attr, + x(), y(), width(), height(), + CWOverrideRedirect | CWBackPixmap); + + LOGDEBUG("init GC for frame"); + initGC(); + label_ = new Label(this->monitor(), frameWindow_, Label::CENTER, gc_); + label_->setY(borderWidth_); + label_->setHeight(titleBarHeight_); + + XCORE->selectEvents(frameWindow_, + ExposureMask | SubstructureRedirectMask | SubstructureNotifyMask | + ButtonPressMask | ButtonReleaseMask | PointerMotionMask); + + KERNEL->installCursor(Cursors::NORMAL_CURSOR, frameWindow_); + hasDecoration_ = true; +} + +Thing::Type Thing::type() const { + return type_; +} + +Monitor *Thing::monitor() const { + return monitor_; +} + +bool Thing::isVisible() const { + return isVisible_; +} + +void Thing::initGC() { + + if (frameWindow_) { + unsigned long mask = + GCForeground | GCBackground | + GCFunction | GCLineWidth | GCLineStyle; + + XGCValues gcv; + gcv.function = GXcopy; + gcv.line_width = 1; + gcv.line_style = LineSolid; + if (monitor()->font()->type() == WFont::NORMAL) { + gcv.font = ((XFont *)monitor()->font())->font()->fid; + mask |= GCFont; + } + gc_ = XCORE->createGC(frameWindow_, mask, &gcv); + } +} + +void Thing::illuminateBorder() { + + if (!isVisible_ || !frameWindow_) { + return; + } + + bool focused = isFocused(); + + if (titleBarHeight_) { + label_->setText(""); + label_->setX(borderWidth_); + label_->setWidth(width() - 2 * borderWidth_); + + if (focused) { + label_->update(theme_->FRAME_BACKGROUND_FOCUSSED, 0, + theme_->FRAME_SHINE_FOCUSSED, + theme_->FRAME_SHADOW_FOCUSSED); + } + else { + label_->update(theme_->FRAME_BACKGROUND_NORMAL, 0, + theme_->FRAME_SHINE_NORMAL, + theme_->FRAME_SHADOW_NORMAL); + } + } + + LOGDEBUG("drawing border"); + if (focused) { + Draw::drawBorder(frameWindow_, gc_, monitor()->borderGC(), this, + theme_->FRAME_BACKGROUND_FOCUSSED, + theme_->FRAME_SHINE_FOCUSSED, + theme_->FRAME_SHADOW_FOCUSSED, + titleBarHeight_ + borderWidth_, + borderWidth_); + } + else { + Draw::drawBorder(frameWindow_, gc_, monitor()->borderGC(), this, + theme_->FRAME_BACKGROUND_NORMAL, + theme_->FRAME_SHINE_NORMAL, + theme_->FRAME_SHADOW_NORMAL, + titleBarHeight_ + borderWidth_, + borderWidth_); + } + + if (titleBarHeight_ && areButtonsVisible_ && focused) { + + if (type_ == FRAME && !((Frame *)this)->size()) { + // no need to draw buttons + return; + } + + // detach button + label_->setText(""); + label_->setX(width() - borderWidth_ - 3 * monitor_->buttonWidth()); + label_->setWidth(monitor_->buttonWidth()); + if (buttonState_ != MINCLIENT) { + + Draw::drawDetachButton(frameWindow_, gc_, label_, + theme_->BUTTON_BACKGROUND_NORMAL, + theme_->BUTTON_SHINE_BORDER_NORMAL, + theme_->BUTTON_SHADOW_BORDER_NORMAL, + theme_->BUTTON_SHINE_FIGURE_NORMAL, + theme_->BUTTON_SHADOW_FIGURE_NORMAL); + } + else { + + Draw::drawDetachButton(frameWindow_, gc_, label_, + theme_->BUTTON_BACKGROUND_PRESSED, + theme_->BUTTON_SHINE_BORDER_PRESSED, + theme_->BUTTON_SHADOW_BORDER_PRESSED, + theme_->BUTTON_SHINE_FIGURE_PRESSED, + theme_->BUTTON_SHADOW_FIGURE_PRESSED); + } + + // (de)max client button + label_->setX(label_->x() + monitor_->buttonWidth()); + + if (buttonState_ != DEMAX) { + + if (type_ == CLIENT) { + + Draw::drawMaxButton(frameWindow_, gc_, label_, + theme_->BUTTON_BACKGROUND_NORMAL, + theme_->BUTTON_SHINE_BORDER_NORMAL, + theme_->BUTTON_SHADOW_BORDER_NORMAL, + theme_->BUTTON_SHINE_FIGURE_NORMAL, + theme_->BUTTON_SHADOW_FIGURE_NORMAL); + } + else { + + Draw::drawFloatButton(frameWindow_, gc_, label_, + theme_->BUTTON_BACKGROUND_NORMAL, + theme_->BUTTON_SHINE_BORDER_NORMAL, + theme_->BUTTON_SHADOW_BORDER_NORMAL, + theme_->BUTTON_SHINE_FIGURE_NORMAL, + theme_->BUTTON_SHADOW_FIGURE_NORMAL); + } + } + else { + + if (type_ == CLIENT) { + + Draw::drawMaxButton(frameWindow_, gc_, label_, + theme_->BUTTON_BACKGROUND_PRESSED, + theme_->BUTTON_SHINE_BORDER_PRESSED, + theme_->BUTTON_SHADOW_BORDER_PRESSED, + theme_->BUTTON_SHINE_FIGURE_PRESSED, + theme_->BUTTON_SHADOW_FIGURE_PRESSED); + } + else { + + Draw::drawFloatButton(frameWindow_, gc_, label_, + theme_->BUTTON_BACKGROUND_PRESSED, + theme_->BUTTON_SHINE_BORDER_PRESSED, + theme_->BUTTON_SHADOW_BORDER_PRESSED, + theme_->BUTTON_SHINE_FIGURE_PRESSED, + theme_->BUTTON_SHADOW_FIGURE_PRESSED); + } + + } + + // close button + label_->setX(label_->x() + monitor_->buttonWidth()); + if (buttonState_ != CLOSE) { + + Draw::drawCloseButton(frameWindow_, gc_, label_, + theme_->BUTTON_BACKGROUND_NORMAL, + theme_->BUTTON_SHINE_BORDER_NORMAL, + theme_->BUTTON_SHADOW_BORDER_NORMAL, + theme_->BUTTON_SHINE_FIGURE_NORMAL, + theme_->BUTTON_SHADOW_FIGURE_NORMAL); + } + else { + + Draw::drawCloseButton(frameWindow_, gc_, label_, + theme_->BUTTON_BACKGROUND_PRESSED, + theme_->BUTTON_SHINE_BORDER_PRESSED, + theme_->BUTTON_SHADOW_BORDER_PRESSED, + theme_->BUTTON_SHINE_FIGURE_PRESSED, + theme_->BUTTON_SHADOW_FIGURE_PRESSED); + + } + } +} + +void Thing::handleMotionNotify(XMotionEvent *event) { + + if (monitor()->isThingMaximized()) { + return; + } + + Cursor cursor = cursorForXY(event->x, event->y); + + if (cursor != cursor_) { + cursor_ = cursor; + KERNEL->installCursor(cursor, frameWindow_); + } + + if (buttonState_ != NONE) { + buttonState_ = NONE; + illuminate(); + } +} + +void Thing::setTitleBarHeight(unsigned int titleBarHeight) { + titleBarHeight_ = titleBarHeight; +} + +void Thing::setBorderWidth(unsigned int borderWidth) { + borderWidth_ = borderWidth; +} + +unsigned int Thing::borderWidth() const { + return borderWidth_; +} + +unsigned int Thing::titleBarHeight() const { + return titleBarHeight_; +} + +Rectangle *Thing::prevRectangle() const { + return prevRect_; +} + +Thing::InvertButton Thing::buttonState() const { + return buttonState_; +} + +void Thing::setButtonState(InvertButton state) { + buttonState_ = state; +} + +void Thing::show() { + if (frameWindow_) { + XCORE->show(frameWindow_); + isVisible_ = true; + } +} + +void Thing::hide() { + if (frameWindow_) { + XCORE->hide(frameWindow_); + isVisible_ = false; + } +} + +void Thing::fitClientArea() { + + clientAreaRect_.setX(borderWidth_); + clientAreaRect_.setY(titleBarHeight_ + borderWidth_ + + (titleBarHeight_ ? 1 : 0)); + clientAreaRect_.setWidth(width() - 2 * borderWidth_); + clientAreaRect_.setHeight(height() - titleBarHeight_ + - 2 * borderWidth_ + - (titleBarHeight_ ? 1 : 0)); +} + +void Thing::setName(string name) { + name_ = name; +} + +string Thing::name() const { + return name_; +} + +bool Thing::hasDecoration() const { + return hasDecoration_; +} diff --git a/thing.h b/thing.h @@ -0,0 +1,125 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: thing.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __THING_H +#define __THING_H + +extern "C" { +#include <X11/Xlib.h> +#include <X11/Xutil.h> +} + +#include <string> + +#include "rectangle.h" +#include "wmi.h" + +class Label; +class Monitor; +class Frame; +class Group; +class Theme; +class Workspace; + +/** + * Base class of frames and clients which provides the base + * functionality for both. + */ +class Thing : public Rectangle { + +public: + + //////////////////////////////////////////////////////////// + // model + + enum Type {CLIENT, FRAME}; + + Thing(Monitor *monitor, Rectangle *rect, Type type_); + + virtual ~Thing(); + + void initFrameWindow(); + + Type type() const; + + Monitor *monitor() const; + + bool isVisible() const; + + //////////////////////////////////////////////////////////// + // view + + enum InvertButton {NONE, MINCLIENT, DEMAX, CLOSE}; + + void setTitleBarHeight(unsigned int titleBarHeight); + + unsigned int titleBarHeight() const; + + void setBorderWidth(unsigned int borderWidth); + + unsigned int borderWidth() const; + + Rectangle *prevRectangle() const; + + InvertButton buttonState() const; + + void setButtonState(InvertButton state); + + void handleMotionNotify(XMotionEvent *event); + + virtual Window window() = 0; + virtual void illuminate() = 0; + virtual void resize() = 0; + virtual bool isFocused() = 0; + virtual void handleButtonPress(XButtonEvent *event) = 0; + virtual void handleButtonRelease(XButtonEvent *event) = 0; + virtual Cursor cursorForXY(int pointerX, int pointerY) = 0; + + virtual void show(); + virtual void hide(); + + void setName(string name); + string name() const; + bool hasDecoration() const; + +protected: + + void fitClientArea(); + + // model + bool isVisible_; + string name_; + + // view + void illuminateBorder(); + + Rectangle clientAreaRect_; + Theme *theme_; + Label *label_; + GC gc_; + unsigned int titleBarHeight_; + unsigned int borderWidth_; + bool areButtonsVisible_; + + Cursor cursor_; + + InvertButton buttonState_; + + // model + Window frameWindow_; + bool hasDecoration_; + +private: + + // view + void initGC(); + + Monitor *monitor_; + Type type_; + + Rectangle *prevRect_; +}; + +#endif // __THING_H diff --git a/tree.cpp b/tree.cpp @@ -0,0 +1,73 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: tree.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include "tree.h" + +#include "frame.h" + +Tree::Tree(Tree *parent, Rectangle *rect) + : Rectangle(*rect) +{ + parent_ = parent; + frame_ = 0; + first_ = last_ = 0; + visits_ = 0; +} + +Tree::~Tree() { +} + +Tree *Tree::parent() const { + return parent_; +} + +void Tree::setParent(Tree *tree) { + parent_ = tree; +} + +void Tree::setFrame(Frame *frame) { + frame_ = frame; + if (frame_) { + frame_->setTree(this); + frame_->copy(this); + } +} + +Frame *Tree::frame() const { + return frame_; +} + +Tree *Tree::first() const { + return first_; +} + +Tree *Tree::last() const { + return last_; +} + +void Tree::setChilds(Tree *first, Tree *last) { + first_ = first; + last_ = last; + if (first_ && last_) { + first_->setParent(this); + last_->setParent(this); + } +} + +void Tree::setHoriz(bool horiz) { + isHoriz_ = horiz; +} + +bool Tree::isHoriz() const { + return isHoriz_; +} + +unsigned int Tree::visits() const { + return visits_; +} + +void Tree::setVisit(unsigned int visit) { + visits_ = visit; +} diff --git a/tree.h b/tree.h @@ -0,0 +1,52 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: tree.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __TREE_H +#define __TREE_H + +#include "rectangle.h" + +class Frame; +class Tree; + +/** Dual-Quad tree with some special WMI related functionality. */ +class Tree : public Rectangle { + +public: + + Tree(Tree *parent, Rectangle *rect); + + ~Tree(); + + Tree *parent() const; + + void setParent(Tree *tree); + + void setFrame(Frame *frame); + + Frame *frame() const; + + Tree *first() const; + Tree *last() const; + + void setChilds(Tree *first, Tree *last); + + void setHoriz(bool horiz); + bool isHoriz() const; + + unsigned int visits() const; + void setVisit(unsigned int visit); + +private: + + Tree *first_; + Tree *last_; + Tree *parent_; + Frame *frame_; + bool isHoriz_; + unsigned int visits_; +}; + +#endif // __TREE_H diff --git a/util.cpp b/util.cpp @@ -0,0 +1,496 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: util.cpp 734 2004-09-27 18:15:45Z garbeam $ + +extern "C" { +#include <unistd.h> +#include <stdlib.h> +#include <X11/Xlib.h> +} + +#include <sstream> +#include <iostream> + +#include "util.h" + +#include "action.h" + +#include "rectangle.h" + +Util::Util() { +} + +Util::~Util() { +} + +string Util::lowerCase(string str) { + string input = str; + + for (string::iterator it = input.begin(); it != input.end(); it++) { + *it = tolower(*it); + } + + return input; +} + +bool Util::containsWhitespaces(string str) { + + for (string::iterator it = str.begin(); it != str.end(); it++) { + if (*it == ' ' || *it == '\t') { + return true; + } + } + + return false; +} + +string Util::truncate(string str, char c) { + + string result = ""; + + for (string::iterator it = str.begin(); it != str.end(); it++) { + if ((*it != c) && (*it != '\t')) { + result += *it; + } + } + + return result; +} + +string Util::canonicalDir(string path) { + string dir = canonicalPath(path); + unsigned int pos = 0; + + pos = dir.find_last_of('/'); + if (pos != string::npos) { + dir = dir.substr(0, pos); + } + + return dir; +} + +string Util::canonicalPath(string file) { + + string result = ""; + for (string::iterator it = file.begin(); it != file.end(); it++) { + + if (*it == '~') { // found HOME + char *home = getenv("HOME"); + // Note: if home would be 0, WMI won't have started + // but who knows what boxes there're around :) + if (home == 0) { + cerr << "wmi[E " << timestamp() << "]: " + << "Util::canonicalPath() cannot determine your " + << "$HOME directory, giving up"; + exit(1); + } + + result += home; + } + else { + result += *it; + } + } + return result; +} + +string Util::encodeEscapes(string str) { + string encoded = ""; + + for (string::iterator it = str.begin(); it != str.end(); it++) { + switch (*it) { + case '\\': + encoded += "\\\\"; + break; + case '#': + encoded += "\\#"; + break; + case '"': + encoded += "\\\""; + break; + case '=': + encoded += "\\="; + break; + default: + encoded += *it; + break; + } + } + + return encoded; +} + +string Util::lastToken(string str, char delim) { + + string result = ""; + unsigned int pos = str.find_last_of(delim); + + if (pos != string::npos) { + result = str.substr(pos + 1, str.length() - pos); + } + + return result; +} + +string Util::nthToken(string str, char delim, unsigned int n) { + + unsigned int delimCounter = 1; + string token = ""; + + for (string::iterator it = str.begin(); it != str.end(); it++) { + + if (*it == delim) { + delimCounter++; + continue; + } + + + if (delimCounter == n) { + token += *it; + } + else if (delimCounter > n) { + return token; // token ready + } + } + + return token; +} + +char **Util::arguments(string command) { + + string arg = ""; + list<const char *> args; + + bool proceed = true; + for (string::iterator it = command.begin(); proceed; it++) { + + proceed = it != command.end(); + if (!proceed || (*it == ' ') || (*it == '\t')) + { + if (arg.length() > 0) { + args.push_back((new string(arg))->c_str()); + } + arg = ""; + } + else { + arg += *it; + } + } + + const char **result = new const char *[args.size() + 1]; + unsigned int i = 0; + for (list<const char *>::iterator it = args.begin(); + it != args.end(); it++, i++) + { + result[i] = *it; + } + result[i] = 0; + + return (char **)result; +} + +unsigned int Util::numDigits(unsigned int number) +{ + unsigned int n = 0; + do { + ++n; number /= 10; + } while (number); + + return n; +} + +string Util::timestamp() { + static time_t utctime; + static struct tm *todaylocal; + static char timestamp[16]; + time(&utctime); + todaylocal = localtime(&utctime); + strftime(timestamp, 16,"%Y%m%d%H%M%S", todaylocal); + + return (string)timestamp; +} + +string Util::stringForButton(unsigned int button) { + ostringstream oss; + + oss << "Button" << button; + return oss.str(); +} + +unsigned int Util::buttonForString(string button) { + + if (button.find("Button1") != string::npos) { + return Button1; + } + else if (button.find("Button2") != string::npos) { + return Button2; + } + else if (button.find("Button3") != string::npos) { + return Button3; + } + else if (button.find("Button4") != string::npos) { + return Button4; + } + else if (button.find("Button5") != string::npos) { + return Button5; + } + + return 0; +} + +string Util::stringForModMask(unsigned long modMask) { + + string result = ""; + if (modMask & ShiftMask) { + result += "shift + "; + } + if (modMask & LockMask) { + result += "lock + "; + } + if (modMask & ControlMask) { + result += "ctrl + "; + } + if (modMask & Mod1Mask) { + result += "mod1 + "; + } + if (modMask & Mod2Mask) { + result += "mod2 + "; + } + if (modMask & Mod3Mask) { + result += "mod3 + "; + } + if (modMask & Mod4Mask) { + result += "mod4 + "; + } + if (modMask & Mod5Mask) { + result += "mod5 + "; + } + if (!modMask) { + result += "none + "; + } + return result; +} + +unsigned long Util::modMaskForString(string modKeys) +{ + unsigned long modMask = 0; + if (modKeys.find("shift") != string::npos) { + modMask |= ShiftMask; + } + if (modKeys.find("lock") != string::npos) { + modMask |= LockMask; + } + if ((modKeys.find("control") != string::npos) || + (modKeys.find("ctrl") != string::npos)) { + modMask |= ControlMask; + } + if ((modKeys.find("alt") != string::npos) || + (modKeys.find("mod1") != string::npos)) { + modMask |= Mod1Mask; + } + if (modKeys.find("mod2") != string::npos) { + modMask |= Mod2Mask; + } + if (modKeys.find("mod3") != string::npos) { + modMask |= Mod3Mask; + } + if (modKeys.find("mod4") != string::npos) { + modMask |= Mod4Mask; + } + if (modKeys.find("mod5") != string::npos) { + modMask |= Mod5Mask; + } + return modMask; +} + +unsigned int Util::strToUInt(string str) { + + return atoi(str.c_str()); +} + +void Util::fitIntoDirection(int horigin, int hw, int *corigin, int *cw) +{ + int horigin1 = horigin; + int horigin2 = horigin + hw; + int corigin1 = *corigin; + int corigin2 = *corigin + *cw; + + if ((corigin1 < horigin1) && (corigin2 <= horigin2)) { + *corigin = horigin; + if (*corigin + *cw > horigin2) { + *cw = hw; + } + } + else if ((corigin1 < horigin1) && (corigin2 > horigin2)) { + *corigin = horigin; + *cw = hw; + } + else if ((corigin1 >= horigin1) && (corigin2 > horigin2)) { + *cw = horigin2 - *corigin; + } +} + + +void Util::fitInto(Rectangle *client, Rectangle *host) { + + int cx = client->x(); + int cw = client->width(); + + fitIntoDirection(host->x(), host->width(), &cx, &cw); + client->setX(cx); + client->setWidth(cw); + + int cy = client->y(); + int ch = client->height(); + + fitIntoDirection(host->y(), host->height(), &cy, &ch); + client->setY(cy); + client->setHeight(ch); +} + +Direction Util::dirForString(string str) { + + string dirStr; + + dirStr = lowerCase(str); + + if (dirStr == "left") { + return LEFT; + } + else if (dirStr == "right") { + return RIGHT; + } + else if (dirStr == "up") { + return UP; + } + else { + return DOWN; + } +} + +bool Util::exists(const char *path) { + + return access(path, F_OK) == 0; +} + +string Util::shortenString(string str, unsigned int n) { + + return str.substr(0, n) + "..."; +} + + +set<string> Util::stringSplit(string s, string delimiter){ + set<string> res; + unsigned int pos = 0; + while (pos != string::npos){ + pos = s.find_first_of(delimiter); + res.insert(s.substr(0, pos)); + s.erase(0, pos + 1); + } + return(res); +} + +string Util::trimL(string s){ + return s.substr(s.find_first_not_of(' ')); +} + + +bool Util::isPointWithinRect(unsigned int x, unsigned int y, Rectangle *rect, + Rectangle *offset) +{ + unsigned int offsetX = rect->x(); + unsigned int offsetY = rect->y(); + if (offset) { + offsetX += offset->x(); + offsetY += offset->y(); + } + + return ((offsetX <= x) && (offsetY <= y) && + (offsetX + rect->width() >= x) && + (offsetY + rect->height() >= y)); +} + + +void Util::swapChars(string *str, char from, char to, + unsigned int *swapCount) +{ + for (string::iterator it = str->begin(); it != str->end(); it++) { + if (*it == from) { + *it = to; + if (swapCount) { + (*swapCount)++; + } + } + } +} + +Direction Util::reverseDir(Direction dir) { + switch (dir) { + case LEFT: + return RIGHT; + break; + case RIGHT: + return LEFT; + break; + case UP: + return DOWN; + break; + case DOWN: + return UP; + break; + case NORTH_WEST: + return SOUTH_EAST; + break; + case NORTH_EAST: + return SOUTH_WEST; + break; + case SOUTH_WEST: + return NORTH_EAST; + break; + case SOUTH_EAST: + return NORTH_WEST; + break; + } + return LEFT; +} + +string Util::get(MSettings *settings, string key) { + MSettings::iterator it = settings->find(key); + return (it != settings->end()) ? (*it).second : ""; +} + +void Util::remove(MSettings *settings, string prefix) { + + unsigned int length = prefix.length(); + for (MSettings::iterator it = settings->begin(); + it != settings->end(); it++) + { + string key = (*it).first; + if (key.length() >= length) { + if (key.substr(0, length) == prefix) { + settings->erase(it); + } + } + } +} + +Action *Util::get(MBindings *bindings, string key) { + MBindings::iterator it = bindings->find(key); + return (it != bindings->end()) ? (*it).second : 0; +} + +void Util::remove(MBindings *bindings, string prefix) { + + unsigned int length = prefix.length(); + for (MBindings::iterator it = bindings->begin(); + it != bindings->end(); it++) + { + string key = (*it).first; + if (key.length() >= length) { + if (key.substr(0, length) == prefix) { + bindings->erase(it); + } + } + } +} diff --git a/util.h b/util.h @@ -0,0 +1,144 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: util.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __UTIL_H +#define __UTIL_H + +extern "C" { +#include <X11/keysym.h> +#include <X11/Xlib.h> +#include <sys/stat.h> +} + +#include <list> +#include <string> +#include <set> +#include <map> + +#include "wmi.h" + +class Action; +class Rectangle; + +typedef map<string, string, less<string> > MSettings; +typedef map<string, Action *, less<string> > MBindings; + +/** + * Contains various helper methods which are missing in STL library. + */ +class Util +{ + +public: + + Util(); + + ~Util(); + + /** Returns n'th Token (substring) of str, delimeted by delim. */ + static string nthToken(string str, char delim, unsigned int n); + + /** Returns last token of str, delimeted by delim. */ + static string lastToken(string str, char delim); + + static string lowerCase(string str); + + /** Returns the canonical path of the given file string. */ + static string canonicalPath(string file); + + /** Returns all dir components of the given path as new string. */ + static string canonicalDir(string path); + + static bool containsWhitespaces(string str); + + /** Returns truncated string without characters given by c or \t. */ + static string truncate(string str, char c); + + /** Returns string with swapped characters (from -> to). */ + static void swapChars(string *str, char from, char to, + unsigned int *swapCount = 0); + + + /** Shortens this string to n characters plus "..." */ + static string shortenString(string str, unsigned int n); + + static string encodeEscapes(string str); + + static unsigned int numDigits(unsigned int number); + + static unsigned long modMaskForString(string modKeys); + static string stringForModMask(unsigned long modMask); + + static string stringForButton(unsigned int button); + static unsigned int buttonForString(string button); + + /** Converts string into char * argument array. */ + static char **arguments(string command); + + /** Returns timestamp of current system time. */ + static string timestamp(); + + static unsigned int strToUInt(string str); + + /** Fits client rectangle into host rectangle. */ + static void fitInto(Rectangle *client, Rectangle *host); + + /** Rectangle <code>true</code> if the coord is within the rectangle. */ + static bool isPointWithinRect(unsigned int x, unsigned int y, Rectangle *rect, + Rectangle *offset = 0); + + /** Returns direction for the given string. */ + static Direction dirForString(string str); + + static bool exists(const char *path); + + static set<string> stringSplit(string s, string delimiter); + + /** removes leading blanks */ + static string trimL(string s); + + static Direction reverseDir(Direction dir); + + /** + * Deletes all elements of a list L, between iterator start and end + * with type T. + */ + template <class L, class LTI, class T> + static void destroy(L *l, LTI start, LTI end) { + for (LTI it = start; it != end; it++) { + T t = (T)*it; + delete t; + } + + l->erase(start, end); + } + + /** + * Returns <code>true</code> if the item is contained in this list. + */ + template <class L, class LTI, class T> + static bool contains(L *l, T *item) { + for (LTI it = l->begin(); it != l->end(); it++) { + if (item == *it) { + return true; + } + } + return false; + } + + static string get(MSettings *settings, string key); + static void remove(MSettings *settings, string prefix); + + static Action *get(MBindings *bindings, string key); + static void remove(MBindings *bindings, string prefix); + +private: + + /** Fits 1-dimensional c-coordinates directional into h-coordinates. */ + static void fitIntoDirection(int horigin, int hw, int *corigin, int *cw); + +}; + +#endif // __UTIL_H diff --git a/validators.cpp b/validators.cpp @@ -0,0 +1,377 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: validators.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include "validators.h" + +#include <map> + +#include "action.h" +#include "client.h" +#include "frame.h" +#include "kernel.h" +#include "inputbar.h" +#include "monitor.h" +#include "slot.h" +#include "statusbar.h" +#include "thing.h" +#include "workspace.h" + +Validators::Validators() { +} + +Validators::~Validators() { +} + +bool Validators::validateSelectClient() { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + + for (LWorkspace::iterator wit = focusedMonitor->begin(); + wit != focusedMonitor->end(); wit++) + { + Workspace *workspace = *wit; + + if (workspace->floatingClients()->size() || + (workspace->focusedFrame() && + workspace->focusedFrame()->size())) + { + return true; + } + + } + + return false; +} + +bool Validators::validateCycleFrame() { + + return existFrames() && isFrameFocused(); + +} + +bool Validators::validateInputMode() { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + return !focusedMonitor->inputBar()->isVisible(); +} + + +bool Validators::isAlwaysPossible() { + + return true; +} + +bool Validators::isWorkspaceFocused() { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + + return focusedMonitor->focused() != 0; +} + +bool Validators::existMonitors() { + return KERNEL->monitors()->size() > 1; +} + +bool Validators::existWorkspaces() { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + + return focusedMonitor->size() > 1; +} + +bool Validators::isEmptyWorkspaceFocused() { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + + if (workspace->floatingClients()->size() || + (workspace->focusedFrame() && + workspace->focusedFrame()->size())) + { + return false; + } + return true; +} + +bool Validators::validateDestroyAction() { + + MBindings *bindings = KERNEL->actionBindings(); + for (MBindings::iterator it = bindings->begin(); + it != bindings->end(); it++) + { + Action *action = (*it).second; + if (action->type() != Action::INTERN) { + return true; + } + } + return false; +} + +bool Validators::validateDestroyWorkspace() { + + return isEmptyWorkspaceFocused() && existWorkspaces(); +} + +bool Validators::existsFrameLeft() { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + + return workspace->neighborTree(LEFT) != 0; +} + +bool Validators::existsFrameRight() { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + + return workspace->neighborTree(RIGHT) != 0; +} + +bool Validators::existsFrameUp() { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + + return workspace->neighborTree(UP) != 0; +} + +bool Validators::existsFrameDown() { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + + return workspace->neighborTree(DOWN) != 0; +} + +bool Validators::validateToggleMode() { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + + if (workspace->isFrameMode()) { + return workspace->floatingClients()->size(); + } + else { + return workspace->frames()->size(); + } +} + +bool Validators::existFrames() { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + + if (workspace) { + return workspace->frames()->size(); + } + + return false; +} + +bool Validators::validateResizeLeft() { + + return isClientFrameFocused() || existsFrameLeft(); +} + +bool Validators::validateResizeRight() { + + return isClientFrameFocused() || existsFrameRight(); +} + +bool Validators::validateResizeUp() { + + return isClientFrameFocused() || existsFrameUp(); +} + +bool Validators::validateResizeDown() { + + return isClientFrameFocused() || existsFrameDown(); +} + +bool Validators::isFrameOrClientFrameFocused() { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + + if (workspace) { + Thing *thing = workspace->focusedThing(); + + if (!thing) { + return false; + } + + return thing->hasDecoration(); + } + return false; + +} + + +bool Validators::isFrameFocused() { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + + if (workspace) { + return workspace->focusedFrame() && workspace->isFrameMode(); + } + return false; +} + + +bool Validators::isClientFrameFocused() { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + + if (!workspace) { + return false; + } + + Client *client = workspace->topClient(); + + if (!client) { + return false; + } + + return !client->frame(); +} + +bool Validators::isFloatingClientFocused() { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + + if (workspace) { + Thing *thing = workspace->focusedThing(); + + if (!thing) { + return false; + } + + return thing->type() != Thing::FRAME; + } + + return false; +} + +bool Validators::isClientFocused() { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + + return workspace->focusedThing() != 0; + +} + +bool Validators::existClientsWithinFrame() { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + + if (workspace) { + Thing *thing = workspace->focusedThing(); + if (thing && (thing->type() == Thing::FRAME)) { + Frame *frame = (Frame *)thing; + return frame->size() > 1; + } + } + + return false; +} + +bool Validators::existClients() { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + + if (workspace->isFrameMode()) { + Frame *frame = workspace->focusedFrame(); + return frame && (frame->size() > 1); + } + else { + return (workspace->floatingClients()->size() > 1); + } +} + +bool Validators::existDetachedClients() { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + + return isWorkspaceFocused() && + (focusedMonitor->detachedClients()->size() > 1); +} + +bool Validators::existsDetachedClient() { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + + return isWorkspaceFocused() && + (focusedMonitor->detachedClients()->size() > 0); +} + +bool Validators::validateCancelRecord() { + return KERNEL->isRecording(); +} + +bool Validators::validateEndRecord() { + return KERNEL->isRecording() && (KERNEL->recordedActions()->size() > 0); +} + +bool Validators::validateBeginRecord() { + return !KERNEL->isRecording(); +} + +#ifdef SLOT_SUPPORT +bool Validators::existsSlotClient() { + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + return focusedMonitor->slot()->focused()->focused() != 0; +} + +bool Validators::existSlotTabs() { + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + return focusedMonitor->slot()->size() > 0; +} +#endif // SLOT_SUPPORT + +bool Validators::validateHookClient() { + +#ifdef SLOT_SUPPORT + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Slot *slot = focusedMonitor->slot(); + Client *client = slot->focused()->focused(); + if (client && slot->isGrabFocus()) { + return true; + } +#endif // SLOT_SUPPORT + return isClientFocused(); +} + +bool Validators::validateUnhookClient() { + + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Client *client = 0; +#ifdef SLOT_SUPPORT + Slot *slot = focusedMonitor->slot(); + client = slot->focused()->focused(); + if (client && (client->hooked() == "") + && slot->isGrabFocus()) + { + return true; + } +#endif // SLOT_SUPPORT + Workspace *workspace = focusedMonitor->focused(); + client = workspace->topClient(); + return client && (client->hooked() == ""); +} + +bool Validators::validateDestroyFrame() { + Monitor *focusedMonitor = KERNEL->focusedMonitor(); + Workspace *workspace = focusedMonitor->focused(); + Frame *frame = workspace->focusedFrame(); + + return frame && !frame->size(); +} diff --git a/validators.h b/validators.h @@ -0,0 +1,127 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: validators.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __VALIDATORS_H +#define __VALIDATORS_H + +#include "wmi.h" + +#include "singleton.h" + +class Kernel; +class Monitor; + +class Validators; + +/** Note: existance checks are qualified only on focused stuff. */ +class Validators : public Singleton<Validators> +{ + +public: + + Validators(); + ~Validators(); + + // validation methods + bool isAlwaysPossible(); + + /** + * Return <code>true</code> if a client can be unhooked. + */ + bool validateUnhookClient(); + + /** + * Return <code>true</code> if a client can be unhooked. + */ + bool validateHookClient(); + + /** + * Returns <code>true</code> if a frame is focussed and there're + * more frames. + */ + bool validateCycleFrame(); + + /** Returns <code>true</code> if the wmi kernel has recorded actions. */ + bool validateEndRecord(); + + /** Returns <code>true</code> if the wmi is recording actions. */ + bool validateCancelRecord(); + + /** Returns <code>true</code> if the wmi kernel is not recording actions. */ + bool validateBeginRecord(); + + /** Returns <code>true</code> if a workspace exists. */ + bool isWorkspaceFocused(); + + /** Returns <code>true</code> if at least two workspaces exist. */ + bool existMonitors(); + + /** Returns <code>true</code> if at least two workspaces exist. */ + bool existWorkspaces(); + + bool isEmptyWorkspaceFocused(); + bool validateDestroyWorkspace(); + bool validateDestroyFrame(); + + bool validateDestroyAction(); + + /** Validates directional grow/shrink actions. */ + bool validateResizeLeft(); + bool validateResizeRight(); + bool validateResizeUp(); + bool validateResizeDown(); + + /** Returns <code>true</code> if a frame into direction exist. */ + bool existsFrameLeft(); + bool existsFrameRight(); + bool existsFrameUp(); + bool existsFrameDown(); + + /** Returns <code>true</code> if a frame is focused. */ + bool isFrameFocused(); + + /** Returns <code>true</code> if a frame or client exist. */ + bool isFrameOrClientFrameFocused(); + + /** Returns <code>true</code> if at least two frames exist. */ + bool existFrames(); + + /** Returns <code>true</code> if toggleMode is valid. */ + bool validateToggleMode(); + + /** Returns <code>true</code> if a client frame exists. */ + bool isClientFrameFocused(); + + /** Returns <code>true</code> if a client exists. */ + bool isClientFocused(); + + /** Returns <code>true</code> if a floating client exists. */ + bool isFloatingClientFocused(); + + /** Returns <code>true</code> if at least two clients exists. */ + bool existClients(); + + /** Returns <code>true</code> if at least two clients exists. */ + bool existClientsWithinFrame(); + + bool existsDetachedClient(); + bool existDetachedClients(); + + /** Returns <code>true</code> if input mode is not active. */ + bool validateInputMode(); + + /** + * Returns <code>true</code> if any client exists on the + * focused monitor. + */ + bool validateSelectClient(); +#ifdef SLOT_SUPPORT + bool existsSlotClient(); + bool existSlotTabs(); +#endif // SLOT_SUPPORT + +}; + +#endif // __VALIDATORS_H diff --git a/version.h.in b/version.h.in @@ -0,0 +1 @@ +#define __WMI_VERSION "@VERSION@" diff --git a/widget.cpp b/widget.cpp @@ -0,0 +1,98 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: widget.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include "widget.h" + +#include "cursors.h" +#include "kernel.h" +#include "monitor.h" +#include "xcore.h" +#include "xfont.h" + +Widget::Widget(Monitor *monitor, Rectangle *rect, bool initWindowAndGC) + : Rectangle(*rect) +{ + monitor_ = monitor; + isVisible_ = false; + if (initWindowAndGC) { + initWindow(); + initGC(); + } + else { + window_ = 0; + gc_ = 0; + } +} + +Widget::~Widget() { + XCORE->free(gc_); + XCORE->destroy(window_); +} + +Monitor *Widget::monitor() const { + return monitor_; +} + +Window Widget::window() const { + return window_; +} + +GC Widget::gc() const { + return gc_; +} + +void Widget::show() { + isVisible_ = true; + XCORE->showRaised(window_); +} + +void Widget::hide() { + isVisible_ = false; + XCORE->hide(window_); +} + +bool Widget::isVisible() const { + return isVisible_; +} + +void Widget::initWindow() { + Kernel *kernel = KERNEL; + + XSetWindowAttributes attr; + attr.override_redirect = 1; + attr.background_pixmap = ParentRelative; + + window_ = XCORE->createWindow(monitor_->rootWindow(), &attr, + x(), y(), width(), height(), + CWOverrideRedirect | CWBackPixmap); + XCORE->selectEvents(window_, + ExposureMask | ButtonPressMask | ButtonReleaseMask | + PointerMotionMask | SubstructureRedirectMask | + SubstructureNotifyMask); + + kernel->installCursor(Cursors::NORMAL_CURSOR, window_); +} + +void Widget::initGC() { + unsigned long mask = 0; + XGCValues gcv; + + mask = GCForeground | GCBackground | + GCFunction | GCLineWidth | GCLineStyle; + + gcv.function = GXcopy; + gcv.line_width = 1; + gcv.line_style = LineSolid; + if (monitor_->font()->type() == WFont::NORMAL) { + gcv.font = ((XFont *)monitor_->font())->font()->fid; + mask |= GCFont; + } + + gc_ = XCORE->createGC(window_, mask, &gcv); +} + +void Widget::resize() { + XCORE->moveResize(window_, this); +} diff --git a/widget.h b/widget.h @@ -0,0 +1,50 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: widget.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __WIDGET_H +#define __WIDGET_H + +extern "C" { +#include <X11/Xlib.h> +} + +#include "rectangle.h" + +class Monitor; + +/** Base class for widgets, such as menu, bar, slot, thing. */ +class Widget : public Rectangle { + +public: + + Widget(Monitor *monitor, Rectangle *rect, + bool initWindowAndGC = true); + virtual ~Widget(); + + Monitor *monitor() const; + GC gc() const; + + Window window() const; + + virtual void resize(); + virtual void show(); + virtual void hide(); + + bool isVisible() const; + +protected: + bool isVisible_; + +private: + + void initWindow(); + void initGC(); + + GC gc_; + Monitor *monitor_; + Window window_; +}; + +#endif // __WIDGET_H diff --git a/wmi.h b/wmi.h @@ -0,0 +1,44 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: wmi.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __WMI_H +#define __WMI_H + +#include "../config.h" + +#define LOGERROR(X, Y) Logger::instance()->error(X, Y) +#define LOGWARN(X) Logger::instance()->warning(X) +#define CONFPATH "/etc/wmi" +#define KERNEL Kernel::instance() +#define XCORE XCore::instance() + +#ifdef DEBUG +#define LOGDEBUG(X) Logger::instance()->debug(X) +#else +#define LOGDEBUG(X) +#endif + +enum Direction {LEFT, RIGHT, UP, DOWN, NORTH_WEST, + NORTH_EAST, SOUTH_WEST, SOUTH_EAST}; + +// we use only std namespace +using namespace std; + +// Motif bits - see Motif reference manual for further information. +#define MWM_HINTS_FUNCTIONS (1L << 0) +#define MWM_HINTS_DECORATIONS (1L << 1) +#define MWM_HINTS_INPUT_MODE (1L << 2) +#define MWM_HINTS_STATUS (1L << 3) + +#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 MINIMAL_BARHEIGHT 13 +#endif // __WMI_H diff --git a/wmi.spec b/wmi.spec @@ -0,0 +1,122 @@ +######################################################################## +# +# How to build RPM packages using this wmi.spec: +# +# a) Make sure you are *NOT* root. +# b) "make dist" +# c) "rpmbuild -ta wmi-$(VERSION).tar.gz" +# +# Your RPM build directory must already been set up for your non-root +# user, though: +# +# r=$HOME/src/rpmbuild +# mkdir -p $r/BUILD $r/RPMS/i386 $r/SOURCES $r/SPECS $r/SRPMS $r/tmp +# echo -e "%_topdir $r\n%_tmppath %{_topdir}/tmp" >> ~/.rpmmacros +# +# You should also add something like +# +# %packager Your Name <my@mail> +# %vendor Your Name's RPM packages +# +# to ~/.rpmmacros so you can easily see where the generated package +# comes from. +# +######################################################################## + + +Summary: Window Manager Improved, a X11 window manager for hackers +Name: wmi +Version: 10 +License: MIT +Release: 2 +Group: User Interface/Desktops +URL: http://wmi.berlios.de/ +Source: wmi-10.tar.gz +BuildRoot: %{_tmppath}/root-%{name}-%{version} + +# Build dependencies are missing on purpose. This spec file is +# intended to build RPM packages from source, regardless of the +# distribution. Therefore, you should be able to build it without RPM +# anyway. +# +# Distributions should roll their own spec file. +# +# Of course, if you know how to write spec files compatible across +# distributions, you're welcome to do so and remove this paragraph. + + +%description +WMI is a new lightweight window manager for X11, which attempts to +combine the best features of LarsWM, Ion, evilwm and ratpoison into +one window manager. + + +%prep +%setup -n wmi-10 + + +%build +%configure +%{__make} %{?_smp_mflags} + +# Generate scripts to hook up WMI into gdm, xdm, and Co. +# +# Note: If you want to have these in non-RPM settings, you'll have to +# create them in some Makefile. I suggest creating a +# "packaging/" subdirectory and let its Makefile.am handle that. + +echo -e "#!/bin/sh\nexec /etc/X11/xdm/Xsession wmi" > hook-gdm + +echo -e "#!/bin/sh\nexec %{_bindir}/wmi" > hook-switchdesk + +echo -e "[Desktop Entry]\nName=WMI Session\nComment=Use this session to run WMI as your desktop environment\nExec=wmi\nTryExec=wmi\nIcon=\nType=Application" > hook-xsessions + + +%install +%{__rm} -rf %{buildroot} + +# Note: the makeinstall macro doesn't use DESTDIR correctly. +%{__make} DESTDIR=%{buildroot} install + +# Install generated scripts to hook up WMI into gdm, xdm, and Co. + +install -m 0755 -d %{buildroot}/etc/X11/gdm/Sessions +install -m 0755 hook-gdm %{buildroot}/etc/X11/gdm/Sessions/wmi + +install -m 0755 -d %{buildroot}/usr/share/app/switchdesk +install -m 0755 hook-switchdesk %{buildroot}/usr/share/app/switchdesk/Xclients.wmi + +install -m 0755 -d %{buildroot}/usr/share/xsessions +install -m 0644 hook-xsessions %{buildroot}/usr/share/xsessions/wmi.desktop + + +%clean +# It's easier to debug something when we haven't deleted it yet. +##${__rm} -rf ${buildroot} + + +%files +%defattr(-, root, root, 0755) +%doc AUTHORS ChangeLog BUGS CONTRIB FAQ INSTALL LICENSE.txt NEWS README TODO +%{_bindir}/wmi +%{_bindir}/wmiremote +%{_mandir}/man1/wmi.1* +%{_mandir}/man1/wmiremote.1* +%{_mandir}/man5/actions.conf.5* +%{_mandir}/man5/common.conf.5* +%{_mandir}/man5/session.conf.5* +%{_mandir}/man5/theme.conf.5* +/etc/X11/gdm/Sessions/wmi +/usr/share/app/switchdesk/Xclients.wmi +/usr/share/xsessions/wmi.desktop + + +%changelog + +* Wed Jul 28 2004 <hun@n-dimensional.de> - 9.current-1 +- initial version + + +# Local Variables: +# mode: rpm-spec +# End: diff --git a/wmi.spec.in b/wmi.spec.in @@ -0,0 +1,122 @@ +######################################################################## +# +# How to build RPM packages using this wmi.spec: +# +# a) Make sure you are *NOT* root. +# b) "make dist" +# c) "rpmbuild -ta wmi-$(VERSION).tar.gz" +# +# Your RPM build directory must already been set up for your non-root +# user, though: +# +# r=$HOME/src/rpmbuild +# mkdir -p $r/BUILD $r/RPMS/i386 $r/SOURCES $r/SPECS $r/SRPMS $r/tmp +# echo -e "%_topdir $r\n%_tmppath %{_topdir}/tmp" >> ~/.rpmmacros +# +# You should also add something like +# +# %packager Your Name <my@mail> +# %vendor Your Name's RPM packages +# +# to ~/.rpmmacros so you can easily see where the generated package +# comes from. +# +######################################################################## + + +Summary: Window Manager Improved, a X11 window manager for hackers +Name: @RPM_NAME@ +Version: @RPM_VERSION@ +License: MIT +Release: 2 +Group: User Interface/Desktops +URL: http://wmi.berlios.de/ +Source: @TAR_NAME@-@TAR_VERSION@.tar.gz +BuildRoot: %{_tmppath}/root-%{name}-%{version} + +# Build dependencies are missing on purpose. This spec file is +# intended to build RPM packages from source, regardless of the +# distribution. Therefore, you should be able to build it without RPM +# anyway. +# +# Distributions should roll their own spec file. +# +# Of course, if you know how to write spec files compatible across +# distributions, you're welcome to do so and remove this paragraph. + + +%description +WMI is a new lightweight window manager for X11, which attempts to +combine the best features of LarsWM, Ion, evilwm and ratpoison into +one window manager. + + +%prep +%setup -n @TAR_NAME@-@TAR_VERSION@ + + +%build +%configure +%{__make} %{?_smp_mflags} + +# Generate scripts to hook up WMI into gdm, xdm, and Co. +# +# Note: If you want to have these in non-RPM settings, you'll have to +# create them in some Makefile. I suggest creating a +# "packaging/" subdirectory and let its Makefile.am handle that. + +echo -e "#!/bin/sh\nexec /etc/X11/xdm/Xsession wmi" > hook-gdm + +echo -e "#!/bin/sh\nexec %{_bindir}/wmi" > hook-switchdesk + +echo -e "[Desktop Entry]\nName=WMI Session\nComment=Use this session to run WMI as your desktop environment\nExec=wmi\nTryExec=wmi\nIcon=\nType=Application" > hook-xsessions + + +%install +%{__rm} -rf %{buildroot} + +# Note: the makeinstall macro doesn't use DESTDIR correctly. +%{__make} DESTDIR=%{buildroot} install + +# Install generated scripts to hook up WMI into gdm, xdm, and Co. + +install -m 0755 -d %{buildroot}/etc/X11/gdm/Sessions +install -m 0755 hook-gdm %{buildroot}/etc/X11/gdm/Sessions/wmi + +install -m 0755 -d %{buildroot}/usr/share/app/switchdesk +install -m 0755 hook-switchdesk %{buildroot}/usr/share/app/switchdesk/Xclients.wmi + +install -m 0755 -d %{buildroot}/usr/share/xsessions +install -m 0644 hook-xsessions %{buildroot}/usr/share/xsessions/wmi.desktop + + +%clean +# It's easier to debug something when we haven't deleted it yet. +##${__rm} -rf ${buildroot} + + +%files +%defattr(-, root, root, 0755) +%doc AUTHORS ChangeLog BUGS CONTRIB FAQ INSTALL LICENSE.txt NEWS README TODO +%{_bindir}/wmi +%{_bindir}/wmiremote +%{_mandir}/man1/wmi.1* +%{_mandir}/man1/wmiremote.1* +%{_mandir}/man5/actions.conf.5* +%{_mandir}/man5/common.conf.5* +%{_mandir}/man5/session.conf.5* +%{_mandir}/man5/theme.conf.5* +/etc/X11/gdm/Sessions/wmi +/usr/share/app/switchdesk/Xclients.wmi +/usr/share/xsessions/wmi.desktop + + +%changelog + +* Wed Jul 28 2004 <hun@n-dimensional.de> - 9.current-1 +- initial version + + +# Local Variables: +# mode: rpm-spec +# End: diff --git a/wmiremote.cpp b/wmiremote.cpp @@ -0,0 +1,162 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: wmiremote.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include "../version.h" + +extern "C" { +#include <unistd.h> // getopt stuff +#include <X11/Xatom.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +} + +#include <iostream> +#include <string> + +using namespace std; + +static void version() { + cout << "wmiremote - window manager improved - " << __WMI_VERSION + << endl << " (C)opyright 2003 - 2004 by Anselm R. Garbe" + << endl; + exit(0); +} + +static void usage() { + cout << "usage: " << endl << endl + << " wmiremote [-d <display>] [-t <text>] [-m <percentage>#<text>,...]" + << endl + << " [-a <action>[+arg1[+...]]] [-p] [-v]" + << endl << endl + << " -a invokes an WMI action remotely" << endl + << " -d specifies the display to use" << endl + << " -m sets meters info (see manual page for details)" << endl + << " -p prints current key bindings of running WMI" << endl + << " -t displays bartext in the wmi" << endl + << " -v show version info" << endl << endl; + exit(1); +} + +int main(int argc, char *argv[]) { + + string *displayName = 0; + string *msgText = 0; + string *actionCmd = 0; + string *meterText = 0; + bool prettyPrint = false; + + int c; + + // command line args + while ((c = getopt(argc, argv, "a:d:t:m:pv")) != -1) { + switch (c) { + case 'a': + actionCmd = new string(optarg); + break; + case 'd': + displayName = new string(optarg); + break; + case 't': + msgText = new string(optarg); + break; + case 'm': + meterText = new string(optarg); + break; + case 'p': + prettyPrint = true; + break; + case '?': + case 'h': + usage(); + break; + case 'v': + version(); + break; + } + } + + if (!msgText && !actionCmd && !prettyPrint && !meterText) { + usage(); + exit(1); + } + + Display *display = XOpenDisplay(displayName ? displayName->c_str() : 0); + + if (display == 0) { + if (displayName) { + cerr << "wmiremote: error, cannot open display '" << + displayName << "'" << endl; + } + else { + cerr << "wmiremote: error, cannot open display '0'" << endl; + } + exit (1); + } + + + XTextProperty property; + + if (msgText) { + Atom WMI_STATUSTEXT = XInternAtom(display, "_WMI_STATUSTEXT", False); + char *text = (char *)msgText->c_str(); + XStringListToTextProperty(&text, 1, &property); + XSetTextProperty(display, DefaultRootWindow(display), &property, WMI_STATUSTEXT); + } + + if (meterText) { + Atom WMI_METERTEXT = XInternAtom(display, "_WMI_METERTEXT", False); + char *text = (char *)meterText->c_str(); + XStringListToTextProperty(&text, 1, &property); + XSetTextProperty(display, DefaultRootWindow(display), &property, WMI_METERTEXT); + } + + if (actionCmd) { + Atom WMI_ACTIONCMD = XInternAtom(display, "_WMI_ACTIONCMD", False); + char *action = (char *)actionCmd->c_str(); + XStringListToTextProperty(&action, 1, &property); + XSetTextProperty(display, DefaultRootWindow(display), &property, WMI_ACTIONCMD); + } + + if (prettyPrint) { + Atom WMI_PRETTYPRINT_REQUEST = XInternAtom(display, + "_WMI_PRETTYPRINT_REQUEST", False); + Atom WMI_PRETTYPRINT_RESPONSE = XInternAtom(display, + "_WMI_PRETTYPRINT_RESPONSE", False); + string value = ""; + char *val = (char *)value.c_str(); + XStringListToTextProperty(&val, 1, &property); + XSetTextProperty(display, DefaultRootWindow(display), &property, + WMI_PRETTYPRINT_REQUEST); + // init's response value + XSetTextProperty(display, DefaultRootWindow(display), &property, + WMI_PRETTYPRINT_RESPONSE); + bool success; + while ((success = XGetTextProperty(display, DefaultRootWindow(display), + &property, WMI_PRETTYPRINT_RESPONSE))) + { + if (property.nitems > 0) { + value = (const char *)property.value; + if (value != "") { + cout << value; + // resets value back to empty + value = ""; + val = (char *)value.c_str(); + XStringListToTextProperty(&val, 1, &property); + XSetTextProperty(display, DefaultRootWindow(display), &property, + WMI_PRETTYPRINT_RESPONSE); + break; + } + } + usleep(500000); // 0.5 seconds + } + if (!success) { + cerr << "wmiremote: error, it seems that WMI is not running" + << endl; + exit(1); + } + } + XSync(display, False); + return 0; +} diff --git a/workspace.cpp b/workspace.cpp @@ -0,0 +1,987 @@ +// See ../LICENSE.txt for license details. +// +// $Id: workspace.cpp 739 2004-09-28 07:17:12Z garbeam $ + +extern "C" { +#include <assert.h> +#include <unistd.h> +#include <X11/Xlib.h> +} + +#include <map> +#include <sstream> + +#include "workspace.h" + +#include "binder.h" +#include "clientbar.h" +#include "float.h" +#include "frame.h" +#include "kernel.h" +#include "logger.h" +#include "kernel.h" +#include "monitor.h" +#include "slot.h" +#include "split.h" +#include "statusbar.h" +#include "thing.h" +#include "tree.h" +#include "util.h" +#include "xcore.h" + +Workspace::Workspace(Monitor *monitor, unsigned int id, Rectangle *rect) + : Rectangle(*rect), floatingClients_(monitor), frames_(monitor) +{ + id_ = id; + root_ = new Tree(0, this); + isFrameMode_ = true; + requestsFocus_ = false; + frameIds_ = 0; + monitor_ = monitor; + + ostringstream oss; + oss << monitor->prefix() << ".workspace[" << id_ << "]"; + prefix_ = oss.str().c_str(); + + isClientBarVisible_ = (Util::get(KERNEL->sessionSettings(), + prefix_ + ".clientbar") == "yes"); + isStatusBarVisible_ = (Util::get(KERNEL->sessionSettings(), + prefix_ + ".statusbar") == "yes"); +#ifdef SLOT_SUPPORT + slotTabName_ = Util::get(KERNEL->sessionSettings(), prefix_ + ".slot"); +#endif // SLOT_SUPPORT + + name_ = Util::get(KERNEL->sessionSettings(), prefix_ + ".name"); + + oss.str(""); + oss << "workspace my dim: " << x() << ", " << y() << ", " << width() + << ", " << height(); + LOGDEBUG(oss.str()); + XCORE->sync(); +} + +Workspace::~Workspace() { + delete root_; +} + +void Workspace::focus(Thing *thing, bool raise) { + + if (!thing) { + XCORE->setInputFocus(PointerRoot); + illuminate(); + return; + } + + Client *client = 0; + Frame *frame = 0; + if (thing->type() == Thing::CLIENT) { + client = (Client *)thing; + if (client->frame()) { + LOGDEBUG("client has frame"); + frame = client->frame(); + frame->focus(client); + } + } + else { + frame = (Frame *)thing; + } + + if (frame) { + LOGDEBUG("focussing frame"); + if (raise) { + for (LFrame::iterator it = frames_.begin(); + it != frames_.end(); it++) + { + XCORE->raise(((Frame *)*it)->window()); + } + XCORE->raise(frame->window()); + } + frames_.focus(frame); + client = frame->focused(); + } + + if (client) { + // grabbing/ungrabbing of the button + Client *tc = topClient(); + if (tc && tc != client) { + Binder::instance()->ungrabButtons(tc->clientWindow()); + Binder::instance()->grabButtons(tc->clientWindow(), AnyModifier); + } + + LOGDEBUG("focussing client"); + client->setRequestsFocus(false); +#ifdef SLOT_SUPPORT + attached()->slot()->setGrabFocus(false); +#endif + + Binder::instance()->ungrabButtons(client->clientWindow()); + + removePushClient(client); + if (!frame) { + floatingClients_.focus(client); + } + + if (raise) { + XCORE->raise(client->window()); + } +#ifdef SLOT_SUPPORT + static bool isSlotOverlap = + Util::get(KERNEL->commonSettings(), "slot.mode") == "overlap"; + if (isSlotOverlap || (isSlotVisible() + && (isFrameMode_ != (bool)frame))) { + XCORE->raise(monitor_->slot()->window()); + } +#endif // SLOT_SUPPORT + XCORE->setInputFocus(client->clientWindow()); + } + isFrameMode_ = frame; + illuminate(); +} + +void Workspace::hide() { + + for (LClient::iterator it = attached()->stickyClients()->begin(); + it != attached()->stickyClients()->end(); it++) + { + Client *client = *it; + client->setAttached(0); + floatingClients_.detach(client); + } + for (LClient::iterator it = floatingClients_.begin(); + it != floatingClients_.end(); it++) + { + (*it)->hide(); + } + + for (LFrame::iterator it = frames_.begin(); + it != frames_.end(); it++) + { + (*it)->hide(); + } +} + +void Workspace::show() { + + for (LClient::iterator it = attached()->stickyClients()->begin(); + it != attached()->stickyClients()->end(); it++) + { + Client *client = *it; + client->setAttached(this); + floatingClients_.attach(client); + } + + for (LClient::iterator it = floatingClients_.begin(); + it != floatingClients_.end(); it++) + { + (*it)->show(); + } + + for (LFrame::iterator it = frames_.begin(); + it != frames_.end(); it++) + { + (*it)->show(); + } + + focus(topClient()); + + if (isClientBarVisible_) { + attached()->clientBar()->show(); + } + else { + attached()->clientBar()->hide(); + } + if (isStatusBarVisible_) { + attached()->statusBar()->show(); + } + else { + attached()->statusBar()->hide(); + } +#ifdef SLOT_SUPPORT + Slot *slot = attached()->slot(); + if (isSlotVisible()) { + bool doManage = (slotTabName_ != slot->tabName()); + slot->show(slotTabName_); + if (doManage) { + slot->manage(); + } + } + else { + slot->hide(); + } + slotTabName_ = slot->isVisible() ? slot->tabName() : ""; +#endif // SLOT_SUPPORT +} + +void Workspace::illuminate() { + + if (attached()->focused() != this) { + return; + } + + for (LClient::iterator it = floatingClients_.begin(); + it != floatingClients_.end(); it++) + { + (*it)->illuminate(); + } + + LOGDEBUG("floating clients illuminated, going to illuminate frames"); + for (LFrame::iterator it = frames_.begin(); + it != frames_.end(); it++) + { + (*it)->illuminate(); + } + attached()->updateBars(); +} + +void Workspace::swapFrame(Direction dir) { + + Frame *frame1 = focusedFrame(); + Frame *frame2 = nextFrame(dir); + if (!frame1 || !frame2) { + return; + } + + Tree *tree1 = frame1->tree(); + Tree *tree2 = frame2->tree(); + + tree1->setFrame(frame2); + tree2->setFrame(frame1); + frame2->setTree(tree1); + frame1->setTree(tree2); + Split::adjustSize(tree1, ((dir == LEFT) || (dir == RIGHT))); + Split::adjustSize(tree2, ((dir == LEFT) || (dir == RIGHT))); +} + +void Workspace::swapClient(Direction dir) { + + Frame *frame1 = focusedFrame(); + if (!frame1) { + return; + } + + Frame *frame2 = nextFrame(dir); + + if (frame1 && frame2) { + + Client *client1 = frame1->focused(); + Client *client2 = frame2->focused(); + + frame1->detach(client1); + frame2->detach(client2); + frame2->attach(client1); + frame1->attach(client2); + frame1->illuminate(); + frame2->illuminate(); + } +} + +Tree *Workspace::neighborTree(Direction dir) { + + if (focusedFrame()) { + return Split::neighbor(root_, focusedFrame()->tree(), dir); + } + return 0; +} + +#define EPSILON 3 + +Frame *Workspace::recentVisitedFrame(Direction dir) { + + if (!focusedFrame()) { + return 0; + } + Frame *focusedFrame = this->focusedFrame(); + Tree *focusedTree = focusedFrame->tree(); + // This algorithm is somewhat magic, because it uses the + // fact of the state of the globalClientStack_. + for (LClient::iterator it = globalClientStack_.begin(); + it != globalClientStack_.end(); it++) + { + Client *client = *it; + Frame *frame = client->frame(); + if (frame && (frame != focusedFrame)) { + + Tree *tree = frame->tree(); + if (Split::isNeighbor(focusedTree, tree, dir)) { + bool isIgnore = false; + switch (dir) { + case LEFT: + isIgnore = + (int)(tree->x() + tree->width() + EPSILON) < + focusedTree->x(); + isIgnore = isIgnore || (focusedTree->y() > tree->y()) || + (focusedTree->height() < tree->height()); + break; + case RIGHT: + isIgnore = + (int)(focusedTree->x() + focusedTree->width() + + EPSILON) < tree->x(); + isIgnore = isIgnore || (focusedTree->y() > tree->y()) || + (focusedTree->height() < tree->height()); + break; + case UP: + isIgnore = + (int)(tree->y() + tree->height() + EPSILON) < + focusedTree->y(); + isIgnore = isIgnore || (focusedTree->x() > tree->x()) || + (focusedTree->width() < tree->width()); + break; + case DOWN: + isIgnore = + (int)(focusedTree->y() + focusedTree->height() + + EPSILON) < tree->y(); + isIgnore = isIgnore || (focusedTree->x() > tree->x()) || + (focusedTree->width() < tree->width()); + break; + default: + break; + } + if (!isIgnore) { + return frame; + } + } + } + } + return 0; +} + +Frame *Workspace::nextFrame(Direction dir, bool isResize) { + + Tree *neighbor = neighborTree(dir); + + if (neighbor && isResize) { // normal case + return Split::firstLeaf(neighbor); + } + else if (neighbor) { + + Frame *result = Split::firstLeaf(neighbor); + Frame *recent = recentVisitedFrame(dir); + + if (recent && recent != result && recent != focusedFrame()) { + result = recent; + } + + return result; + } + + return 0; +} + +void Workspace::selectFrame(Direction dir) { + + Frame *next = nextFrame(dir, false); + + if (next) { + focus(next->focused()); + } +} + +void Workspace::attachFrame(Frame *frame, Direction dir) { + + Tree *root = root_; + + if (focusedFrame()) { + root = focusedFrame()->tree(); + } + + Split::attach(root, frame, dir); + + frames_.attach(frame); + frame->show(); +} + +Frame *Workspace::newFrame() { + + assert((frames_.size() == 0)); + Frame *frame = new Frame(this, this); + attachFrame(frame, LEFT); // direction doesn't matter + + return frame; +} + +void Workspace::attachClient(Client *client, bool isChangeMode) { + + if (!client->frameWindow() && client->hasDecoration()) { + LOGDEBUG("creating frame window for client"); + client->createFrame(); + } + + client->setAttached(this); + if (client->mode() == Client::MAX) { + // MAX mode is only allowed with decoration + Frame *frame = 0; + if (isChangeMode) { + frame = frameForPoint( + client->x() + client->width() / 2, + client->y() + client->height() / 2); + } + else { + frame = focusedFrame(); + } + if (!frame) { + frame = newFrame(); + } + frame->attach(client); + focus(frame->focused()); + return; + } + else if (client->mode() == Client::STICKY) { + attached()->stickyClients()->attach(client); + } + + for (LClient::iterator it = floatingClients_.begin(); + it != floatingClients_.end(); it++) + { + if (*it == client) { + return; + } + } + floatingClients_.attach(client); + if (client->frameWindow()) { + client->reparent(client->frameWindow(), client->x(), client->y()); + } + XCORE->sync(); + Util::fitInto(client, attached()); + if (!isChangeMode) { + if (client->isCentered()) { + Float::center(client, this); + } + } + client->resize(); + client->show(); + focus(client); +} + +void Workspace::destroyFrame(Frame *frame) { + + unsigned int i = frame->size(); + while (i) { + Client *client = *frame->begin(); + attached()->detachClient(client); + KERNEL->killClient(client); + i--; + } + assert(frame->size() < 1); + frames_.detach(frame); + Split::detach(root_, frame->tree()); + delete frame; + LOGDEBUG("frame destroyed"); +} + +void Workspace::sendClient(Direction dir) { + + Frame *from = focusedFrame(); + Frame *to = nextFrame(dir); + + if (from && to) { + Client *client = from->focused(); + if (!from->detach(client) && + (Util::get(KERNEL->commonSettings(), "frame.autodestroy") == "yes")) + { + destroyFrame(from); + } + client->initICCCM(); + to->attach(client); + focus(to->focused()); + } +} + +void Workspace::joinFrame(Direction dir) { + + Frame *from = focusedFrame(); + Frame *to = nextFrame(dir); + + if (from && to) { + + for (unsigned int i = from->size(); i > 0; i--) { + Client *client = from->focused(); + if (from->detach(client) == 0) { + destroyFrame(from); + } + client->initICCCM(); + to->attach(client); + } + focus(to->focused()); + } +} + +void Workspace::splitFrame(Direction dir) { + + Frame *frame = focusedFrame(); + if (frame && frame->size() > 1) { + Frame *splitFrame = new Frame(this, frame); + LOGDEBUG("split frame"); + Client *client = frame->focused(); + frame->detach(client); + attachFrame(splitFrame, dir); + splitFrame->attach(client); + focus(splitFrame->focused()); + } +} + +void Workspace::resize(Thing *thing, Direction dir, bool grow) { + + switch (thing->type()) { + case Thing::FRAME: + resizeFrame(dir, grow); + break; + case Thing::CLIENT: + if (((Client *)thing)->hasDecoration()) { + resizeClient(dir, grow); + } + break; + } +} + +void Workspace::resizeFrame(Direction dir, bool grow) { + + Monitor *monitor = attached(); + int stepW = width() / 100 * monitor->resizeFactor(); + int stepH = height() / 100 * monitor->resizeFactor(); + + if (!grow) { + stepW *= -1; + stepH *= -1; + dir = Util::reverseDir(dir); + } + + Split::resize(root_, focusedFrame()->tree(), + dir, stepW, stepH); +} + +void Workspace::detachClient(Client *client) { + + // we need to remove all references to a sticky client on *all* + // other workspaces first + if (client->mode() == Client::STICKY) { + for (LWorkspace::iterator it = attached()->begin(); + it != attached()->end(); it++) + { + Workspace *workspace = *it; + if (workspace == this) { + continue; + } + workspace->removeClient(client); + } + attached()->stickyClients()->detach(client); + } + + Frame *frame = client->frame(); + if (frame) { + if (!frame->detach(client) && + (Util::get(KERNEL->commonSettings(), "frame.autodestroy") == "yes")) + { + destroyFrame(frame); + } + } + else { + floatingClients_.detach(client); + if (client->isVisible()) { + client->hide(); + } + client->reparent(attached()->rootWindow(), + client->x(), client->y()); + } + LOGDEBUG("detached from containers"); + + removeClient(client); + + client->setAttached(0); + + assert(client != topClient()); + if (topClient()) { + focus(topClient()); + } + else { + illuminate(); + } + LOGDEBUG("final stuff of detaching client"); +} + +Frame *Workspace::focusedFrame() const { + return frames_.focused(); +} + +Thing *Workspace::thingWindow(Window window) { + + for (LClient::iterator it = floatingClients_.begin(); + it != floatingClients_.end(); it++) + { + Client *client = *it; + if (client->frameWindow() == window) { + return client; + } + } + for (LFrame::iterator it = frames_.begin(); + it != frames_.end(); it++) + { + Frame *frame = *it; + if (frame->window() == window) { + return frame; + } + } + return 0; +} + +void Workspace::matchBarNeighbors(Direction dir) { + + // TODO: take care of dir + // commits current workspace rectangle to root_ tree map element + root_->copy(this); + Split::adjustSize(root_, ((dir == LEFT) || (dir == RIGHT))); +} + +void Workspace::lower() { + + Thing *thing = focusedThing(); + + if (!thing) { + return; + } + + XCORE->lower(thing->window()); +} + +void Workspace::raise() { + + Client *client = topClient(); + + if (!client) { + return; + } + + focus(client); +} + +void Workspace::changeClientMode(Client *client, Client::Mode mode) { + assert(client); + detachClient(client); + client->setMode(mode); + attachClient(client, true); +} + +void Workspace::toggleClientMode() { + Client *client = topClient(); + if (client) { + changeClientMode(client, (client->mode() == Client::MAX) ? + Client::FLOAT : Client::MAX); + } +} + +void Workspace::toggleClientSticky() { + Client *client = topClient(); + if (client) { + if (client->mode() != Client::STICKY) { + changeClientMode(client, Client::STICKY); + } + else { + changeClientMode(client, Client::FLOAT); + } + } +} + +void Workspace::resizeClient(Direction dir, bool grow) { + + Client *client = topClient(); + if (!client || !client->hasDecoration()) { + return; + } + + Monitor *monitor = attached(); + + int stepW = width() / 100 * monitor->resizeFactor(); + int stepH = height() / 100 * monitor->resizeFactor(); + + if ((dir == LEFT) || (dir == UP)) { + stepW *= -1; + stepH *= -1; + } + + Float::resize(client, grow ? dir : Util::reverseDir(dir), + stepW, stepH); + + client->resize(); +} + +void Workspace::moveClient(Direction dir) { + + Client *client = topClient(); + if (!client) { + return; + } + + Monitor *monitor = attached(); + + // review: correct + int stepW = width() / 100 * monitor->resizeFactor(); + int stepH = height() / 100 * monitor->resizeFactor(); + + if ((dir == LEFT) || (dir == UP)) { + stepW *= -1; + stepH *= -1; + } + + if ((dir == LEFT) || (dir == RIGHT)) { + Float::move(client, stepW, 0); + } + else { + Float::move(client, 0, stepH); + } + + client->resize(); +} + + +void Workspace::serialize() { + + (*KERNEL->sessionSettings())[prefix_ + ".name"] = name_; + (*KERNEL->sessionSettings())[prefix_ + ".clientbar"] = + isClientBarVisible_ ? "yes" : "no"; + (*KERNEL->sessionSettings())[prefix_ + ".statusbar"] = + isStatusBarVisible_ ? "yes" : "no"; +#ifdef SLOT_SUPPORT + (*KERNEL->sessionSettings())[prefix_ + ".slot"] = slotTabName_; +#endif // SLOT_SUPPORT +} + +Frame *Workspace::frameForPoint(unsigned int x, unsigned int y) { + + for (LFrame::iterator it = frames_.begin(); + it != frames_.end(); it++) + { + Frame *frame = *it; + if (Util::isPointWithinRect(x, y, frame, this)) { + return frame; + } + } + return focusedFrame(); +} + +void Workspace::toggleBorders(bool visible) { + + for (LFrame::iterator it = frames_.begin(); + it != frames_.end(); it++) + { + Frame *frame = *it; + frame->setBorderWidth(visible ? KERNEL->borderWidth() : 0); + frame->resize(); + } + for (LClient::iterator it = floatingClients_.begin(); + it != floatingClients_.end(); it++) + { + Client *client = *it; + if (client->hasDecoration()) { + client->setBorderWidth(visible ? KERNEL->borderWidth() : 0); + client->resize(); + } + } +} + +void Workspace::toggleBars(bool visible) { + + for (LFrame::iterator it = frames_.begin(); + it != frames_.end(); it++) + { + Frame *frame = *it; + frame->setTitleBarHeight(visible ? attached()->titleBarHeight() : 0); + frame->resize(); + } + for (LClient::iterator it = floatingClients_.begin(); + it != floatingClients_.end(); it++) + { + Client *client = *it; + if (client->hasDecoration()) { + client->setTitleBarHeight(visible ? attached()->titleBarHeight() : 0); + client->resize(); + } + } +} + +void Workspace::cycleClientNext() { + + if (isFrameMode_) { + if (focusedFrame()) { + focus(focusedFrame()->next()); + } + } + else { + focus(floatingClients_.next()); + } +} + +void Workspace::cycleClientPrev() { + + if (isFrameMode_) { + if (focusedFrame()) { + focus(focusedFrame()->prev()); + } + } + else { + focus(floatingClients_.prev()); + } +} + +void Workspace::toggleMode() { + isFrameMode_ = !isFrameMode_; + if (isFrameMode_) { + if (focusedFrame()) { + focus(focusedFrame()->focused()); + } + else { + focus(0); + } + } + else { + for (LClient::iterator it = floatingClients_.begin(); + it != floatingClients_.end(); it++) + { + XCORE->raise(((Client *)*it)->window()); + } + focus(floatingClients_.focused()); + } +} + +void Workspace::removePushClient(Client *client) { + removeClient(client); + pushClient(client); +} + +void Workspace::removeClient(Client *client) { + if (stackContainsClient(client)) { + globalClientStack_.remove(client); + } +} + +void Workspace::pushClient(Client *client) { + if (!stackContainsClient(client)) { + globalClientStack_.push_front(client); + } +} + +bool Workspace::stackContainsClient(Client *client) { + for (LClient::iterator it = globalClientStack_.begin(); + it != globalClientStack_.end(); it++) + { + if (client == *it) { + return true; + } + } + return false; +} + +Client *Workspace::topClient() { + +#ifdef SLOT_SUPPORT + if (isSlotVisible() && attached()->slot()->isGrabFocus()) { + // if the slot grabs the focus currently, this workspace + // has temprarily no focussed topClient - so just return + // 0. + return 0; + } +#endif + if (globalClientStack_.size()) { + return globalClientStack_.front(); + } + return 0; +} + +unsigned int Workspace::nextFrameId() { + ++frameIds_; + return frameIds_; +} + +unsigned int Workspace::id() const { + return id_; +} + +void Workspace::setName(string name) { + name_ = name; +} + +string Workspace::name() const { + return name_; +} + +string Workspace::prefix() const { + return prefix_; +} + +Tree* Workspace::root() const { + return root_; +} + +bool Workspace::isFrameMode() const { + return isFrameMode_; +} + +void Workspace::setClientBarVisible(bool visible) { + isClientBarVisible_ = visible; +} + +void Workspace::setStatusBarVisible(bool visible) { + isStatusBarVisible_ = visible; +} + +#ifdef SLOT_SUPPORT +void Workspace::setSlotVisible(bool visible) { + slotTabName_ = visible ? + attached()->slot()->tabName() : ""; +} + +bool Workspace::isSlotVisible() const { + return slotTabName_ != ""; +} + +string Workspace::slotTabName() const { + return slotTabName_; +} +#endif // SLOT_SUPPORT + +Thing *Workspace::focusedThing() { + + Client *client = topClient(); + return (client && client->frame()) ? (Thing *)client->frame() : + (Thing *)client; +} + +void Workspace::fitClient() { + + Client *client = topClient(); + if (client) { + Util::fitInto(client, this); + client->resize(); + } +} + +bool Workspace::isClientBarVisible() const { + return isClientBarVisible_; +} + +bool Workspace::isStatusBarVisible() const { + return isStatusBarVisible_; +} + +Monitor *Workspace::attached() const { + return monitor_; +} + +CClient *Workspace::floatingClients() { + return &floatingClients_; +} + +CFrame *Workspace::frames() { + return &frames_; +} + +bool Workspace::requestsFocus() const { + return requestsFocus_; +} + +void Workspace::setRequestsFocus(bool requestsFocus) { + requestsFocus_ = requestsFocus; +} + +LClient *Workspace::clients() { + return &globalClientStack_; +} + diff --git a/workspace.h b/workspace.h @@ -0,0 +1,197 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: workspace.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __WORKSPACE_H +#define __WORKSPACE_H + +#include <string> +#include <list> + +#include "rectangle.h" +#include "container.h" +#include "client.h" + +// forward declaration +class Frame; +class Monitor; +class Settings; +class Thing; +class Tree; +class Workspace; +class XCore; + +typedef list<Client *> LClient; +typedef list<Frame *> LFrame; +typedef Container<Monitor, LClient, LClient::iterator, Client> CClient; +typedef Container<Monitor, LFrame, LFrame::iterator, Frame> CFrame; + +/** + * Represents a workspace of WMI. + */ +class Workspace : + public Rectangle +{ + +public: + + Workspace(Monitor *monitor, unsigned int id, Rectangle *rect); + + ~Workspace(); + + unsigned int id() const; + + /** Hides this workspace. */ + void hide(); + + /** Shows this workspace. */ + void show(); + + void illuminate(); + + void setName(string name); + + string name() const; + + string prefix() const; + + Tree* root() const; + + bool isFrameMode() const; + + void toggleMode(); + void raiseFrames(); + + /** + * Attaches client to this workspace, if client->mode() is + * <code>Client::MAX</code> and isChangeMode is <code>true</code> + * this method will try to attach the client to the frame where the + * center point of the client is located. + */ + void attachClient(Client *client, bool isChangeMode = false); + void detachClient(Client *client); + + /** + * Splits the focused frame, if it has more than two clients + * and attaches the focused client to it. + */ + void splitFrame(Direction dir); + void joinFrame(Direction dir); + void sendClient(Direction dir); + + /** + * Resize behavior for the focused frame. + */ + void resizeFrame(Direction dir, bool grow); + + void resizeClient(Direction dir, bool grow); + + /** Focused client resize methods. */ + void moveClient(Direction dir); + + void selectFrame(Direction dir); + void swapFrame(Direction dir); + void swapClient(Direction dir); + + Thing *focusedThing(); + Frame *frameForPoint(unsigned int x, unsigned int y); + + void focus(Thing *thing, bool raise = true); + + Thing *thingWindow(Window window); + + void matchBarNeighbors(Direction dir); + + void raise(); + void lower(); + + void toggleClientMode(); + void toggleClientSticky(); + void changeClientMode(Client *client, Client::Mode mode); + + void serialize(); + + Tree *neighborTree(Direction dir); + + void toggleBars(bool visible); + void toggleBorders(bool visible); + + void cycleClientNext(); + void cycleClientPrev(); + + void removeClient(Client *client); + + /** + * Used for differentiation of multiframes, each client has an + * unique id. + */ + unsigned int nextFrameId(); + + void setClientBarVisible(bool visible); + void setStatusBarVisible(bool visible); +#ifdef SLOT_SUPPORT + void setSlotVisible(bool visible); + bool isSlotVisible() const; + string slotTabName() const; +#endif // SLOT_SUPPORT + + void resize(Thing *thing, Direction dir, bool grow); + + Client *topClient(); + void removePushClient(Client *client); + + void fitClient(); + + bool isClientBarVisible() const; + bool isStatusBarVisible() const; + + Frame *focusedFrame() const; + Monitor *attached() const; + + LClient *clients(); + CClient *floatingClients(); + CFrame *frames(); + + bool requestsFocus() const; + void setRequestsFocus(bool requestsFocus); + void destroyFrame(Frame *frame); + +private: + + Monitor *monitor_; + void pushClient(Client *client); + bool stackContainsClient(Client *client); + + Frame *nextFrame(Direction dir, bool isResize = true); + + /** Returns the recently visited frame in the given direction. */ + Frame *recentVisitedFrame(Direction dir); + + /** Helper for resizing clients. */ + + void attachFrame(Frame *frame, Direction dir = DOWN); + + /** Creates empty attached frame and returns it. */ + Frame *newFrame(); + + LClient globalClientStack_; + CClient floatingClients_; + CFrame frames_; + bool isFrameMode_; + bool requestsFocus_; + unsigned int id_; + string name_; + string prefix_; + + Tree *root_; + unsigned int frameIds_; + + bool isClientBarVisible_; + bool isStatusBarVisible_; +#ifdef SLOT_SUPPORT + string slotTabName_; // "" means not slot visible +#endif // SLOT_SUPPORT +}; + +#endif // __WORKSPACE_H diff --git a/xcore.cpp b/xcore.cpp @@ -0,0 +1,686 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: xcore.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include "xcore.h" + +extern "C" { +#include <X11/Xatom.h> +#include <X11/Xproto.h> +} + +#include <sstream> + +#include "atoms.h" +#include "font.h" +#include "kernel.h" +#include "logger.h" +#include "rectangle.h" + +#include "xfont.h" +#include "xftfont.h" + +XCore::XCore() {} + +XCore::~XCore() {} + +void XCore::setDisplay(Display *display) { + display_ = display; +} + +Window XCore::createWindow(Window root, XSetWindowAttributes *attr, + int x, int y, unsigned int w, unsigned int h, + unsigned long mask) +{ + return XCreateWindow(display_, root, x, y, w, h, 0, + CopyFromParent, InputOutput, CopyFromParent, + mask, attr); +} + +void XCore::sendEvent(Window window, unsigned long mask, XEvent *event) { + XSendEvent(display_, window, True, mask, event); +} + +void XCore::maskEvent(unsigned long mask, XEvent *event) { + XMaskEvent(display_, mask, event); +} + +void XCore::selectEvents(Window window, long mask) { + XSelectInput(display_, window, mask); +} + +void XCore::show(Window window) { + XMapWindow(display_, window); +} + +void XCore::showRaised(Window window) { + XMapRaised(display_, window); +} + +void XCore::hide(Window window) { + XUnmapWindow(display_, window); +} + +GC XCore::createGC(Window window, unsigned long mask, XGCValues *gcv) { + return XCreateGC(display_, window, mask, gcv); +} + +void XCore::ungrabKey(Window window, unsigned int modMask, KeyCode keycode) +{ + XUngrabKey(display_, keycode, modMask, window); +} + +void XCore::grabKeyboard(Window window) { + XGrabKeyboard(display_, window, True, GrabModeAsync, + GrabModeAsync, CurrentTime); +} + +void XCore::ungrabKeyboard() { + XUngrabKeyboard(display_, CurrentTime); +} + +void XCore::free(void *data) { + XFree(data); +} + +void XCore::freeCursor(Cursor cursor) { + XFreeCursor(display_, cursor); +} + +void XCore::sync(bool discard) { + XSync(display_, discard); +} + +void XCore::setForeground(GC gc, unsigned long color) { + XSetForeground(display_, gc, color); +} + +void XCore::drawLines(Window window, GC gc, XPoint *points, unsigned int num) +{ + XDrawLines(display_, window, gc, points, num, + CoordModeOrigin); +} + +void XCore::drawRectangle(Window window, GC gc, int x, int y, + unsigned int w, unsigned int h) +{ + XDrawRectangle(display_, window, gc, x, y, w, h); +} + +void XCore::drawRectangle(Window window, GC gc, Rectangle *rect) { + XDrawRectangle(display_, window, gc, rect->x(), rect->y(), + rect->width(), rect->height()); +} + +void XCore::drawLine(Window window, GC gc, unsigned int x1, unsigned int y1, + unsigned int x2, unsigned int y2) +{ + XDrawLine(display_, window, gc, x1, y1, x2, y2); +} + +void XCore::clearArea(Window window, Rectangle *rect) { + XClearArea(display_, window, rect->x(), rect->y(), + rect->width(), rect->height(), False); +} + +void XCore::clearArea(Window window, int x, int y, unsigned int w, unsigned int h) { + XClearArea(display_, window, x, y, w, h, False); +} + +void XCore::clearWindow(Window window) { + XClearWindow(display_, window); +} + +void XCore::fillRectangle(Window window, GC gc, Rectangle *rect) { + XFillRectangle(display_, window, gc, rect->x(), rect->y(), + rect->width(), rect->height()); +} + +void XCore::fillRectangle(Window window, GC gc, int x, int y, + unsigned int w, unsigned int h) +{ + XFillRectangle(display_, window, gc, x, y, w, h); +} + +XFontStruct *XCore::loadQueryFont(string name) { + return XLoadQueryFont(display_, name.c_str()); +} + +void XCore::drawText(Window window, GC gc, int x, int y, + string text) +{ + XDrawString(display_, window, gc, x, y, + text.c_str(), text.length()); +} + +int XCore::textWidth(XFontStruct *font, string text) { + return XTextWidth(font, text.c_str(), text.length()); +} + +#ifdef XFT_SUPPORT +XftFont *XCore::xftOpenFontName(unsigned int screen, string name) { + return XftFontOpenName(display_, screen, name.c_str()); +} + +void XCore::xftCloseFont(XftFont *font) { + if (font != 0) { + XftFontClose(display_, font); + } +} + +int XCore::textWidth(XftFont *font, string text) { + + if (font == 0) { + return 0; + } + XGlyphInfo ginfo; + XftTextExtents8(display_, font, (XftChar8 *)text.c_str(), + text.length(), &ginfo); + return ginfo.xOff; +} + +void XCore::drawText(XftFont *font, Window window, GC gc, + unsigned int screen, int x, int y, string text) +{ + if (font == 0) { + return; + } + + Visual *visual = DefaultVisual(display_, screen); + Colormap cmap = DefaultColormap(display_, screen); + + XftDraw *draw = XftDrawCreate(display_, window, visual, cmap); + + XGCValues gcv; + + // foreground pixel for XRenderColor value + XGetGCValues(display_, gc, GCForeground, &gcv); + + // RGB values + XColor color; + color.pixel = gcv.foreground; + XQueryColor(display_, cmap, &color); + + XRenderColor renderColor; + renderColor.red = color.red; + renderColor.green = color.green; + renderColor.blue = color.blue; + renderColor.alpha = 0xFFFF; + XftColor xftColor; + XftColorAllocValue(display_, visual, cmap, &renderColor, &xftColor); + + // draw text + XftDrawString8(draw, &xftColor, font, x, y, + (XftChar8 *)(text.c_str()), text.length()); + + // clean up + XftColorFree(display_, visual, cmap, &xftColor); + XftDrawDestroy(draw); +} + +#endif // XFT_SUPPORT + +string XCore::className(Window window) { + XClassHint classHints; + + if (XGetClassHint(display_, window, &classHints) != 0) { + return (string)classHints.res_class; + } + return ""; +} + +string XCore::instanceName(Window window) { + XClassHint classHints; + + if (XGetClassHint(display_, window, &classHints) != 0) { + return (string)classHints.res_name; + } + return ""; +} + +int XCore::state(Window window) { + + // state hints + XWMHints *hints = XGetWMHints(display_, window); + int result; + + long *prop = 0; + if (property(window, Atoms::WM_STATE, Atoms::WM_STATE, + 2L, (unsigned char**)&prop) > 0) + { + result = (int)*prop; + free((long *)prop); + } + else { + result = hints ? hints->initial_state : NormalState; + } + + if (hints) { + free(hints); + } + + return result; +} + +void XCore::setState(Window window, int state) { + + long data[2]; + data[0] = (long)state; + data[1] = (long)None; + + XChangeProperty(display_, window, + Atoms::WM_STATE, Atoms::WM_STATE, + 32, PropModeReplace, (unsigned char *)data, 2); +} + +string XCore::atomValue(Window window, Atom atom) { + + string result; + unsigned char *prop; + + if (property(window, atom, XA_STRING, 100L, &prop) > 0) { + result = (char *)prop; + free((char *)prop); + } + else { + result = ""; + } + + return result; +} + +void XCore::sizeHints(Window window, XSizeHints *sizeHints) { + long msize; + // size hints + XGetWMNormalHints(display_, window, sizeHints, &msize); +} + +void XCore::updateSize(Window window, + unsigned int *minW, unsigned int *minH, + unsigned int *maxW, unsigned int *maxH, + bool *isCentered) +{ + XSizeHints sizeHints; + long msize; + + // size hints + if (!XGetWMNormalHints(display_, window, &sizeHints, &msize) + || !sizeHints.flags) + { + sizeHints.flags = PSize; + } + + *isCentered = !((sizeHints.flags & USPosition) || + (sizeHints.flags & PPosition)); + + // minimal dimensions + if (sizeHints.flags & PBaseSize) { + *minW = sizeHints.base_width; + *minH = sizeHints.base_height; + } + else if (sizeHints.flags & PMinSize) { + *minW = sizeHints.min_width; + *minH = sizeHints.min_height; + } + else { + *minW = *minH = 23; + } + + // maximal dimensions + if (sizeHints.flags & PMaxSize) { + *maxW = sizeHints.max_width; + *maxH = sizeHints.max_height; + } +} + +bool XCore::hasDecoration(Window window) { + + MWMHints *mwmHints = 0; + long result = property(window, Atoms::MWM_HINTS, + Atoms::MWM_HINTS, 5, (unsigned char **) + &mwmHints); + + if ((result >= 0) && mwmHints) { + bool decor = !(mwmHints->decorations == 0 && + (mwmHints->flags & MWM_HINTS_DECORATIONS)); + free((void *)mwmHints); + return decor; + } + // fallback, assumes decoration + return true; +} + +Window XCore::transient(Window window) { + Window trans; + + if (!XGetTransientForHint(display_, window, &trans)) { + return 0; + } + return trans; +} + +int XCore::property(Window window, Atom atom, Atom type, + long length, unsigned char **prop) +{ + Atom realType; + int format; + unsigned long result, extra; + int status; + + status = XGetWindowProperty(display_, window, + atom, 0L, length, + False, type, &realType, &format, + &result, + &extra, + prop); + + if (status != Success || *prop == 0) { + return 0; + } + if (result == 0) { + free((void*) *prop); + } + + return result; +} + +void XCore::configureWindow(Window window, unsigned int mask, XWindowChanges *wc) { + + XConfigureWindow(display_, window, mask, wc); +} + +void XCore::configure(Window window, XConfigureEvent *event) { + XSendEvent(display_, window, False, StructureNotifyMask, + (XEvent *)event); + XFlush(display_); +} + +int XCore::protocols(Window window) { + Atom *protocols; + long result; + int protos = 0; + + result = property(window, Atoms::WM_PROTOCOLS, XA_ATOM, + 20L, (unsigned char **) &protocols); + if (result <= 0) { + return protos; + } + + for (int i = 0; i < result; i++) { + if (protocols[i] == Atoms::WM_DELETE) { + protos |= PDELETE; + } + else if (protocols[i] == Atoms::WM_TAKE_FOCUS) { + protos |= PTAKEFOCUS; + } + } + free((char *) protocols); + return protos; +} + +void XCore::sendMessage(Window window, Atom atom, long value) { + + XEvent event; + event.type = ClientMessage; + event.xclient.window = window; + event.xclient.message_type = atom; + event.xclient.format = 32; + event.xclient.data.l[0] = value; + event.xclient.data.l[1] = CurrentTime; + + XSendEvent(display_, window, False, NoEventMask, &event); + XFlush(display_); +} + +void XCore::kill(Window window, int protos) { + + if (protos & PDELETE) { + sendMessage(window, Atoms::WM_PROTOCOLS, Atoms::WM_DELETE); + } + else { + XKillClient(display_, window); + } +} + +void XCore::moveResize(Window window, Rectangle *rect) { + XMoveResizeWindow(display_, window, rect->x(), rect->y(), + rect->width(), rect->height()); +} + +void XCore::destroy(Window window) { + XDestroyWindow(display_, window); +} + +void XCore::raise(Window window) { + XRaiseWindow(display_, window); +} + +void XCore::lower(Window window) { + XLowerWindow(display_, window); +} + +void XCore::reparent(Window child, Window parent, int x, int y) { + XReparentWindow(display_, child, parent, x, y); +} + +void XCore::setInputFocus(Window window) { + XSetInputFocus(display_, window, RevertToPointerRoot, CurrentTime); +} + +void XCore::grabKey(Window window, unsigned int modMask, KeyCode keycode) { + XGrabKey(display_, keycode, modMask, window, True, GrabModeAsync, + GrabModeAsync); +} + +void XCore::grabButton(Window window, unsigned int modMask, unsigned int button) { + XGrabButton(display_, button, modMask, window, False, + ButtonPressMask | ButtonReleaseMask, GrabModeAsync, + GrabModeAsync, None, None); +} + +void XCore::ungrabButton(Window window, unsigned int modMask, unsigned int button) { + XUngrabButton(display_, button, modMask, window); +} + +void XCore::setWindowAttributes(Window window, unsigned int mask, + XSetWindowAttributes *attr) +{ + XChangeWindowAttributes(display_, window, mask, attr); +} + +void XCore::windowAttributes(Window window, XWindowAttributes *attr) +{ + + XGetWindowAttributes(display_, window, attr); +} + +Atom XCore::internAtom(string atom) { + return XInternAtom(display_, atom.c_str(), False); +} + + +Cursor XCore::createFontCursor(unsigned int cursor) { + return XCreateFontCursor(display_, cursor); +} + + +string XCore::atomName(Atom atom) { + return (string)XGetAtomName(display_, atom); +} + + +void XCore::nextEvent(XEvent *event) { + XNextEvent(display_, event); +} + +bool XCore::checkMaskEvent(long mask, XEvent *event) { + return XCheckMaskEvent(display_, mask, event); +} + +KeyCode XCore::stringToKeyCode(string key) { + KeySym keySym = XStringToKeysym(key.c_str()); + if (keySym) { + return XKeysymToKeycode(display_, keySym); + } + return 0; +} + +KeySym XCore::keyCodeToKeySym(KeyCode keyCode) { + return XKeycodeToKeysym(display_, keyCode, 0); +} + +string XCore::keyCodeToString(KeyCode keyCode) { + KeySym keySym = XKeycodeToKeysym(display_, keyCode, 0); + if (keySym) { + return XKeysymToString(XKeycodeToKeysym(display_, keyCode, 0)); + } + return ""; +} + +void XCore::grabServer() { + XGrabServer(display_); +} + +void XCore::ungrabServer() { + XUngrabServer(display_); +} + +void XCore::grabPointer(Window window, unsigned int mask, + Time time, Cursor cursor) +{ + + XGrabPointer(display_, window, False, mask, + GrabModeAsync, GrabModeAsync, + None, cursor, time); +} + +void XCore::ungrabPointer(Time time) { + XUngrabPointer(display_, time); +} + +void XCore::translateCoordinates(Window child, Window parent, + int srcX, int srcY, int *destX, int *destY) +{ + + Window dummy; + XTranslateCoordinates(display_, child, parent, srcX, srcY, + destX, destY, &dummy); +} + +bool XCore::allocNamedColor(Colormap colormap, string name, XColor *color) { + return XAllocNamedColor(display_, colormap, name.c_str(), + color, color); +} + +void XCore::installColormap(Colormap colormap) { + XInstallColormap(display_, colormap); +} + +KeySym XCore::lookupNextKeySym(XKeyEvent *event, int *count, char *buffer) { + KeySym result; + *count = XLookupString(event, buffer, 32, &result, 0); + return result; +} + +bool XCore::textProperty(Window window, Atom atom, string *value) { + XTextProperty property; + + if (XGetTextProperty(display_, window, &property, atom)) { + + if (property.nitems > 0) { + *value = (const char *)property.value; + } + else { + *value = ""; + } + free(property.value); + return true; + } + return false; +} + +void XCore::queryTree(Window root, Window **windows, unsigned int *num) { + + Window rootReturn, parentReturn; + + XQueryTree(display_, root, &rootReturn, + &parentReturn, windows, num); +} + +// X error manager +int XCore::handleErrors(Display *display, XErrorEvent *e) +{ + Logger *log = Logger::instance(); + Kernel *kernel = Kernel::instance(); + + if ((kernel->runlevel() == Kernel::START) && + (e->request_code == X_ChangeWindowAttributes) && + (e->error_code == BadAccess)) + { + log->error("seems, that there's running another window manager", true); + // exits wmi + } + + char errtxt[128]; + + XGetErrorText(kernel->display(), e->error_code, errtxt, 128); + ostringstream oss; + oss << errtxt << "(" << (int)e->error_code << ") opcodes " + << (int)e->request_code << "/" << (int)e->minor_code + << " resource 0x"<< hex << (int)e->resourceid; + log->warning(oss.str()); + +#ifdef DEBUG + XTextProperty property; + + char *text = (char *)oss.str().c_str(); + XStringListToTextProperty(&text, 1, &property); + XSetTextProperty(kernel->display(), kernel->defaultRootWindow(), &property, + Atoms::WMI_STATUSTEXT); +#endif + + return 0; +} + +void XCore::setTextProperty(Display *display, Window window, + XTextProperty *textProperty, Atom atom) +{ + XSetTextProperty(display, window, textProperty, atom); +} + +void XCore::stringListToTextProperty(string text, XTextProperty *textProperty) +{ + char *txt = (char *)text.c_str(); + XStringListToTextProperty(&txt, 1, textProperty); +} + +Colormap XCore::defaultColormap(unsigned int id) { + return DefaultColormap(display_, id); +} + +XModifierKeymap *XCore::modifierMapping() { + return XGetModifierMapping(display_); +} + +void XCore::freeModifierMapping(XModifierKeymap *modmap) { + if (modmap) { + XFreeModifiermap(modmap); + } +} + +void XCore::addToSaveSet(Window window) { + XAddToSaveSet(display_, window); +} + +void XCore::removeFromSaveSet(Window window) { + XRemoveFromSaveSet(display_, window); +} + +void XCore::warpPointer(Window window, int x, int y) { + XWarpPointer(display_, None, window, 0, 0, 0, 0, x, y); +} + +XWMHints *XCore::getWMHints(Window window) { + return XGetWMHints(display_, window); +} diff --git a/xcore.h b/xcore.h @@ -0,0 +1,329 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: xcore.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __XCORE_H +#define __XCORE_H + +#include "wmi.h" + +extern "C" { +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#ifdef XFT_SUPPORT +#include <X11/Xft/Xft.h> +#endif // XFT_SUPPORT +} + +#include <string> + +#include "singleton.h" + +#define PDELETE 1 +#define PTAKEFOCUS 2 + +/** + * Motif bits - see Motif reference manual for further details. + */ +struct MWMHints { + // Think: do we need CARD32 and INT32 here? + long flags; + long functions; + long decorations; + int inputMode; + long status; +}; + +class XCore; +class Rectangle; +class WFont; + +/** + * This class provides an abstraction layer for graphical user + * interfaces such as X11 or maybe Y in future. + */ +class XCore : public Singleton<XCore> +{ + +public: + + /** Constructs new kernel instance. */ + XCore(); + + ~XCore(); + + void setDisplay(Display *display); + + /** Creates new window. */ + Window createWindow(Window root, XSetWindowAttributes *attr, + int x, int y, unsigned int w, unsigned int h, + unsigned long mask); + + /** Selects events specified by mask for window. */ + void selectEvents(Window window, long mask); + + /** Input focus setting. */ + void setInputFocus(Window window); + + /** Shows the specified window. (map) */ + void show(Window window); + + /** Shows the specified window raised. (map raised) */ + void showRaised(Window window); + + /** Hides the window. (unmap) */ + void hide(Window window); + + /** + * Creates new GC for the specified window, with gcv masked values. + */ + GC createGC(Window window, unsigned long mask, XGCValues *gcv); + + /** Grabs the keyboard for the specific window. */ + void grabKeyboard(Window window); + + /** Ungrabs the keyboard. */ + void ungrabKeyboard(); + + /** Frees the data by X request. */ + void free(void *data); + + /** Syncs with X. */ + void sync(bool discard = False); + + /** Sets foreground color. */ + void setForeground(GC gc, unsigned long color); + + /** Draws lines performantly. */ + void drawLines(Window window, GC gc, XPoint *points, unsigned int num); + + /** Draws a line. */ + void drawLine(Window window, GC gc, unsigned int x1, unsigned int y1, + unsigned int x2, unsigned int y2); + + /** Draws rectangle. */ + void drawRectangle(Window window, GC gc, int x, int y, unsigned int w, + unsigned int h); + + /** Draws rectangle. */ + void drawRectangle(Window window, GC gc, Rectangle *rect); + + /** Clears the specific area within specified window. */ + void clearArea(Window window, Rectangle *rect); + + /** Clears the specific area within specified window. */ + void clearArea(Window window, int x, int y, unsigned int w, unsigned int h); + + /** Clears the specified window. */ + void clearWindow(Window window); + + /** Fills the specific window with rectangle. */ + void fillRectangle(Window window, GC gc, Rectangle *rect); + + /** Fills the specific window with rectangle. */ + void fillRectangle(Window window, GC gc, int x, int y, + unsigned int w, unsigned int h); + + /** Loads the font specified by name. */ + XFontStruct *loadQueryFont(string name); + + /** Draws a string at (x, y) to the specific window. */ + void drawText(Window window, GC gc, int x, int y, + string text); + + /** Returns text width for the given values. */ + int textWidth(XFontStruct *font, string text); + +#ifdef XFT_SUPPORT + /** Opens a XftFont. */ + XftFont *xftOpenFontName(unsigned int screen, string name); + + /** Closes the specific XftFont. */ + void xftCloseFont(XftFont *font); + + /** Draws a string at (x, y) to the specific window. */ + void drawText(XftFont *font, Window window, GC gc, + unsigned int screen, int x, int y, + string text); + + /** Returns text width for the given values. */ + int textWidth(XftFont *font, string text); +#endif + + /** Returns class name for the specific window. */ + string className(Window window); + + /** Returns instance name for the specific window. */ + string instanceName(Window window); + + /** Returns state for the specific window. */ + int state(Window window); + + /** Sets the state for the specific window. */ + void setState(Window window, int state); + + /** Returns value of the specific atom as string. */ + string atomValue(Window window, Atom atom); + + /** Updates size infos for the specific window. */ + void updateSize(Window window, + unsigned int *minW, unsigned int *minH, + unsigned int *maxW, unsigned int *maxH, + bool *isCentered); + + /** Returns true if the specific window has MWM decoration. */ + bool hasDecoration(Window window); + + /** Returns transient for the specific window. */ + Window transient(Window window); + + /** Returns property for specific values. */ + int property(Window window, Atom atom, Atom type, + long length, unsigned char **prop); + + /** Sends configuration to the specific window. */ + void configure(Window window, XConfigureEvent *event); + + /** Returns protocols for the specific window. */ + int protocols(Window window); + + /** Sends a message to the specific window. */ + void sendMessage(Window window, Atom atom, long value); + + /** Kills the client with the specific window. */ + void kill(Window window, int protos); + + /** Resizes the specific window. */ + void moveResize(Window window, Rectangle *rect); + + /** Destroys the window. */ + void destroy(Window window); + + /** Raises the specific window. */ + void raise(Window window); + + /** Lowers the specific window. */ + void lower(Window window); + + /** Reparents the specific window. */ + void reparent(Window child, Window parent, int x, int y); + + /** Grabs the key for the specified window. */ + void grabKey(Window window, unsigned int modMask, KeyCode keycode); + + /** Ungrabs key. */ + void ungrabKey(Window window, unsigned int modMask, KeyCode keycode); + + /** Grabs button. */ + void grabButton(Window window, unsigned int modMask, unsigned int button); + + /** Ungrabs button. */ + void ungrabButton(Window window, unsigned int modMask, unsigned int button); + + /** Grabs the server. */ + void grabServer(); + + /** Ungrabs the server. */ + void ungrabServer(); + + /** Grabs the pointer. */ + void grabPointer(Window window, unsigned int mask, Time time, + Cursor cursor = None); + + /** Ungrabs pointer. */ + void ungrabPointer(Time time); + + /** Returns specified atom. */ + Atom internAtom(string atom); + + /** Returns new font cursor specified by cursor. */ + Cursor createFontCursor(unsigned int cursor); + + /** Set window attributes. */ + void setWindowAttributes(Window window, unsigned int mask, + XSetWindowAttributes *attr); + + /** Writes window attributes to attr. */ + void windowAttributes(Window window, XWindowAttributes *attr); + + /** Returns KeyCode for string. */ + KeyCode stringToKeyCode(string key); + + /** Returns string for KeyCode. */ + string keyCodeToString(KeyCode keyCode); + + /** Returns KeySym for KeyCode. */ + KeySym keyCodeToKeySym(KeyCode keyCode); + + /** Returns name of atom. */ + string atomName(Atom atom); + + /** Writes next event back to event. */ + void nextEvent(XEvent *event); + + /** Checks for events specified by mask, returns true if matched. */ + bool checkMaskEvent(long mask, XEvent *event); + + /** + * Translates Coordinates given by srcX and srcY absoluted to child + * window into destX and destY coordinates absoluted to parent + * to window. + */ + void translateCoordinates(Window child, Window parent, + int srcX, int srcY, int *destX, int *destY); + + /** Returns true if color could be allocated, otherwise false. */ + bool allocNamedColor(Colormap colormap, string name, XColor *color); + + /** Installs colormap. */ + void installColormap(Colormap colormap); + + Colormap defaultColormap(unsigned int id); + + /** Queries a window tree. */ + void queryTree(Window root, Window **windows, unsigned int *num); + + /** Returns KeySym for next char by this XKeyEvent. */ + KeySym lookupNextKeySym(XKeyEvent *event, int *count, char *buffer); + + /** Writes back text property value for window and specified atom. */ + bool textProperty(Window window, Atom atom, string *value); + + /** Converts string to XTextProperty. */ + void stringListToTextProperty(string text, XTextProperty *textProperty); + void setTextProperty(Display *display, Window window, + XTextProperty *textProperty, Atom atom); + + /** Default error handler. */ + static int handleErrors(Display *display, XErrorEvent *e); + + void configureWindow(Window window, unsigned int mask, XWindowChanges *wc); + + /** NumLock/ScrollLock modifier detection. */ + XModifierKeymap *modifierMapping(); + void freeModifierMapping(XModifierKeymap *modmap); + + void addToSaveSet(Window window); + void removeFromSaveSet(Window window); + + /** Fetches size hints. */ + void sizeHints(Window window, XSizeHints *sizeHints); + + void warpPointer(Window window, int x, int y); + + void freeCursor(Cursor cursor); + + void maskEvent(unsigned long mask, XEvent *event); + + void sendEvent(Window window, unsigned long mask, XEvent *event); + + XWMHints *getWMHints(Window window); + +private: + + Display *display_; + +}; + +#endif // __XCORE_H diff --git a/xfont.cpp b/xfont.cpp @@ -0,0 +1,62 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: xfont.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include "xfont.h" + +#include "monitor.h" +#include "xcore.h" + +XFont::XFont(Monitor *monitor, XFontStruct *font) : + WFont(monitor) +{ + font_ = font; + type_ = WFont::NORMAL; +} + +XFont *XFont::load(Monitor *monitor, string name) { + + XFontStruct *font = XCORE->loadQueryFont(name); + XFont *xfont = 0; + if (font) { + xfont = new XFont(monitor, font); + xfont->setHeight(font->ascent + font->descent); + } + else { + delete font; + } + return xfont; +} + +XFont::~XFont() { +} + +int XFont::textWidth(string text) { + return XCORE->textWidth(font_, text); +} + +unsigned int XFont::height() { + return height_; +} + +void XFont::setHeight(unsigned int height) { + height_ = height; +} + +void XFont::drawText(Window window, GC gc, int x, int y, string text) { + XCORE->drawText(window, gc, x, y, text); +} + +int XFont::ascent() { + return font_->ascent; +} + +int XFont::descent() { + return font_->descent; +} + + +XFontStruct *XFont::font() const { + return font_; +} diff --git a/xfont.h b/xfont.h @@ -0,0 +1,52 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: xfont.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __XFONT_H +#define __XFONT_H + +#include "wmi.h" + +extern "C" { +#include <X11/Xlib.h> +} + +#include <string> + +#include "font.h" + +class Monitor; + +/** Base class for default XFonts. */ +class XFont : public WFont { + +public: + + XFont(Monitor *monitor, XFontStruct *font); + virtual ~XFont(); + + virtual void drawText(Window window, GC gc, int x, int y, string text); + + virtual int textWidth(string text); + + virtual unsigned int height(); + + virtual void setHeight(unsigned int height); + + XFontStruct *font() const; + + virtual int ascent(); + + virtual int descent(); + + static XFont *load(Monitor *monitor, string name); + +private: + + XFontStruct *font_; + unsigned int height_; + +}; + +#endif // __XFONT_H diff --git a/xft.m4 b/xft.m4 @@ -0,0 +1,83 @@ +# some patches by Anselm (removed --enable-xft ac argument) + +# xft.m4 +# Copyright (c) 2002 Henrik Kinnunen (fluxgen at linuxmail.org) + +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +# AM_PATH_XFT1([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +AC_DEFUN([AM_PATH_XFT1], +[ + AC_CHECK_LIB(Xft, XftFontOpen, + XFT_LIBS="-lXft" + [$1], + [$2] + ) +]) + +# AM_PATH_XFT2([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +AC_DEFUN([AM_PATH_XFT2], +[ + if test x$pkg_exec_prefix != x ; then + xft_args="$xft_args --exec-prefix=$pkg_exec_prefix" + if test x${PKG_CONFIG+set} != xset ; then + PKG_CONFIG=$pkg_exec_prefix/bin/pkg-config + fi +fi + +if test x$xft_prefix != x ; then + xft_args="$xft_args --prefix=$xft_prefix" + if test x${PKG_CONFIG+set} != xset ; then + PKG_CONFIG=$xft_prefix/bin/pkg-config + fi +fi + +AC_PATH_PROG(PKG_CONFIG, pkg-config, no) +if test "x$PKG_CONFIG" = "xno" ; then + ifelse([$2], , :, [$2]) +else + XFT_CFLAGS=`$PKG_CONFIG $xftconf_args --cflags xft` + XFT_LIBS=`$PKG_CONFIG $xftconf_args --libs xft` + ifelse([$1], , :, [$1]) +fi + +]) + +# AM_PATH_XFT(default-value, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +# Test for Xft, and define XFT_CFLAGS and XFT_LIBS +AC_DEFUN([AM_PATH_XFT], +[ + AC_ARG_WITH(xft-prefix,[ --with-xft-prefix=path Prefix where Xft is installed (optional)], + xft_prefix="$withval", xft_prefix="") + AC_ARG_WITH(pkg-exec-prefix,[ --with-pkg-exec-prefix=path Exec prefix where pkg-config is installed (optional)], + pkg_exec_prefix="$withval", pkg_exec_prefix="") + +AM_PATH_XFT2( + [$2], + # xft2 failed: try xft1 + AM_PATH_XFT1( + [$2], + [$3] + AC_MSG_RESULT([Cant find Xft libraries! Disabling Xft])) +) + +CXXFLAGS="$CXXFLAGS $XFT_CFLAGS" +LIBS="$LIBS $XFT_LIBS" + +]) diff --git a/xftfont.cpp b/xftfont.cpp @@ -0,0 +1,64 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: xftfont.cpp 734 2004-09-27 18:15:45Z garbeam $ + +#include "xftfont.h" + +#ifdef XFT_SUPPORT + +extern "C" { +#include <X11/Xlib.h> +} + +#include "monitor.h" +#include "xcore.h" + +WXftFont::WXftFont(Monitor *monitor, XftFont *font) : + WFont(monitor) +{ + font_ = font; + type_ = WFont::XFT; +} + +WXftFont *WXftFont::load(Monitor *monitor, string name) { + + XftFont *font = XCORE->xftOpenFontName(monitor->id(), name); + + WXftFont *result = 0; + if (font) { + result = new WXftFont(monitor, font); + result->setHeight(font->height); + } + return result; +} + +WXftFont::~WXftFont() { + XCORE->xftCloseFont(font_); +} + +int WXftFont::textWidth(string text) { + return XCORE->textWidth(font_, text); +} + +unsigned int WXftFont::height() { + return height_; +} + +void WXftFont::setHeight(unsigned int height) { + height_ = height; +} + +void WXftFont::drawText(Window window, GC gc, int x, int y, string text) { + XCORE->drawText(font_, window, gc, monitor_->id(), x, y, text); +} + +int WXftFont::ascent() { + return font_->ascent; +} + +int WXftFont::descent() { + return font_->descent; +} + +#endif diff --git a/xftfont.h b/xftfont.h @@ -0,0 +1,54 @@ +// Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de> +// See ../LICENSE.txt for license details. +// +// $Id: xftfont.h 734 2004-09-27 18:15:45Z garbeam $ + +#ifndef __XFTFONT_H +#define __XFTFONT_H + +#include "wmi.h" + +#ifdef XFT_SUPPORT + +extern "C" { +#include <X11/Xft/Xft.h> +} + +#include <string> + +#include "font.h" + +class Monitor; + +/** Base class for XftFonts. */ +class WXftFont : public WFont { + +public: + + WXftFont(Monitor *monitor, XftFont *font); + virtual ~WXftFont(); + + virtual void drawText(Window window, GC gc, int x, int y, string text); + + virtual int textWidth(string text); + + virtual unsigned int height(); + + virtual void setHeight(unsigned int height); + + virtual int ascent(); + + virtual int descent(); + + static WXftFont *load(Monitor *monitor, string name); + +private: + + XftFont *font_; + unsigned int height_; + +}; + +#endif // XFT_SUPPORT + +#endif // __XFTFONT_H