├── .gitignore ├── AUTHORS ├── COPYING ├── ChangeLog ├── INSTALL ├── Makefile.am ├── Makefile.in ├── NEWS ├── README ├── aclocal.m4 ├── compile ├── configure ├── configure.ac ├── depcomp ├── example.conf ├── install-sh ├── missing ├── src ├── Makefile.am ├── Makefile.in ├── binding.c ├── binding.h ├── key.c ├── key.h ├── popup.c ├── popup.h ├── util.c ├── util.h ├── xchainkeys.c └── xchainkeys.h └── xchainkeys.1 /.gitignore: -------------------------------------------------------------------------------- 1 | autom4te.cache/* 2 | *Makefile 3 | config.log 4 | config.status 5 | *.tar.gz 6 | 7 | src/*.o 8 | src/*.o.* 9 | src/.deps/* 10 | src/xchainkeys 11 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Henning Bekel 2 | sssslang 3 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2012-09-09 Henning Bekel 2 | * Released version 0.11 3 | * Added the ability to override manual abort on a per-key basis 4 | for :exec and :group actions (requested by Salam Taya) 5 | 6 | 2011-03-28 Henning Bekel 7 | 8 | * Released version 0.10 9 | * Added new options "position" and "hold" to control the 10 | positioning of the feedback window and to set the duration of 11 | error messages being displayed. Based on a patch from Lourens 12 | Rozema. 13 | 14 | 2011-03-20 Henning Bekel 15 | 16 | * Released version 0.9.1 17 | * Fixed a bug in :wait action that left the keyboard grabbed if 18 | :wait was invoked from a toplevel key 19 | 20 | 2011-03-12 Henning Bekel 21 | 22 | * Released version 0.9 23 | * Added new action :wait to execute commands synchronously while 24 | releasing xchainkey's keyboard grab (requested by tum). 25 | 26 | 2011-02-11 Henning Bekel 27 | 28 | * Released version 0.8 29 | * Addded ability to also bind keys by specifying a numeric keycode 30 | instead of a keysym 31 | 32 | 2011-01-28 Henning Bekel 33 | 34 | * Released version 0.7 35 | * Applied a patch contributed by sssslang that avoids using 100% 36 | cpu time while waiting for a timeout to occur. 37 | 38 | 2010-09-30 Henning Bekel 39 | 40 | * Released version 0.6 41 | * Added improved feedback for named :group actions 42 | * Added common modifier synonyms: Ctrl, Alt, Meta, Super, Windows 43 | * Fixed bogus keys may have been bound on startup from xinit 44 | * Fixed useless default actions were created when the default keys 45 | were already bound to different actions 46 | * Fixed output streams were not properly flushed 47 | * Fixed leaked some memory during parsing 48 | 49 | 2010-09-27 Henning Bekel 50 | 51 | * Released version 0.5 52 | * Added display of action names in feedback window 53 | * Added improved error reporting during parsing 54 | * Fixed spaces in action names were not possible 55 | * Fixed :abort, :escape, :group were allowed as toplevel bindings 56 | * Fixed :escape did not imply :abort as documented 57 | * Fixed parsing failed with unknown words in :enter arguments 58 | * Code cleanups 59 | 60 | 2010-09-20 Henning Bekel 61 | 62 | * Released version 0.4 63 | * Deprecated :repeat action in favor of a new :group action 64 | * Added :load and :reload actions to load config files 65 | * Fixed possibility of creating of non-abortable chains 66 | * Fixed segfault on binding a key sequence multiple times 67 | * Fixed argument parsing for :enter action 68 | * Improved error reporting 69 | * Updated manual page 70 | * Code cleanups 71 | 72 | 2010-09-16 Henning Bekel 73 | 74 | * Released version 0.3 75 | * Added timeout and abort options to :enter action 76 | * Added new action :repeat 77 | * Added option --file to load an alternative config file 78 | * Added option feedback [on|off] (requested by tum) 79 | * Added capitalized generic modifier names (requested by tum) 80 | * Fixed invalid free()'s in config parsing (reported by tum) 81 | * Fixed popup window is not raised when shown 82 | * Updated documentation, added a manual page 83 | * Code cleanups and minor bugfixes 84 | 85 | 2010-09-15 Henning Bekel 86 | 87 | * Released version 0.2 88 | * Fixed possibility of invalid free() in xc_show_keys() 89 | 90 | 2010-09-14 Henning Bekel 91 | 92 | * Released version 0.1 93 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation Instructions 2 | ************************* 3 | 4 | Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, 5 | 2006, 2007, 2008, 2009 Free Software Foundation, Inc. 6 | 7 | Copying and distribution of this file, with or without modification, 8 | are permitted in any medium without royalty provided the copyright 9 | notice and this notice are preserved. This file is offered as-is, 10 | without warranty of any kind. 11 | 12 | Basic Installation 13 | ================== 14 | 15 | To create the configure script, Makefile and other necessary files, 16 | please run 17 | 18 | $ autoreconf --install 19 | 20 | Briefly, the shell commands `./configure; make; make install' should 21 | configure, build, and install this package. The following 22 | more-detailed instructions are generic; see the `README' file for 23 | instructions specific to this package. Some packages provide this 24 | `INSTALL' file but do not implement all of the features documented 25 | below. The lack of an optional feature in a given package is not 26 | necessarily a bug. More recommendations for GNU packages can be found 27 | in *note Makefile Conventions: (standards)Makefile Conventions. 28 | 29 | The `configure' shell script attempts to guess correct values for 30 | various system-dependent variables used during compilation. It uses 31 | those values to create a `Makefile' in each directory of the package. 32 | It may also create one or more `.h' files containing system-dependent 33 | definitions. Finally, it creates a shell script `config.status' that 34 | you can run in the future to recreate the current configuration, and a 35 | file `config.log' containing compiler output (useful mainly for 36 | debugging `configure'). 37 | 38 | It can also use an optional file (typically called `config.cache' 39 | and enabled with `--cache-file=config.cache' or simply `-C') that saves 40 | the results of its tests to speed up reconfiguring. Caching is 41 | disabled by default to prevent problems with accidental use of stale 42 | cache files. 43 | 44 | If you need to do unusual things to compile the package, please try 45 | to figure out how `configure' could check whether to do them, and mail 46 | diffs or instructions to the address given in the `README' so they can 47 | be considered for the next release. If you are using the cache, and at 48 | some point `config.cache' contains results you don't want to keep, you 49 | may remove or edit it. 50 | 51 | The file `configure.ac' (or `configure.in') is used to create 52 | `configure' by a program called `autoconf'. You need `configure.ac' if 53 | you want to change it or regenerate `configure' using a newer version 54 | of `autoconf'. 55 | 56 | The simplest way to compile this package is: 57 | 58 | 1. `cd' to the directory containing the package's source code and type 59 | `./configure' to configure the package for your system. 60 | 61 | Running `configure' might take a while. While running, it prints 62 | some messages telling which features it is checking for. 63 | 64 | 2. Type `make' to compile the package. 65 | 66 | 3. Optionally, type `make check' to run any self-tests that come with 67 | the package, generally using the just-built uninstalled binaries. 68 | 69 | 4. Type `make install' to install the programs and any data files and 70 | documentation. When installing into a prefix owned by root, it is 71 | recommended that the package be configured and built as a regular 72 | user, and only the `make install' phase executed with root 73 | privileges. 74 | 75 | 5. Optionally, type `make installcheck' to repeat any self-tests, but 76 | this time using the binaries in their final installed location. 77 | This target does not install anything. Running this target as a 78 | regular user, particularly if the prior `make install' required 79 | root privileges, verifies that the installation completed 80 | correctly. 81 | 82 | 6. You can remove the program binaries and object files from the 83 | source code directory by typing `make clean'. To also remove the 84 | files that `configure' created (so you can compile the package for 85 | a different kind of computer), type `make distclean'. There is 86 | also a `make maintainer-clean' target, but that is intended mainly 87 | for the package's developers. If you use it, you may have to get 88 | all sorts of other programs in order to regenerate files that came 89 | with the distribution. 90 | 91 | 7. Often, you can also type `make uninstall' to remove the installed 92 | files again. In practice, not all packages have tested that 93 | uninstallation works correctly, even though it is required by the 94 | GNU Coding Standards. 95 | 96 | 8. Some packages, particularly those that use Automake, provide `make 97 | distcheck', which can by used by developers to test that all other 98 | targets like `make install' and `make uninstall' work correctly. 99 | This target is generally not run by end users. 100 | 101 | Compilers and Options 102 | ===================== 103 | 104 | Some systems require unusual options for compilation or linking that 105 | the `configure' script does not know about. Run `./configure --help' 106 | for details on some of the pertinent environment variables. 107 | 108 | You can give `configure' initial values for configuration parameters 109 | by setting variables in the command line or in the environment. Here 110 | is an example: 111 | 112 | ./configure CC=c99 CFLAGS=-g LIBS=-lposix 113 | 114 | *Note Defining Variables::, for more details. 115 | 116 | Compiling For Multiple Architectures 117 | ==================================== 118 | 119 | You can compile the package for more than one kind of computer at the 120 | same time, by placing the object files for each architecture in their 121 | own directory. To do this, you can use GNU `make'. `cd' to the 122 | directory where you want the object files and executables to go and run 123 | the `configure' script. `configure' automatically checks for the 124 | source code in the directory that `configure' is in and in `..'. This 125 | is known as a "VPATH" build. 126 | 127 | With a non-GNU `make', it is safer to compile the package for one 128 | architecture at a time in the source code directory. After you have 129 | installed the package for one architecture, use `make distclean' before 130 | reconfiguring for another architecture. 131 | 132 | On MacOS X 10.5 and later systems, you can create libraries and 133 | executables that work on multiple system types--known as "fat" or 134 | "universal" binaries--by specifying multiple `-arch' options to the 135 | compiler but only a single `-arch' option to the preprocessor. Like 136 | this: 137 | 138 | ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 139 | CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 140 | CPP="gcc -E" CXXCPP="g++ -E" 141 | 142 | This is not guaranteed to produce working output in all cases, you 143 | may have to build one architecture at a time and combine the results 144 | using the `lipo' tool if you have problems. 145 | 146 | Installation Names 147 | ================== 148 | 149 | By default, `make install' installs the package's commands under 150 | `/usr/local/bin', include files under `/usr/local/include', etc. You 151 | can specify an installation prefix other than `/usr/local' by giving 152 | `configure' the option `--prefix=PREFIX', where PREFIX must be an 153 | absolute file name. 154 | 155 | You can specify separate installation prefixes for 156 | architecture-specific files and architecture-independent files. If you 157 | pass the option `--exec-prefix=PREFIX' to `configure', the package uses 158 | PREFIX as the prefix for installing programs and libraries. 159 | Documentation and other data files still use the regular prefix. 160 | 161 | In addition, if you use an unusual directory layout you can give 162 | options like `--bindir=DIR' to specify different values for particular 163 | kinds of files. Run `configure --help' for a list of the directories 164 | you can set and what kinds of files go in them. In general, the 165 | default for these options is expressed in terms of `${prefix}', so that 166 | specifying just `--prefix' will affect all of the other directory 167 | specifications that were not explicitly provided. 168 | 169 | The most portable way to affect installation locations is to pass the 170 | correct locations to `configure'; however, many packages provide one or 171 | both of the following shortcuts of passing variable assignments to the 172 | `make install' command line to change installation locations without 173 | having to reconfigure or recompile. 174 | 175 | The first method involves providing an override variable for each 176 | affected directory. For example, `make install 177 | prefix=/alternate/directory' will choose an alternate location for all 178 | directory configuration variables that were expressed in terms of 179 | `${prefix}'. Any directories that were specified during `configure', 180 | but not in terms of `${prefix}', must each be overridden at install 181 | time for the entire installation to be relocated. The approach of 182 | makefile variable overrides for each directory variable is required by 183 | the GNU Coding Standards, and ideally causes no recompilation. 184 | However, some platforms have known limitations with the semantics of 185 | shared libraries that end up requiring recompilation when using this 186 | method, particularly noticeable in packages that use GNU Libtool. 187 | 188 | The second method involves providing the `DESTDIR' variable. For 189 | example, `make install DESTDIR=/alternate/directory' will prepend 190 | `/alternate/directory' before all installation names. The approach of 191 | `DESTDIR' overrides is not required by the GNU Coding Standards, and 192 | does not work on platforms that have drive letters. On the other hand, 193 | it does better at avoiding recompilation issues, and works well even 194 | when some directory options were not specified in terms of `${prefix}' 195 | at `configure' time. 196 | 197 | Optional Features 198 | ================= 199 | 200 | If the package supports it, you can cause programs to be installed 201 | with an extra prefix or suffix on their names by giving `configure' the 202 | option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. 203 | 204 | Some packages pay attention to `--enable-FEATURE' options to 205 | `configure', where FEATURE indicates an optional part of the package. 206 | They may also pay attention to `--with-PACKAGE' options, where PACKAGE 207 | is something like `gnu-as' or `x' (for the X Window System). The 208 | `README' should mention any `--enable-' and `--with-' options that the 209 | package recognizes. 210 | 211 | For packages that use the X Window System, `configure' can usually 212 | find the X include and library files automatically, but if it doesn't, 213 | you can use the `configure' options `--x-includes=DIR' and 214 | `--x-libraries=DIR' to specify their locations. 215 | 216 | Some packages offer the ability to configure how verbose the 217 | execution of `make' will be. For these packages, running `./configure 218 | --enable-silent-rules' sets the default to minimal output, which can be 219 | overridden with `make V=1'; while running `./configure 220 | --disable-silent-rules' sets the default to verbose, which can be 221 | overridden with `make V=0'. 222 | 223 | Particular systems 224 | ================== 225 | 226 | On HP-UX, the default C compiler is not ANSI C compatible. If GNU 227 | CC is not installed, it is recommended to use the following options in 228 | order to use an ANSI C compiler: 229 | 230 | ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" 231 | 232 | and if that doesn't work, install pre-built binaries of GCC for HP-UX. 233 | 234 | On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot 235 | parse its `' header file. The option `-nodtk' can be used as 236 | a workaround. If GNU CC is not installed, it is therefore recommended 237 | to try 238 | 239 | ./configure CC="cc" 240 | 241 | and if that doesn't work, try 242 | 243 | ./configure CC="cc -nodtk" 244 | 245 | On Solaris, don't put `/usr/ucb' early in your `PATH'. This 246 | directory contains several dysfunctional programs; working variants of 247 | these programs are available in `/usr/bin'. So, if you need `/usr/ucb' 248 | in your `PATH', put it _after_ `/usr/bin'. 249 | 250 | On Haiku, software installed for all users goes in `/boot/common', 251 | not `/usr/local'. It is recommended to use the following options: 252 | 253 | ./configure --prefix=/boot/common 254 | 255 | Specifying the System Type 256 | ========================== 257 | 258 | There may be some features `configure' cannot figure out 259 | automatically, but needs to determine by the type of machine the package 260 | will run on. Usually, assuming the package is built to be run on the 261 | _same_ architectures, `configure' can figure that out, but if it prints 262 | a message saying it cannot guess the machine type, give it the 263 | `--build=TYPE' option. TYPE can either be a short name for the system 264 | type, such as `sun4', or a canonical name which has the form: 265 | 266 | CPU-COMPANY-SYSTEM 267 | 268 | where SYSTEM can have one of these forms: 269 | 270 | OS 271 | KERNEL-OS 272 | 273 | See the file `config.sub' for the possible values of each field. If 274 | `config.sub' isn't included in this package, then this package doesn't 275 | need to know the machine type. 276 | 277 | If you are _building_ compiler tools for cross-compiling, you should 278 | use the option `--target=TYPE' to select the type of system they will 279 | produce code for. 280 | 281 | If you want to _use_ a cross compiler, that generates code for a 282 | platform different from the build platform, you should specify the 283 | "host" platform (i.e., that on which the generated programs will 284 | eventually be run) with `--host=TYPE'. 285 | 286 | Sharing Defaults 287 | ================ 288 | 289 | If you want to set default values for `configure' scripts to share, 290 | you can create a site shell script called `config.site' that gives 291 | default values for variables like `CC', `cache_file', and `prefix'. 292 | `configure' looks for `PREFIX/share/config.site' if it exists, then 293 | `PREFIX/etc/config.site' if it exists. Or, you can set the 294 | `CONFIG_SITE' environment variable to the location of the site script. 295 | A warning: not all `configure' scripts look for a site script. 296 | 297 | Defining Variables 298 | ================== 299 | 300 | Variables not defined in a site shell script can be set in the 301 | environment passed to `configure'. However, some packages may run 302 | configure again during the build, and the customized values of these 303 | variables may be lost. In order to avoid this problem, you should set 304 | them in the `configure' command line, using `VAR=value'. For example: 305 | 306 | ./configure CC=/usr/local2/bin/gcc 307 | 308 | causes the specified `gcc' to be used as the C compiler (unless it is 309 | overridden in the site shell script). 310 | 311 | Unfortunately, this technique does not work for `CONFIG_SHELL' due to 312 | an Autoconf bug. Until the bug is fixed you can use this workaround: 313 | 314 | CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash 315 | 316 | `configure' Invocation 317 | ====================== 318 | 319 | `configure' recognizes the following options to control how it 320 | operates. 321 | 322 | `--help' 323 | `-h' 324 | Print a summary of all of the options to `configure', and exit. 325 | 326 | `--help=short' 327 | `--help=recursive' 328 | Print a summary of the options unique to this package's 329 | `configure', and exit. The `short' variant lists options used 330 | only in the top level, while the `recursive' variant lists options 331 | also present in any nested packages. 332 | 333 | `--version' 334 | `-V' 335 | Print the version of Autoconf used to generate the `configure' 336 | script, and exit. 337 | 338 | `--cache-file=FILE' 339 | Enable the cache: use and save the results of the tests in FILE, 340 | traditionally `config.cache'. FILE defaults to `/dev/null' to 341 | disable caching. 342 | 343 | `--config-cache' 344 | `-C' 345 | Alias for `--cache-file=config.cache'. 346 | 347 | `--quiet' 348 | `--silent' 349 | `-q' 350 | Do not print messages saying which checks are being made. To 351 | suppress all normal output, redirect it to `/dev/null' (any error 352 | messages will still be shown). 353 | 354 | `--srcdir=DIR' 355 | Look for the package's source code in directory DIR. Usually 356 | `configure' can determine that directory automatically. 357 | 358 | `--prefix=DIR' 359 | Use DIR as the installation prefix. *note Installation Names:: 360 | for more details, including other options available for fine-tuning 361 | the installation locations. 362 | 363 | `--no-create' 364 | `-n' 365 | Run the configure checks, but stop before creating any output 366 | files. 367 | 368 | `configure' also accepts some other, not widely useful, options. Run 369 | `configure --help' for more details. 370 | 371 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = src 2 | dist_doc_DATA = README example.conf 3 | 4 | man_MANS = xchainkeys.1 5 | EXTRA_DIST = xchainkeys.1 6 | 7 | install-data-hook : 8 | $(SED) -E -i.orig 's|__PREFIX__|@prefix@|g' $(DESTDIR)$(man1dir)/xchainkeys.1 9 | rm $(DESTDIR)$(man1dir)/*.orig 10 | -------------------------------------------------------------------------------- /Makefile.in: -------------------------------------------------------------------------------- 1 | # Makefile.in generated by automake 1.16.1 from Makefile.am. 2 | # @configure_input@ 3 | 4 | # Copyright (C) 1994-2018 Free Software Foundation, Inc. 5 | 6 | # This Makefile.in is free software; the Free Software Foundation 7 | # gives unlimited permission to copy and/or distribute it, 8 | # with or without modifications, as long as this notice is preserved. 9 | 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without 12 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | # PARTICULAR PURPOSE. 14 | 15 | @SET_MAKE@ 16 | 17 | VPATH = @srcdir@ 18 | am__is_gnu_make = { \ 19 | if test -z '$(MAKELEVEL)'; then \ 20 | false; \ 21 | elif test -n '$(MAKE_HOST)'; then \ 22 | true; \ 23 | elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ 24 | true; \ 25 | else \ 26 | false; \ 27 | fi; \ 28 | } 29 | am__make_running_with_option = \ 30 | case $${target_option-} in \ 31 | ?) ;; \ 32 | *) echo "am__make_running_with_option: internal error: invalid" \ 33 | "target option '$${target_option-}' specified" >&2; \ 34 | exit 1;; \ 35 | esac; \ 36 | has_opt=no; \ 37 | sane_makeflags=$$MAKEFLAGS; \ 38 | if $(am__is_gnu_make); then \ 39 | sane_makeflags=$$MFLAGS; \ 40 | else \ 41 | case $$MAKEFLAGS in \ 42 | *\\[\ \ ]*) \ 43 | bs=\\; \ 44 | sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ 45 | | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ 46 | esac; \ 47 | fi; \ 48 | skip_next=no; \ 49 | strip_trailopt () \ 50 | { \ 51 | flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ 52 | }; \ 53 | for flg in $$sane_makeflags; do \ 54 | test $$skip_next = yes && { skip_next=no; continue; }; \ 55 | case $$flg in \ 56 | *=*|--*) continue;; \ 57 | -*I) strip_trailopt 'I'; skip_next=yes;; \ 58 | -*I?*) strip_trailopt 'I';; \ 59 | -*O) strip_trailopt 'O'; skip_next=yes;; \ 60 | -*O?*) strip_trailopt 'O';; \ 61 | -*l) strip_trailopt 'l'; skip_next=yes;; \ 62 | -*l?*) strip_trailopt 'l';; \ 63 | -[dEDm]) skip_next=yes;; \ 64 | -[JT]) skip_next=yes;; \ 65 | esac; \ 66 | case $$flg in \ 67 | *$$target_option*) has_opt=yes; break;; \ 68 | esac; \ 69 | done; \ 70 | test $$has_opt = yes 71 | am__make_dryrun = (target_option=n; $(am__make_running_with_option)) 72 | am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 73 | pkgdatadir = $(datadir)/@PACKAGE@ 74 | pkgincludedir = $(includedir)/@PACKAGE@ 75 | pkglibdir = $(libdir)/@PACKAGE@ 76 | pkglibexecdir = $(libexecdir)/@PACKAGE@ 77 | am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd 78 | install_sh_DATA = $(install_sh) -c -m 644 79 | install_sh_PROGRAM = $(install_sh) -c 80 | install_sh_SCRIPT = $(install_sh) -c 81 | INSTALL_HEADER = $(INSTALL_DATA) 82 | transform = $(program_transform_name) 83 | NORMAL_INSTALL = : 84 | PRE_INSTALL = : 85 | POST_INSTALL = : 86 | NORMAL_UNINSTALL = : 87 | PRE_UNINSTALL = : 88 | POST_UNINSTALL = : 89 | subdir = . 90 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 91 | am__aclocal_m4_deps = $(top_srcdir)/configure.ac 92 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ 93 | $(ACLOCAL_M4) 94 | DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ 95 | $(am__configure_deps) $(dist_doc_DATA) $(am__DIST_COMMON) 96 | am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ 97 | configure.lineno config.status.lineno 98 | mkinstalldirs = $(install_sh) -d 99 | CONFIG_CLEAN_FILES = 100 | CONFIG_CLEAN_VPATH_FILES = 101 | AM_V_P = $(am__v_P_@AM_V@) 102 | am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) 103 | am__v_P_0 = false 104 | am__v_P_1 = : 105 | AM_V_GEN = $(am__v_GEN_@AM_V@) 106 | am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) 107 | am__v_GEN_0 = @echo " GEN " $@; 108 | am__v_GEN_1 = 109 | AM_V_at = $(am__v_at_@AM_V@) 110 | am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) 111 | am__v_at_0 = @ 112 | am__v_at_1 = 113 | SOURCES = 114 | DIST_SOURCES = 115 | RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ 116 | ctags-recursive dvi-recursive html-recursive info-recursive \ 117 | install-data-recursive install-dvi-recursive \ 118 | install-exec-recursive install-html-recursive \ 119 | install-info-recursive install-pdf-recursive \ 120 | install-ps-recursive install-recursive installcheck-recursive \ 121 | installdirs-recursive pdf-recursive ps-recursive \ 122 | tags-recursive uninstall-recursive 123 | am__can_run_installinfo = \ 124 | case $$AM_UPDATE_INFO_DIR in \ 125 | n|no|NO) false;; \ 126 | *) (install-info --version) >/dev/null 2>&1;; \ 127 | esac 128 | am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; 129 | am__vpath_adj = case $$p in \ 130 | $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ 131 | *) f=$$p;; \ 132 | esac; 133 | am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; 134 | am__install_max = 40 135 | am__nobase_strip_setup = \ 136 | srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` 137 | am__nobase_strip = \ 138 | for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" 139 | am__nobase_list = $(am__nobase_strip_setup); \ 140 | for p in $$list; do echo "$$p $$p"; done | \ 141 | sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ 142 | $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ 143 | if (++n[$$2] == $(am__install_max)) \ 144 | { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ 145 | END { for (dir in files) print dir, files[dir] }' 146 | am__base_list = \ 147 | sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ 148 | sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' 149 | am__uninstall_files_from_dir = { \ 150 | test -z "$$files" \ 151 | || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ 152 | || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ 153 | $(am__cd) "$$dir" && rm -f $$files; }; \ 154 | } 155 | man1dir = $(mandir)/man1 156 | am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(docdir)" 157 | NROFF = nroff 158 | MANS = $(man_MANS) 159 | DATA = $(dist_doc_DATA) 160 | RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ 161 | distclean-recursive maintainer-clean-recursive 162 | am__recursive_targets = \ 163 | $(RECURSIVE_TARGETS) \ 164 | $(RECURSIVE_CLEAN_TARGETS) \ 165 | $(am__extra_recursive_targets) 166 | AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ 167 | cscope distdir distdir-am dist dist-all distcheck 168 | am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) 169 | # Read a list of newline-separated strings from the standard input, 170 | # and print each of them once, without duplicates. Input order is 171 | # *not* preserved. 172 | am__uniquify_input = $(AWK) '\ 173 | BEGIN { nonempty = 0; } \ 174 | { items[$$0] = 1; nonempty = 1; } \ 175 | END { if (nonempty) { for (i in items) print i; }; } \ 176 | ' 177 | # Make sure the list of sources is unique. This is necessary because, 178 | # e.g., the same source file might be shared among _SOURCES variables 179 | # for different programs/libraries. 180 | am__define_uniq_tagged_files = \ 181 | list='$(am__tagged_files)'; \ 182 | unique=`for i in $$list; do \ 183 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ 184 | done | $(am__uniquify_input)` 185 | ETAGS = etags 186 | CTAGS = ctags 187 | CSCOPE = cscope 188 | DIST_SUBDIRS = $(SUBDIRS) 189 | am__DIST_COMMON = $(srcdir)/Makefile.in AUTHORS COPYING ChangeLog \ 190 | INSTALL NEWS README compile depcomp install-sh missing 191 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) 192 | distdir = $(PACKAGE)-$(VERSION) 193 | top_distdir = $(distdir) 194 | am__remove_distdir = \ 195 | if test -d "$(distdir)"; then \ 196 | find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ 197 | && rm -rf "$(distdir)" \ 198 | || { sleep 5 && rm -rf "$(distdir)"; }; \ 199 | else :; fi 200 | am__post_remove_distdir = $(am__remove_distdir) 201 | am__relativize = \ 202 | dir0=`pwd`; \ 203 | sed_first='s,^\([^/]*\)/.*$$,\1,'; \ 204 | sed_rest='s,^[^/]*/*,,'; \ 205 | sed_last='s,^.*/\([^/]*\)$$,\1,'; \ 206 | sed_butlast='s,/*[^/]*$$,,'; \ 207 | while test -n "$$dir1"; do \ 208 | first=`echo "$$dir1" | sed -e "$$sed_first"`; \ 209 | if test "$$first" != "."; then \ 210 | if test "$$first" = ".."; then \ 211 | dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ 212 | dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ 213 | else \ 214 | first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ 215 | if test "$$first2" = "$$first"; then \ 216 | dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ 217 | else \ 218 | dir2="../$$dir2"; \ 219 | fi; \ 220 | dir0="$$dir0"/"$$first"; \ 221 | fi; \ 222 | fi; \ 223 | dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ 224 | done; \ 225 | reldir="$$dir2" 226 | DIST_ARCHIVES = $(distdir).tar.gz 227 | GZIP_ENV = --best 228 | DIST_TARGETS = dist-gzip 229 | distuninstallcheck_listfiles = find . -type f -print 230 | am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ 231 | | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' 232 | distcleancheck_listfiles = find . -type f -print 233 | ACLOCAL = @ACLOCAL@ 234 | AMTAR = @AMTAR@ 235 | AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ 236 | AUTOCONF = @AUTOCONF@ 237 | AUTOHEADER = @AUTOHEADER@ 238 | AUTOMAKE = @AUTOMAKE@ 239 | AWK = @AWK@ 240 | CC = @CC@ 241 | CCDEPMODE = @CCDEPMODE@ 242 | CFLAGS = @CFLAGS@ 243 | CPP = @CPP@ 244 | CPPFLAGS = @CPPFLAGS@ 245 | CYGPATH_W = @CYGPATH_W@ 246 | DEFS = @DEFS@ 247 | DEPDIR = @DEPDIR@ 248 | ECHO_C = @ECHO_C@ 249 | ECHO_N = @ECHO_N@ 250 | ECHO_T = @ECHO_T@ 251 | EGREP = @EGREP@ 252 | EXEEXT = @EXEEXT@ 253 | GREP = @GREP@ 254 | INSTALL = @INSTALL@ 255 | INSTALL_DATA = @INSTALL_DATA@ 256 | INSTALL_PROGRAM = @INSTALL_PROGRAM@ 257 | INSTALL_SCRIPT = @INSTALL_SCRIPT@ 258 | INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ 259 | LDFLAGS = @LDFLAGS@ 260 | LIBOBJS = @LIBOBJS@ 261 | LIBS = @LIBS@ 262 | LTLIBOBJS = @LTLIBOBJS@ 263 | MAKEINFO = @MAKEINFO@ 264 | MKDIR_P = @MKDIR_P@ 265 | OBJEXT = @OBJEXT@ 266 | PACKAGE = @PACKAGE@ 267 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ 268 | PACKAGE_NAME = @PACKAGE_NAME@ 269 | PACKAGE_STRING = @PACKAGE_STRING@ 270 | PACKAGE_TARNAME = @PACKAGE_TARNAME@ 271 | PACKAGE_URL = @PACKAGE_URL@ 272 | PACKAGE_VERSION = @PACKAGE_VERSION@ 273 | PATH_SEPARATOR = @PATH_SEPARATOR@ 274 | SED = @SED@ 275 | SET_MAKE = @SET_MAKE@ 276 | SHELL = @SHELL@ 277 | STRIP = @STRIP@ 278 | VERSION = @VERSION@ 279 | abs_builddir = @abs_builddir@ 280 | abs_srcdir = @abs_srcdir@ 281 | abs_top_builddir = @abs_top_builddir@ 282 | abs_top_srcdir = @abs_top_srcdir@ 283 | ac_ct_CC = @ac_ct_CC@ 284 | am__include = @am__include@ 285 | am__leading_dot = @am__leading_dot@ 286 | am__quote = @am__quote@ 287 | am__tar = @am__tar@ 288 | am__untar = @am__untar@ 289 | bindir = @bindir@ 290 | build_alias = @build_alias@ 291 | builddir = @builddir@ 292 | datadir = @datadir@ 293 | datarootdir = @datarootdir@ 294 | docdir = @docdir@ 295 | dvidir = @dvidir@ 296 | exec_prefix = @exec_prefix@ 297 | host_alias = @host_alias@ 298 | htmldir = @htmldir@ 299 | includedir = @includedir@ 300 | infodir = @infodir@ 301 | install_sh = @install_sh@ 302 | libdir = @libdir@ 303 | libexecdir = @libexecdir@ 304 | localedir = @localedir@ 305 | localstatedir = @localstatedir@ 306 | mandir = @mandir@ 307 | mkdir_p = @mkdir_p@ 308 | oldincludedir = @oldincludedir@ 309 | pdfdir = @pdfdir@ 310 | prefix = @prefix@ 311 | program_transform_name = @program_transform_name@ 312 | psdir = @psdir@ 313 | sbindir = @sbindir@ 314 | sharedstatedir = @sharedstatedir@ 315 | srcdir = @srcdir@ 316 | sysconfdir = @sysconfdir@ 317 | target_alias = @target_alias@ 318 | top_build_prefix = @top_build_prefix@ 319 | top_builddir = @top_builddir@ 320 | top_srcdir = @top_srcdir@ 321 | SUBDIRS = src 322 | dist_doc_DATA = README example.conf 323 | man_MANS = xchainkeys.1 324 | EXTRA_DIST = xchainkeys.1 325 | all: all-recursive 326 | 327 | .SUFFIXES: 328 | am--refresh: Makefile 329 | @: 330 | $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) 331 | @for dep in $?; do \ 332 | case '$(am__configure_deps)' in \ 333 | *$$dep*) \ 334 | echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ 335 | $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ 336 | && exit 0; \ 337 | exit 1;; \ 338 | esac; \ 339 | done; \ 340 | echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ 341 | $(am__cd) $(top_srcdir) && \ 342 | $(AUTOMAKE) --gnu Makefile 343 | Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status 344 | @case '$?' in \ 345 | *config.status*) \ 346 | echo ' $(SHELL) ./config.status'; \ 347 | $(SHELL) ./config.status;; \ 348 | *) \ 349 | echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ 350 | cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ 351 | esac; 352 | 353 | $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) 354 | $(SHELL) ./config.status --recheck 355 | 356 | $(top_srcdir)/configure: $(am__configure_deps) 357 | $(am__cd) $(srcdir) && $(AUTOCONF) 358 | $(ACLOCAL_M4): $(am__aclocal_m4_deps) 359 | $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) 360 | $(am__aclocal_m4_deps): 361 | install-man1: $(man_MANS) 362 | @$(NORMAL_INSTALL) 363 | @list1=''; \ 364 | list2='$(man_MANS)'; \ 365 | test -n "$(man1dir)" \ 366 | && test -n "`echo $$list1$$list2`" \ 367 | || exit 0; \ 368 | echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ 369 | $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ 370 | { for i in $$list1; do echo "$$i"; done; \ 371 | if test -n "$$list2"; then \ 372 | for i in $$list2; do echo "$$i"; done \ 373 | | sed -n '/\.1[a-z]*$$/p'; \ 374 | fi; \ 375 | } | while read p; do \ 376 | if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ 377 | echo "$$d$$p"; echo "$$p"; \ 378 | done | \ 379 | sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ 380 | -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ 381 | sed 'N;N;s,\n, ,g' | { \ 382 | list=; while read file base inst; do \ 383 | if test "$$base" = "$$inst"; then list="$$list $$file"; else \ 384 | echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ 385 | $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ 386 | fi; \ 387 | done; \ 388 | for i in $$list; do echo "$$i"; done | $(am__base_list) | \ 389 | while read files; do \ 390 | test -z "$$files" || { \ 391 | echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ 392 | $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ 393 | done; } 394 | 395 | uninstall-man1: 396 | @$(NORMAL_UNINSTALL) 397 | @list=''; test -n "$(man1dir)" || exit 0; \ 398 | files=`{ for i in $$list; do echo "$$i"; done; \ 399 | l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ 400 | sed -n '/\.1[a-z]*$$/p'; \ 401 | } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ 402 | -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ 403 | dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) 404 | install-dist_docDATA: $(dist_doc_DATA) 405 | @$(NORMAL_INSTALL) 406 | @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ 407 | if test -n "$$list"; then \ 408 | echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ 409 | $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ 410 | fi; \ 411 | for p in $$list; do \ 412 | if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ 413 | echo "$$d$$p"; \ 414 | done | $(am__base_list) | \ 415 | while read files; do \ 416 | echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ 417 | $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ 418 | done 419 | 420 | uninstall-dist_docDATA: 421 | @$(NORMAL_UNINSTALL) 422 | @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ 423 | files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ 424 | dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) 425 | 426 | # This directory's subdirectories are mostly independent; you can cd 427 | # into them and run 'make' without going through this Makefile. 428 | # To change the values of 'make' variables: instead of editing Makefiles, 429 | # (1) if the variable is set in 'config.status', edit 'config.status' 430 | # (which will cause the Makefiles to be regenerated when you run 'make'); 431 | # (2) otherwise, pass the desired values on the 'make' command line. 432 | $(am__recursive_targets): 433 | @fail=; \ 434 | if $(am__make_keepgoing); then \ 435 | failcom='fail=yes'; \ 436 | else \ 437 | failcom='exit 1'; \ 438 | fi; \ 439 | dot_seen=no; \ 440 | target=`echo $@ | sed s/-recursive//`; \ 441 | case "$@" in \ 442 | distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ 443 | *) list='$(SUBDIRS)' ;; \ 444 | esac; \ 445 | for subdir in $$list; do \ 446 | echo "Making $$target in $$subdir"; \ 447 | if test "$$subdir" = "."; then \ 448 | dot_seen=yes; \ 449 | local_target="$$target-am"; \ 450 | else \ 451 | local_target="$$target"; \ 452 | fi; \ 453 | ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ 454 | || eval $$failcom; \ 455 | done; \ 456 | if test "$$dot_seen" = "no"; then \ 457 | $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ 458 | fi; test -z "$$fail" 459 | 460 | ID: $(am__tagged_files) 461 | $(am__define_uniq_tagged_files); mkid -fID $$unique 462 | tags: tags-recursive 463 | TAGS: tags 464 | 465 | tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) 466 | set x; \ 467 | here=`pwd`; \ 468 | if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ 469 | include_option=--etags-include; \ 470 | empty_fix=.; \ 471 | else \ 472 | include_option=--include; \ 473 | empty_fix=; \ 474 | fi; \ 475 | list='$(SUBDIRS)'; for subdir in $$list; do \ 476 | if test "$$subdir" = .; then :; else \ 477 | test ! -f $$subdir/TAGS || \ 478 | set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ 479 | fi; \ 480 | done; \ 481 | $(am__define_uniq_tagged_files); \ 482 | shift; \ 483 | if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ 484 | test -n "$$unique" || unique=$$empty_fix; \ 485 | if test $$# -gt 0; then \ 486 | $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ 487 | "$$@" $$unique; \ 488 | else \ 489 | $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ 490 | $$unique; \ 491 | fi; \ 492 | fi 493 | ctags: ctags-recursive 494 | 495 | CTAGS: ctags 496 | ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) 497 | $(am__define_uniq_tagged_files); \ 498 | test -z "$(CTAGS_ARGS)$$unique" \ 499 | || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ 500 | $$unique 501 | 502 | GTAGS: 503 | here=`$(am__cd) $(top_builddir) && pwd` \ 504 | && $(am__cd) $(top_srcdir) \ 505 | && gtags -i $(GTAGS_ARGS) "$$here" 506 | cscope: cscope.files 507 | test ! -s cscope.files \ 508 | || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) 509 | clean-cscope: 510 | -rm -f cscope.files 511 | cscope.files: clean-cscope cscopelist 512 | cscopelist: cscopelist-recursive 513 | 514 | cscopelist-am: $(am__tagged_files) 515 | list='$(am__tagged_files)'; \ 516 | case "$(srcdir)" in \ 517 | [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ 518 | *) sdir=$(subdir)/$(srcdir) ;; \ 519 | esac; \ 520 | for i in $$list; do \ 521 | if test -f "$$i"; then \ 522 | echo "$(subdir)/$$i"; \ 523 | else \ 524 | echo "$$sdir/$$i"; \ 525 | fi; \ 526 | done >> $(top_builddir)/cscope.files 527 | 528 | distclean-tags: 529 | -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags 530 | -rm -f cscope.out cscope.in.out cscope.po.out cscope.files 531 | 532 | distdir: $(BUILT_SOURCES) 533 | $(MAKE) $(AM_MAKEFLAGS) distdir-am 534 | 535 | distdir-am: $(DISTFILES) 536 | $(am__remove_distdir) 537 | test -d "$(distdir)" || mkdir "$(distdir)" 538 | @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 539 | topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 540 | list='$(DISTFILES)'; \ 541 | dist_files=`for file in $$list; do echo $$file; done | \ 542 | sed -e "s|^$$srcdirstrip/||;t" \ 543 | -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ 544 | case $$dist_files in \ 545 | */*) $(MKDIR_P) `echo "$$dist_files" | \ 546 | sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ 547 | sort -u` ;; \ 548 | esac; \ 549 | for file in $$dist_files; do \ 550 | if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ 551 | if test -d $$d/$$file; then \ 552 | dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ 553 | if test -d "$(distdir)/$$file"; then \ 554 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ 555 | fi; \ 556 | if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ 557 | cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ 558 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ 559 | fi; \ 560 | cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ 561 | else \ 562 | test -f "$(distdir)/$$file" \ 563 | || cp -p $$d/$$file "$(distdir)/$$file" \ 564 | || exit 1; \ 565 | fi; \ 566 | done 567 | @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ 568 | if test "$$subdir" = .; then :; else \ 569 | $(am__make_dryrun) \ 570 | || test -d "$(distdir)/$$subdir" \ 571 | || $(MKDIR_P) "$(distdir)/$$subdir" \ 572 | || exit 1; \ 573 | dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ 574 | $(am__relativize); \ 575 | new_distdir=$$reldir; \ 576 | dir1=$$subdir; dir2="$(top_distdir)"; \ 577 | $(am__relativize); \ 578 | new_top_distdir=$$reldir; \ 579 | echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ 580 | echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ 581 | ($(am__cd) $$subdir && \ 582 | $(MAKE) $(AM_MAKEFLAGS) \ 583 | top_distdir="$$new_top_distdir" \ 584 | distdir="$$new_distdir" \ 585 | am__remove_distdir=: \ 586 | am__skip_length_check=: \ 587 | am__skip_mode_fix=: \ 588 | distdir) \ 589 | || exit 1; \ 590 | fi; \ 591 | done 592 | -test -n "$(am__skip_mode_fix)" \ 593 | || find "$(distdir)" -type d ! -perm -755 \ 594 | -exec chmod u+rwx,go+rx {} \; -o \ 595 | ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ 596 | ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ 597 | ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ 598 | || chmod -R a+r "$(distdir)" 599 | dist-gzip: distdir 600 | tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz 601 | $(am__post_remove_distdir) 602 | 603 | dist-bzip2: distdir 604 | tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 605 | $(am__post_remove_distdir) 606 | 607 | dist-lzip: distdir 608 | tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz 609 | $(am__post_remove_distdir) 610 | 611 | dist-xz: distdir 612 | tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz 613 | $(am__post_remove_distdir) 614 | 615 | dist-tarZ: distdir 616 | @echo WARNING: "Support for distribution archives compressed with" \ 617 | "legacy program 'compress' is deprecated." >&2 618 | @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 619 | tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z 620 | $(am__post_remove_distdir) 621 | 622 | dist-shar: distdir 623 | @echo WARNING: "Support for shar distribution archives is" \ 624 | "deprecated." >&2 625 | @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 626 | shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz 627 | $(am__post_remove_distdir) 628 | 629 | dist-zip: distdir 630 | -rm -f $(distdir).zip 631 | zip -rq $(distdir).zip $(distdir) 632 | $(am__post_remove_distdir) 633 | 634 | dist dist-all: 635 | $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' 636 | $(am__post_remove_distdir) 637 | 638 | # This target untars the dist file and tries a VPATH configuration. Then 639 | # it guarantees that the distribution is self-contained by making another 640 | # tarfile. 641 | distcheck: dist 642 | case '$(DIST_ARCHIVES)' in \ 643 | *.tar.gz*) \ 644 | eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ 645 | *.tar.bz2*) \ 646 | bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ 647 | *.tar.lz*) \ 648 | lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ 649 | *.tar.xz*) \ 650 | xz -dc $(distdir).tar.xz | $(am__untar) ;;\ 651 | *.tar.Z*) \ 652 | uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ 653 | *.shar.gz*) \ 654 | eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ 655 | *.zip*) \ 656 | unzip $(distdir).zip ;;\ 657 | esac 658 | chmod -R a-w $(distdir) 659 | chmod u+w $(distdir) 660 | mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst 661 | chmod a-w $(distdir) 662 | test -d $(distdir)/_build || exit 0; \ 663 | dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ 664 | && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ 665 | && am__cwd=`pwd` \ 666 | && $(am__cd) $(distdir)/_build/sub \ 667 | && ../../configure \ 668 | $(AM_DISTCHECK_CONFIGURE_FLAGS) \ 669 | $(DISTCHECK_CONFIGURE_FLAGS) \ 670 | --srcdir=../.. --prefix="$$dc_install_base" \ 671 | && $(MAKE) $(AM_MAKEFLAGS) \ 672 | && $(MAKE) $(AM_MAKEFLAGS) dvi \ 673 | && $(MAKE) $(AM_MAKEFLAGS) check \ 674 | && $(MAKE) $(AM_MAKEFLAGS) install \ 675 | && $(MAKE) $(AM_MAKEFLAGS) installcheck \ 676 | && $(MAKE) $(AM_MAKEFLAGS) uninstall \ 677 | && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ 678 | distuninstallcheck \ 679 | && chmod -R a-w "$$dc_install_base" \ 680 | && ({ \ 681 | (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ 682 | && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ 683 | && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ 684 | && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ 685 | distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ 686 | } || { rm -rf "$$dc_destdir"; exit 1; }) \ 687 | && rm -rf "$$dc_destdir" \ 688 | && $(MAKE) $(AM_MAKEFLAGS) dist \ 689 | && rm -rf $(DIST_ARCHIVES) \ 690 | && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ 691 | && cd "$$am__cwd" \ 692 | || exit 1 693 | $(am__post_remove_distdir) 694 | @(echo "$(distdir) archives ready for distribution: "; \ 695 | list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ 696 | sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' 697 | distuninstallcheck: 698 | @test -n '$(distuninstallcheck_dir)' || { \ 699 | echo 'ERROR: trying to run $@ with an empty' \ 700 | '$$(distuninstallcheck_dir)' >&2; \ 701 | exit 1; \ 702 | }; \ 703 | $(am__cd) '$(distuninstallcheck_dir)' || { \ 704 | echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ 705 | exit 1; \ 706 | }; \ 707 | test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ 708 | || { echo "ERROR: files left after uninstall:" ; \ 709 | if test -n "$(DESTDIR)"; then \ 710 | echo " (check DESTDIR support)"; \ 711 | fi ; \ 712 | $(distuninstallcheck_listfiles) ; \ 713 | exit 1; } >&2 714 | distcleancheck: distclean 715 | @if test '$(srcdir)' = . ; then \ 716 | echo "ERROR: distcleancheck can only run from a VPATH build" ; \ 717 | exit 1 ; \ 718 | fi 719 | @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ 720 | || { echo "ERROR: files left in build directory after distclean:" ; \ 721 | $(distcleancheck_listfiles) ; \ 722 | exit 1; } >&2 723 | check-am: all-am 724 | check: check-recursive 725 | all-am: Makefile $(MANS) $(DATA) 726 | installdirs: installdirs-recursive 727 | installdirs-am: 728 | for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(docdir)"; do \ 729 | test -z "$$dir" || $(MKDIR_P) "$$dir"; \ 730 | done 731 | install: install-recursive 732 | install-exec: install-exec-recursive 733 | install-data: install-data-recursive 734 | uninstall: uninstall-recursive 735 | 736 | install-am: all-am 737 | @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am 738 | 739 | installcheck: installcheck-recursive 740 | install-strip: 741 | if test -z '$(STRIP)'; then \ 742 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ 743 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ 744 | install; \ 745 | else \ 746 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ 747 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ 748 | "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ 749 | fi 750 | mostlyclean-generic: 751 | 752 | clean-generic: 753 | 754 | distclean-generic: 755 | -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) 756 | -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) 757 | 758 | maintainer-clean-generic: 759 | @echo "This command is intended for maintainers to use" 760 | @echo "it deletes files that may require special tools to rebuild." 761 | clean: clean-recursive 762 | 763 | clean-am: clean-generic mostlyclean-am 764 | 765 | distclean: distclean-recursive 766 | -rm -f $(am__CONFIG_DISTCLEAN_FILES) 767 | -rm -f Makefile 768 | distclean-am: clean-am distclean-generic distclean-tags 769 | 770 | dvi: dvi-recursive 771 | 772 | dvi-am: 773 | 774 | html: html-recursive 775 | 776 | html-am: 777 | 778 | info: info-recursive 779 | 780 | info-am: 781 | 782 | install-data-am: install-dist_docDATA install-man 783 | @$(NORMAL_INSTALL) 784 | $(MAKE) $(AM_MAKEFLAGS) install-data-hook 785 | install-dvi: install-dvi-recursive 786 | 787 | install-dvi-am: 788 | 789 | install-exec-am: 790 | 791 | install-html: install-html-recursive 792 | 793 | install-html-am: 794 | 795 | install-info: install-info-recursive 796 | 797 | install-info-am: 798 | 799 | install-man: install-man1 800 | 801 | install-pdf: install-pdf-recursive 802 | 803 | install-pdf-am: 804 | 805 | install-ps: install-ps-recursive 806 | 807 | install-ps-am: 808 | 809 | installcheck-am: 810 | 811 | maintainer-clean: maintainer-clean-recursive 812 | -rm -f $(am__CONFIG_DISTCLEAN_FILES) 813 | -rm -rf $(top_srcdir)/autom4te.cache 814 | -rm -f Makefile 815 | maintainer-clean-am: distclean-am maintainer-clean-generic 816 | 817 | mostlyclean: mostlyclean-recursive 818 | 819 | mostlyclean-am: mostlyclean-generic 820 | 821 | pdf: pdf-recursive 822 | 823 | pdf-am: 824 | 825 | ps: ps-recursive 826 | 827 | ps-am: 828 | 829 | uninstall-am: uninstall-dist_docDATA uninstall-man 830 | 831 | uninstall-man: uninstall-man1 832 | 833 | .MAKE: $(am__recursive_targets) install-am install-data-am \ 834 | install-strip 835 | 836 | .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ 837 | am--refresh check check-am clean clean-cscope clean-generic \ 838 | cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ 839 | dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \ 840 | distcheck distclean distclean-generic distclean-tags \ 841 | distcleancheck distdir distuninstallcheck dvi dvi-am html \ 842 | html-am info info-am install install-am install-data \ 843 | install-data-am install-data-hook install-dist_docDATA \ 844 | install-dvi install-dvi-am install-exec install-exec-am \ 845 | install-html install-html-am install-info install-info-am \ 846 | install-man install-man1 install-pdf install-pdf-am install-ps \ 847 | install-ps-am install-strip installcheck installcheck-am \ 848 | installdirs installdirs-am maintainer-clean \ 849 | maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ 850 | pdf-am ps ps-am tags tags-am uninstall uninstall-am \ 851 | uninstall-dist_docDATA uninstall-man uninstall-man1 852 | 853 | .PRECIOUS: Makefile 854 | 855 | 856 | install-data-hook : 857 | $(SED) -E -i.orig 's|__PREFIX__|@prefix@|g' $(DESTDIR)$(man1dir)/xchainkeys.1 858 | rm $(DESTDIR)$(man1dir)/*.orig 859 | 860 | # Tell versions [3.59,3.63) of GNU make to not export all variables. 861 | # Otherwise a system limit (for SysV at least) may be exceeded. 862 | .NOEXPORT: 863 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hbekel/xchainkeys/b725a52ad72209cbbc0c31516470dfab1252f317/NEWS -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Installation 2 | ============ 3 | 4 | GNU autotools are used for building and installing xchainkeys: 5 | 6 | $ ./configure --prefix=/usr 7 | $ make 8 | $ sudo make install 9 | 10 | This README file and an example configuration file will be installed 11 | to $PREFIX/share/doc/xchainkeys/. A manual page is included. 12 | 13 | The standard DESTDIR variable can be used for a staged install. 14 | 15 | Description 16 | =========== 17 | 18 | xchainkeys is a standalone X11 program to create chained key bindings 19 | similar to those found in the ratpoison window manager or the screen 20 | terminal multiplexer. 21 | 22 | Invocation 23 | ========== 24 | 25 | To autostart xchainkeys on X startup, add the following command to 26 | your ~/.xinitrc: 27 | 28 | xchainkeys & 29 | 30 | Alternatively use your WM/DE's autostart mechanism to start xchainkeys 31 | as a background process. 32 | 33 | Configuration 34 | ============= 35 | 36 | Create the file ~/.config/xchainkeys/xchainkeys.conf or copy the 37 | example config file $PREFIX/share/doc/xchainkeys/example.conf to the 38 | above location. 39 | 40 | See the manual page for further details and examples. 41 | -------------------------------------------------------------------------------- /compile: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Wrapper for compilers which do not understand '-c -o'. 3 | 4 | scriptversion=2016-01-11.22; # UTC 5 | 6 | # Copyright (C) 1999-2017 Free Software Foundation, Inc. 7 | # Written by Tom Tromey . 8 | # 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | # As a special exception to the GNU General Public License, if you 23 | # distribute this file as part of a program that contains a 24 | # configuration script generated by Autoconf, you may include it under 25 | # the same distribution terms that you use for the rest of that program. 26 | 27 | # This file is maintained in Automake, please report 28 | # bugs to or send patches to 29 | # . 30 | 31 | nl=' 32 | ' 33 | 34 | # We need space, tab and new line, in precisely that order. Quoting is 35 | # there to prevent tools from complaining about whitespace usage. 36 | IFS=" "" $nl" 37 | 38 | file_conv= 39 | 40 | # func_file_conv build_file lazy 41 | # Convert a $build file to $host form and store it in $file 42 | # Currently only supports Windows hosts. If the determined conversion 43 | # type is listed in (the comma separated) LAZY, no conversion will 44 | # take place. 45 | func_file_conv () 46 | { 47 | file=$1 48 | case $file in 49 | / | /[!/]*) # absolute file, and not a UNC file 50 | if test -z "$file_conv"; then 51 | # lazily determine how to convert abs files 52 | case `uname -s` in 53 | MINGW*) 54 | file_conv=mingw 55 | ;; 56 | CYGWIN*) 57 | file_conv=cygwin 58 | ;; 59 | *) 60 | file_conv=wine 61 | ;; 62 | esac 63 | fi 64 | case $file_conv/,$2, in 65 | *,$file_conv,*) 66 | ;; 67 | mingw/*) 68 | file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` 69 | ;; 70 | cygwin/*) 71 | file=`cygpath -m "$file" || echo "$file"` 72 | ;; 73 | wine/*) 74 | file=`winepath -w "$file" || echo "$file"` 75 | ;; 76 | esac 77 | ;; 78 | esac 79 | } 80 | 81 | # func_cl_dashL linkdir 82 | # Make cl look for libraries in LINKDIR 83 | func_cl_dashL () 84 | { 85 | func_file_conv "$1" 86 | if test -z "$lib_path"; then 87 | lib_path=$file 88 | else 89 | lib_path="$lib_path;$file" 90 | fi 91 | linker_opts="$linker_opts -LIBPATH:$file" 92 | } 93 | 94 | # func_cl_dashl library 95 | # Do a library search-path lookup for cl 96 | func_cl_dashl () 97 | { 98 | lib=$1 99 | found=no 100 | save_IFS=$IFS 101 | IFS=';' 102 | for dir in $lib_path $LIB 103 | do 104 | IFS=$save_IFS 105 | if $shared && test -f "$dir/$lib.dll.lib"; then 106 | found=yes 107 | lib=$dir/$lib.dll.lib 108 | break 109 | fi 110 | if test -f "$dir/$lib.lib"; then 111 | found=yes 112 | lib=$dir/$lib.lib 113 | break 114 | fi 115 | if test -f "$dir/lib$lib.a"; then 116 | found=yes 117 | lib=$dir/lib$lib.a 118 | break 119 | fi 120 | done 121 | IFS=$save_IFS 122 | 123 | if test "$found" != yes; then 124 | lib=$lib.lib 125 | fi 126 | } 127 | 128 | # func_cl_wrapper cl arg... 129 | # Adjust compile command to suit cl 130 | func_cl_wrapper () 131 | { 132 | # Assume a capable shell 133 | lib_path= 134 | shared=: 135 | linker_opts= 136 | for arg 137 | do 138 | if test -n "$eat"; then 139 | eat= 140 | else 141 | case $1 in 142 | -o) 143 | # configure might choose to run compile as 'compile cc -o foo foo.c'. 144 | eat=1 145 | case $2 in 146 | *.o | *.[oO][bB][jJ]) 147 | func_file_conv "$2" 148 | set x "$@" -Fo"$file" 149 | shift 150 | ;; 151 | *) 152 | func_file_conv "$2" 153 | set x "$@" -Fe"$file" 154 | shift 155 | ;; 156 | esac 157 | ;; 158 | -I) 159 | eat=1 160 | func_file_conv "$2" mingw 161 | set x "$@" -I"$file" 162 | shift 163 | ;; 164 | -I*) 165 | func_file_conv "${1#-I}" mingw 166 | set x "$@" -I"$file" 167 | shift 168 | ;; 169 | -l) 170 | eat=1 171 | func_cl_dashl "$2" 172 | set x "$@" "$lib" 173 | shift 174 | ;; 175 | -l*) 176 | func_cl_dashl "${1#-l}" 177 | set x "$@" "$lib" 178 | shift 179 | ;; 180 | -L) 181 | eat=1 182 | func_cl_dashL "$2" 183 | ;; 184 | -L*) 185 | func_cl_dashL "${1#-L}" 186 | ;; 187 | -static) 188 | shared=false 189 | ;; 190 | -Wl,*) 191 | arg=${1#-Wl,} 192 | save_ifs="$IFS"; IFS=',' 193 | for flag in $arg; do 194 | IFS="$save_ifs" 195 | linker_opts="$linker_opts $flag" 196 | done 197 | IFS="$save_ifs" 198 | ;; 199 | -Xlinker) 200 | eat=1 201 | linker_opts="$linker_opts $2" 202 | ;; 203 | -*) 204 | set x "$@" "$1" 205 | shift 206 | ;; 207 | *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) 208 | func_file_conv "$1" 209 | set x "$@" -Tp"$file" 210 | shift 211 | ;; 212 | *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) 213 | func_file_conv "$1" mingw 214 | set x "$@" "$file" 215 | shift 216 | ;; 217 | *) 218 | set x "$@" "$1" 219 | shift 220 | ;; 221 | esac 222 | fi 223 | shift 224 | done 225 | if test -n "$linker_opts"; then 226 | linker_opts="-link$linker_opts" 227 | fi 228 | exec "$@" $linker_opts 229 | exit 1 230 | } 231 | 232 | eat= 233 | 234 | case $1 in 235 | '') 236 | echo "$0: No command. Try '$0 --help' for more information." 1>&2 237 | exit 1; 238 | ;; 239 | -h | --h*) 240 | cat <<\EOF 241 | Usage: compile [--help] [--version] PROGRAM [ARGS] 242 | 243 | Wrapper for compilers which do not understand '-c -o'. 244 | Remove '-o dest.o' from ARGS, run PROGRAM with the remaining 245 | arguments, and rename the output as expected. 246 | 247 | If you are trying to build a whole package this is not the 248 | right script to run: please start by reading the file 'INSTALL'. 249 | 250 | Report bugs to . 251 | EOF 252 | exit $? 253 | ;; 254 | -v | --v*) 255 | echo "compile $scriptversion" 256 | exit $? 257 | ;; 258 | cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ 259 | icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) 260 | func_cl_wrapper "$@" # Doesn't return... 261 | ;; 262 | esac 263 | 264 | ofile= 265 | cfile= 266 | 267 | for arg 268 | do 269 | if test -n "$eat"; then 270 | eat= 271 | else 272 | case $1 in 273 | -o) 274 | # configure might choose to run compile as 'compile cc -o foo foo.c'. 275 | # So we strip '-o arg' only if arg is an object. 276 | eat=1 277 | case $2 in 278 | *.o | *.obj) 279 | ofile=$2 280 | ;; 281 | *) 282 | set x "$@" -o "$2" 283 | shift 284 | ;; 285 | esac 286 | ;; 287 | *.c) 288 | cfile=$1 289 | set x "$@" "$1" 290 | shift 291 | ;; 292 | *) 293 | set x "$@" "$1" 294 | shift 295 | ;; 296 | esac 297 | fi 298 | shift 299 | done 300 | 301 | if test -z "$ofile" || test -z "$cfile"; then 302 | # If no '-o' option was seen then we might have been invoked from a 303 | # pattern rule where we don't need one. That is ok -- this is a 304 | # normal compilation that the losing compiler can handle. If no 305 | # '.c' file was seen then we are probably linking. That is also 306 | # ok. 307 | exec "$@" 308 | fi 309 | 310 | # Name of file we expect compiler to create. 311 | cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` 312 | 313 | # Create the lock directory. 314 | # Note: use '[/\\:.-]' here to ensure that we don't use the same name 315 | # that we are using for the .o file. Also, base the name on the expected 316 | # object file name, since that is what matters with a parallel build. 317 | lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d 318 | while true; do 319 | if mkdir "$lockdir" >/dev/null 2>&1; then 320 | break 321 | fi 322 | sleep 1 323 | done 324 | # FIXME: race condition here if user kills between mkdir and trap. 325 | trap "rmdir '$lockdir'; exit 1" 1 2 15 326 | 327 | # Run the compile. 328 | "$@" 329 | ret=$? 330 | 331 | if test -f "$cofile"; then 332 | test "$cofile" = "$ofile" || mv "$cofile" "$ofile" 333 | elif test -f "${cofile}bj"; then 334 | test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" 335 | fi 336 | 337 | rmdir "$lockdir" 338 | exit $ret 339 | 340 | # Local Variables: 341 | # mode: shell-script 342 | # sh-indentation: 2 343 | # eval: (add-hook 'write-file-hooks 'time-stamp) 344 | # time-stamp-start: "scriptversion=" 345 | # time-stamp-format: "%:y-%02m-%02d.%02H" 346 | # time-stamp-time-zone: "UTC0" 347 | # time-stamp-end: "; # UTC" 348 | # End: 349 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.65]) 5 | AC_INIT([xchainkeys], [0.11], [h.bekel@googlemail.com]) 6 | AC_CONFIG_SRCDIR([src/xchainkeys.c]) 7 | AM_INIT_AUTOMAKE 8 | 9 | # Checks for programs. 10 | AC_PROG_CC 11 | AC_PROG_SED 12 | 13 | # Make sure headers and libs are found on BSD as well. 14 | CFLAGS="-I/usr/local/include $CFLAGS" 15 | CPPFLAGS="-I/usr/local/include $CPPFLAGS" 16 | LDFLAGS="-L/usr/local/lib $LDFLAGS" 17 | 18 | # Checks for headers. 19 | AC_CHECK_HEADER(X11/Xlib.h,, 20 | AC_MSG_ERROR([Could not find X11/Xlib.h]) 21 | ) 22 | 23 | # Checks for libraries. 24 | AC_CHECK_LIB(X11, XOpenDisplay, 25 | LIBS="$LIBS -lX11", 26 | AC_MSG_ERROR([Could not find XOpenDisplay in -lX11.]) 27 | ) 28 | 29 | # Create Makefiles 30 | AC_OUTPUT(Makefile src/Makefile) 31 | AC_OUTPUT 32 | -------------------------------------------------------------------------------- /depcomp: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # depcomp - compile a program generating dependencies as side-effects 3 | 4 | scriptversion=2016-01-11.22; # UTC 5 | 6 | # Copyright (C) 1999-2017 Free Software Foundation, Inc. 7 | 8 | # This program is free software; you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation; either version 2, or (at your option) 11 | # any later version. 12 | 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | 21 | # As a special exception to the GNU General Public License, if you 22 | # distribute this file as part of a program that contains a 23 | # configuration script generated by Autoconf, you may include it under 24 | # the same distribution terms that you use for the rest of that program. 25 | 26 | # Originally written by Alexandre Oliva . 27 | 28 | case $1 in 29 | '') 30 | echo "$0: No command. Try '$0 --help' for more information." 1>&2 31 | exit 1; 32 | ;; 33 | -h | --h*) 34 | cat <<\EOF 35 | Usage: depcomp [--help] [--version] PROGRAM [ARGS] 36 | 37 | Run PROGRAMS ARGS to compile a file, generating dependencies 38 | as side-effects. 39 | 40 | Environment variables: 41 | depmode Dependency tracking mode. 42 | source Source file read by 'PROGRAMS ARGS'. 43 | object Object file output by 'PROGRAMS ARGS'. 44 | DEPDIR directory where to store dependencies. 45 | depfile Dependency file to output. 46 | tmpdepfile Temporary file to use when outputting dependencies. 47 | libtool Whether libtool is used (yes/no). 48 | 49 | Report bugs to . 50 | EOF 51 | exit $? 52 | ;; 53 | -v | --v*) 54 | echo "depcomp $scriptversion" 55 | exit $? 56 | ;; 57 | esac 58 | 59 | # Get the directory component of the given path, and save it in the 60 | # global variables '$dir'. Note that this directory component will 61 | # be either empty or ending with a '/' character. This is deliberate. 62 | set_dir_from () 63 | { 64 | case $1 in 65 | */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; 66 | *) dir=;; 67 | esac 68 | } 69 | 70 | # Get the suffix-stripped basename of the given path, and save it the 71 | # global variable '$base'. 72 | set_base_from () 73 | { 74 | base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` 75 | } 76 | 77 | # If no dependency file was actually created by the compiler invocation, 78 | # we still have to create a dummy depfile, to avoid errors with the 79 | # Makefile "include basename.Plo" scheme. 80 | make_dummy_depfile () 81 | { 82 | echo "#dummy" > "$depfile" 83 | } 84 | 85 | # Factor out some common post-processing of the generated depfile. 86 | # Requires the auxiliary global variable '$tmpdepfile' to be set. 87 | aix_post_process_depfile () 88 | { 89 | # If the compiler actually managed to produce a dependency file, 90 | # post-process it. 91 | if test -f "$tmpdepfile"; then 92 | # Each line is of the form 'foo.o: dependency.h'. 93 | # Do two passes, one to just change these to 94 | # $object: dependency.h 95 | # and one to simply output 96 | # dependency.h: 97 | # which is needed to avoid the deleted-header problem. 98 | { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" 99 | sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" 100 | } > "$depfile" 101 | rm -f "$tmpdepfile" 102 | else 103 | make_dummy_depfile 104 | fi 105 | } 106 | 107 | # A tabulation character. 108 | tab=' ' 109 | # A newline character. 110 | nl=' 111 | ' 112 | # Character ranges might be problematic outside the C locale. 113 | # These definitions help. 114 | upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ 115 | lower=abcdefghijklmnopqrstuvwxyz 116 | digits=0123456789 117 | alpha=${upper}${lower} 118 | 119 | if test -z "$depmode" || test -z "$source" || test -z "$object"; then 120 | echo "depcomp: Variables source, object and depmode must be set" 1>&2 121 | exit 1 122 | fi 123 | 124 | # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. 125 | depfile=${depfile-`echo "$object" | 126 | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} 127 | tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} 128 | 129 | rm -f "$tmpdepfile" 130 | 131 | # Avoid interferences from the environment. 132 | gccflag= dashmflag= 133 | 134 | # Some modes work just like other modes, but use different flags. We 135 | # parameterize here, but still list the modes in the big case below, 136 | # to make depend.m4 easier to write. Note that we *cannot* use a case 137 | # here, because this file can only contain one case statement. 138 | if test "$depmode" = hp; then 139 | # HP compiler uses -M and no extra arg. 140 | gccflag=-M 141 | depmode=gcc 142 | fi 143 | 144 | if test "$depmode" = dashXmstdout; then 145 | # This is just like dashmstdout with a different argument. 146 | dashmflag=-xM 147 | depmode=dashmstdout 148 | fi 149 | 150 | cygpath_u="cygpath -u -f -" 151 | if test "$depmode" = msvcmsys; then 152 | # This is just like msvisualcpp but w/o cygpath translation. 153 | # Just convert the backslash-escaped backslashes to single forward 154 | # slashes to satisfy depend.m4 155 | cygpath_u='sed s,\\\\,/,g' 156 | depmode=msvisualcpp 157 | fi 158 | 159 | if test "$depmode" = msvc7msys; then 160 | # This is just like msvc7 but w/o cygpath translation. 161 | # Just convert the backslash-escaped backslashes to single forward 162 | # slashes to satisfy depend.m4 163 | cygpath_u='sed s,\\\\,/,g' 164 | depmode=msvc7 165 | fi 166 | 167 | if test "$depmode" = xlc; then 168 | # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. 169 | gccflag=-qmakedep=gcc,-MF 170 | depmode=gcc 171 | fi 172 | 173 | case "$depmode" in 174 | gcc3) 175 | ## gcc 3 implements dependency tracking that does exactly what 176 | ## we want. Yay! Note: for some reason libtool 1.4 doesn't like 177 | ## it if -MD -MP comes after the -MF stuff. Hmm. 178 | ## Unfortunately, FreeBSD c89 acceptance of flags depends upon 179 | ## the command line argument order; so add the flags where they 180 | ## appear in depend2.am. Note that the slowdown incurred here 181 | ## affects only configure: in makefiles, %FASTDEP% shortcuts this. 182 | for arg 183 | do 184 | case $arg in 185 | -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; 186 | *) set fnord "$@" "$arg" ;; 187 | esac 188 | shift # fnord 189 | shift # $arg 190 | done 191 | "$@" 192 | stat=$? 193 | if test $stat -ne 0; then 194 | rm -f "$tmpdepfile" 195 | exit $stat 196 | fi 197 | mv "$tmpdepfile" "$depfile" 198 | ;; 199 | 200 | gcc) 201 | ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. 202 | ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. 203 | ## (see the conditional assignment to $gccflag above). 204 | ## There are various ways to get dependency output from gcc. Here's 205 | ## why we pick this rather obscure method: 206 | ## - Don't want to use -MD because we'd like the dependencies to end 207 | ## up in a subdir. Having to rename by hand is ugly. 208 | ## (We might end up doing this anyway to support other compilers.) 209 | ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like 210 | ## -MM, not -M (despite what the docs say). Also, it might not be 211 | ## supported by the other compilers which use the 'gcc' depmode. 212 | ## - Using -M directly means running the compiler twice (even worse 213 | ## than renaming). 214 | if test -z "$gccflag"; then 215 | gccflag=-MD, 216 | fi 217 | "$@" -Wp,"$gccflag$tmpdepfile" 218 | stat=$? 219 | if test $stat -ne 0; then 220 | rm -f "$tmpdepfile" 221 | exit $stat 222 | fi 223 | rm -f "$depfile" 224 | echo "$object : \\" > "$depfile" 225 | # The second -e expression handles DOS-style file names with drive 226 | # letters. 227 | sed -e 's/^[^:]*: / /' \ 228 | -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" 229 | ## This next piece of magic avoids the "deleted header file" problem. 230 | ## The problem is that when a header file which appears in a .P file 231 | ## is deleted, the dependency causes make to die (because there is 232 | ## typically no way to rebuild the header). We avoid this by adding 233 | ## dummy dependencies for each header file. Too bad gcc doesn't do 234 | ## this for us directly. 235 | ## Some versions of gcc put a space before the ':'. On the theory 236 | ## that the space means something, we add a space to the output as 237 | ## well. hp depmode also adds that space, but also prefixes the VPATH 238 | ## to the object. Take care to not repeat it in the output. 239 | ## Some versions of the HPUX 10.20 sed can't process this invocation 240 | ## correctly. Breaking it into two sed invocations is a workaround. 241 | tr ' ' "$nl" < "$tmpdepfile" \ 242 | | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ 243 | | sed -e 's/$/ :/' >> "$depfile" 244 | rm -f "$tmpdepfile" 245 | ;; 246 | 247 | hp) 248 | # This case exists only to let depend.m4 do its work. It works by 249 | # looking at the text of this script. This case will never be run, 250 | # since it is checked for above. 251 | exit 1 252 | ;; 253 | 254 | sgi) 255 | if test "$libtool" = yes; then 256 | "$@" "-Wp,-MDupdate,$tmpdepfile" 257 | else 258 | "$@" -MDupdate "$tmpdepfile" 259 | fi 260 | stat=$? 261 | if test $stat -ne 0; then 262 | rm -f "$tmpdepfile" 263 | exit $stat 264 | fi 265 | rm -f "$depfile" 266 | 267 | if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files 268 | echo "$object : \\" > "$depfile" 269 | # Clip off the initial element (the dependent). Don't try to be 270 | # clever and replace this with sed code, as IRIX sed won't handle 271 | # lines with more than a fixed number of characters (4096 in 272 | # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; 273 | # the IRIX cc adds comments like '#:fec' to the end of the 274 | # dependency line. 275 | tr ' ' "$nl" < "$tmpdepfile" \ 276 | | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ 277 | | tr "$nl" ' ' >> "$depfile" 278 | echo >> "$depfile" 279 | # The second pass generates a dummy entry for each header file. 280 | tr ' ' "$nl" < "$tmpdepfile" \ 281 | | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ 282 | >> "$depfile" 283 | else 284 | make_dummy_depfile 285 | fi 286 | rm -f "$tmpdepfile" 287 | ;; 288 | 289 | xlc) 290 | # This case exists only to let depend.m4 do its work. It works by 291 | # looking at the text of this script. This case will never be run, 292 | # since it is checked for above. 293 | exit 1 294 | ;; 295 | 296 | aix) 297 | # The C for AIX Compiler uses -M and outputs the dependencies 298 | # in a .u file. In older versions, this file always lives in the 299 | # current directory. Also, the AIX compiler puts '$object:' at the 300 | # start of each line; $object doesn't have directory information. 301 | # Version 6 uses the directory in both cases. 302 | set_dir_from "$object" 303 | set_base_from "$object" 304 | if test "$libtool" = yes; then 305 | tmpdepfile1=$dir$base.u 306 | tmpdepfile2=$base.u 307 | tmpdepfile3=$dir.libs/$base.u 308 | "$@" -Wc,-M 309 | else 310 | tmpdepfile1=$dir$base.u 311 | tmpdepfile2=$dir$base.u 312 | tmpdepfile3=$dir$base.u 313 | "$@" -M 314 | fi 315 | stat=$? 316 | if test $stat -ne 0; then 317 | rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" 318 | exit $stat 319 | fi 320 | 321 | for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" 322 | do 323 | test -f "$tmpdepfile" && break 324 | done 325 | aix_post_process_depfile 326 | ;; 327 | 328 | tcc) 329 | # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 330 | # FIXME: That version still under development at the moment of writing. 331 | # Make that this statement remains true also for stable, released 332 | # versions. 333 | # It will wrap lines (doesn't matter whether long or short) with a 334 | # trailing '\', as in: 335 | # 336 | # foo.o : \ 337 | # foo.c \ 338 | # foo.h \ 339 | # 340 | # It will put a trailing '\' even on the last line, and will use leading 341 | # spaces rather than leading tabs (at least since its commit 0394caf7 342 | # "Emit spaces for -MD"). 343 | "$@" -MD -MF "$tmpdepfile" 344 | stat=$? 345 | if test $stat -ne 0; then 346 | rm -f "$tmpdepfile" 347 | exit $stat 348 | fi 349 | rm -f "$depfile" 350 | # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. 351 | # We have to change lines of the first kind to '$object: \'. 352 | sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" 353 | # And for each line of the second kind, we have to emit a 'dep.h:' 354 | # dummy dependency, to avoid the deleted-header problem. 355 | sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" 356 | rm -f "$tmpdepfile" 357 | ;; 358 | 359 | ## The order of this option in the case statement is important, since the 360 | ## shell code in configure will try each of these formats in the order 361 | ## listed in this file. A plain '-MD' option would be understood by many 362 | ## compilers, so we must ensure this comes after the gcc and icc options. 363 | pgcc) 364 | # Portland's C compiler understands '-MD'. 365 | # Will always output deps to 'file.d' where file is the root name of the 366 | # source file under compilation, even if file resides in a subdirectory. 367 | # The object file name does not affect the name of the '.d' file. 368 | # pgcc 10.2 will output 369 | # foo.o: sub/foo.c sub/foo.h 370 | # and will wrap long lines using '\' : 371 | # foo.o: sub/foo.c ... \ 372 | # sub/foo.h ... \ 373 | # ... 374 | set_dir_from "$object" 375 | # Use the source, not the object, to determine the base name, since 376 | # that's sadly what pgcc will do too. 377 | set_base_from "$source" 378 | tmpdepfile=$base.d 379 | 380 | # For projects that build the same source file twice into different object 381 | # files, the pgcc approach of using the *source* file root name can cause 382 | # problems in parallel builds. Use a locking strategy to avoid stomping on 383 | # the same $tmpdepfile. 384 | lockdir=$base.d-lock 385 | trap " 386 | echo '$0: caught signal, cleaning up...' >&2 387 | rmdir '$lockdir' 388 | exit 1 389 | " 1 2 13 15 390 | numtries=100 391 | i=$numtries 392 | while test $i -gt 0; do 393 | # mkdir is a portable test-and-set. 394 | if mkdir "$lockdir" 2>/dev/null; then 395 | # This process acquired the lock. 396 | "$@" -MD 397 | stat=$? 398 | # Release the lock. 399 | rmdir "$lockdir" 400 | break 401 | else 402 | # If the lock is being held by a different process, wait 403 | # until the winning process is done or we timeout. 404 | while test -d "$lockdir" && test $i -gt 0; do 405 | sleep 1 406 | i=`expr $i - 1` 407 | done 408 | fi 409 | i=`expr $i - 1` 410 | done 411 | trap - 1 2 13 15 412 | if test $i -le 0; then 413 | echo "$0: failed to acquire lock after $numtries attempts" >&2 414 | echo "$0: check lockdir '$lockdir'" >&2 415 | exit 1 416 | fi 417 | 418 | if test $stat -ne 0; then 419 | rm -f "$tmpdepfile" 420 | exit $stat 421 | fi 422 | rm -f "$depfile" 423 | # Each line is of the form `foo.o: dependent.h', 424 | # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. 425 | # Do two passes, one to just change these to 426 | # `$object: dependent.h' and one to simply `dependent.h:'. 427 | sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" 428 | # Some versions of the HPUX 10.20 sed can't process this invocation 429 | # correctly. Breaking it into two sed invocations is a workaround. 430 | sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ 431 | | sed -e 's/$/ :/' >> "$depfile" 432 | rm -f "$tmpdepfile" 433 | ;; 434 | 435 | hp2) 436 | # The "hp" stanza above does not work with aCC (C++) and HP's ia64 437 | # compilers, which have integrated preprocessors. The correct option 438 | # to use with these is +Maked; it writes dependencies to a file named 439 | # 'foo.d', which lands next to the object file, wherever that 440 | # happens to be. 441 | # Much of this is similar to the tru64 case; see comments there. 442 | set_dir_from "$object" 443 | set_base_from "$object" 444 | if test "$libtool" = yes; then 445 | tmpdepfile1=$dir$base.d 446 | tmpdepfile2=$dir.libs/$base.d 447 | "$@" -Wc,+Maked 448 | else 449 | tmpdepfile1=$dir$base.d 450 | tmpdepfile2=$dir$base.d 451 | "$@" +Maked 452 | fi 453 | stat=$? 454 | if test $stat -ne 0; then 455 | rm -f "$tmpdepfile1" "$tmpdepfile2" 456 | exit $stat 457 | fi 458 | 459 | for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" 460 | do 461 | test -f "$tmpdepfile" && break 462 | done 463 | if test -f "$tmpdepfile"; then 464 | sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" 465 | # Add 'dependent.h:' lines. 466 | sed -ne '2,${ 467 | s/^ *// 468 | s/ \\*$// 469 | s/$/:/ 470 | p 471 | }' "$tmpdepfile" >> "$depfile" 472 | else 473 | make_dummy_depfile 474 | fi 475 | rm -f "$tmpdepfile" "$tmpdepfile2" 476 | ;; 477 | 478 | tru64) 479 | # The Tru64 compiler uses -MD to generate dependencies as a side 480 | # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. 481 | # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put 482 | # dependencies in 'foo.d' instead, so we check for that too. 483 | # Subdirectories are respected. 484 | set_dir_from "$object" 485 | set_base_from "$object" 486 | 487 | if test "$libtool" = yes; then 488 | # Libtool generates 2 separate objects for the 2 libraries. These 489 | # two compilations output dependencies in $dir.libs/$base.o.d and 490 | # in $dir$base.o.d. We have to check for both files, because 491 | # one of the two compilations can be disabled. We should prefer 492 | # $dir$base.o.d over $dir.libs/$base.o.d because the latter is 493 | # automatically cleaned when .libs/ is deleted, while ignoring 494 | # the former would cause a distcleancheck panic. 495 | tmpdepfile1=$dir$base.o.d # libtool 1.5 496 | tmpdepfile2=$dir.libs/$base.o.d # Likewise. 497 | tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 498 | "$@" -Wc,-MD 499 | else 500 | tmpdepfile1=$dir$base.d 501 | tmpdepfile2=$dir$base.d 502 | tmpdepfile3=$dir$base.d 503 | "$@" -MD 504 | fi 505 | 506 | stat=$? 507 | if test $stat -ne 0; then 508 | rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" 509 | exit $stat 510 | fi 511 | 512 | for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" 513 | do 514 | test -f "$tmpdepfile" && break 515 | done 516 | # Same post-processing that is required for AIX mode. 517 | aix_post_process_depfile 518 | ;; 519 | 520 | msvc7) 521 | if test "$libtool" = yes; then 522 | showIncludes=-Wc,-showIncludes 523 | else 524 | showIncludes=-showIncludes 525 | fi 526 | "$@" $showIncludes > "$tmpdepfile" 527 | stat=$? 528 | grep -v '^Note: including file: ' "$tmpdepfile" 529 | if test $stat -ne 0; then 530 | rm -f "$tmpdepfile" 531 | exit $stat 532 | fi 533 | rm -f "$depfile" 534 | echo "$object : \\" > "$depfile" 535 | # The first sed program below extracts the file names and escapes 536 | # backslashes for cygpath. The second sed program outputs the file 537 | # name when reading, but also accumulates all include files in the 538 | # hold buffer in order to output them again at the end. This only 539 | # works with sed implementations that can handle large buffers. 540 | sed < "$tmpdepfile" -n ' 541 | /^Note: including file: *\(.*\)/ { 542 | s//\1/ 543 | s/\\/\\\\/g 544 | p 545 | }' | $cygpath_u | sort -u | sed -n ' 546 | s/ /\\ /g 547 | s/\(.*\)/'"$tab"'\1 \\/p 548 | s/.\(.*\) \\/\1:/ 549 | H 550 | $ { 551 | s/.*/'"$tab"'/ 552 | G 553 | p 554 | }' >> "$depfile" 555 | echo >> "$depfile" # make sure the fragment doesn't end with a backslash 556 | rm -f "$tmpdepfile" 557 | ;; 558 | 559 | msvc7msys) 560 | # This case exists only to let depend.m4 do its work. It works by 561 | # looking at the text of this script. This case will never be run, 562 | # since it is checked for above. 563 | exit 1 564 | ;; 565 | 566 | #nosideeffect) 567 | # This comment above is used by automake to tell side-effect 568 | # dependency tracking mechanisms from slower ones. 569 | 570 | dashmstdout) 571 | # Important note: in order to support this mode, a compiler *must* 572 | # always write the preprocessed file to stdout, regardless of -o. 573 | "$@" || exit $? 574 | 575 | # Remove the call to Libtool. 576 | if test "$libtool" = yes; then 577 | while test "X$1" != 'X--mode=compile'; do 578 | shift 579 | done 580 | shift 581 | fi 582 | 583 | # Remove '-o $object'. 584 | IFS=" " 585 | for arg 586 | do 587 | case $arg in 588 | -o) 589 | shift 590 | ;; 591 | $object) 592 | shift 593 | ;; 594 | *) 595 | set fnord "$@" "$arg" 596 | shift # fnord 597 | shift # $arg 598 | ;; 599 | esac 600 | done 601 | 602 | test -z "$dashmflag" && dashmflag=-M 603 | # Require at least two characters before searching for ':' 604 | # in the target name. This is to cope with DOS-style filenames: 605 | # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. 606 | "$@" $dashmflag | 607 | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" 608 | rm -f "$depfile" 609 | cat < "$tmpdepfile" > "$depfile" 610 | # Some versions of the HPUX 10.20 sed can't process this sed invocation 611 | # correctly. Breaking it into two sed invocations is a workaround. 612 | tr ' ' "$nl" < "$tmpdepfile" \ 613 | | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ 614 | | sed -e 's/$/ :/' >> "$depfile" 615 | rm -f "$tmpdepfile" 616 | ;; 617 | 618 | dashXmstdout) 619 | # This case only exists to satisfy depend.m4. It is never actually 620 | # run, as this mode is specially recognized in the preamble. 621 | exit 1 622 | ;; 623 | 624 | makedepend) 625 | "$@" || exit $? 626 | # Remove any Libtool call 627 | if test "$libtool" = yes; then 628 | while test "X$1" != 'X--mode=compile'; do 629 | shift 630 | done 631 | shift 632 | fi 633 | # X makedepend 634 | shift 635 | cleared=no eat=no 636 | for arg 637 | do 638 | case $cleared in 639 | no) 640 | set ""; shift 641 | cleared=yes ;; 642 | esac 643 | if test $eat = yes; then 644 | eat=no 645 | continue 646 | fi 647 | case "$arg" in 648 | -D*|-I*) 649 | set fnord "$@" "$arg"; shift ;; 650 | # Strip any option that makedepend may not understand. Remove 651 | # the object too, otherwise makedepend will parse it as a source file. 652 | -arch) 653 | eat=yes ;; 654 | -*|$object) 655 | ;; 656 | *) 657 | set fnord "$@" "$arg"; shift ;; 658 | esac 659 | done 660 | obj_suffix=`echo "$object" | sed 's/^.*\././'` 661 | touch "$tmpdepfile" 662 | ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" 663 | rm -f "$depfile" 664 | # makedepend may prepend the VPATH from the source file name to the object. 665 | # No need to regex-escape $object, excess matching of '.' is harmless. 666 | sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" 667 | # Some versions of the HPUX 10.20 sed can't process the last invocation 668 | # correctly. Breaking it into two sed invocations is a workaround. 669 | sed '1,2d' "$tmpdepfile" \ 670 | | tr ' ' "$nl" \ 671 | | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ 672 | | sed -e 's/$/ :/' >> "$depfile" 673 | rm -f "$tmpdepfile" "$tmpdepfile".bak 674 | ;; 675 | 676 | cpp) 677 | # Important note: in order to support this mode, a compiler *must* 678 | # always write the preprocessed file to stdout. 679 | "$@" || exit $? 680 | 681 | # Remove the call to Libtool. 682 | if test "$libtool" = yes; then 683 | while test "X$1" != 'X--mode=compile'; do 684 | shift 685 | done 686 | shift 687 | fi 688 | 689 | # Remove '-o $object'. 690 | IFS=" " 691 | for arg 692 | do 693 | case $arg in 694 | -o) 695 | shift 696 | ;; 697 | $object) 698 | shift 699 | ;; 700 | *) 701 | set fnord "$@" "$arg" 702 | shift # fnord 703 | shift # $arg 704 | ;; 705 | esac 706 | done 707 | 708 | "$@" -E \ 709 | | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ 710 | -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ 711 | | sed '$ s: \\$::' > "$tmpdepfile" 712 | rm -f "$depfile" 713 | echo "$object : \\" > "$depfile" 714 | cat < "$tmpdepfile" >> "$depfile" 715 | sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" 716 | rm -f "$tmpdepfile" 717 | ;; 718 | 719 | msvisualcpp) 720 | # Important note: in order to support this mode, a compiler *must* 721 | # always write the preprocessed file to stdout. 722 | "$@" || exit $? 723 | 724 | # Remove the call to Libtool. 725 | if test "$libtool" = yes; then 726 | while test "X$1" != 'X--mode=compile'; do 727 | shift 728 | done 729 | shift 730 | fi 731 | 732 | IFS=" " 733 | for arg 734 | do 735 | case "$arg" in 736 | -o) 737 | shift 738 | ;; 739 | $object) 740 | shift 741 | ;; 742 | "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") 743 | set fnord "$@" 744 | shift 745 | shift 746 | ;; 747 | *) 748 | set fnord "$@" "$arg" 749 | shift 750 | shift 751 | ;; 752 | esac 753 | done 754 | "$@" -E 2>/dev/null | 755 | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" 756 | rm -f "$depfile" 757 | echo "$object : \\" > "$depfile" 758 | sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" 759 | echo "$tab" >> "$depfile" 760 | sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" 761 | rm -f "$tmpdepfile" 762 | ;; 763 | 764 | msvcmsys) 765 | # This case exists only to let depend.m4 do its work. It works by 766 | # looking at the text of this script. This case will never be run, 767 | # since it is checked for above. 768 | exit 1 769 | ;; 770 | 771 | none) 772 | exec "$@" 773 | ;; 774 | 775 | *) 776 | echo "Unknown depmode $depmode" 1>&2 777 | exit 1 778 | ;; 779 | esac 780 | 781 | exit 0 782 | 783 | # Local Variables: 784 | # mode: shell-script 785 | # sh-indentation: 2 786 | # eval: (add-hook 'write-file-hooks 'time-stamp) 787 | # time-stamp-start: "scriptversion=" 788 | # time-stamp-format: "%:y-%02m-%02d.%02H" 789 | # time-stamp-time-zone: "UTC0" 790 | # time-stamp-end: "; # UTC" 791 | # End: 792 | -------------------------------------------------------------------------------- /example.conf: -------------------------------------------------------------------------------- 1 | # xchainkeys configuration file 2 | # 3 | 4 | # chain options 5 | timeout 3000 # timeout chain after 3 seconds of inactivity 6 | 7 | # feedback options 8 | 9 | feedback on # enable feedback 10 | delay 1000 # display current key combination after 1 second of inactivity 11 | hold 1000 # display error messages for 1 second 12 | position center # center feedback window 13 | 14 | font fixed # use the font "fixed" for the popup window 15 | foreground black # black text and border 16 | background white # white background 17 | 18 | # keybindings 19 | 20 | C-t :enter 21 | C-t C-t :escape 22 | C-t C-g :abort 23 | C-t r :reload 24 | 25 | C-t Return :exec xterm 26 | -------------------------------------------------------------------------------- /install-sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # install - install a program, script, or datafile 3 | 4 | scriptversion=2016-01-11.22; # UTC 5 | 6 | # This originates from X11R5 (mit/util/scripts/install.sh), which was 7 | # later released in X11R6 (xc/config/util/install.sh) with the 8 | # following copyright and license. 9 | # 10 | # Copyright (C) 1994 X Consortium 11 | # 12 | # Permission is hereby granted, free of charge, to any person obtaining a copy 13 | # of this software and associated documentation files (the "Software"), to 14 | # deal in the Software without restriction, including without limitation the 15 | # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16 | # sell copies of the Software, and to permit persons to whom the Software is 17 | # furnished to do so, subject to the following conditions: 18 | # 19 | # The above copyright notice and this permission notice shall be included in 20 | # all copies or substantial portions of the Software. 21 | # 22 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26 | # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27 | # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | # 29 | # Except as contained in this notice, the name of the X Consortium shall not 30 | # be used in advertising or otherwise to promote the sale, use or other deal- 31 | # ings in this Software without prior written authorization from the X Consor- 32 | # tium. 33 | # 34 | # 35 | # FSF changes to this file are in the public domain. 36 | # 37 | # Calling this script install-sh is preferred over install.sh, to prevent 38 | # 'make' implicit rules from creating a file called install from it 39 | # when there is no Makefile. 40 | # 41 | # This script is compatible with the BSD install script, but was written 42 | # from scratch. 43 | 44 | tab=' ' 45 | nl=' 46 | ' 47 | IFS=" $tab$nl" 48 | 49 | # Set DOITPROG to "echo" to test this script. 50 | 51 | doit=${DOITPROG-} 52 | doit_exec=${doit:-exec} 53 | 54 | # Put in absolute file names if you don't have them in your path; 55 | # or use environment vars. 56 | 57 | chgrpprog=${CHGRPPROG-chgrp} 58 | chmodprog=${CHMODPROG-chmod} 59 | chownprog=${CHOWNPROG-chown} 60 | cmpprog=${CMPPROG-cmp} 61 | cpprog=${CPPROG-cp} 62 | mkdirprog=${MKDIRPROG-mkdir} 63 | mvprog=${MVPROG-mv} 64 | rmprog=${RMPROG-rm} 65 | stripprog=${STRIPPROG-strip} 66 | 67 | posix_mkdir= 68 | 69 | # Desired mode of installed file. 70 | mode=0755 71 | 72 | chgrpcmd= 73 | chmodcmd=$chmodprog 74 | chowncmd= 75 | mvcmd=$mvprog 76 | rmcmd="$rmprog -f" 77 | stripcmd= 78 | 79 | src= 80 | dst= 81 | dir_arg= 82 | dst_arg= 83 | 84 | copy_on_change=false 85 | is_target_a_directory=possibly 86 | 87 | usage="\ 88 | Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 89 | or: $0 [OPTION]... SRCFILES... DIRECTORY 90 | or: $0 [OPTION]... -t DIRECTORY SRCFILES... 91 | or: $0 [OPTION]... -d DIRECTORIES... 92 | 93 | In the 1st form, copy SRCFILE to DSTFILE. 94 | In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 95 | In the 4th, create DIRECTORIES. 96 | 97 | Options: 98 | --help display this help and exit. 99 | --version display version info and exit. 100 | 101 | -c (ignored) 102 | -C install only if different (preserve the last data modification time) 103 | -d create directories instead of installing files. 104 | -g GROUP $chgrpprog installed files to GROUP. 105 | -m MODE $chmodprog installed files to MODE. 106 | -o USER $chownprog installed files to USER. 107 | -s $stripprog installed files. 108 | -t DIRECTORY install into DIRECTORY. 109 | -T report an error if DSTFILE is a directory. 110 | 111 | Environment variables override the default commands: 112 | CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG 113 | RMPROG STRIPPROG 114 | " 115 | 116 | while test $# -ne 0; do 117 | case $1 in 118 | -c) ;; 119 | 120 | -C) copy_on_change=true;; 121 | 122 | -d) dir_arg=true;; 123 | 124 | -g) chgrpcmd="$chgrpprog $2" 125 | shift;; 126 | 127 | --help) echo "$usage"; exit $?;; 128 | 129 | -m) mode=$2 130 | case $mode in 131 | *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) 132 | echo "$0: invalid mode: $mode" >&2 133 | exit 1;; 134 | esac 135 | shift;; 136 | 137 | -o) chowncmd="$chownprog $2" 138 | shift;; 139 | 140 | -s) stripcmd=$stripprog;; 141 | 142 | -t) 143 | is_target_a_directory=always 144 | dst_arg=$2 145 | # Protect names problematic for 'test' and other utilities. 146 | case $dst_arg in 147 | -* | [=\(\)!]) dst_arg=./$dst_arg;; 148 | esac 149 | shift;; 150 | 151 | -T) is_target_a_directory=never;; 152 | 153 | --version) echo "$0 $scriptversion"; exit $?;; 154 | 155 | --) shift 156 | break;; 157 | 158 | -*) echo "$0: invalid option: $1" >&2 159 | exit 1;; 160 | 161 | *) break;; 162 | esac 163 | shift 164 | done 165 | 166 | # We allow the use of options -d and -T together, by making -d 167 | # take the precedence; this is for compatibility with GNU install. 168 | 169 | if test -n "$dir_arg"; then 170 | if test -n "$dst_arg"; then 171 | echo "$0: target directory not allowed when installing a directory." >&2 172 | exit 1 173 | fi 174 | fi 175 | 176 | if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then 177 | # When -d is used, all remaining arguments are directories to create. 178 | # When -t is used, the destination is already specified. 179 | # Otherwise, the last argument is the destination. Remove it from $@. 180 | for arg 181 | do 182 | if test -n "$dst_arg"; then 183 | # $@ is not empty: it contains at least $arg. 184 | set fnord "$@" "$dst_arg" 185 | shift # fnord 186 | fi 187 | shift # arg 188 | dst_arg=$arg 189 | # Protect names problematic for 'test' and other utilities. 190 | case $dst_arg in 191 | -* | [=\(\)!]) dst_arg=./$dst_arg;; 192 | esac 193 | done 194 | fi 195 | 196 | if test $# -eq 0; then 197 | if test -z "$dir_arg"; then 198 | echo "$0: no input file specified." >&2 199 | exit 1 200 | fi 201 | # It's OK to call 'install-sh -d' without argument. 202 | # This can happen when creating conditional directories. 203 | exit 0 204 | fi 205 | 206 | if test -z "$dir_arg"; then 207 | if test $# -gt 1 || test "$is_target_a_directory" = always; then 208 | if test ! -d "$dst_arg"; then 209 | echo "$0: $dst_arg: Is not a directory." >&2 210 | exit 1 211 | fi 212 | fi 213 | fi 214 | 215 | if test -z "$dir_arg"; then 216 | do_exit='(exit $ret); exit $ret' 217 | trap "ret=129; $do_exit" 1 218 | trap "ret=130; $do_exit" 2 219 | trap "ret=141; $do_exit" 13 220 | trap "ret=143; $do_exit" 15 221 | 222 | # Set umask so as not to create temps with too-generous modes. 223 | # However, 'strip' requires both read and write access to temps. 224 | case $mode in 225 | # Optimize common cases. 226 | *644) cp_umask=133;; 227 | *755) cp_umask=22;; 228 | 229 | *[0-7]) 230 | if test -z "$stripcmd"; then 231 | u_plus_rw= 232 | else 233 | u_plus_rw='% 200' 234 | fi 235 | cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; 236 | *) 237 | if test -z "$stripcmd"; then 238 | u_plus_rw= 239 | else 240 | u_plus_rw=,u+rw 241 | fi 242 | cp_umask=$mode$u_plus_rw;; 243 | esac 244 | fi 245 | 246 | for src 247 | do 248 | # Protect names problematic for 'test' and other utilities. 249 | case $src in 250 | -* | [=\(\)!]) src=./$src;; 251 | esac 252 | 253 | if test -n "$dir_arg"; then 254 | dst=$src 255 | dstdir=$dst 256 | test -d "$dstdir" 257 | dstdir_status=$? 258 | else 259 | 260 | # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 261 | # might cause directories to be created, which would be especially bad 262 | # if $src (and thus $dsttmp) contains '*'. 263 | if test ! -f "$src" && test ! -d "$src"; then 264 | echo "$0: $src does not exist." >&2 265 | exit 1 266 | fi 267 | 268 | if test -z "$dst_arg"; then 269 | echo "$0: no destination specified." >&2 270 | exit 1 271 | fi 272 | dst=$dst_arg 273 | 274 | # If destination is a directory, append the input filename; won't work 275 | # if double slashes aren't ignored. 276 | if test -d "$dst"; then 277 | if test "$is_target_a_directory" = never; then 278 | echo "$0: $dst_arg: Is a directory" >&2 279 | exit 1 280 | fi 281 | dstdir=$dst 282 | dst=$dstdir/`basename "$src"` 283 | dstdir_status=0 284 | else 285 | dstdir=`dirname "$dst"` 286 | test -d "$dstdir" 287 | dstdir_status=$? 288 | fi 289 | fi 290 | 291 | obsolete_mkdir_used=false 292 | 293 | if test $dstdir_status != 0; then 294 | case $posix_mkdir in 295 | '') 296 | # Create intermediate dirs using mode 755 as modified by the umask. 297 | # This is like FreeBSD 'install' as of 1997-10-28. 298 | umask=`umask` 299 | case $stripcmd.$umask in 300 | # Optimize common cases. 301 | *[2367][2367]) mkdir_umask=$umask;; 302 | .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; 303 | 304 | *[0-7]) 305 | mkdir_umask=`expr $umask + 22 \ 306 | - $umask % 100 % 40 + $umask % 20 \ 307 | - $umask % 10 % 4 + $umask % 2 308 | `;; 309 | *) mkdir_umask=$umask,go-w;; 310 | esac 311 | 312 | # With -d, create the new directory with the user-specified mode. 313 | # Otherwise, rely on $mkdir_umask. 314 | if test -n "$dir_arg"; then 315 | mkdir_mode=-m$mode 316 | else 317 | mkdir_mode= 318 | fi 319 | 320 | posix_mkdir=false 321 | case $umask in 322 | *[123567][0-7][0-7]) 323 | # POSIX mkdir -p sets u+wx bits regardless of umask, which 324 | # is incompatible with FreeBSD 'install' when (umask & 300) != 0. 325 | ;; 326 | *) 327 | tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ 328 | trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 329 | 330 | if (umask $mkdir_umask && 331 | exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 332 | then 333 | if test -z "$dir_arg" || { 334 | # Check for POSIX incompatibilities with -m. 335 | # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or 336 | # other-writable bit of parent directory when it shouldn't. 337 | # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. 338 | ls_ld_tmpdir=`ls -ld "$tmpdir"` 339 | case $ls_ld_tmpdir in 340 | d????-?r-*) different_mode=700;; 341 | d????-?--*) different_mode=755;; 342 | *) false;; 343 | esac && 344 | $mkdirprog -m$different_mode -p -- "$tmpdir" && { 345 | ls_ld_tmpdir_1=`ls -ld "$tmpdir"` 346 | test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" 347 | } 348 | } 349 | then posix_mkdir=: 350 | fi 351 | rmdir "$tmpdir/d" "$tmpdir" 352 | else 353 | # Remove any dirs left behind by ancient mkdir implementations. 354 | rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null 355 | fi 356 | trap '' 0;; 357 | esac;; 358 | esac 359 | 360 | if 361 | $posix_mkdir && ( 362 | umask $mkdir_umask && 363 | $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" 364 | ) 365 | then : 366 | else 367 | 368 | # The umask is ridiculous, or mkdir does not conform to POSIX, 369 | # or it failed possibly due to a race condition. Create the 370 | # directory the slow way, step by step, checking for races as we go. 371 | 372 | case $dstdir in 373 | /*) prefix='/';; 374 | [-=\(\)!]*) prefix='./';; 375 | *) prefix='';; 376 | esac 377 | 378 | oIFS=$IFS 379 | IFS=/ 380 | set -f 381 | set fnord $dstdir 382 | shift 383 | set +f 384 | IFS=$oIFS 385 | 386 | prefixes= 387 | 388 | for d 389 | do 390 | test X"$d" = X && continue 391 | 392 | prefix=$prefix$d 393 | if test -d "$prefix"; then 394 | prefixes= 395 | else 396 | if $posix_mkdir; then 397 | (umask=$mkdir_umask && 398 | $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break 399 | # Don't fail if two instances are running concurrently. 400 | test -d "$prefix" || exit 1 401 | else 402 | case $prefix in 403 | *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; 404 | *) qprefix=$prefix;; 405 | esac 406 | prefixes="$prefixes '$qprefix'" 407 | fi 408 | fi 409 | prefix=$prefix/ 410 | done 411 | 412 | if test -n "$prefixes"; then 413 | # Don't fail if two instances are running concurrently. 414 | (umask $mkdir_umask && 415 | eval "\$doit_exec \$mkdirprog $prefixes") || 416 | test -d "$dstdir" || exit 1 417 | obsolete_mkdir_used=true 418 | fi 419 | fi 420 | fi 421 | 422 | if test -n "$dir_arg"; then 423 | { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && 424 | { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && 425 | { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || 426 | test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 427 | else 428 | 429 | # Make a couple of temp file names in the proper directory. 430 | dsttmp=$dstdir/_inst.$$_ 431 | rmtmp=$dstdir/_rm.$$_ 432 | 433 | # Trap to clean up those temp files at exit. 434 | trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 435 | 436 | # Copy the file name to the temp name. 437 | (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && 438 | 439 | # and set any options; do chmod last to preserve setuid bits. 440 | # 441 | # If any of these fail, we abort the whole thing. If we want to 442 | # ignore errors from any of these, just make sure not to ignore 443 | # errors from the above "$doit $cpprog $src $dsttmp" command. 444 | # 445 | { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && 446 | { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && 447 | { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && 448 | { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && 449 | 450 | # If -C, don't bother to copy if it wouldn't change the file. 451 | if $copy_on_change && 452 | old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && 453 | new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && 454 | set -f && 455 | set X $old && old=:$2:$4:$5:$6 && 456 | set X $new && new=:$2:$4:$5:$6 && 457 | set +f && 458 | test "$old" = "$new" && 459 | $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 460 | then 461 | rm -f "$dsttmp" 462 | else 463 | # Rename the file to the real destination. 464 | $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || 465 | 466 | # The rename failed, perhaps because mv can't rename something else 467 | # to itself, or perhaps because mv is so ancient that it does not 468 | # support -f. 469 | { 470 | # Now remove or move aside any old file at destination location. 471 | # We try this two ways since rm can't unlink itself on some 472 | # systems and the destination file might be busy for other 473 | # reasons. In this case, the final cleanup might fail but the new 474 | # file should still install successfully. 475 | { 476 | test ! -f "$dst" || 477 | $doit $rmcmd -f "$dst" 2>/dev/null || 478 | { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && 479 | { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } 480 | } || 481 | { echo "$0: cannot unlink or rename $dst" >&2 482 | (exit 1); exit 1 483 | } 484 | } && 485 | 486 | # Now rename the file to the real destination. 487 | $doit $mvcmd "$dsttmp" "$dst" 488 | } 489 | fi || exit 1 490 | 491 | trap '' 0 492 | fi 493 | done 494 | 495 | # Local variables: 496 | # eval: (add-hook 'write-file-hooks 'time-stamp) 497 | # time-stamp-start: "scriptversion=" 498 | # time-stamp-format: "%:y-%02m-%02d.%02H" 499 | # time-stamp-time-zone: "UTC0" 500 | # time-stamp-end: "; # UTC" 501 | # End: 502 | -------------------------------------------------------------------------------- /missing: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Common wrapper for a few potentially missing GNU programs. 3 | 4 | scriptversion=2016-01-11.22; # UTC 5 | 6 | # Copyright (C) 1996-2017 Free Software Foundation, Inc. 7 | # Originally written by Fran,cois Pinard , 1996. 8 | 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | # As a special exception to the GNU General Public License, if you 23 | # distribute this file as part of a program that contains a 24 | # configuration script generated by Autoconf, you may include it under 25 | # the same distribution terms that you use for the rest of that program. 26 | 27 | if test $# -eq 0; then 28 | echo 1>&2 "Try '$0 --help' for more information" 29 | exit 1 30 | fi 31 | 32 | case $1 in 33 | 34 | --is-lightweight) 35 | # Used by our autoconf macros to check whether the available missing 36 | # script is modern enough. 37 | exit 0 38 | ;; 39 | 40 | --run) 41 | # Back-compat with the calling convention used by older automake. 42 | shift 43 | ;; 44 | 45 | -h|--h|--he|--hel|--help) 46 | echo "\ 47 | $0 [OPTION]... PROGRAM [ARGUMENT]... 48 | 49 | Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due 50 | to PROGRAM being missing or too old. 51 | 52 | Options: 53 | -h, --help display this help and exit 54 | -v, --version output version information and exit 55 | 56 | Supported PROGRAM values: 57 | aclocal autoconf autoheader autom4te automake makeinfo 58 | bison yacc flex lex help2man 59 | 60 | Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 61 | 'g' are ignored when checking the name. 62 | 63 | Send bug reports to ." 64 | exit $? 65 | ;; 66 | 67 | -v|--v|--ve|--ver|--vers|--versi|--versio|--version) 68 | echo "missing $scriptversion (GNU Automake)" 69 | exit $? 70 | ;; 71 | 72 | -*) 73 | echo 1>&2 "$0: unknown '$1' option" 74 | echo 1>&2 "Try '$0 --help' for more information" 75 | exit 1 76 | ;; 77 | 78 | esac 79 | 80 | # Run the given program, remember its exit status. 81 | "$@"; st=$? 82 | 83 | # If it succeeded, we are done. 84 | test $st -eq 0 && exit 0 85 | 86 | # Also exit now if we it failed (or wasn't found), and '--version' was 87 | # passed; such an option is passed most likely to detect whether the 88 | # program is present and works. 89 | case $2 in --version|--help) exit $st;; esac 90 | 91 | # Exit code 63 means version mismatch. This often happens when the user 92 | # tries to use an ancient version of a tool on a file that requires a 93 | # minimum version. 94 | if test $st -eq 63; then 95 | msg="probably too old" 96 | elif test $st -eq 127; then 97 | # Program was missing. 98 | msg="missing on your system" 99 | else 100 | # Program was found and executed, but failed. Give up. 101 | exit $st 102 | fi 103 | 104 | perl_URL=http://www.perl.org/ 105 | flex_URL=http://flex.sourceforge.net/ 106 | gnu_software_URL=http://www.gnu.org/software 107 | 108 | program_details () 109 | { 110 | case $1 in 111 | aclocal|automake) 112 | echo "The '$1' program is part of the GNU Automake package:" 113 | echo "<$gnu_software_URL/automake>" 114 | echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" 115 | echo "<$gnu_software_URL/autoconf>" 116 | echo "<$gnu_software_URL/m4/>" 117 | echo "<$perl_URL>" 118 | ;; 119 | autoconf|autom4te|autoheader) 120 | echo "The '$1' program is part of the GNU Autoconf package:" 121 | echo "<$gnu_software_URL/autoconf/>" 122 | echo "It also requires GNU m4 and Perl in order to run:" 123 | echo "<$gnu_software_URL/m4/>" 124 | echo "<$perl_URL>" 125 | ;; 126 | esac 127 | } 128 | 129 | give_advice () 130 | { 131 | # Normalize program name to check for. 132 | normalized_program=`echo "$1" | sed ' 133 | s/^gnu-//; t 134 | s/^gnu//; t 135 | s/^g//; t'` 136 | 137 | printf '%s\n' "'$1' is $msg." 138 | 139 | configure_deps="'configure.ac' or m4 files included by 'configure.ac'" 140 | case $normalized_program in 141 | autoconf*) 142 | echo "You should only need it if you modified 'configure.ac'," 143 | echo "or m4 files included by it." 144 | program_details 'autoconf' 145 | ;; 146 | autoheader*) 147 | echo "You should only need it if you modified 'acconfig.h' or" 148 | echo "$configure_deps." 149 | program_details 'autoheader' 150 | ;; 151 | automake*) 152 | echo "You should only need it if you modified 'Makefile.am' or" 153 | echo "$configure_deps." 154 | program_details 'automake' 155 | ;; 156 | aclocal*) 157 | echo "You should only need it if you modified 'acinclude.m4' or" 158 | echo "$configure_deps." 159 | program_details 'aclocal' 160 | ;; 161 | autom4te*) 162 | echo "You might have modified some maintainer files that require" 163 | echo "the 'autom4te' program to be rebuilt." 164 | program_details 'autom4te' 165 | ;; 166 | bison*|yacc*) 167 | echo "You should only need it if you modified a '.y' file." 168 | echo "You may want to install the GNU Bison package:" 169 | echo "<$gnu_software_URL/bison/>" 170 | ;; 171 | lex*|flex*) 172 | echo "You should only need it if you modified a '.l' file." 173 | echo "You may want to install the Fast Lexical Analyzer package:" 174 | echo "<$flex_URL>" 175 | ;; 176 | help2man*) 177 | echo "You should only need it if you modified a dependency" \ 178 | "of a man page." 179 | echo "You may want to install the GNU Help2man package:" 180 | echo "<$gnu_software_URL/help2man/>" 181 | ;; 182 | makeinfo*) 183 | echo "You should only need it if you modified a '.texi' file, or" 184 | echo "any other file indirectly affecting the aspect of the manual." 185 | echo "You might want to install the Texinfo package:" 186 | echo "<$gnu_software_URL/texinfo/>" 187 | echo "The spurious makeinfo call might also be the consequence of" 188 | echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" 189 | echo "want to install GNU make:" 190 | echo "<$gnu_software_URL/make/>" 191 | ;; 192 | *) 193 | echo "You might have modified some files without having the proper" 194 | echo "tools for further handling them. Check the 'README' file, it" 195 | echo "often tells you about the needed prerequisites for installing" 196 | echo "this package. You may also peek at any GNU archive site, in" 197 | echo "case some other package contains this missing '$1' program." 198 | ;; 199 | esac 200 | } 201 | 202 | give_advice "$1" | sed -e '1s/^/WARNING: /' \ 203 | -e '2,$s/^/ /' >&2 204 | 205 | # Propagate the correct exit status (expected to be 127 for a program 206 | # not found, 63 for a program that failed due to version mismatch). 207 | exit $st 208 | 209 | # Local variables: 210 | # eval: (add-hook 'write-file-hooks 'time-stamp) 211 | # time-stamp-start: "scriptversion=" 212 | # time-stamp-format: "%:y-%02m-%02d.%02H" 213 | # time-stamp-time-zone: "UTC0" 214 | # time-stamp-end: "; # UTC" 215 | # End: 216 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | AM_CFLAGS = -Wall 2 | 3 | bin_PROGRAMS = xchainkeys 4 | xchainkeys_SOURCES = key.c binding.c popup.c util.c xchainkeys.c 5 | noinst_HEADERS = key.h binding.h popup.h util.h xchainkeys.h 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/Makefile.in: -------------------------------------------------------------------------------- 1 | # Makefile.in generated by automake 1.16.1 from Makefile.am. 2 | # @configure_input@ 3 | 4 | # Copyright (C) 1994-2018 Free Software Foundation, Inc. 5 | 6 | # This Makefile.in is free software; the Free Software Foundation 7 | # gives unlimited permission to copy and/or distribute it, 8 | # with or without modifications, as long as this notice is preserved. 9 | 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without 12 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | # PARTICULAR PURPOSE. 14 | 15 | @SET_MAKE@ 16 | 17 | 18 | VPATH = @srcdir@ 19 | am__is_gnu_make = { \ 20 | if test -z '$(MAKELEVEL)'; then \ 21 | false; \ 22 | elif test -n '$(MAKE_HOST)'; then \ 23 | true; \ 24 | elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ 25 | true; \ 26 | else \ 27 | false; \ 28 | fi; \ 29 | } 30 | am__make_running_with_option = \ 31 | case $${target_option-} in \ 32 | ?) ;; \ 33 | *) echo "am__make_running_with_option: internal error: invalid" \ 34 | "target option '$${target_option-}' specified" >&2; \ 35 | exit 1;; \ 36 | esac; \ 37 | has_opt=no; \ 38 | sane_makeflags=$$MAKEFLAGS; \ 39 | if $(am__is_gnu_make); then \ 40 | sane_makeflags=$$MFLAGS; \ 41 | else \ 42 | case $$MAKEFLAGS in \ 43 | *\\[\ \ ]*) \ 44 | bs=\\; \ 45 | sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ 46 | | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ 47 | esac; \ 48 | fi; \ 49 | skip_next=no; \ 50 | strip_trailopt () \ 51 | { \ 52 | flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ 53 | }; \ 54 | for flg in $$sane_makeflags; do \ 55 | test $$skip_next = yes && { skip_next=no; continue; }; \ 56 | case $$flg in \ 57 | *=*|--*) continue;; \ 58 | -*I) strip_trailopt 'I'; skip_next=yes;; \ 59 | -*I?*) strip_trailopt 'I';; \ 60 | -*O) strip_trailopt 'O'; skip_next=yes;; \ 61 | -*O?*) strip_trailopt 'O';; \ 62 | -*l) strip_trailopt 'l'; skip_next=yes;; \ 63 | -*l?*) strip_trailopt 'l';; \ 64 | -[dEDm]) skip_next=yes;; \ 65 | -[JT]) skip_next=yes;; \ 66 | esac; \ 67 | case $$flg in \ 68 | *$$target_option*) has_opt=yes; break;; \ 69 | esac; \ 70 | done; \ 71 | test $$has_opt = yes 72 | am__make_dryrun = (target_option=n; $(am__make_running_with_option)) 73 | am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 74 | pkgdatadir = $(datadir)/@PACKAGE@ 75 | pkgincludedir = $(includedir)/@PACKAGE@ 76 | pkglibdir = $(libdir)/@PACKAGE@ 77 | pkglibexecdir = $(libexecdir)/@PACKAGE@ 78 | am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd 79 | install_sh_DATA = $(install_sh) -c -m 644 80 | install_sh_PROGRAM = $(install_sh) -c 81 | install_sh_SCRIPT = $(install_sh) -c 82 | INSTALL_HEADER = $(INSTALL_DATA) 83 | transform = $(program_transform_name) 84 | NORMAL_INSTALL = : 85 | PRE_INSTALL = : 86 | POST_INSTALL = : 87 | NORMAL_UNINSTALL = : 88 | PRE_UNINSTALL = : 89 | POST_UNINSTALL = : 90 | bin_PROGRAMS = xchainkeys$(EXEEXT) 91 | subdir = src 92 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 93 | am__aclocal_m4_deps = $(top_srcdir)/configure.ac 94 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ 95 | $(ACLOCAL_M4) 96 | DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ 97 | $(am__DIST_COMMON) 98 | mkinstalldirs = $(install_sh) -d 99 | CONFIG_CLEAN_FILES = 100 | CONFIG_CLEAN_VPATH_FILES = 101 | am__installdirs = "$(DESTDIR)$(bindir)" 102 | PROGRAMS = $(bin_PROGRAMS) 103 | am_xchainkeys_OBJECTS = key.$(OBJEXT) binding.$(OBJEXT) \ 104 | popup.$(OBJEXT) util.$(OBJEXT) xchainkeys.$(OBJEXT) 105 | xchainkeys_OBJECTS = $(am_xchainkeys_OBJECTS) 106 | xchainkeys_LDADD = $(LDADD) 107 | AM_V_P = $(am__v_P_@AM_V@) 108 | am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) 109 | am__v_P_0 = false 110 | am__v_P_1 = : 111 | AM_V_GEN = $(am__v_GEN_@AM_V@) 112 | am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) 113 | am__v_GEN_0 = @echo " GEN " $@; 114 | am__v_GEN_1 = 115 | AM_V_at = $(am__v_at_@AM_V@) 116 | am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) 117 | am__v_at_0 = @ 118 | am__v_at_1 = 119 | DEFAULT_INCLUDES = -I.@am__isrc@ 120 | depcomp = $(SHELL) $(top_srcdir)/depcomp 121 | am__maybe_remake_depfiles = depfiles 122 | am__depfiles_remade = ./$(DEPDIR)/binding.Po ./$(DEPDIR)/key.Po \ 123 | ./$(DEPDIR)/popup.Po ./$(DEPDIR)/util.Po \ 124 | ./$(DEPDIR)/xchainkeys.Po 125 | am__mv = mv -f 126 | COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ 127 | $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) 128 | AM_V_CC = $(am__v_CC_@AM_V@) 129 | am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) 130 | am__v_CC_0 = @echo " CC " $@; 131 | am__v_CC_1 = 132 | CCLD = $(CC) 133 | LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ 134 | AM_V_CCLD = $(am__v_CCLD_@AM_V@) 135 | am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) 136 | am__v_CCLD_0 = @echo " CCLD " $@; 137 | am__v_CCLD_1 = 138 | SOURCES = $(xchainkeys_SOURCES) 139 | DIST_SOURCES = $(xchainkeys_SOURCES) 140 | am__can_run_installinfo = \ 141 | case $$AM_UPDATE_INFO_DIR in \ 142 | n|no|NO) false;; \ 143 | *) (install-info --version) >/dev/null 2>&1;; \ 144 | esac 145 | HEADERS = $(noinst_HEADERS) 146 | am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) 147 | # Read a list of newline-separated strings from the standard input, 148 | # and print each of them once, without duplicates. Input order is 149 | # *not* preserved. 150 | am__uniquify_input = $(AWK) '\ 151 | BEGIN { nonempty = 0; } \ 152 | { items[$$0] = 1; nonempty = 1; } \ 153 | END { if (nonempty) { for (i in items) print i; }; } \ 154 | ' 155 | # Make sure the list of sources is unique. This is necessary because, 156 | # e.g., the same source file might be shared among _SOURCES variables 157 | # for different programs/libraries. 158 | am__define_uniq_tagged_files = \ 159 | list='$(am__tagged_files)'; \ 160 | unique=`for i in $$list; do \ 161 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ 162 | done | $(am__uniquify_input)` 163 | ETAGS = etags 164 | CTAGS = ctags 165 | am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp 166 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) 167 | ACLOCAL = @ACLOCAL@ 168 | AMTAR = @AMTAR@ 169 | AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ 170 | AUTOCONF = @AUTOCONF@ 171 | AUTOHEADER = @AUTOHEADER@ 172 | AUTOMAKE = @AUTOMAKE@ 173 | AWK = @AWK@ 174 | CC = @CC@ 175 | CCDEPMODE = @CCDEPMODE@ 176 | CFLAGS = @CFLAGS@ 177 | CPP = @CPP@ 178 | CPPFLAGS = @CPPFLAGS@ 179 | CYGPATH_W = @CYGPATH_W@ 180 | DEFS = @DEFS@ 181 | DEPDIR = @DEPDIR@ 182 | ECHO_C = @ECHO_C@ 183 | ECHO_N = @ECHO_N@ 184 | ECHO_T = @ECHO_T@ 185 | EGREP = @EGREP@ 186 | EXEEXT = @EXEEXT@ 187 | GREP = @GREP@ 188 | INSTALL = @INSTALL@ 189 | INSTALL_DATA = @INSTALL_DATA@ 190 | INSTALL_PROGRAM = @INSTALL_PROGRAM@ 191 | INSTALL_SCRIPT = @INSTALL_SCRIPT@ 192 | INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ 193 | LDFLAGS = @LDFLAGS@ 194 | LIBOBJS = @LIBOBJS@ 195 | LIBS = @LIBS@ 196 | LTLIBOBJS = @LTLIBOBJS@ 197 | MAKEINFO = @MAKEINFO@ 198 | MKDIR_P = @MKDIR_P@ 199 | OBJEXT = @OBJEXT@ 200 | PACKAGE = @PACKAGE@ 201 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ 202 | PACKAGE_NAME = @PACKAGE_NAME@ 203 | PACKAGE_STRING = @PACKAGE_STRING@ 204 | PACKAGE_TARNAME = @PACKAGE_TARNAME@ 205 | PACKAGE_URL = @PACKAGE_URL@ 206 | PACKAGE_VERSION = @PACKAGE_VERSION@ 207 | PATH_SEPARATOR = @PATH_SEPARATOR@ 208 | SED = @SED@ 209 | SET_MAKE = @SET_MAKE@ 210 | SHELL = @SHELL@ 211 | STRIP = @STRIP@ 212 | VERSION = @VERSION@ 213 | abs_builddir = @abs_builddir@ 214 | abs_srcdir = @abs_srcdir@ 215 | abs_top_builddir = @abs_top_builddir@ 216 | abs_top_srcdir = @abs_top_srcdir@ 217 | ac_ct_CC = @ac_ct_CC@ 218 | am__include = @am__include@ 219 | am__leading_dot = @am__leading_dot@ 220 | am__quote = @am__quote@ 221 | am__tar = @am__tar@ 222 | am__untar = @am__untar@ 223 | bindir = @bindir@ 224 | build_alias = @build_alias@ 225 | builddir = @builddir@ 226 | datadir = @datadir@ 227 | datarootdir = @datarootdir@ 228 | docdir = @docdir@ 229 | dvidir = @dvidir@ 230 | exec_prefix = @exec_prefix@ 231 | host_alias = @host_alias@ 232 | htmldir = @htmldir@ 233 | includedir = @includedir@ 234 | infodir = @infodir@ 235 | install_sh = @install_sh@ 236 | libdir = @libdir@ 237 | libexecdir = @libexecdir@ 238 | localedir = @localedir@ 239 | localstatedir = @localstatedir@ 240 | mandir = @mandir@ 241 | mkdir_p = @mkdir_p@ 242 | oldincludedir = @oldincludedir@ 243 | pdfdir = @pdfdir@ 244 | prefix = @prefix@ 245 | program_transform_name = @program_transform_name@ 246 | psdir = @psdir@ 247 | sbindir = @sbindir@ 248 | sharedstatedir = @sharedstatedir@ 249 | srcdir = @srcdir@ 250 | sysconfdir = @sysconfdir@ 251 | target_alias = @target_alias@ 252 | top_build_prefix = @top_build_prefix@ 253 | top_builddir = @top_builddir@ 254 | top_srcdir = @top_srcdir@ 255 | AM_CFLAGS = -Wall 256 | xchainkeys_SOURCES = key.c binding.c popup.c util.c xchainkeys.c 257 | noinst_HEADERS = key.h binding.h popup.h util.h xchainkeys.h 258 | all: all-am 259 | 260 | .SUFFIXES: 261 | .SUFFIXES: .c .o .obj 262 | $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) 263 | @for dep in $?; do \ 264 | case '$(am__configure_deps)' in \ 265 | *$$dep*) \ 266 | ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ 267 | && { if test -f $@; then exit 0; else break; fi; }; \ 268 | exit 1;; \ 269 | esac; \ 270 | done; \ 271 | echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ 272 | $(am__cd) $(top_srcdir) && \ 273 | $(AUTOMAKE) --gnu src/Makefile 274 | Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status 275 | @case '$?' in \ 276 | *config.status*) \ 277 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ 278 | *) \ 279 | echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ 280 | cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ 281 | esac; 282 | 283 | $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) 284 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 285 | 286 | $(top_srcdir)/configure: $(am__configure_deps) 287 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 288 | $(ACLOCAL_M4): $(am__aclocal_m4_deps) 289 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 290 | $(am__aclocal_m4_deps): 291 | install-binPROGRAMS: $(bin_PROGRAMS) 292 | @$(NORMAL_INSTALL) 293 | @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ 294 | if test -n "$$list"; then \ 295 | echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ 296 | $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ 297 | fi; \ 298 | for p in $$list; do echo "$$p $$p"; done | \ 299 | sed 's/$(EXEEXT)$$//' | \ 300 | while read p p1; do if test -f $$p \ 301 | ; then echo "$$p"; echo "$$p"; else :; fi; \ 302 | done | \ 303 | sed -e 'p;s,.*/,,;n;h' \ 304 | -e 's|.*|.|' \ 305 | -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ 306 | sed 'N;N;N;s,\n, ,g' | \ 307 | $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ 308 | { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ 309 | if ($$2 == $$4) files[d] = files[d] " " $$1; \ 310 | else { print "f", $$3 "/" $$4, $$1; } } \ 311 | END { for (d in files) print "f", d, files[d] }' | \ 312 | while read type dir files; do \ 313 | if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ 314 | test -z "$$files" || { \ 315 | echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ 316 | $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ 317 | } \ 318 | ; done 319 | 320 | uninstall-binPROGRAMS: 321 | @$(NORMAL_UNINSTALL) 322 | @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ 323 | files=`for p in $$list; do echo "$$p"; done | \ 324 | sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ 325 | -e 's/$$/$(EXEEXT)/' \ 326 | `; \ 327 | test -n "$$list" || exit 0; \ 328 | echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ 329 | cd "$(DESTDIR)$(bindir)" && rm -f $$files 330 | 331 | clean-binPROGRAMS: 332 | -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) 333 | 334 | xchainkeys$(EXEEXT): $(xchainkeys_OBJECTS) $(xchainkeys_DEPENDENCIES) $(EXTRA_xchainkeys_DEPENDENCIES) 335 | @rm -f xchainkeys$(EXEEXT) 336 | $(AM_V_CCLD)$(LINK) $(xchainkeys_OBJECTS) $(xchainkeys_LDADD) $(LIBS) 337 | 338 | mostlyclean-compile: 339 | -rm -f *.$(OBJEXT) 340 | 341 | distclean-compile: 342 | -rm -f *.tab.c 343 | 344 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/binding.Po@am__quote@ # am--include-marker 345 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/key.Po@am__quote@ # am--include-marker 346 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/popup.Po@am__quote@ # am--include-marker 347 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@ # am--include-marker 348 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xchainkeys.Po@am__quote@ # am--include-marker 349 | 350 | $(am__depfiles_remade): 351 | @$(MKDIR_P) $(@D) 352 | @echo '# dummy' >$@-t && $(am__mv) $@-t $@ 353 | 354 | am--depfiles: $(am__depfiles_remade) 355 | 356 | .c.o: 357 | @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< 358 | @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po 359 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ 360 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 361 | @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< 362 | 363 | .c.obj: 364 | @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` 365 | @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po 366 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ 367 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 368 | @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` 369 | 370 | ID: $(am__tagged_files) 371 | $(am__define_uniq_tagged_files); mkid -fID $$unique 372 | tags: tags-am 373 | TAGS: tags 374 | 375 | tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) 376 | set x; \ 377 | here=`pwd`; \ 378 | $(am__define_uniq_tagged_files); \ 379 | shift; \ 380 | if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ 381 | test -n "$$unique" || unique=$$empty_fix; \ 382 | if test $$# -gt 0; then \ 383 | $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ 384 | "$$@" $$unique; \ 385 | else \ 386 | $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ 387 | $$unique; \ 388 | fi; \ 389 | fi 390 | ctags: ctags-am 391 | 392 | CTAGS: ctags 393 | ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) 394 | $(am__define_uniq_tagged_files); \ 395 | test -z "$(CTAGS_ARGS)$$unique" \ 396 | || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ 397 | $$unique 398 | 399 | GTAGS: 400 | here=`$(am__cd) $(top_builddir) && pwd` \ 401 | && $(am__cd) $(top_srcdir) \ 402 | && gtags -i $(GTAGS_ARGS) "$$here" 403 | cscopelist: cscopelist-am 404 | 405 | cscopelist-am: $(am__tagged_files) 406 | list='$(am__tagged_files)'; \ 407 | case "$(srcdir)" in \ 408 | [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ 409 | *) sdir=$(subdir)/$(srcdir) ;; \ 410 | esac; \ 411 | for i in $$list; do \ 412 | if test -f "$$i"; then \ 413 | echo "$(subdir)/$$i"; \ 414 | else \ 415 | echo "$$sdir/$$i"; \ 416 | fi; \ 417 | done >> $(top_builddir)/cscope.files 418 | 419 | distclean-tags: 420 | -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags 421 | 422 | distdir: $(BUILT_SOURCES) 423 | $(MAKE) $(AM_MAKEFLAGS) distdir-am 424 | 425 | distdir-am: $(DISTFILES) 426 | @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 427 | topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 428 | list='$(DISTFILES)'; \ 429 | dist_files=`for file in $$list; do echo $$file; done | \ 430 | sed -e "s|^$$srcdirstrip/||;t" \ 431 | -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ 432 | case $$dist_files in \ 433 | */*) $(MKDIR_P) `echo "$$dist_files" | \ 434 | sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ 435 | sort -u` ;; \ 436 | esac; \ 437 | for file in $$dist_files; do \ 438 | if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ 439 | if test -d $$d/$$file; then \ 440 | dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ 441 | if test -d "$(distdir)/$$file"; then \ 442 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ 443 | fi; \ 444 | if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ 445 | cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ 446 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ 447 | fi; \ 448 | cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ 449 | else \ 450 | test -f "$(distdir)/$$file" \ 451 | || cp -p $$d/$$file "$(distdir)/$$file" \ 452 | || exit 1; \ 453 | fi; \ 454 | done 455 | check-am: all-am 456 | check: check-am 457 | all-am: Makefile $(PROGRAMS) $(HEADERS) 458 | installdirs: 459 | for dir in "$(DESTDIR)$(bindir)"; do \ 460 | test -z "$$dir" || $(MKDIR_P) "$$dir"; \ 461 | done 462 | install: install-am 463 | install-exec: install-exec-am 464 | install-data: install-data-am 465 | uninstall: uninstall-am 466 | 467 | install-am: all-am 468 | @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am 469 | 470 | installcheck: installcheck-am 471 | install-strip: 472 | if test -z '$(STRIP)'; then \ 473 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ 474 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ 475 | install; \ 476 | else \ 477 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ 478 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ 479 | "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ 480 | fi 481 | mostlyclean-generic: 482 | 483 | clean-generic: 484 | 485 | distclean-generic: 486 | -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) 487 | -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) 488 | 489 | maintainer-clean-generic: 490 | @echo "This command is intended for maintainers to use" 491 | @echo "it deletes files that may require special tools to rebuild." 492 | clean: clean-am 493 | 494 | clean-am: clean-binPROGRAMS clean-generic mostlyclean-am 495 | 496 | distclean: distclean-am 497 | -rm -f ./$(DEPDIR)/binding.Po 498 | -rm -f ./$(DEPDIR)/key.Po 499 | -rm -f ./$(DEPDIR)/popup.Po 500 | -rm -f ./$(DEPDIR)/util.Po 501 | -rm -f ./$(DEPDIR)/xchainkeys.Po 502 | -rm -f Makefile 503 | distclean-am: clean-am distclean-compile distclean-generic \ 504 | distclean-tags 505 | 506 | dvi: dvi-am 507 | 508 | dvi-am: 509 | 510 | html: html-am 511 | 512 | html-am: 513 | 514 | info: info-am 515 | 516 | info-am: 517 | 518 | install-data-am: 519 | 520 | install-dvi: install-dvi-am 521 | 522 | install-dvi-am: 523 | 524 | install-exec-am: install-binPROGRAMS 525 | 526 | install-html: install-html-am 527 | 528 | install-html-am: 529 | 530 | install-info: install-info-am 531 | 532 | install-info-am: 533 | 534 | install-man: 535 | 536 | install-pdf: install-pdf-am 537 | 538 | install-pdf-am: 539 | 540 | install-ps: install-ps-am 541 | 542 | install-ps-am: 543 | 544 | installcheck-am: 545 | 546 | maintainer-clean: maintainer-clean-am 547 | -rm -f ./$(DEPDIR)/binding.Po 548 | -rm -f ./$(DEPDIR)/key.Po 549 | -rm -f ./$(DEPDIR)/popup.Po 550 | -rm -f ./$(DEPDIR)/util.Po 551 | -rm -f ./$(DEPDIR)/xchainkeys.Po 552 | -rm -f Makefile 553 | maintainer-clean-am: distclean-am maintainer-clean-generic 554 | 555 | mostlyclean: mostlyclean-am 556 | 557 | mostlyclean-am: mostlyclean-compile mostlyclean-generic 558 | 559 | pdf: pdf-am 560 | 561 | pdf-am: 562 | 563 | ps: ps-am 564 | 565 | ps-am: 566 | 567 | uninstall-am: uninstall-binPROGRAMS 568 | 569 | .MAKE: install-am install-strip 570 | 571 | .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ 572 | clean-binPROGRAMS clean-generic cscopelist-am ctags ctags-am \ 573 | distclean distclean-compile distclean-generic distclean-tags \ 574 | distdir dvi dvi-am html html-am info info-am install \ 575 | install-am install-binPROGRAMS install-data install-data-am \ 576 | install-dvi install-dvi-am install-exec install-exec-am \ 577 | install-html install-html-am install-info install-info-am \ 578 | install-man install-pdf install-pdf-am install-ps \ 579 | install-ps-am install-strip installcheck installcheck-am \ 580 | installdirs maintainer-clean maintainer-clean-generic \ 581 | mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ 582 | ps ps-am tags tags-am uninstall uninstall-am \ 583 | uninstall-binPROGRAMS 584 | 585 | .PRECIOUS: Makefile 586 | 587 | 588 | # Tell versions [3.59,3.63) of GNU make to not export all variables. 589 | # Otherwise a system limit (for SysV at least) may be exceeded. 590 | .NOEXPORT: 591 | -------------------------------------------------------------------------------- /src/binding.c: -------------------------------------------------------------------------------- 1 | #ifndef _XOPEN_SOURCE 2 | #define _XOPEN_SOURCE 500 3 | #endif /* _XOPEN_SOURCE */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "key.h" 14 | #include "binding.h" 15 | #include "popup.h" 16 | #include "util.h" 17 | #include "xchainkeys.h" 18 | 19 | extern XChainKeys_t *xc; 20 | 21 | Binding_t* binding_new() { 22 | Binding_t *self = (Binding_t *) calloc(1, sizeof(Binding_t)); 23 | 24 | self->key = NULL; 25 | self->action = XC_ACTION_ENTER; 26 | 27 | self->name = calloc(128, sizeof(char)); 28 | strcpy(self->name, "default"); 29 | 30 | self->argument = calloc(4096, sizeof(char)); 31 | 32 | self->timeout = 3000; 33 | self->abort = XC_ABORT_AUTO; 34 | 35 | self->parent = NULL; 36 | self->num_children = 0; 37 | 38 | return self; 39 | } 40 | 41 | void binding_set_action(Binding_t *self, char *str) { 42 | int i; 43 | for( i=0; iaction_names[i], str, strlen(str)) == 0) { 45 | self->action = i; 46 | break; 47 | } 48 | } 49 | if(strcmp(str, ":reload") == 0) { 50 | self->action = XC_ACTION_LOAD; 51 | } 52 | if(strcmp(str, ":repeat") == 0) { 53 | self->action = XC_ACTION_GROUP; 54 | self->name = "default"; 55 | fprintf(stderr, 56 | "%s: ':repeat' is deprecated, using ':group \"default\"' instead.\n", 57 | PACKAGE_NAME); 58 | fflush(stderr); 59 | } 60 | } 61 | 62 | void binding_parse_arguments(Binding_t *self) { 63 | 64 | char *argument; 65 | char *argument_ptr; 66 | char *value; 67 | char *value_ptr; 68 | 69 | char *ws = " \t"; 70 | int i; 71 | 72 | if(self->action == XC_ACTION_ENTER) 73 | self->timeout = xc->timeout; 74 | 75 | if(self->action != XC_ACTION_ENTER) 76 | self->abort = XC_ABORT_MANUAL; 77 | 78 | argument = (char *) calloc(strlen(self->argument)+1, sizeof(char)); 79 | argument_ptr = argument; 80 | 81 | strncpy(argument, self->argument, strlen(self->argument)+1); 82 | 83 | while(strlen(argument)) { 84 | 85 | if(self->action == XC_ACTION_ENTER) { // parse timeout value only for :enter 86 | 87 | if(strncmp(argument, "timeout=", 8) == 0) { 88 | 89 | value = (char *) calloc(strlen(argument)+1, sizeof(char)); 90 | value_ptr = value; 91 | 92 | strncpy(value, argument, strlen(argument)+1); 93 | value += 8; 94 | value[strcspn(value, ws)] = '\0'; 95 | 96 | self->timeout = atoi(value); 97 | 98 | argument += 8 + strlen(value); 99 | argument += strspn(argument, ws); 100 | 101 | free(value_ptr); 102 | continue; 103 | } 104 | } 105 | 106 | if(strncmp(argument, "abort=", 6) == 0) { // parse abort for any action 107 | 108 | value = (char *) calloc(strlen(argument)+1, sizeof(char)); 109 | value_ptr = value; 110 | 111 | strncpy(value, argument, strlen(argument)+1); 112 | value += 6; 113 | value[strcspn(value, ws)] = '\0'; 114 | 115 | if(strcmp(value, "auto") == 0) 116 | self->abort = XC_ABORT_AUTO; 117 | 118 | if(strcmp(value, "manual") == 0) 119 | self->abort = XC_ABORT_MANUAL; 120 | 121 | argument += 6 + strlen(value); 122 | argument += strspn(argument, ws); 123 | 124 | free(value_ptr); 125 | continue; 126 | } 127 | /* skip unparsed words */ 128 | argument += strcspn(argument, ws); 129 | argument += strspn(argument, ws); 130 | 131 | if(strcspn(argument, ws) == 0) 132 | break; 133 | } 134 | free(argument_ptr); 135 | 136 | /* recurse into children and parse their arguments as well */ 137 | for( i=0; inum_children; i++ ) { 138 | binding_parse_arguments(self->children[i]); 139 | } 140 | } 141 | 142 | void binding_create_default_bindings(Binding_t *self) { 143 | 144 | Binding_t *binding; 145 | Key_t *key; 146 | char *keyspec; 147 | int i; 148 | 149 | if(self->parent != NULL && self->action == XC_ACTION_ENTER) { 150 | 151 | /* create default :escape binding unless present */ 152 | if (!binding_get_child_by_action(self, XC_ACTION_ESCAPE)) { 153 | 154 | keyspec = key_to_str(self->key); 155 | key = key_new(keyspec); 156 | 157 | if(!binding_get_child_by_key(self, key)) { 158 | 159 | binding = binding_new(); 160 | binding->key = key; 161 | binding->action = XC_ACTION_ESCAPE; 162 | 163 | binding_append_child(self, binding); 164 | } 165 | else { 166 | fprintf(stderr, 167 | "%s: chain '%s': :escape action not found and '%s %s' " 168 | "already bound:\n" 169 | "%s: -> skipping creation of default :escape binding...\n", 170 | PACKAGE_NAME, keyspec, keyspec, keyspec, PACKAGE_NAME); 171 | fflush(stderr); 172 | free(key); 173 | } 174 | free(keyspec); 175 | } 176 | 177 | /* create default :abort binding unless present */ 178 | if (!binding_get_child_by_action(self, XC_ACTION_ABORT)) { 179 | 180 | keyspec = key_to_str(self->key); 181 | key = key_new("C-g"); 182 | 183 | if(!binding_get_child_by_key(self, key)) { 184 | 185 | binding = binding_new(); 186 | binding->key = key; 187 | binding->action = XC_ACTION_ABORT; 188 | 189 | binding_append_child(self, binding); 190 | } 191 | else { 192 | fprintf(stderr, 193 | "%s: chain '%s': :abort action not found and '%s C-g' " 194 | "already bound:\n" 195 | "%s: -> skipping creation of default :abort binding...\n", 196 | PACKAGE_NAME, keyspec, keyspec, PACKAGE_NAME); 197 | fflush(stderr); 198 | free(key); 199 | } 200 | free(keyspec); 201 | } 202 | } 203 | 204 | /* recurse children */ 205 | for (i=0; inum_children; i++) { 206 | binding_create_default_bindings(self->children[i]); 207 | } 208 | 209 | } 210 | 211 | void binding_append_child(Binding_t *self, Binding_t *child) { 212 | self->children[self->num_children] = child; 213 | child->parent = self; 214 | self->num_children += 1; 215 | } 216 | 217 | Binding_t *binding_get_child_by_key(Binding_t *self, Key_t *key) { 218 | int i; 219 | for( i=0; inum_children; i++ ) { 220 | if (key_equals(self->children[i]->key, key)) 221 | return self->children[i]; 222 | } 223 | return NULL; 224 | } 225 | 226 | Binding_t *binding_get_child_by_action(Binding_t *self, int action) { 227 | int i; 228 | for( i=0; inum_children; i++ ) { 229 | if (self->children[i]->action == action) 230 | return self->children[i]; 231 | } 232 | return NULL; 233 | } 234 | 235 | void binding_activate(Binding_t *self) { 236 | char *path; 237 | path = binding_to_path(self); 238 | 239 | if (xc->debug) { 240 | printf(" -> %s %s %s\n", 241 | path, xc->action_names[self->action], self->argument); 242 | fflush(stdout); 243 | } 244 | 245 | switch(self->action) { 246 | 247 | case XC_ACTION_ENTER: 248 | binding_enter(self); 249 | break; 250 | 251 | case XC_ACTION_ESCAPE: 252 | binding_escape(self); 253 | break; 254 | 255 | case XC_ACTION_EXEC: 256 | binding_exec(self); 257 | break; 258 | 259 | case XC_ACTION_WAIT: 260 | binding_wait(self); 261 | break; 262 | 263 | case XC_ACTION_GROUP: 264 | binding_group(self); 265 | break; 266 | 267 | case XC_ACTION_LOAD: 268 | if(strlen(self->argument)) 269 | strncpy(xc->config, self->argument, strlen(self->argument)+1); 270 | xc->reload = True; 271 | break; 272 | } 273 | free(path); 274 | } 275 | 276 | int binding_wait_event(Binding_t *self) { 277 | struct timeval tv1, tv2, *delay_tv, *timeout_tv; 278 | fd_set in; 279 | int ignore_delay = False; 280 | 281 | if (xc->delay > 0) { 282 | if (self->timeout > 0 && xc->delay > self->timeout) { 283 | ignore_delay = True; 284 | delay_tv = NULL; 285 | } else { 286 | tv1.tv_sec = xc->delay / 1000; 287 | tv1.tv_usec = (xc->delay % 1000) * 1000; 288 | delay_tv = &tv1; 289 | } 290 | } else { 291 | delay_tv = NULL; 292 | } 293 | 294 | if (self->timeout > 0) { 295 | if (ignore_delay) { 296 | tv2.tv_sec = self->timeout / 1000; 297 | tv2.tv_usec = (self->timeout % 1000) * 1000; 298 | } else { 299 | tv2.tv_sec = (self->timeout - xc->delay) / 1000; 300 | tv2.tv_usec = (self->timeout - xc->delay) % 1000 * 1000; 301 | } 302 | timeout_tv = &tv2; 303 | } else { 304 | timeout_tv = NULL; 305 | } 306 | 307 | FD_ZERO(&in); 308 | FD_SET(xc->connection, &in); 309 | 310 | if (ignore_delay) { 311 | return select(xc->connection + 1, &in, 0, 0, timeout_tv); 312 | } else { 313 | if (delay_tv 314 | && select(xc->connection + 1, &in, 0, 0, delay_tv)) { 315 | return 1; 316 | } 317 | 318 | if(!xc->popup->mapped) 319 | popup_show(xc->popup); 320 | 321 | if (!FD_ISSET(xc->connection, &in)) 322 | FD_SET(xc->connection, &in); 323 | return select(xc->connection + 1, &in, 0, 0, timeout_tv); 324 | } 325 | } 326 | 327 | void binding_enter(Binding_t *self) { 328 | XEvent event; 329 | KeyCode keycode; 330 | Binding_t *binding; 331 | Key_t *key; 332 | char *keystr; 333 | char *keyspec; 334 | int done = False; 335 | char *path = binding_to_path(self); 336 | 337 | /* prepare popup */ 338 | strncpy(xc->popup->text, path, 4096); 339 | 340 | if(xc->popup->mapped) 341 | popup_show(xc->popup); 342 | 343 | /* get exclusive grab on keyboard... */ 344 | if (self->parent == xc->root) { 345 | XGrabKeyboard(xc->display, DefaultRootWindow(xc->display), 346 | True, GrabModeAsync, GrabModeAsync, CurrentTime); 347 | } 348 | 349 | while(!done) { 350 | if (!binding_wait_event(self)) { 351 | if (xc->debug) { printf("Timed out\n"); fflush(stdout); } 352 | done = True; 353 | continue; 354 | } 355 | 356 | /* look for key press events... */ 357 | if(XPending(xc->display)) { 358 | XNextEvent(xc->display, &event); 359 | 360 | /* dispatch exec, abort or escape */ 361 | if(event.type == KeyPress) { 362 | 363 | /* get keycode and keystr */ 364 | keycode = ((XKeyPressedEvent*)&event)->keycode; 365 | keystr = XKeysymToString(XKeycodeToKeysym(xc->display, keycode, 0)); 366 | 367 | /* check if this key is a modifier */ 368 | if (keycode_to_modifier(xc->xmodmap, keycode) != 0) { 369 | continue; 370 | } 371 | else { 372 | /* non-modifier key hit... */ 373 | key = key_new(keystr); 374 | key->modifiers = get_modifiers(xc->display); 375 | 376 | /* check if this key is bound in this keymap */ 377 | if( (binding = binding_get_child_by_key(self, key)) != NULL) { 378 | 379 | /* :abort from here... */ 380 | if (binding->action == XC_ACTION_ABORT) { 381 | if (xc->debug) { printf("Aborted\n"); fflush(stdout); } 382 | done = True; 383 | free(key); 384 | continue; 385 | } 386 | 387 | /* ... or activate the binding */ 388 | binding_activate(binding); 389 | 390 | /* check if the binding overrides abort in a manual chain */ 391 | if(self->abort == XC_ABORT_MANUAL && binding->abort == XC_ABORT_AUTO) 392 | done = True; 393 | } 394 | else { 395 | keyspec = key_to_str(key); 396 | sprintf(xc->popup->text, "%s %s: no binding", path, keyspec); 397 | popup_show(xc->popup); 398 | xc->popup->timeout = (xc->hold == -1) ? xc->delay : xc->hold; 399 | 400 | if (xc->debug) { 401 | printf(" -> %s %s: no binding\n", path, keyspec); 402 | fflush(stdout); 403 | } 404 | free(keyspec); 405 | } 406 | 407 | /* done, exit this keymap unless manual abort was requested */ 408 | if (self->abort == XC_ABORT_AUTO) 409 | done = True; 410 | 411 | /* always exit if the prefix key was escaped */ 412 | if (binding != NULL && binding->action == XC_ACTION_ESCAPE) 413 | done = True; 414 | 415 | free(key); 416 | } 417 | } 418 | } 419 | } 420 | 421 | /* ungrab keyboard... */ 422 | if (self->parent == xc->root) { 423 | XUngrabKeyboard(xc->display, CurrentTime); 424 | } 425 | 426 | /* hide popup if no timeout is set for it */ 427 | if(xc->popup->timeout == 0) 428 | popup_hide(xc->popup); 429 | 430 | free(path); 431 | } 432 | 433 | void binding_escape(Binding_t *self) { 434 | 435 | Window window; 436 | int focus_ret; 437 | 438 | if(self->parent == NULL) 439 | return; 440 | 441 | XUngrabKeyboard(xc->display, CurrentTime); 442 | XGetInputFocus(xc->display, &window, &focus_ret); 443 | 444 | send_key(xc->display, self->parent->key, window); 445 | 446 | XGrabKeyboard(xc->display, DefaultRootWindow(xc->display), 447 | True, GrabModeAsync, GrabModeAsync, CurrentTime); 448 | } 449 | 450 | void binding_group(Binding_t *self) { 451 | Key_t *key; 452 | Binding_t *binding; 453 | XEvent event; 454 | KeyCode keycode; 455 | char *keystr; 456 | int i; 457 | int abort = False; 458 | char *path; 459 | 460 | path = binding_to_path(self->parent); 461 | strncat(path, " (", 4096-strlen(path)-1); 462 | strncat(path, self->name, 4096-strlen(path)-1); 463 | strncat(path, ")", 4096-strlen(path)-1); 464 | 465 | strncpy(xc->popup->text, path, 4096); 466 | free(path); 467 | 468 | popup_show(xc->popup); 469 | binding_exec(self); 470 | 471 | while(True) { 472 | XNextEvent(xc->display, &event); 473 | 474 | switch(event.type) { 475 | case KeyPress: 476 | 477 | /* get keycode and keystr */ 478 | keycode = ((XKeyPressedEvent*)&event)->keycode; 479 | keystr = XKeysymToString(XKeycodeToKeysym(xc->display, keycode, 0)); 480 | 481 | /* check if this key is a modifier */ 482 | if (keycode_to_modifier(xc->xmodmap, keycode) != 0) { 483 | break; 484 | } 485 | else { 486 | /* non-modifier key hit... */ 487 | key = key_new(keystr); 488 | key->modifiers = get_modifiers(xc->display); 489 | 490 | /* :exec any :group actions of the same name in the parent 491 | * binding, and abort on any non-repeating key 492 | */ 493 | for(i=0; iparent->num_children; i++) { 494 | binding = self->parent->children[i]; 495 | 496 | if ( binding->action == XC_ACTION_GROUP && 497 | strcmp(binding->name, self->name) == 0 && 498 | key_equals(binding->key, key) ) { 499 | 500 | binding_exec(binding); 501 | 502 | if(binding->action != XC_ACTION_ESCAPE) 503 | abort = False; 504 | if(binding->abort == XC_ABORT_AUTO) 505 | abort = True; 506 | break; 507 | } 508 | abort = True; 509 | } 510 | 511 | if(abort) { 512 | /* if the aborting key matches any root :enter bindings, 513 | * prepare immediate re-entry into that chain from 514 | * xc_mainloop() 515 | */ 516 | 517 | for(i=0; iroot->num_children; i++) { 518 | binding = xc->root->children[i]; 519 | if ( binding->action == XC_ACTION_ENTER && 520 | key_equals(binding->key, key) ) { 521 | xc->reentry = binding; 522 | } 523 | } 524 | free(key); 525 | return; 526 | } 527 | free(key); 528 | } 529 | } 530 | } 531 | } 532 | 533 | void binding_wait(Binding_t *self) { 534 | char *command = self->argument; 535 | 536 | XUngrabKeyboard(xc->display, CurrentTime); 537 | XFlush(xc->display); 538 | 539 | system(command); 540 | 541 | if (self->parent != xc->root) 542 | XGrabKeyboard(xc->display, DefaultRootWindow(xc->display), 543 | True, GrabModeAsync, GrabModeAsync, CurrentTime); 544 | 545 | XFlush(xc->display); 546 | } 547 | 548 | void binding_exec(Binding_t *self) { 549 | pid_t pid; 550 | char *command = self->argument; 551 | 552 | if (!(pid = fork())) { 553 | setsid(); 554 | switch (fork()) 555 | { 556 | case 0: execlp ("sh", "sh", "-c", command, (char *) NULL); 557 | break; 558 | default: _exit(0); 559 | break; 560 | } 561 | } 562 | if (pid > 0) wait(NULL); 563 | } 564 | 565 | char *binding_to_path(Binding_t *self) { 566 | Binding_t *binding = self; 567 | char *path = (char *) calloc(4096, sizeof(char)); 568 | char *str; 569 | do { 570 | str = key_to_str(binding->key); 571 | 572 | if(strcmp(binding->name, "default") != 0) { 573 | strncat(str, " (", 256-strlen(str)); 574 | strncat(str, binding->name, 256-strlen(str)); 575 | strncat(str, ")", 256-strlen(str)); 576 | } 577 | 578 | if(strlen(path) > 0) 579 | strncat(str, " ", 256-strlen(str)); 580 | 581 | memmove(path+strlen(str), path, strlen(path)); 582 | memmove(path, str, strlen(str)); 583 | 584 | free(str); 585 | 586 | binding = binding->parent; 587 | 588 | } while(binding->parent != NULL); 589 | 590 | return path; 591 | } 592 | 593 | void binding_list(Binding_t *self) { 594 | Binding_t *current; 595 | char *keyspec; 596 | int depth = 0; 597 | int i; 598 | 599 | current = self; 600 | while( current->parent != NULL ) { 601 | depth++; 602 | current = current->parent; 603 | } 604 | for( i=1; i 0) { 608 | keyspec = key_to_str(self->key); 609 | 610 | if(strcmp(self->name, "default") == 0) 611 | printf("%s %s %s\n", 612 | keyspec, xc->action_names[self->action], self->argument); 613 | else 614 | printf("%s %s \"%s\" %s\n", 615 | keyspec, xc->action_names[self->action], self->name, self->argument); 616 | fflush(stdout); 617 | free(keyspec); 618 | } 619 | 620 | for( i=0; inum_children; i++ ) { 621 | binding_list(self->children[i]); 622 | } 623 | } 624 | 625 | void binding_free(Binding_t *self) { 626 | int i; 627 | 628 | for( i=0; inum_children; i++ ) { 629 | binding_free(self->children[i]); 630 | self->children[i] = NULL; 631 | } 632 | self->num_children = 0; 633 | self->parent = NULL; 634 | free(self->name); 635 | free(self->argument); 636 | free(self->key); 637 | free(self); 638 | } 639 | -------------------------------------------------------------------------------- /src/binding.h: -------------------------------------------------------------------------------- 1 | #ifndef BINDING_H 2 | #define BINDING_H 3 | 4 | struct Binding { 5 | Key_t *key; 6 | int action; 7 | char *argument; 8 | char *name; 9 | int timeout; 10 | int abort; 11 | struct Binding *parent; 12 | int num_children; 13 | struct Binding *children[1024]; 14 | }; 15 | typedef struct Binding Binding_t; 16 | 17 | Binding_t* binding_new(); 18 | void binding_set_action(Binding_t *self, char *str); 19 | void binding_parse_arguments(Binding_t *self); 20 | void binding_create_default_bindings(Binding_t *self); 21 | void binding_append_child(Binding_t *self, Binding_t *child); 22 | Binding_t *binding_get_child_by_key(Binding_t *self, Key_t *key); 23 | Binding_t *binding_get_child_by_action(Binding_t *self, int action); 24 | int binding_wait_event(Binding_t *self); 25 | void binding_activate(Binding_t *self); 26 | void binding_enter(Binding_t *self); 27 | void binding_escape(Binding_t *self); 28 | void binding_send(Binding_t *self); 29 | void binding_exec(Binding_t *self); 30 | void binding_wait(Binding_t *self); 31 | void binding_group(Binding_t *self); 32 | char *binding_to_path(Binding_t *self); 33 | void binding_list(Binding_t *self); 34 | void binding_free(Binding_t *self); 35 | 36 | #endif /* #ifndef BINDING_H */ 37 | -------------------------------------------------------------------------------- /src/key.c: -------------------------------------------------------------------------------- 1 | #ifndef _XOPEN_SOURCE 2 | #define _XOPEN_SOURCE 500 3 | #endif /* _XOPEN_SOURCE */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "key.h" 12 | #include "util.h" 13 | #include "xchainkeys.h" 14 | 15 | extern XChainKeys_t *xc; 16 | 17 | Key_t* key_new(char *keyspec) { 18 | 19 | Key_t *self = (Key_t *) calloc(1, sizeof(Key_t));; 20 | 21 | self->keysym = NoSymbol; 22 | self->keycode = 0; 23 | 24 | if( key_parse_keyspec(self, keyspec) ) { 25 | return(self); 26 | } 27 | else { 28 | free(self); 29 | return(NULL); 30 | } 31 | } 32 | 33 | int key_parse_keyspec(Key_t *self, char *keyspec) { 34 | 35 | char str[256]; 36 | char *original_keyspec = strdup(keyspec); 37 | int len; 38 | int ret = True; 39 | 40 | if (keyspec[0] == ':') 41 | return 0; 42 | 43 | /* parse modifiers */ 44 | while( strstr(keyspec, "-") != NULL ) { 45 | 46 | len = strcspn(keyspec, "-"); 47 | strncpy(str, keyspec, 256); 48 | str[len] = '\0'; 49 | 50 | if(!key_add_modifier(self, str)) { 51 | free(original_keyspec); 52 | return False; 53 | } 54 | keyspec += len + 1; 55 | } 56 | 57 | /* keyspec now contains the valid keysym string or a numeric keycode */ 58 | 59 | /* parse as keysym string */ 60 | self->keysym = XStringToKeysym(keyspec); 61 | 62 | if(self->keysym == NoSymbol) { 63 | 64 | /* not a valid symbol, try to parse numeric keycode */ 65 | self->keycode = (unsigned int)strtol(keyspec, NULL, 0); 66 | 67 | if(self->keycode < 8) { // not a valid xlib keycode 68 | ret = False; 69 | } 70 | } 71 | 72 | free(original_keyspec); 73 | return ret; 74 | } 75 | 76 | int key_add_modifier(Key_t *self, char *str) { 77 | unsigned int modifier = 0; 78 | 79 | if( (modifier = modname_to_modifier(str)) != 0 ) 80 | self->modifiers |= modifier; 81 | else 82 | return False; 83 | 84 | return True; 85 | } 86 | 87 | int key_get_keycode(Key_t *self) { 88 | if(self->keysym != NoSymbol) 89 | return XKeysymToKeycode(xc->display, self->keysym); 90 | else 91 | return self->keycode; 92 | } 93 | 94 | int key_equals(Key_t *self, Key_t *key) { 95 | if(self->modifiers == key->modifiers && 96 | key_get_keycode(self) == key_get_keycode(key)) 97 | return 1; 98 | return 0; 99 | } 100 | 101 | void key_grab(Key_t *self) { 102 | int i; 103 | 104 | for( i=0; i<8; i++ ) { 105 | XGrabKey(xc->display, key_get_keycode(self), self->modifiers | xc->modmask[i], 106 | DefaultRootWindow(xc->display), False, 107 | GrabModeAsync, GrabModeAsync); 108 | } 109 | } 110 | 111 | void key_ungrab(Key_t *self) { 112 | int i; 113 | 114 | for( i=0; i<8; i++ ) { 115 | XUngrabKey(xc->display, key_get_keycode(self), self->modifiers | xc->modmask[i], 116 | DefaultRootWindow(xc->display)); 117 | } 118 | } 119 | 120 | char *key_to_str(Key_t *self) { 121 | 122 | char *str = (char *) calloc(256, sizeof(char)); 123 | 124 | if (self->modifiers & LockMask) strcat(str, "lock-"); 125 | if (self->modifiers & ControlMask) strcat(str, "C-"); 126 | if (self->modifiers & Mod1Mask) strcat(str, "A-"); 127 | if (self->modifiers & Mod2Mask) strcat(str, "mod2-"); 128 | if (self->modifiers & Mod3Mask) strcat(str, "mod3-"); 129 | if (self->modifiers & Mod4Mask) strcat(str, "W-"); 130 | if (self->modifiers & Mod5Mask) strcat(str, "mod5-"); 131 | if (self->modifiers & ShiftMask) strcat(str, "S-"); 132 | 133 | if(self->keysym != NoSymbol) 134 | strcat(str, XKeysymToString(self->keysym)); 135 | else 136 | snprintf(str, 5, "0x%x", self->keycode); 137 | 138 | return str; 139 | } 140 | -------------------------------------------------------------------------------- /src/key.h: -------------------------------------------------------------------------------- 1 | #ifndef KEY_H 2 | #define KEY_H 3 | 4 | typedef struct Key { 5 | unsigned int modifiers; 6 | KeySym keysym; 7 | unsigned int keycode; 8 | } Key_t; 9 | 10 | Key_t* key_new(char *keyspec); 11 | int key_parse_keyspec(Key_t *key, char *keyspec); 12 | int key_add_modifier(Key_t *self, char *str); 13 | int key_get_keycode(Key_t *self); 14 | int key_equals(Key_t *self, Key_t *key); 15 | void key_grab(Key_t *self); 16 | void key_ungrab(Key_t *self); 17 | char *key_to_str(Key_t *self); 18 | 19 | #endif /* #ifndef KEY_H */ 20 | -------------------------------------------------------------------------------- /src/popup.c: -------------------------------------------------------------------------------- 1 | #ifndef _XOPEN_SOURCE 2 | #define _XOPEN_SOURCE 500 3 | #endif /* _XOPEN_SOURCE */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "popup.h" 15 | 16 | void* popup_new(Display *display, char *font, char *fg, char *bg, char *position) { 17 | 18 | Popup_t *self = (Popup_t *) calloc(1, sizeof(Popup_t)); 19 | self->display = display; 20 | self->root = DefaultRootWindow(self->display); 21 | self->position = position; 22 | self->enabled = True; 23 | 24 | XSetWindowAttributes winattrs; 25 | winattrs.override_redirect = True; 26 | winattrs.cursor = popup_get_cursor(self); 27 | 28 | self->window = XCreateWindow(self->display, 29 | self->root, 30 | 0, 0, 1, 1, 2, 31 | CopyFromParent, 32 | InputOutput, 33 | CopyFromParent, 34 | CWOverrideRedirect | CWCursor, 35 | &winattrs); 36 | 37 | Colormap colormap = DefaultColormap(self->display, 0); 38 | XColor fgcolor; 39 | XColor bgcolor; 40 | 41 | XParseColor(self->display, colormap, fg, &fgcolor); 42 | XAllocColor(self->display, colormap, &fgcolor); 43 | 44 | XParseColor(self->display, colormap, bg, &bgcolor); 45 | XAllocColor(self->display, colormap, &bgcolor); 46 | 47 | XSetWindowBorder(self->display, self->window, fgcolor.pixel); 48 | XSetWindowBackground(self->display, self->window, bgcolor.pixel); 49 | 50 | XGCValues values; 51 | values.cap_style = CapButt; 52 | values.join_style = JoinBevel; 53 | values.foreground = fgcolor.pixel; 54 | values.background = bgcolor.pixel; 55 | 56 | unsigned long valuemask = GCCapStyle | GCJoinStyle; 57 | 58 | self->gc = XCreateGC(self->display, self->window, valuemask, &values); 59 | if (self->gc < 0) { 60 | printf("XCreateGC: \n"); 61 | exit(EXIT_FAILURE); 62 | } 63 | XSetForeground(self->display, self->gc, fgcolor.pixel); 64 | 65 | self->font = XLoadQueryFont(self->display, font); 66 | if (!self->font) { 67 | fprintf(stderr, "%s: error: XLoadQueryFont: failed to load font '%s'\n", 68 | PACKAGE_NAME, font); 69 | exit(EXIT_FAILURE); 70 | } 71 | XSetFont(self->display, self->gc, self->font->fid); 72 | 73 | self->timeout = 0; 74 | self->mapped = False; 75 | self->w = self->h = 1; 76 | 77 | return self; 78 | } 79 | 80 | void popup_update(Popup_t *self) { 81 | 82 | int margin = 3; 83 | int dw = DisplayWidth(self->display, DefaultScreen(self->display)); 84 | int dh = DisplayHeight(self->display, DefaultScreen(self->display)); 85 | 86 | int parsed = 0; 87 | int centered_at_position = True; 88 | char *ws = " \t"; 89 | 90 | int x, y = 0; 91 | unsigned int ignored_width, ignored_height; 92 | Window root, child; 93 | unsigned int mask; 94 | 95 | self->x = 0; 96 | self->y = 0; 97 | 98 | self->w = XTextWidth(self->font, self->text, strlen(self->text)) + margin*2; 99 | self->h = self->font->ascent + self->font->descent + margin*2; 100 | 101 | if( (parsed = XParseGeometry(self->position, &x, &y, 102 | &ignored_width, &ignored_height)) & (XValue | YValue)) { 103 | centered_at_position = False; 104 | 105 | self->x = (parsed & XNegative) ? dw - self->w - margin + x - 1 : x; 106 | self->y = (parsed & YNegative) ? dh - self->h - margin + y - 1 : y; 107 | } 108 | else if (strncmp(self->position, "center", 6) == 0) { 109 | self->x = dw / 2; 110 | self->y = dh / 2; 111 | } 112 | else if (strncmp(self->position, "mouse", 5) == 0) { 113 | 114 | XQueryPointer(self->display, self->root, &root, &child, 115 | &self->x, &self->y, &x, &y, &mask); 116 | } 117 | else if(strlen(self->position) > 0) { 118 | self->x = atoi(self->position); 119 | self->y = atoi(self->position + strcspn(self->position, ws)); 120 | centered_at_position = False; 121 | } 122 | 123 | if (centered_at_position) { 124 | self->x -= (self->w + margin) / 2; 125 | self->y -= (self->h + margin) / 2; 126 | } 127 | 128 | if (self->x < 0) 129 | self->x = 0; 130 | if (self->x > dw - (self->w + margin)) 131 | self->x = dw - self->w - margin; 132 | if (self->y < 0) 133 | self->y = 0; 134 | if (self->y > dh - (self->h + margin)) 135 | self->y = dh - self->h - margin; 136 | 137 | XMoveResizeWindow(self->display, self->window, 138 | self->x, self->y, self->w, self->h); 139 | 140 | XClearArea(self->display, self->window, 141 | 0, 0, 0, 0,False); 142 | XFlush(self->display); 143 | 144 | XDrawString(self->display, self->window, self->gc, 145 | margin, self->h - margin*2, 146 | self->text, strlen(self->text)); 147 | 148 | XFlush(self->display); 149 | } 150 | 151 | void popup_show(Popup_t *self) { 152 | if(self->enabled) { 153 | XMapWindow(self->display, self->window); 154 | XRaiseWindow(self->display, self->window); 155 | self->mapped = True; 156 | popup_update(self); 157 | } 158 | } 159 | 160 | void popup_hide(Popup_t *self) { 161 | XUnmapWindow(self->display, self->window); 162 | self->mapped = False; 163 | XFlush(self->display); 164 | } 165 | 166 | void popup_set_timeout(Popup_t *self, unsigned int ms) { 167 | struct timeval tval; 168 | unsigned int now; 169 | 170 | gettimeofday(&tval, NULL); 171 | now =(long)(tval.tv_sec*1000 + (tval.tv_usec/1000)); 172 | self->timeout = now + ms; 173 | } 174 | 175 | Cursor popup_get_cursor(Popup_t *self) { 176 | 177 | Pixmap mask; 178 | GC gc; 179 | XGCValues values; 180 | XColor color; 181 | Cursor cursor; 182 | 183 | mask = XCreatePixmap(self->display, self->root, 1, 1, 1); 184 | values.function = GXclear; 185 | gc = XCreateGC(self->display, mask, GCFunction, &values); 186 | 187 | XFillRectangle(self->display, mask, gc, 0, 0, 1, 1); 188 | color.pixel = 0; color.red = 0; color.flags = 04; 189 | 190 | cursor = XCreatePixmapCursor(self->display, mask, mask, 191 | &color,&color, 0,0); 192 | 193 | XFreePixmap(self->display, mask); 194 | XFreeGC(self->display, gc); 195 | return cursor; 196 | } 197 | 198 | void popup_free(Popup_t *self) { 199 | XFreeFont(self->display, self->font); 200 | XFreeGC(self->display, self->gc); 201 | free(self); 202 | } 203 | -------------------------------------------------------------------------------- /src/popup.h: -------------------------------------------------------------------------------- 1 | #ifndef POPUP_H 2 | #define POPUP_H 3 | 4 | typedef struct Popup { 5 | Display *display; 6 | Window root; 7 | Window window; 8 | XFontStruct *font; 9 | GC gc; 10 | int x, y, w, h; 11 | char text[4096]; 12 | char *position; 13 | unsigned int timeout; 14 | int mapped; 15 | int enabled; 16 | } Popup_t; 17 | 18 | void* popup_new(Display *display, char *font, char *fg, char *bg, char *position); 19 | Cursor popup_get_cursor(Popup_t *self); 20 | void popup_set_timeout(Popup_t *self, unsigned int ms); 21 | void popup_update(Popup_t *self); 22 | void popup_show(Popup_t *self); 23 | void popup_hide(Popup_t *self); 24 | void popup_free(Popup_t *self); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/util.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "key.h" 8 | #include "xchainkeys.h" 9 | 10 | extern XChainKeys_t *xc; 11 | 12 | void version() { 13 | printf("%s %s Copyright (C) 2010-2012 Henning Bekel <%s>\n", 14 | PACKAGE_NAME, PACKAGE_VERSION, PACKAGE_BUGREPORT); 15 | 16 | printf("License GPLv3: GNU GPL version 3 \n\n"); 17 | printf("This is free software; you are free to change and redistribute it.\n"); 18 | printf("There is NO WARRANTY, to the extent permitted by law.\n"); 19 | fflush(stdout); 20 | } 21 | 22 | void usage() { 23 | version(); 24 | printf("\n"); 25 | printf("Usage: %s [options]\n\n", PACKAGE_NAME); 26 | printf(" -f, --file : alternative config file\n"); 27 | printf(" -k, --keys : Show valid keyspecs\n"); 28 | printf(" -d, --debug : Enable debug messages\n"); 29 | printf(" -h, --help : Print this help text\n"); 30 | printf(" -v, --version : Print version information\n"); 31 | printf("\n"); 32 | fflush(stdout); 33 | } 34 | 35 | unsigned int modname_to_modifier(char *str) { 36 | 37 | if( strcasecmp(str, "shift") == 0 || 38 | strcmp(str, "S") == 0 ) 39 | return ShiftMask; 40 | 41 | if( strcasecmp(str, "lock") == 0 ) 42 | return LockMask; 43 | 44 | if( strcasecmp(str, "control") == 0 || 45 | strcasecmp(str, "ctrl") == 0 || 46 | strcmp(str, "C") == 0) 47 | return ControlMask; 48 | 49 | if( strcasecmp(str, "mod1") == 0 || 50 | strcasecmp(str, "alt") == 0 || 51 | strcasecmp(str, "meta") == 0 || 52 | strcmp(str, "A") == 0 || 53 | strcmp(str, "M") == 0 ) 54 | return Mod1Mask; 55 | 56 | if( strcasecmp(str, "mod2") == 0 ) 57 | return Mod2Mask; 58 | 59 | if( strcasecmp(str, "mod3") == 0 ) 60 | return Mod3Mask; 61 | 62 | if( strcasecmp(str, "mod4") == 0 || 63 | strcasecmp(str, "super") == 0 || 64 | strncasecmp(str, "win", 3) == 0 || 65 | strcasecmp(str, "hyper") == 0 || 66 | strcmp(str, "W") == 0 || 67 | strcmp(str, "H") == 0 ) 68 | return Mod4Mask; 69 | 70 | if( strcasecmp(str, "mod5") == 0 ) 71 | return Mod5Mask; 72 | 73 | return 0; 74 | } 75 | 76 | unsigned int keycode_to_modifier(XModifierKeymap *xmodmap, KeyCode keycode) { 77 | 78 | int i = 0; 79 | int j = 0; 80 | int max = xmodmap->max_keypermod; 81 | 82 | for (i = 0; i < 8; i++) { 83 | for (j = 0; j < max && xmodmap->modifiermap[(i * max) + j]; j++) { 84 | if (keycode == xmodmap->modifiermap[(i * max) + j]) { 85 | switch (i) { 86 | case ShiftMapIndex: return ShiftMask; break; 87 | case LockMapIndex: return LockMask; break; 88 | case ControlMapIndex: return ControlMask; break; 89 | case Mod1MapIndex: return Mod1Mask; break; 90 | case Mod2MapIndex: return Mod2Mask; break; 91 | case Mod3MapIndex: return Mod3Mask; break; 92 | case Mod4MapIndex: return Mod4Mask; break; 93 | case Mod5MapIndex: return Mod5Mask; break; 94 | } 95 | } 96 | } 97 | } 98 | return (KeyCode) 0; 99 | } 100 | 101 | unsigned int get_modifiers(Display *display) { 102 | 103 | char keymap[32]; 104 | unsigned int keycode; 105 | unsigned int modifiers = 0; 106 | 107 | XQueryKeymap(display, keymap); 108 | 109 | for (keycode = 0; keycode < 256; keycode++) { 110 | if ((keymap[(keycode / 8)] & (1 << (keycode % 8))) \ 111 | && keycode_to_modifier(xc->xmodmap, keycode)) { 112 | 113 | modifiers |= keycode_to_modifier(xc->xmodmap, keycode); 114 | } 115 | } 116 | return modifiers; 117 | } 118 | 119 | void send_key(Display *display, Key_t *key, Window window) { 120 | 121 | XKeyEvent e; 122 | char *keyspec; 123 | 124 | if (xc->debug) { 125 | keyspec = key_to_str(key); 126 | printf("Sending synthetic KeyPressEvent (%s) to window id %d\n", 127 | keyspec, (int)window); 128 | fflush(stdout); 129 | free(keyspec); 130 | } 131 | 132 | e.display = display; 133 | e.window = window; 134 | e.subwindow = None; 135 | e.time = CurrentTime; 136 | e.same_screen = True; 137 | e.keycode = key_get_keycode(key); 138 | e.state = key->modifiers; 139 | e.type = KeyPress; 140 | e.x = e.y = e.x_root = e.y_root = 1; 141 | 142 | XSendEvent(display, e.window, True, KeyPressMask, (XEvent *)&e); 143 | XSync(display, False); 144 | } 145 | 146 | long get_msec(void) { 147 | long msec; 148 | struct timeval tv; 149 | gettimeofday(&tv, NULL); 150 | msec = (long)(tv.tv_sec*1000 + (tv.tv_usec/1000)); 151 | return msec; 152 | } 153 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTIL_H 3 | 4 | void usage(void); 5 | void version(void); 6 | unsigned int get_modifiers(Display *display); 7 | unsigned int modname_to_modifier(char *str); 8 | unsigned int keycode_to_modifier(XModifierKeymap *xmodmap, KeyCode keycode); 9 | void send_key(Display *display, Key_t *key, Window window); 10 | long get_msec(void); 11 | 12 | #endif /* ifndef XCHAINKEYS_H */ 13 | -------------------------------------------------------------------------------- /src/xchainkeys.c: -------------------------------------------------------------------------------- 1 | /* xchainkeys -- chained keybindings for X11 2 | * Copyright (C) 2010, 2011 Henning Bekel 3 | * Improved timeout code contributed by sssslang. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License as 7 | * published by the Free Software Foundation; either version 3 of the 8 | * License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 | * 02110-1301, USA. 19 | */ 20 | 21 | #ifndef _XOPEN_SOURCE 22 | #define _XOPEN_SOURCE 500 23 | #endif /* _XOPEN_SOURCE */ 24 | 25 | #ifndef _GNU_SOURCE 26 | #define _GNU_SOURCE 27 | #endif /* _GNU_SOURCE */ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include "key.h" 38 | #include "binding.h" 39 | #include "popup.h" 40 | #include "util.h" 41 | #include "xchainkeys.h" 42 | 43 | XChainKeys_t *xc; 44 | 45 | XChainKeys_t* xc_new() { 46 | 47 | XChainKeys_t *self = (XChainKeys_t *) calloc(1, sizeof(XChainKeys_t)); 48 | 49 | if(NULL == (self->display=XOpenDisplay(NULL))) { 50 | 51 | fprintf(stderr, "%s: error: XOpenDisplay() failed for DISPLAY=%s.\n", 52 | PACKAGE_NAME, getenv("DISPLAY")); 53 | fflush(stderr); 54 | 55 | free(self); 56 | exit(EXIT_FAILURE); 57 | } 58 | 59 | XSetErrorHandler(xc_handle_error); 60 | 61 | self->debug = False; 62 | self->timeout = 3000; 63 | self->delay = 1000; 64 | self->hold = -1; 65 | self->position = "center"; 66 | self->reentry = NULL; 67 | self->reload = False; 68 | 69 | self->xmodmap = XGetModifierMapping(self->display); 70 | xc_init_modmask(self); 71 | 72 | self->connection = ConnectionNumber(self->display); 73 | 74 | self->action_names[0] = ":none"; 75 | self->action_names[1] = ":enter"; 76 | self->action_names[2] = ":escape"; 77 | self->action_names[3] = ":abort"; 78 | self->action_names[4] = ":exec"; 79 | self->action_names[5] = ":group"; 80 | self->action_names[6] = ":load"; 81 | self->action_names[7] = ":wait"; 82 | 83 | self->root = binding_new(); 84 | self->root->action = XC_ACTION_NONE; 85 | 86 | xc_find_config(self); 87 | 88 | return self; 89 | } 90 | 91 | void xc_init_modmask(XChainKeys_t *self) { 92 | unsigned int num, caps, scroll; 93 | 94 | /* setup self->modmask to contain all possible combinations of num, 95 | * caps and scroll lock modifiers. 96 | * 97 | * Xchainkeys ignores these modifiers by default, e.g. each key will 98 | * be bound to all possible combinations */ 99 | 100 | /* get the keycodes for num, caps and scroll lock */ 101 | num = 102 | keycode_to_modifier(self->xmodmap, 103 | XKeysymToKeycode(self->display, XStringToKeysym("Num_Lock"))); 104 | caps = 105 | keycode_to_modifier(self->xmodmap, 106 | XKeysymToKeycode(self->display, XStringToKeysym("Caps_Lock"))); 107 | scroll = 108 | keycode_to_modifier(self->xmodmap, 109 | XKeysymToKeycode(self->display, XStringToKeysym("Scoll_Lock"))); 110 | 111 | /* populate modmask array with all possible combinations */ 112 | self->modmask[0] = 0; 113 | self->modmask[1] = num; 114 | self->modmask[2] = caps; 115 | self->modmask[3] = scroll; 116 | self->modmask[4] = num | caps; 117 | self->modmask[5] = num | scroll; 118 | self->modmask[6] = caps | scroll; 119 | self->modmask[7] = num | caps | scroll; 120 | } 121 | 122 | int xc_handle_error(Display *display, XErrorEvent *event ) { 123 | 124 | /* Xlib error handler. Report the standard error text and exit. 125 | * Hint if a key is already grabbed by another application */ 126 | 127 | char error[1024]; 128 | XGetErrorText( display, event->error_code, error, sizeof(error)); 129 | fprintf(stderr, "error: (X) %s\n", error); 130 | 131 | if (event->error_code == BadAccess && event->request_code == 33) { 132 | fprintf(stderr, "A key is already grabbed by another application " 133 | "(most likely your wm/DE).\n"); 134 | } 135 | fflush(stderr); 136 | exit(EXIT_FAILURE); 137 | } 138 | 139 | void xc_show_keys(XChainKeys_t *self) { 140 | 141 | XEvent event; 142 | Key_t *key; 143 | KeyCode keycode; 144 | KeySym keysym; 145 | char *keystr = ""; 146 | char *keyspec = ""; 147 | 148 | if(!xc->debug) { 149 | version(); 150 | printf("\n"); 151 | } 152 | 153 | printf("Press a key combination to show the corresponding keyspec.\n"); 154 | printf("Press Control-c to quit.\n\n"); 155 | fflush(stdout); 156 | 157 | XGrabKeyboard(self->display, DefaultRootWindow(self->display), 158 | True, GrabModeAsync, GrabModeAsync, CurrentTime); 159 | 160 | while(True) { 161 | 162 | /* block until an event occurs */ 163 | XNextEvent(self->display, &event); 164 | 165 | /* we're only interested in KeyPress events */ 166 | if (event.type == KeyPress) { 167 | 168 | keycode = ((XKeyPressedEvent*)&event)->keycode; 169 | 170 | /* skip modifier key press */ 171 | if(keycode_to_modifier(xc->xmodmap, keycode) != 0) 172 | continue; 173 | 174 | keysym = XKeycodeToKeysym(self->display, keycode, 0); 175 | 176 | /* get a string from keysym or keycode */ 177 | if(keysym != NoSymbol) 178 | keystr = XKeysymToString(keysym); 179 | else 180 | snprintf(keystr, 5, "0x%x", (int)keycode); 181 | 182 | /* abort on Ctrl-c */ 183 | if (strcmp(keystr, "c") == 0 && 184 | get_modifiers(self->display) == ControlMask ) { 185 | 186 | XUngrabKeyboard(self->display, CurrentTime); 187 | return; 188 | } 189 | 190 | /* create a key object from the key string and add the currently 191 | * pressed modifiers */ 192 | 193 | key = key_new(keystr); 194 | key->modifiers = get_modifiers(self->display); 195 | 196 | /* get the key specifier in Xchainkey format and print it */ 197 | keyspec = key_to_str(key); 198 | 199 | printf("%s\n", keyspec); 200 | fflush(stdout); 201 | 202 | free(keyspec); 203 | free(key); 204 | } 205 | } 206 | } 207 | 208 | void xc_find_config(XChainKeys_t *self) { 209 | 210 | /* find the config file while respecting XDG_CONFIG_HOME */ 211 | 212 | int n = 4096; 213 | self->config = (char *) calloc(n, sizeof(char)); 214 | 215 | strncpy(self->config, getenv("HOME"), n); 216 | 217 | if(getenv("XDG_CONFIG_HOME") != NULL ) { 218 | strncpy(self->config, getenv("XDG_CONFIG_HOME"), n); 219 | strcat(self->config, "/xchainkeys/xchainkeys.conf"); 220 | } 221 | else { 222 | strcat(self->config, "/.config/xchainkeys/xchainkeys.conf"); 223 | } 224 | } 225 | 226 | void xc_parse_config(XChainKeys_t *self) { 227 | 228 | FILE *f; 229 | char *buffer = (char *) calloc(4096, sizeof(char)); 230 | char *argument= (char *) calloc(4096, sizeof(char)); 231 | char *argument_ptr = argument; 232 | char *line, *token, *expect, *path; 233 | const char *ws = " \t"; 234 | int linenum = 0; 235 | int len, pos; 236 | 237 | Key_t *key; 238 | Binding_t *binding; 239 | Binding_t *parent; 240 | Binding_t *existing; 241 | 242 | int feedback = True; 243 | 244 | char *font = calloc(512, sizeof(char)); 245 | strcpy(font, "fixed"); 246 | 247 | char *fg = calloc(64, sizeof(char)); 248 | strcpy(fg, "black"); 249 | 250 | char *bg = calloc(64, sizeof(char)); 251 | strcpy(bg, "white"); 252 | 253 | /* try to open config file */ 254 | f = fopen(self->config, "r"); 255 | 256 | if(f == NULL) { 257 | fprintf(stderr, "%s: error: '%s': %s\n", 258 | PACKAGE_NAME, self->config, strerror(errno)); 259 | fflush(stderr); 260 | exit(EXIT_FAILURE); 261 | } 262 | 263 | if (self->debug) { 264 | printf("Parsing config file %s\n", self->config); 265 | fflush(stdout); 266 | } 267 | 268 | /* parse file */ 269 | while(fgets(buffer, 4096, f) != NULL) { 270 | linenum++; 271 | line = buffer; 272 | 273 | /* discard whitespace at the beginning */ 274 | line += strspn(line, ws); 275 | 276 | /* ignore empty lines and comments */ 277 | if( line[0] == '\n' || line[0] == '#' ) 278 | continue; 279 | 280 | /* discard newline at end of string */ 281 | if( line[strlen(line)-1] == '\n' ) 282 | line[strlen(line)-1] = '\0'; 283 | 284 | /* parse options */ 285 | if( strncmp(line, "timeout", 7) == 0 ) { 286 | line += 7; 287 | line += strspn(line, ws); 288 | line[strcspn(line, ws)] = '\0'; 289 | self->timeout = (unsigned int)atoi(line); 290 | continue; 291 | } 292 | 293 | if( strncmp(line, "feedback", 8) == 0 ) { 294 | line += 8; 295 | line += strspn(line, ws); 296 | line[strcspn(line, ws)] = '\0'; 297 | 298 | if(strcmp(line, "off") == 0) 299 | feedback = False; 300 | if(strcmp(line, "on") == 0) 301 | feedback = True; 302 | 303 | continue; 304 | } 305 | 306 | if( strncmp(line, "delay", 5) == 0 ) { 307 | line += 5; 308 | line += strspn(line, ws); 309 | line[strcspn(line, ws)] = '\0'; 310 | self->delay = (unsigned int)atoi(line); 311 | continue; 312 | } 313 | 314 | if( strncmp(line, "hold", 4) == 0 ) { 315 | line += 4; 316 | line += strspn(line, ws); 317 | line[strcspn(line, ws)] = '\0'; 318 | self->hold = (unsigned int)atoi(line); 319 | continue; 320 | } 321 | 322 | if( strncmp(line, "position", 8) == 0 ) { 323 | line += 8; 324 | line += strspn(line, ws); 325 | self->position = (char *) calloc(strlen(line)+1, sizeof(char)); 326 | self->position = strncpy(self->position, line, strlen(line)); 327 | continue; 328 | } 329 | 330 | if( strncmp(line, "font", 4) == 0 ) { 331 | line += 4; 332 | line += strspn(line, ws); 333 | line[strcspn(line, ws)] = '\0'; 334 | strncpy(font, line, 512); 335 | font[strlen(line)] = '\0'; 336 | continue; 337 | } 338 | 339 | if( strncmp(line, "foreground", 10) == 0 ) { 340 | line += 10; 341 | line += strspn(line, ws); 342 | line[strcspn(line, ws)] = '\0'; 343 | strncpy(fg, line, 64); 344 | fg[strlen(line)] = '\0'; 345 | continue; 346 | } 347 | 348 | if( strncmp(line, "background", 10) == 0 ) { 349 | line += 10; 350 | line += strspn(line, ws); 351 | line[strcspn(line, ws)] = '\0'; 352 | strncpy(bg, line, 64); 353 | bg[strlen(line)] = '\0'; 354 | continue; 355 | } 356 | 357 | /* parse bindings */ 358 | 359 | pos = 0; 360 | parent = xc->root; 361 | binding = NULL; 362 | expect = "key"; 363 | argument[0] = '\0'; 364 | 365 | while(strlen(line)) { 366 | len = strcspn(line, ws); 367 | 368 | token = calloc((len+1), sizeof(char)); 369 | strncpy(token, line, len); 370 | 371 | line += strcspn(line, ws); 372 | line += strspn(line, ws); 373 | 374 | if( token[0] == ':' ) 375 | expect = "action"; 376 | 377 | if (strcmp(expect, "key") == 0) { 378 | if ((key = key_new(token)) != NULL) { 379 | 380 | /* if this key is already bound in the parent binding, 381 | * then make that binding the parent binding for the next key 382 | */ 383 | existing = binding_get_child_by_key(parent, key); 384 | 385 | if( existing != NULL) { 386 | if(line[0] == ':' || line[0] == '\0') { 387 | path = binding_to_path(existing); 388 | fprintf(stderr, "%s: line %d: '%s': already bound, skipping...\n", 389 | PACKAGE_NAME, linenum, path); 390 | fflush(stderr); 391 | free(path); 392 | free(key); 393 | free(token); 394 | goto next_line; 395 | } 396 | else { 397 | parent = binding_get_child_by_key(parent, key); 398 | free(key); 399 | goto next_token; 400 | } 401 | } 402 | 403 | /* avoid binding :abort, :escape or :group at toplevel */ 404 | if(parent == xc->root) { 405 | if(strncmp(line, ":abort", 6) == 0 || 406 | strncmp(line, ":escape", 7) == 0 || 407 | strncmp(line, ":group", 6) == 0 ) { 408 | 409 | fprintf(stderr, "%s: line %d: '%s': " 410 | "action is invalid outside of chain, skipping...\n", 411 | PACKAGE_NAME, linenum, line); 412 | fflush(stderr); 413 | free(key); 414 | free(token); 415 | goto next_line; 416 | } 417 | } 418 | 419 | /* create a binding for this key */ 420 | binding = binding_new(); 421 | binding->key = key; 422 | 423 | /* append the new binding to the current parent */ 424 | binding_append_child(parent, binding); 425 | 426 | /* make this binding the parent for the next */ 427 | parent = binding; 428 | } 429 | else { 430 | fprintf(stderr, 431 | "%s: line %d: '%s': invalid keyspec, skipping...\n", 432 | PACKAGE_NAME, linenum, token); 433 | fflush(stderr); 434 | free(token); 435 | goto next_line; 436 | } 437 | } 438 | 439 | if (strcmp(expect, "action") == 0) { 440 | binding_set_action(binding, token); 441 | expect = "argument"; 442 | goto next_token; 443 | } 444 | 445 | if (strcmp(expect, "argument") == 0) { 446 | if(strlen(argument)) 447 | strcat(argument, " "); 448 | strncat(argument, token, 4096-strlen(argument)-1); 449 | goto next_token; 450 | } 451 | 452 | next_token: 453 | pos++; 454 | free(token); 455 | } 456 | /* all tokens parsed */ 457 | 458 | if (binding != NULL) { 459 | 460 | /* parse the name portion of the argument */ 461 | if(argument[0] == '"') { 462 | argument += 1; 463 | if(strrchr(argument, '"') == NULL) { 464 | fprintf(stderr, 465 | "%s: line %d: missing closing double quote " 466 | "for action name, ignoring arguments...\n", 467 | PACKAGE_NAME, linenum); 468 | fflush(stderr); 469 | goto next_line; 470 | } 471 | len = strcspn(argument, "\""); 472 | strncpy(binding->name, argument, 128); 473 | binding->name[len] = '\0'; 474 | argument += len + 1; 475 | argument += strspn(argument, ws); 476 | } 477 | 478 | /* append the argument to the current binding */ 479 | if (strlen(argument)) { 480 | strncpy(binding->argument, argument, 4096); 481 | } 482 | argument = argument_ptr; 483 | } 484 | next_line: 485 | ; 486 | } 487 | fclose(f); 488 | 489 | binding_parse_arguments(self->root); 490 | binding_create_default_bindings(self->root); 491 | 492 | /* initialize popup window */ 493 | self->popup = popup_new(self->display, font, fg, bg, self->position); 494 | self->popup->enabled = feedback; 495 | 496 | /* display settings and chains on stdout */ 497 | if (self->debug) { 498 | printf("\n"); 499 | printf("timeout %d\n", self->timeout); 500 | 501 | if (feedback) { 502 | printf("feedback on\n"); 503 | printf("delay %d\n", self->delay); 504 | printf("hold %d\n", self->hold); 505 | printf("position %s\n", self->position); 506 | printf("font %s\n", font); 507 | printf("foreground %s\n", fg); 508 | printf("background %s\n\n", bg); 509 | } 510 | else { 511 | printf("feedback off\n\n"); 512 | } 513 | 514 | binding_list(self->root); 515 | printf("\n"); 516 | fflush(stdout); 517 | } 518 | free(buffer); 519 | free(argument); 520 | free(font); 521 | free(fg); 522 | free(bg); 523 | } 524 | 525 | void xc_grab_prefix_keys(XChainKeys_t *self) { 526 | /* grab top level keys individually */ 527 | int i; 528 | for (i=0; iroot->num_children; i++) { 529 | key_grab(self->root->children[i]->key); 530 | } 531 | } 532 | 533 | void xc_mainloop(XChainKeys_t *self) { 534 | Binding_t *binding; 535 | Binding_t *reentry; 536 | XEvent event; 537 | KeyCode keycode; 538 | struct timeval tv; 539 | fd_set in; 540 | int i; 541 | 542 | while(True) { 543 | xc_grab_prefix_keys(self); 544 | 545 | if (xc->popup->timeout > 0) { 546 | 547 | FD_ZERO(&in); 548 | FD_SET(xc->connection, &in); 549 | tv.tv_sec = xc->popup->timeout / 1000; 550 | tv.tv_usec = (xc->popup->timeout % 1000) * 1000; 551 | if (!select(xc->connection + 1, &in, 0, 0, &tv)) { 552 | popup_hide(xc->popup); 553 | xc->popup->timeout = 0; 554 | } 555 | } 556 | 557 | XNextEvent(self->display, &event); 558 | 559 | if (event.type == KeyPress) { 560 | keycode = ((XKeyPressedEvent*)&event)->keycode; 561 | 562 | for( i=0; iroot->num_children; i++ ) { 563 | binding = self->root->children[i]; 564 | 565 | if (key_get_keycode(binding->key) == keycode) { 566 | if(binding->key->modifiers == get_modifiers(xc->display)) { 567 | 568 | popup_hide(xc->popup); 569 | xc->popup->timeout = 0; 570 | 571 | binding_activate(binding); 572 | break; 573 | } 574 | } 575 | } 576 | } 577 | reentry: 578 | if(xc->reentry != NULL) { 579 | reentry = xc->reentry; 580 | xc->reentry = NULL; 581 | binding_activate(reentry); 582 | goto reentry; 583 | } 584 | 585 | if(xc->reload) { 586 | xc_reload(self); 587 | } 588 | } 589 | } 590 | 591 | void xc_reset(XChainKeys_t *self) { 592 | int i; 593 | Binding_t *prefix; 594 | 595 | for(i=0; iroot->num_children; i++) { 596 | prefix = self->root->children[i]; 597 | 598 | key_ungrab(prefix->key); 599 | binding_free(prefix); 600 | self->root->children[i] = NULL; 601 | } 602 | self->root->num_children = 0; 603 | 604 | self->reentry = NULL; 605 | self->reload = False; 606 | 607 | popup_free(self->popup); 608 | self->popup = NULL; 609 | } 610 | 611 | void xc_reload(XChainKeys_t *self) { 612 | xc_reset(self); 613 | xc_parse_config(self); 614 | xc_grab_prefix_keys(self); 615 | } 616 | 617 | void xc_parse_options(XChainKeys_t *self, int argc, char **argv) { 618 | 619 | struct option options[] = { 620 | { "debug", no_argument, NULL, 'd' }, 621 | { "help", no_argument, NULL, 'h' }, 622 | { "version", no_argument, NULL, 'v' }, 623 | { "keys", no_argument, NULL, 'k' }, 624 | { "file", no_argument, NULL, 'f' }, 625 | { 0, 0, 0, 0 }, 626 | }; 627 | int option, option_index; 628 | 629 | while (1) { 630 | 631 | option = getopt_long(argc, argv, "dhvkf:", options, &option_index); 632 | 633 | switch (option) { 634 | 635 | case 'f': 636 | strncpy(self->config, optarg, 4096); 637 | self->config[strlen(optarg)] = '\0'; 638 | break; 639 | 640 | case 'k': 641 | xc_show_keys(self); 642 | exit(EXIT_SUCCESS); 643 | 644 | case 'd': 645 | self->debug = True; 646 | version(); 647 | printf("\n"); fflush(stdout); 648 | break; 649 | 650 | case 'h': 651 | usage(); 652 | exit(EXIT_SUCCESS); 653 | break; 654 | 655 | case 'v': 656 | version(); 657 | exit(EXIT_SUCCESS); 658 | break; 659 | 660 | case -1: 661 | break; 662 | 663 | default: 664 | usage(); 665 | exit(EXIT_FAILURE); 666 | break; 667 | } 668 | if(option == -1) 669 | break; 670 | } 671 | } 672 | 673 | int main(int argc, char **argv) { 674 | 675 | xc = xc_new(); 676 | 677 | xc_parse_options(xc, argc, argv); 678 | xc_parse_config(xc); 679 | xc_mainloop(xc); 680 | 681 | exit(EXIT_SUCCESS); 682 | } 683 | -------------------------------------------------------------------------------- /src/xchainkeys.h: -------------------------------------------------------------------------------- 1 | #ifndef XCHAINKEYS_H 2 | #define XCHAINKEYS_H 3 | 4 | #define XC_ACTION_NONE 0 5 | #define XC_ACTION_ENTER 1 6 | #define XC_ACTION_ESCAPE 2 7 | #define XC_ACTION_ABORT 3 8 | #define XC_ACTION_EXEC 4 9 | #define XC_ACTION_GROUP 5 10 | #define XC_ACTION_LOAD 6 11 | #define XC_ACTION_WAIT 7 12 | #define XC_NUM_ACTIONS 8 13 | 14 | #define XC_ABORT_AUTO 1 15 | #define XC_ABORT_MANUAL 0 16 | 17 | typedef struct XChainKeys { 18 | Display *display; 19 | XModifierKeymap *xmodmap; 20 | int modmask[8]; 21 | char *action_names[XC_NUM_ACTIONS]; 22 | int debug; 23 | unsigned int timeout; 24 | unsigned int delay; 25 | unsigned int hold; 26 | int connection; 27 | char *position; 28 | char *config; 29 | int reload; 30 | struct Popup *popup; 31 | struct Binding *root; 32 | struct Binding *reentry; 33 | } XChainKeys_t; 34 | 35 | XChainKeys_t* xc_new(void); 36 | void xc_parse_options(XChainKeys_t *self, int argc, char **argv); 37 | void xc_init_modmask(XChainKeys_t *self); 38 | int xc_handle_error(Display *display, XErrorEvent *event); 39 | void xc_show_keys(XChainKeys_t *self); 40 | void xc_find_config(XChainKeys_t *self); 41 | void xc_parse_config(XChainKeys_t *self); 42 | void xc_grab_prefix_keys(XChainKeys_t *self); 43 | void xc_mainloop(XChainKeys_t *self); 44 | void xc_reload(XChainKeys_t *self); 45 | void xc_reset(XChainKeys_t *self); 46 | void xc_shutdown(XChainKeys_t *self); 47 | 48 | #endif /* ifndef XCHAINKEYS_H */ 49 | -------------------------------------------------------------------------------- /xchainkeys.1: -------------------------------------------------------------------------------- 1 | .TH XCHAINKEYS 1 "2010-09-16" "Linux" "User manuals" 2 | .SH NAME 3 | \fBxchainkeys\fP \- chained keybindings for X11 4 | .SH SYNOPSIS 5 | \fBxchainkeys\fP [\fIoptions\fP] 6 | .SH DESCRIPTION 7 | xchainkeys is a standalone X11 program to create chained key 8 | bindings similar to those found in the \fBratpoison\fP(1) window 9 | manager or the \fBscreen\fP(1) terminal multiplexer. 10 | .SH OPTIONS 11 | .IP \fB-f\fP,\ \fB--file\fP\ \fI\fP 12 | Load an alternative configuration file. 13 | .IP \fB-k\fP,\ \fB--keys\fP 14 | Interactively show valid keyspecs for key combinations. 15 | .IP \fB-d\fP,\ \fB--debug\fP 16 | Show debug messages on stdout. 17 | .IP \fB-h\fP,\ \fB--help\fP 18 | Show usage information. 19 | .IP \fB-v\fP,\ \fB--version\fP 20 | Show version information. 21 | .SH CONFIGURATION 22 | The configuration file is located at 23 | 24 | \fI~/.config/xchainkeys/xchainkeys.conf\fP 25 | 26 | The \fIXDG_CONFIG_HOME\fP environment variable will be respected in 27 | compliance with the \fBXDG Base Directory Specification\fP (see 28 | \fBREFERENCES\fP below). 29 | 30 | An example configuration file has been installed to 31 | 32 | \fI__PREFIX__/share/doc/xchainkeys/example.conf\fP 33 | .SS Syntax 34 | Each line may contain either a global setting or a keybinding 35 | definition. Empty lines and lines starting with a numbersign (#) are 36 | ignored. 37 | .SS Global Settings 38 | Global settings are defined as key-value pairs, separated by 39 | whitespace. 40 | .IP \fBtimeout\fP\ \fI\fP\ (default:\ \fB3000\fP) 41 | 42 | Wait \fIn\fP milliseconds for another key to be pressed before 43 | aborting an active keychain. A value of 0 will prevent automatic 44 | timeout. This value may be overridden by a \fBtimeout\fP argument 45 | supplied to an \fB:enter\fP action, see \fBActions\fP below. 46 | .IP \fBfeedback\fP\ \fI<\fBon\fP|\fBoff\fP>\fP\ (default:\ \fBon\fP) 47 | 48 | Show feedback in a small popup window. 49 | .IP \fBdelay\fP\ \fI\fP\ (default:\ \fB1000\fP) 50 | 51 | Show current chain status after \fIn\fP milliseconds of inactivity 52 | in an active chain. 53 | .IP \fBhold\fP\ \fI\fP\ (default:\ \fI\fP) 54 | 55 | Show error messages for \fIn\fP milliseconds after a chain has been 56 | aborted. If not set, the value of \fBdelay\fP will be used. 57 | .IP \fBposition\fP\ \fI\ [\fI\fP]\ (default:\ \fBcenter\fP) 58 | 59 | The position of the feedback window. An absolute position can be 60 | specified with the \fIx\fP and \fIy\fP arguments. A relative position 61 | can be specified using the offset portion of a standard X geometry 62 | string. The value \fBmouse\fP will cause the window to appear centered 63 | around the current mouse pointer position. The value \fBcenter\fP will 64 | center the window on the default screen. 65 | .IP \fBfont\fP\ \fI\fP\ (default:\ \fBfixed\fP) 66 | 67 | The X11 font to use for text in the feedback window. 68 | .IP \fBforeground\fP\ \fI\fP\ (default:\ \fBblack\fP) 69 | 70 | The foreground color of the text and the border of the feedback window. 71 | .IP \fBbackground\fP\ \fI\fP\ (default:\ \fBwhite\fP) 72 | 73 | The background color of the feedback window. 74 | .SS Keybindings 75 | Keybindings are defined using the following syntax: 76 | 77 | \fI\fP \fB[\fP\fI\fP\fB...]\fP :\fI\fP \fB[\fP"\fI\fP"\fB]\fP\ \fB[\fP\fI\fP\fB...]\fP 78 | 79 | A \fIkeyspec\fP consists of one or more optional \fBmodifier names\fP, 80 | followed by either a symbolic \fBkey name\fP or a numeric keycode, 81 | each separated by a hyphen (-): 82 | 83 | \fI\fP-\fB[\fP\fI\fP-\fB...]\fP\fI\fP 84 | 85 | Modifier names: 86 | 87 | .RS 88 | \fIS\fP, \fIShift\fP = Shift key 89 | \fIC\fP, \fICtrl\fP = Control key 90 | \fIA\fP, \fIM\fP, \fIAlt\fP, \fIMeta\fP = Alt key 91 | \fIW\fP, \fIH\fP, \fISuper\fP, \fIHyper\fP, \fIWindows\fP = Super key 92 | .RE 93 | 94 | The generic modifier names \fIShift\fP, \fILock\fP, \fIControl\fP, 95 | \fIMod1\fP, \fIMod2\fP, \fIMod3\fP, \fIMod4\fP and \fIMod5\fP are 96 | recognized in addition to the above. 97 | 98 | Key names correspond to the symbolic key names defined in 99 | \fI/usr/include/X11/keysymdef.h\fP (with their \fIXK_\fP prefix 100 | removed). 101 | 102 | Numeric keycodes may be supplied in decimal, hexadecimal or octal 103 | format, e.g. 16 (decimal) = 0x10 (hexadecimal) = 020 octal. 104 | 105 | You can use \fBxchainkeys -k\fP to find the proper \fIkeyspec\fP for 106 | key combinations. 107 | .SS Actions 108 | 109 | .IP \fB:enter\fP\ [\fBtimeout=\fP\fI\fP]\ [\fBabort=\fP\fI\fP] 110 | 111 | Enters a keychain. The keyboard will be grabbed exclusively until 112 | another keystroke has been processed, or until the chain times out 113 | after \fIn\fP milliseconds. If the key is bound within this chain, 114 | the associated action will be invoked, otherwise the user will be 115 | notified that an unbound key has been pressed. 116 | 117 | If the \fPabort\fP argument is set to \fImanual\fP, the chain prefix 118 | will remain activated and further keystrokes will be processed until 119 | the chain is manually aborted with the \fB:abort\fP action. If set to 120 | \fIauto\fP (the default), the chain will abort immediately after the 121 | first keystroke has been processed. 122 | 123 | If the \fBtimeout\fP argument is omitted, the global timeout setting 124 | will apply. A value of \fI0\fP disables the timeout for this chain. 125 | .IP \fB:abort\fP 126 | Abort the current keychain, releasing any previous grab on the 127 | keyboard. If not explicitly bound, \fB:abort\fP will be bound to 128 | \fBprefix C-g\fP by default. 129 | .IP \fB:escape\fP 130 | Send the \fBprefix key\fP key of this chain to the currently focused 131 | window and abort the chain. If not explicitly bound, \fB:escape\fP 132 | will be bound to \fBprefix prefix\fP, e.g. for a chain prefixed with 133 | \fBC-t\fP the \fB:escape\fP action will be bound to \fBC-t C-t\fP by 134 | default. 135 | 136 | This feature is implemented using \fBXSendEvent(3)\fP. Note that 137 | applications may refuse to accept synthetic events generated with 138 | \fBXSendEvent\fP. 139 | .IP \fB:exec\fP\ [\fBabort=\fP\fIauto\fP]\ \fI\fP 140 | Asynchronously execute \fIcommand\fP as a shell command. If 141 | \fBabort=\fP\fIauto\fP is given, this binding will always abort the 142 | current chain after executing the command, even if the chain was 143 | entered with \fBabort=\fP\fImanual\fP. 144 | .IP \fB:wait\fP\ \fI\fP 145 | Ungrab the keyboard, execute \fIcommand\fP as a shell command, wait 146 | until the \fIcommand\fP has completed and grab the keyboard again if 147 | necessary. Use this action to run commands that also grab the keyboard 148 | (e.g. \fIscrot --select\fP). 149 | .IP \fB:group\fP\ \fB[\fP"\fI\fP"\fB]\fP\ [\fBabort=\fP\fIauto\fP]\ \fI\fP 150 | Associate a binding with a named group and asynchronously execute 151 | \fIcommand\fP as a shell command. 152 | 153 | When a \fB:group\fP action is activated, timeout and automatic abort 154 | are disabled for the current chain prefix, and only bindings in the 155 | same group will be recognized for subsequent key presses. Any other 156 | keys will abort the chain and revert the above changes. 157 | 158 | If \fBabort=\fP\fIauto\fP is given for particular binding within a 159 | group, this binding will always abort the current chain after 160 | executing the command, effectively overriding the implied 161 | \fBabort=\fP\fImanual\fP option. 162 | 163 | In addition, if the key used to abort the chain key is a toplevel 164 | chain \fBprefix key\fP, the corresponding chain will be entered 165 | immediately after this chain aborts. See \fBEXAMPLES\fP below for 166 | possible uses. 167 | 168 | If no explicit name is given, the group name "default" is used. 169 | 170 | .IP \fB:repeat\fP\ \fI\fP 171 | Deprecated. Equivalent to \fB:group\fP \fB"default"\fP. 172 | .IP \fB:load\fP\ [\fI\fP] 173 | .IP \fB:reload\fP\ [\fI\fP] 174 | Clear the current bindings and (re)load the configuration file specified 175 | by \fIfilename\fP. If no file is specified, the current configuration 176 | file is reloaded. 177 | .SH EXAMPLES 178 | Bind the key sequence "Control-t Return" to run xterm:\fP 179 | 180 | C-t Return :exec xterm 181 | 182 | \fPThis implies creating a default chain with the prefix key 183 | \fBC-t\fP, containing default bindings for the \fB:abort\fP and 184 | \fB:escape\fP actions, and is thus equivalent to\fB 185 | 186 | C-t :enter timeout=3000 abort=auto 187 | C-t C-t :escape 188 | C-t C-g :abort 189 | C-t Return :exec xterm 190 | 191 | \fPNote that the number of keys in a keychain is not limited, e.g\fB 192 | 193 | C-t x c h a i n k e y s :exec xmessage "xchainkeys!" 194 | 195 | \fPcan be invoked by pressing \fBC-t\fP and then typing "xchainkeys". 196 | 197 | The following example creates a named \fP:group\fP of bindings to 198 | implement a dedicated frame resize mode for the \fBmusca\fP(1) window 199 | manager:\fB 200 | 201 | C-w i :group "resize" musca -c 'resize up' 202 | C-w k :group "resize" musca -c 'resize down' 203 | C-w j :group "resize" musca -c 'resize left' 204 | C-w l :group "resize" musca -c 'resize right' 205 | 206 | C-w ... (other bindings for window management) 207 | 208 | \fPInvoke any of the above bindings (e.g. press \fBC-w i\fP) and then 209 | continue to press \fBi\fP, \fBk\fP, \fBj\fP or \fBl\fP to resize the 210 | current musca frame. Since timeout and automatic abort are disabled, 211 | you can continue resizing until you are satisfied with the 212 | result. Then simply press any other key to quit resize mode. If 213 | you want to invoke another window management command right away, you 214 | can use \fBC-w\fP to quit resize mode and immediately enter the 215 | \fBC-w\fP chain (or any other toplevel chain) again. 216 | 217 | The benefit of using a named \fB:group\fP over a dedicated chain with 218 | \fBtimeout=0\fP and \fBabort=manual\fP is that you don't have to waste 219 | another prefix key. Instead you can temporarily redefine an existing 220 | chain to contain only a specific subset of keys, behaving in the 221 | desired manner. 222 | .SH KNOWN ISSUES 223 | Some window managers assume that no other program has grabbed any 224 | global key combinations before them, and may fail with a fatal error 225 | when trying to grab a key that has already been grabbed as a prefix 226 | key by xchainkeys. This situation is likely to occur when xchainkeys 227 | is started before the window manager in \fI~/.xinitrc\fP. 228 | 229 | In general, binding the same key combinations in xchainkeys and other 230 | programs should be avoided. 231 | .SH BUGS 232 | This software is currently in beta state. Please file bugs on the 233 | googlecode issue tracker. 234 | 235 | http://code.google.com/p/xchainkeys/issues 236 | 237 | Use the email address below for questions, feature requests and 238 | comments. 239 | .SH COPYRIGHT 240 | Copyright (C) 2010-2012 Henning Bekel 241 | .SH LICENSE 242 | xchainkeys is licensed under the GNU General Public License v3, see 243 | http://www.gnu.org/licenses/gpl.html. 244 | .SH REFERENCES 245 | .IP \fBX11\ key\ symbols\fP 246 | /usr/include/X11/keysymdef.h 247 | .IP \fBXDG\ Base\ Directory\ Specification\fP 248 | http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html 249 | .SH "SEE ALSO" 250 | .BR Xorg (1) 251 | .BR screen (1) 252 | .BR ratpoison (1) 253 | .BR musca (1) 254 | --------------------------------------------------------------------------------