File dzen2-1379930259.488ab66.obscpio of Package dzen2

070701303F14D3000081A40000420C0000003200000001524010930000030A000000080000001100000000000000000000002100000000dzen2-1379930259.488ab66/CREDITS==================================
  dzen, (c) 2007 by Robert Manea
==================================


The following people have contributed especially to dzen:


Cyrille Bagard <nocbos at gmail dot com>
  * patch allowing to use EWMH for docking dzen.

Jason Creighton <jcreigh at gmail dot com>
  * XINERAMA support
  * _NET_WM_STRUT_PARTIAL support

Adam Langley <agl at imperialviolet dot org>
  * patch to add optional timeout to '-p'

Mauke <mauke at ...>
  * Code clean ups to remove compiler warnings

Alexander V. Inyukhin <shurick at sectorb dot msk dot ru>
  * fix to action handling

Valery V. Vorotyntsev <valery dot vv at gmail.com>
  * patch to correctly handle the -geometry and -y options for
    dzen at the bottom of the screen
  * cosmetic code clean ups

070701303F14D4000081A40000420C00000032000000015240109300000279000000080000001100000000000000000000002100000000dzen2-1379930259.488ab66/INSTALL==================================
 dzen, (c) 2007 by Robert Manea
==================================


Edit config.mk to match your local setup (dzen is installed into
the /usr/local namespace by default).

Afterwards enter the following command to build and install dzen (if
necessary as root):

    make clean install


Optionally if you want to use dzen's gadgets:

    cd gadgets
    make clean install


Note:       By default dzen will not be compiled with Xinerama and XPM support.
            Uncomment the respective lines in config.mk to change this.


Use "./help" to view a nicely formated version of the documentation.
070701303F14D5000081A40000420C00000032000000015240109300000464000000080000001100000000000000000000002100000000dzen2-1379930259.488ab66/LICENSEMIT/X Consortium License

(C)opyright MMVII Robert Manea <rob dot manea at gmail dot com>

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the 
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in 
all copies or substantial portions of the Software. 

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL 
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
DEALINGS IN THE SOFTWARE.
070701303F14D6000081A40000420C000000320000000152401093000006C9000000080000001100000000000000000000002200000000dzen2-1379930259.488ab66/Makefile# dzen2
#   (C)opyright MMVII Robert Manea

include config.mk

SRC = draw.c main.c util.c action.c
OBJ = ${SRC:.c=.o}

all: options dzen2

options:
	@echo dzen2 build options:
	@echo "CFLAGS   = ${CFLAGS}"
	@echo "LDFLAGS  = ${LDFLAGS}"
	@echo "CC       = ${CC}"
	@echo "LD       = ${LD}"

.c.o:
	@echo CC $<
	@${CC} -c ${CFLAGS} $<

${OBJ}: dzen.h action.h config.mk

dzen2: ${OBJ}
	@echo LD $@
	@${LD} -o $@ ${OBJ} ${LDFLAGS}
	@strip $@
	@echo "Run ./help for documentation"

clean:
	@echo cleaning
	@rm -f dzen2 ${OBJ} dzen2-${VERSION}.tar.gz

dist: clean
	@echo creating dist tarball
	@mkdir -p dzen2-${VERSION}
	@mkdir -p dzen2-${VERSION}/gadgets
	@mkdir -p dzen2-${VERSION}/bitmaps
	@cp -R CREDITS LICENSE Makefile INSTALL README.dzen README help config.mk action.h dzen.h ${SRC} dzen2-${VERSION}
	@cp -R gadgets/Makefile  gadgets/config.mk gadgets/README.dbar gadgets/textwidth.c gadgets/README.textwidth gadgets/dbar.c gadgets/gdbar.c gadgets/README.gdbar gadgets/gcpubar.c gadgets/README.gcpubar gadgets/kittscanner.sh gadgets/README.kittscanner gadgets/noisyalert.sh dzen2-${VERSION}/gadgets
	@cp -R bitmaps/alert.xbm bitmaps/ball.xbm bitmaps/battery.xbm bitmaps/envelope.xbm bitmaps/volume.xbm bitmaps/pause.xbm bitmaps/play.xbm bitmaps/music.xbm  dzen2-${VERSION}/bitmaps
	@tar -cf dzen2-${VERSION}.tar dzen2-${VERSION}
	@gzip dzen2-${VERSION}.tar
	@rm -rf dzen2-${VERSION}

install: all
	@echo installing executable file to ${DESTDIR}${PREFIX}/bin
	@mkdir -p ${DESTDIR}${PREFIX}/bin
	@cp -f dzen2 ${DESTDIR}${PREFIX}/bin
	@chmod 755 ${DESTDIR}${PREFIX}/bin/dzen2

uninstall:
	@echo removing executable file from ${DESTDIR}${PREFIX}/bin
	@rm -f ${DESTDIR}${PREFIX}/bin/dzen2

.PHONY: all options clean dist install uninstall
070701303F14D7000081A40000420C000000320000000152401093000049EC000000080000001100000000000000000000002000000000dzen2-1379930259.488ab66/README====================================
 dzen, (c) 2007-2010 by Robert Manea
====================================

Dzen is a general purpose messaging, notification and menuing program for X11.
It was designed to be fast, tiny and scriptable in any language.


Features
--------

    * Small, fast, very tiny set of dependencies (Xlib only by default)
    * Scriptable in any language
    * Sophisticated formating language - including colours, icons, graphics
    * Versatile - display all sorts of information
    * Interactive - user defined mouse and keyboard actions
    * Optional XFT support
    * Optional XINERAMA support


Requirements
------------
In order to build dzen you need the Xlib header files.


Installation
------------
Edit config.mk to match your local setup (dzen is installed into
the /usr/local namespace by default).

Afterwards enter the following command to build and install dzen (if
necessary as root):

    make clean install


Optionally if you want to use dzen's gadgets:

    cd gadgets
    make clean install


Note:       By default dzen will not be compiled with Xinerama and XPM support.
            Uncomment the respective lines in config.mk to change this.


Contact:
--------
Feature requests, patches or anything else related to dzen can be send
to: rob dot manea at gmail dot com


Running dzen
------------
dzen accepts a couple of options:

    -fg     foreground color
    -bg     background color
    -fn     font 
    -ta     alignement of title window content 
            l(eft), c(center), r(ight)
    -tw     title window width
    -sa     alignment of slave window, see "-ta"
    -l      lines, see (1)
    -e      events and actions, see (2)
    -m      menu mode, see (3)
    -u      update contents of title and 
            slave window simultaneously, see (4)
    -p      persist EOF (optional timeout in seconds)
    -x      x position
    -y      y position
    -h      line height (default: fontheight + 2 pixels)
    -w      width
    -xs     number of Xinerama screen
    -v      version information

    see (5) for the in-text formating language.



X resources
-----------

Dzen is able to read font and color setting from X resources.
As an example you can add following lines to ~/.Xresources

dzen2.font:       -*-fixed-*-*-*-*-*-*-*-*-*-*-*-*
dzen2.foreground: #22EE11
dzen2.background: black



Window layout
-------------

Dzen's window layout is as follows:

     ------------------------------------------
    |        Title window, single line         |
    `------------------------------------------´
    |                                          |
    |               scrollable                 |
    |              Slave window                |
    |             multiple lines               |
    |     lines to display simultaneously      |
    |           controlled with the            |
    |              '-l' option                 |
    |                                          |
    |                                          |
    `------------------------------------------´

The first line you provide to dzen always goes to the title window, 
all other consecutive lines will be drawn to the slave window unless
you explicitly overide this with the (5) In-text formating language
command ^tw().


QA:
---

Q1:  I don't want a slave window, what to do?

A1:  Do not provide the '-l' option, all lines will be displayed
     in the title window, this is the default behaviour.


Q2:  I used the '-l' option but no slave window appears.

A2:  With the default event/action handling the slave window will
     only be displayed if you hoover with the mouse over the title
     window. See "(2) Events and actions" if you'd like to change
     this.


Q3:  If I echo some text or cat a file dzen closes itself imediatelly.

A3:  There are 2 different approaches dzen uses to terminate itself, 
     see next section "Termination".


Q4:  Ok, the title and slave thing works, can I update the
     contents of both windows at the same time?

A4:  Sure, see "(4) Simultaneous updates" or use the in-text 
     command "^tw()" to explicitly draw to the title windwow.
     See section (5) for further details


Q5:  Can i chnage color of my input at runtime?

A5:  Yes, you can change both background and foreground colors and 
     much more See "(5) In-Text formating language"


Q6:  Can I use dzen as a menu?

A6:  Yes, both vertical and horizontal menus are supported. 
     See "(3) Menu" for further details.




Termination:
------------
dzen uses two different approaches to terminate itself:

    * Timed termination: if EOF is received -> terminate
        - unless the '-p' option is set
            · '-p' without argument persist forever
            · '-p' with argument n  persist for n seconds

    * Interactive termination: if mouse button3 is clicked -> terminate
        - this is the default behaviour, see (2)
        - in some modes the Escape key terminates too, see (2)



Return values:
--------------
0               -   dzen received EOF
1               -   some error occured, inspect the error message
user defined    -   set with 'exit:retval' action, see (2)



(1) Option "-l": Slave window
--------------------------------

Enables support for displaying multiple lines. The parameter to "-l"
specifies the number of lines to be displayed.

These lines of input are held in the slave window which becomes active as soon
as the pointer enters the title (default action) window.

If the mouse leaves the slave window it will be hidden unless it is set
sticky by clicking with Button2 into it (default action).

Button4 and Button5 (mouse wheel) will scroll the slave window up
and down if the content exceeds the window height (default action).



(2) Option '-e': Events and actions
-----------------------------------

dzen allows the user to associate actions to events.

The command line syntax is as follows:
-e 'event1=action1:option1:...option<n>,...,action<m>;...;event<l>'

Every event can take any number of actions and every action can take any number
of options. (By default limited to 64 each, easily changable in action.h)

An example:
    -e 'button1=exec:xterm:firefox;entertitle=uncollapse,unhide;button3=exit'

    Meaning:

    button1=exec:xterm:firefox;
    on Button1 event (Button1 press on the mouse) execute xterm and
    firefox. 
    Note: xterm and firefox are options to the exec action

    entertitle=uncollapse,unhide;
    on entertitle (mouse pointer enters the title window) uncollapse
    slave window and unhide the title window

    button3=exit
    on button3 event exit dzen


Supported events:
-----------------

    onstart             Perform actions right after startup
    onexit              Perform actions just before exiting
    onnewinput          Perform actions if there is new input for the slave window
    button1             Mouse button1 released 
    button2             Mouse button2 released
    button3             Mouse button3 released
    button4             Mouse button4 released (usually scrollwheel)
    button5             Mouse button5 released (usually scrollwheel)
    button6             Mouse button6 released
    button7             Mouse button7 released
    entertitle          Mouse enters the title window
    leavetitle          Mouse leaves the title window
    enterslave          Mouse enters the slave window
    leaveslave          Mouse leaves the slave window
    sigusr1             SIGUSR1 received 
    sigusr2             SIGUSR2 received
    key_KEYNAME         Keyboard events (*)


    (*) Keyboard events:
    --------------------

    Every key can be bound to an action (see below). The format is:
    key_KEYNAME where KEYNAME is the name of the key as defined in
    keysymdef.h (usually: /usr/include/X11/keysymdef.h).  The part 
    after 'XK_' in keysymdef.h must be used for KEYNAME.



Supported actions:
------------------

    exec:command1:..:n  execute all given options
    menuexec            executes selected menu entry
    exit:retval         exit dzen and return 'retval'
    print:str1:...:n    write all given options to STDOUT
    menuprint           write selected menu entry to STDOUT
    collapse            collapse (roll-up) slave window
    uncollapse          uncollapse (roll-down) slave window
    togglecollapse      toggle collapsed state
    stick               stick slave window
    unstick             unstick slave window
    togglestick         toggle sticky state
    hide                hide title window
    unhide              unhide title window
    togglehide          toggle hide state
    raise               raise window to view (above all others)
    lower               lower window (behind all others)
    scrollhome          show head of input
    scrollend           show tail of input
    scrollup:n          scroll slave window n lines up   (default n=1)
    scrolldown:n        scroll slave window n lines down (default n=1)
    grabkeys            enable keyboard support
    ungrabkeys          disable keyboard support
    grabmouse           enable mouse support 
                        only needed with specific windowmanagers, such as fluxbox
    ungrabmouse         release mouse
                        only needed with specific windowmanagers, such as fluxbox


Note:   If no events/actions are specified dzen defaults to:

        Title only mode:
        ----------------

        -e 'button3=exit:13'


        Multiple lines and vertical menu mode:
        --------------------------------------

        -e 'entertitle=uncollapse,grabkeys;
            enterslave=grabkeys;leaveslave=collapse,ungrabkeys;
            button1=menuexec;button2=togglestick;button3=exit:13;
            button4=scrollup;button5=scrolldown;
            key_Escape=ungrabkeys,exit'


        Horizontal menu mode:
        ---------------------

        -e 'enterslave=grabkeys;leaveslave=ungrabkeys;
            button4=scrollup;button5=scrolldown;
            key_Left=scrollup;key_Right=scrolldown;
            button1=menuexec;button3=exit:13
            key_Escape=ungrabkeys,exit'


        If you define any events/actions, there is no default behaviour,
        i.e. you will have to specify _all_ events/actions you want to
        use.



(3) Option '-m', Menu
---------------------

Dzen provides two menu modes, vertical and horizontal menus. You can
access these modes by adding 'v'(ertical) or 'h'(horizontal) to the 
'-m' option. If nothing is specified dzen defaults to vertical menus.

Vertical menu, both invocations are equivalent:
    dzen2 -p -l 4 -m < file
    dzen2 -p -l 4 -m v < file

Horizontal menu:
    dzen2 -p -l 4 -m h < file


All actions beginning with "menu" work on the selected menu entry.

Note:   Menu mode only makes sense if '-l <n>' is specified!

        Horizontal menus have no title window, so all actions
        affecting the title window will be silently discarded
        in this mode.



(4) Option '-u', Simultaneous updates
-------------------------------------

** DEPRECATED **

This option provides facilities to update the title and slave window at
the same time.

The way it works is best described by an example:

  Motivation:

  We want to display an updating clock in the title and some log
  output in the slave window.

  Solution:

  while true; do
        date                # output goes to the title window
        dmesg | tail -n 10  # output goes to the slave window
        sleep 1
  done | dzen2 -l 10 -u

For this to work correctly it is essential to provide exactly the number
of lines to the slave window as defined by the parameter to '-l'.



(5) In-text formating & control language:
-----------------------------------------

This feature allows to dynamically (at runtime) format the text dzen
displays and control its behaviour.

Currently the following commands are supported:


Note:  Doubling the '^' character ('^^') will remove the special meaning from it.


Colors:
-------

    ^fg(color)         set foreground color
    ^fg()              without arguments, sets default fg color
    ^bg(color)         set background color
    ^bg()              without arguments, sets default bg color

Graphics:
---------

    ^i(path)           draw icon specified by path
                       Supported formats: XBM and optionally XPM

    ^r(WIDTHxHEIGHT)   draw a rectangle with the dimensions 
                       WIDTH and HEIGHT
    ^ro(WIDTHxHEIGHT)  rectangle outline

    ^c(RADIUS)         draw a circle with size RADIUS pixels
    ^co(RADIUS)        circle outline

Positioning:
------------

    ^p(ARGUMENT)       position next input amount of PIXELs to the right
                       or left of the current position
                       a.k.a. relative positioning

    ^pa(ARGUMENT)      position next input at PIXEL
                       a.k.a. absolute positioning

     ARGUMENT:

     ^p(+-X)          move X pixels to the right or left of the current position (on the X axis) 

     ^p(+-X;+-Y)      move X pixels to the right or left and Y pixels up or down of the current 
                      position (on the X and Y axis) 

     ^p(;+-Y)         move Y pixels up or down of the current position (on the Y axis)

     ^p()             without parameters resets the Y position to its default 

     ^pa()            takes the same parameters as described above but positions at
                      the absolute X and Y coordinates 

     Further ^p() also takes some symbolic names as argument:

     _LOCK_X          Lock the current X position, useful if you want to
                      align things vertically
     _UNLOCK_X        Unlock the X position 
     _LEFT            Move current x-position to the left edge 
     _RIGHT           Move current x-position to the right edge 
     _TOP             Move current y-position to the top edge 
     _CENTER          Move current x-position to center of the window 
     _BOTTOM          Move current y-position to the bottom edge 

Interaction:
------------

    ^ca(BTN, CMD) ... ^ca()      

                       Used to define 'clickable areas' anywhere inside the
                       title window or slave window. 
                       - 'BTN' denotes the mouse button (1=left, 2=right, 3=middle, etc.) 
                       - 'CMD' denotes the command that should be spawned when the specific
                         area has been clicked with the defined button
                       - '...' denotes any text or formating commands dzen accepts
                       - '^ca()' without arguments denotes the end of this clickable area

                       Example:
                         foo ^ca(1, echo one)^fg(red)click me and i'll echo one^fg()^ca() bar
                        
Actions as commands:
--------------------

    ^togglecollapse()
    ^collapse()
    ^uncollapse()
    ^togglestick()
    ^stick()            See section (2) 'Events and actions' for a detailed description 
    ^unstick()          of each command.
    ^togglehide()
    ^hide()
    ^unhide()
    ^raise()
    ^lower()
    ^scrollhome()
    ^scrollend()
    ^exit()  

Other:
------

    ^tw()              draw to title window
                       This command has some annoyances, as only 
                       the input after the command will be drawn
                       to the title window, so it is best used 
                       only once and as first command per line.

    ^cs()              clear slave window
                       This command must be the first and only command
                       per line.

    ^ib(VALUE)         ignore background setting, VALUE can be either
                       1 to ignore or 0 to not ignore the bg color set
                       with ^bg(color).
                       This command is useful in combination with ^p()
                       and ^pa() in order to position the input inside 
                       other already drawn input.

                       Example: 
                         ^ib(1)^fg(red)^ro(100x15)^p(-98)^fg(blue)^r(20x10)^fg(orange)^p(3)^r(40x10)^p(4)^fg(darkgreen)^co(12)^p(2)^c(10)



These commands can appear anywhere and in any combination in dzen's
input. 

The color can be specified either as symbolic name (e.g. red,
darkgreen, etc.) or as #rrggbb hex-value (e.g. #ffffaa).

Icons must be in the XBM or optionally XPM format, see the "bitmaps"
directory for some sample icons. With the standard "bitmap" application
you can easily draw your own icons.



Some examples:

   Input:  
          ^fg(red)I'm red text ^fg(blue)I am blue


   Input:
          ^bg(#ffaaaa)The ^fg(yellow)text to ^bg(blue)^fg(orange)colorize


   Input:
          ^fg(grey70)Some text containing ^^ characters


   Input for icons:
          ^i(bitmaps/envelope.xbm) I am an envelope ^fg(yellow)and ^i(bitmaps/battery.xbm) I'm a baterry.


   Input for rectangles:
          6x4 rectangle ^r(6x4) ^fg(red)12x8 ^r(12x8) ^fg(yellow)and finally 100x15 ^r(100x15)


   Input for relative positioning:
          Some text^p(100)^fg(yellow)100 pixels to the right^p(50)^fg(red)50 more pixels to the right




Examples:
---------

* Display message and timeout after 10 seconds:
    (echo "This is a message"; sleep 10) | dzen2 -bg darkred -fg grey80 -fn fixed 


* Display message and never timeout:
    echo "This is a message"| dzen2 -p


* Display updating single line message:
    for i in $(seq 1 20); do A=${A}'='; print $A; sleep 1; done | dzen2


* Display header and a message with multiple lines:
    (echo Header; cal; sleep 20) | dzen2 -l 8

    Displays "Header" in the title window and the output of cal in the 8
    lines high slave window.


* Display updating messages:
    (echo Header; while true; do echo test$((i++)); sleep 1; done) | dzen2 -l 12

    The slave window will update contents if new input has arrived.


* Display log files:
    (su -c "echo LOGFILENAME; tail -f /var/log/messages") | dzen2 -l 20 -x 100 -y 300 -w 500


* Monthly schedule with remind:
    (echo Monthly Schedule; remind -c1 -m) | dzen2 -l 52 -w 410 -p -fn lime -bg '#e0e8ea' -fg black -x 635


* Simple menu:
    echo "Applications" | dzen2 -l 4 -p -m < menufile


* Horizontal menu without any files:
    {echo Menu; echo -e "xterm\nxclock\nxeyes\nxfontsel"} | dzen2 -l 4 -m h -p


* Extract PIDs from the process table:

    {echo Procs; ps -a} | dzen2 -m -l 12 -p \
    -e 'button1=menuprint;button3=exit;button4=scrollup:3;button5=scrolldown:3;entertitle=uncollapse;leaveslave=collapse' \
            | awk '{print $1}'


* Dzen as xmonad (see http://xmonad.org) statusbar:

    status.sh | dzen2 -ta r -fn '-*-profont-*-*-*-*-11-*-*-*-*-*-iso8859' -bg '#aecf96' -fg black \
        -p -e 'sigusr1=raise;sigusr2=lower;onquit=exec:rm /tmp/dzen2-pid;button3=exit' & echo $! > /tmp/dzen2-pid




Have fun.
070701303F14D8000081A40000420C00000032000000015240109300004BF2000000080000001100000000000000000000002500000000dzen2-1379930259.488ab66/README.dzen^fg(lightgreen)^r(190x4)^fg(#6fbf47)^r(38x4)^fg(darkgreen)^r(9x4)
^fg(#6fbf47)  dzen, (c) 2007 by Robert Manea
^fg(darkgreen)^r(9x4)^fg(#6fbf47)^r(38x4)^fg(lightgreen)^r(190x4)

A general purpose messaging, notification and menu program


The "gadgets" subdirectory contains some tools that you can 
use in combination with dzen.

Script archive with a collection of interesting ideas:
^fg(lightblue)  http://gotmor.googlepages.com/dzenscriptarchive



^fg(#6fbf47)Features
^fg(#6fbf47)--------

    ^co(4x4) scriptable in any language

    ^co(4x4) dynamic colorizer

    ^co(4x4) icons support

    ^co(4x4) keyboard support

    ^co(4x4) single line and/or windows holding multiple lines

    ^co(4x4) menu functionality

    ^co(4x4) in-text formating language

    ^co(4x4) flexible event/action mechanism

    ^co(4x4) hideable, collapsable

    ^co(4x4) Xinerama support


^fg(#6fbf47)Requirements
^fg(#6fbf47)------------
In order to build dzen you need the Xlib header files.


^fg(#6fbf47)Installation
^fg(#6fbf47)------------
Edit config.mk to match your local setup (dzen is installed into
the /usr/local namespace by default).

Afterwards enter the following command to build and install dzen (if
necessary as root):

    ^fg(grey85)make clean install


Optionally if you want to use dzen's gadgets:

    ^fg(grey85)cd gadgets
    ^fg(grey85)make clean install


^fg(Khaki)Note:       By default dzen will ^fg(red)not^fg(Khaki) be compiled with Xinerama and XPM support.
            ^fg(Khaki)Uncomment the respective lines in config.mk to change this.


^fg(#6fbf47)Contact:
^fg(#6fbf47)--------
Feature requests, patches or anything else related to dzen can be send
to: ^fg(Khaki)rob dot manea at gmail dot com


^fg(#6fbf47)Running dzen
^fg(#6fbf47)------------
dzen accepts a couple of options:

    -fg     foreground color
    -bg     background color
    -fn     font 
    -ta     alignement of title window content 
            l(eft), c(center), r(ight)
    -tw     title window width
    -sa     alignment of slave window, see "-ta"
    -l      lines,  ^fg(#6fbf47)see (1)
    -e      events and actions, ^fg(#6fbf47)see (2)
    -m      menu mode, ^fg(#6fbf47)see (3)
    -u      update contents of title and 
            slave window simultaneously, ^fg(#6fbf47)see (4)
    -p      persist EOF (optional timeout in seconds)
    -x      x position
    -y      y position
    -h      line height (default: fontheight + 2 pixels)
    -w      width
    -xs     number of Xinerama screen
    -v      version information

    ^fg(#6fbf47)see (5)^fg(), for the in-text formating language.



^fg(#6fbf47)X resources
^fg(#6fbf47)-----------

Dzen is able to read font and color setting from X resources.
As an example you can add following lines to ~/.Xresources

^fg(Khaki)dzen2.font:       -*-fixed-*-*-*-*-*-*-*-*-*-*-*-*
^fg(Khaki)dzen2.foreground: #22EE11
^fg(Khaki)dzen2.background: black



^fg(#6fbf47)Window layout
^fg(#6fbf47)-------------

Dzen's window layout is as follows:

^fg(red)     ------------------------------------------
^fg(red)    |        Title window, single line         |
^fg(red)    `------------------------------------------´
^fg(#6fbf47)    |                                          |
^fg(#6fbf47)    |               scrollable                 |
^fg(#6fbf47)    |              Slave window                |
^fg(#6fbf47)    |             multiple lines               |
^fg(#6fbf47)    |     lines to display simultaneously      |
^fg(#6fbf47)    |           controlled with the            |
^fg(#6fbf47)    |              '-l' option                 |
^fg(#6fbf47)    |                                          |
^fg(#6fbf47)    |                                          |
^fg(#6fbf47)    `------------------------------------------´

The first line you provide to dzen always goes to the title window, 
all other consecutive lines will be drawn to the slave window unless
you explicitly overide this with the ^fg(#6fbf47)(5) In-text formating language
^fg()command ^^tw().


^fg(#6fbf47)QA:
^fg(#6fbf47)---

Q1:  I don't want a slave window, what to do?

A1:  Do not provide the '-l' option, all lines will be displayed
     in the title window, this is the default behaviour.


Q2:  I used the '-l' option but no slave window appears.

A2:  With the default event/action handling the slave window will
     only be displayed if you hoover with the mouse over the title
     window. See ^fg(#6fbf47)(2) Events and actions ^fg()if you'd like to change
     this.


Q3:  If I echo some text or cat a file dzen closes itself imediatelly.

A3:  There are 2 different approaches dzen uses to terminate itself, 
     see next section ^fg(#6fbf47)Termination^fg().


Q4:  Ok, the title and slave thing works, can I update the
     contents of both windows at the same time?

A4:  Sure, see ^fg(#6fbf47)(4) Simultaneous updates ^fg()or use the in-text 
     command ^^tw() to explicitly draw to the title windwow.
     See ^fg(#6fbf47)(5) In-Text formating language ^fg()for further details

Q5:  Can i chnage color of my input at runtime?

A5:  Yes, you can change both background and foreground colors and 
     much more See ^fg(#6fbf47)(5) In-Text formating language^fg().


Q6:  Can I use dzen as a menu?

A6:  Yes, both vertical and horizontal menus are supported. 
     See ^fg(#6fbf47)(3) Menu ^fg()for further details.




^fg(#6fbf47)Termination:
^fg(#6fbf47)------------
dzen uses two different approaches to terminate itself:

    ^co(4x4) Timed termination: if EOF is received -> terminate
        - unless the '-p' option is set
            · '-p' without argument persist forever
            · '-p' with argument n  persist for n seconds

    ^co(4x4) Interactive termination: if mouse button3 is clicked -> terminate
        - this is the default behaviour, ^fg(#6fbf47)see (2)
        - in some modes the Escape key terminates too, ^fg(#6fbf47)see (2)



^fg(#6fbf47)Return values:
^fg(#6fbf47)--------------
0               -   dzen received EOF
1               -   some error occured, inspect the error message
user defined    -   set with 'exit:retval' action, ^fg(#6fbf47)see (2)



^fg(#6fbf47)(1) Option "-l": Slave window
^fg(#6fbf47)--------------------------------

Enables support for displaying multiple lines. The parameter to "-l"
specifies the number of lines to be displayed.

These lines of input are held in the slave window which becomes active as soon
as the pointer enters the title (default action) window.

If the mouse leaves the slave window it will be hidden unless it is set
sticky by clicking with Button2 into it (default action).

Button4 and Button5 (mouse wheel) will scroll the slave window up
and down if the content exceeds the window height (default action).



^fg(#6fbf47)(2) Option '-e': Events and actions
^fg(#6fbf47)-----------------------------------

dzen allows the user to associate actions to events.

The command line syntax is as follows:
-e 'event1=action1:option1:...option<n>,...,action<m>;...;event<l>'

Every event can take any number of actions and every action can take any number
of options. (By default limited to 64 each, easily changable in action.h)

An example:
^fg(grey70)    -e 'button1=exec:xterm:firefox;entertitle=uncollapse,unhide;button3=exit'

    Meaning:

    ^fg(grey70)button1=exec:xterm:firefox;
    on Button1 event (Button1 press on the mouse) execute xterm and
    firefox. 
    ^fg(Khaki)Note: xterm and firefox are options to the exec action

    ^fg(grey70)entertitle=uncollapse,unhide;
    on entertitle (mouse pointer enters the title window) uncollapse
    slave window and unhide the title window

    ^fg(grey70)button3=exit
    on button3 event exit dzen


^fg(#6fbf47)Supported events:
^fg(#6fbf47)-----------------

    onstart             Perform actions right after startup
    onexit              Perform actions just before exiting
    onnewinput          Perform actions if there is new input for the slave window
    button1             Mouse button1 released 
    button2             Mouse button2 released
    button3             Mouse button3 released
    button4             Mouse button4 released (usually scrollwheel)
    button5             Mouse button5 released (usually scrollwheel)
    button6             Mouse button6 released
    button7             Mouse button7 released
    entertitle          Mouse enters the title window
    leavetitle          Mouse leaves the title window
    enterslave          Mouse enters the slave window
    leaveslave          Mouse leaves the slave window
    sigusr1             SIGUSR1 received 
    sigusr2             SIGUSR2 received
    key_KEYNAME         Keyboard events (*)


    ^fg(#6fbf47)(*) Keyboard events:
    ^fg(#6fbf47)--------------------

    Every key can be bound to an action (see below). The format is:
    key_KEYNAME where KEYNAME is the name of the key as defined in
    keysymdef.h (usually: /usr/include/X11/keysymdef.h).  The part 
    after 'XK_' in keysymdef.h must be used for KEYNAME.



^fg(#6fbf47)Supported actions:
^fg(#6fbf47)------------------

    exec:command1:..:n  execute all given options
    menuexec            executes selected menu entry
    exit:retval         exit dzen and return 'retval'
    print:str1:...:n    write all given options to STDOUT
    menuprint           write selected menu entry to STDOUT
    collapse            collapse (roll-up) slave window
    uncollapse          uncollapse (roll-down) slave window
    togglecollapse      toggle collapsed state
    stick               stick slave window
    unstick             unstick slave window
    togglestick         toggle sticky state
    hide                hide title window
    unhide              unhide title window
    togglehide          toggle hide state
    raise               raise window to view (above all others)
    lower               lower window (behind all others)
    scrollhome          show head of input
    scrollend           show tail of input
    scrollup:n          scroll slave window n lines up   (default n=1)
    scrolldown:n        scroll slave window n lines down (default n=1)
    grabkeys            enable keyboard support
    ungrabkeys          disable keyboard support
    grabmouse           enable mouse support 
                        only needed with specific windowmanagers, such as fluxbox
    ungrabmouse         release mouse 
                        only needed with specific windowmanagers, such as fluxbox


^fg(Khaki)Note:   If no events/actions are specified dzen defaults to:

        ^fg(#6fbf47)Title only mode:
        ^fg(#6fbf47)----------------

        -e 'button3=exit:13'


        ^fg(#6fbf47)Multiple lines and vertical menu mode:
        ^fg(#6fbf47)--------------------------------------

        -e 'entertitle=uncollapse,grabkeys;
            enterslave=grabkeys;leaveslave=collapse,ungrabkeys;
            button1=menuexec;button2=togglestick;button3=exit:13;
            button4=scrollup;button5=scrolldown;
            key_Escape=ungrabkeys,exit'


        ^fg(#6fbf47)Horizontal menu mode:
        ^fg(#6fbf47)---------------------

        -e 'enterslave=grabkeys;leaveslave=ungrabkeys;
            button4=scrollup;button5=scrolldown;
            key_Left=scrollup;key_Right=scrolldown;
            button1=menuexec;button3=exit:13
            key_Escape=ungrabkeys,exit'


        ^fg(Khaki)If you define any events/actions, there is no default behaviour,
        ^fg(Khaki)i.e. you will have to specify _all_ events/actions you want to
        ^fg(Khaki)use.



^fg(#6fbf47)(3) Option '-m', Menu
^fg(#6fbf47)---------------------

Dzen provides two menu modes, vertical and horizontal menus. You can
access these modes by adding 'v'(ertical) or 'h'(orizontal) to the 
'-m' option. If nothing is specified dzen defaults to vertical menus.

Vertical menu, both invocations are equivalent:
    ^fg(grey70)dzen2 -p -l 4 -m < file
    ^fg(grey70)dzen2 -p -l 4 -m v < file

Horizontal menu:
    ^fg(grey70)dzen2 -p -l 4 -m h < file


All actions beginning with "menu" work on the selected menu entry.

^fg(Khaki)Note:   Menu mode only makes sense if '-l <n>' is specified!

        ^fg(Khaki)Horizontal menus have no title window, so all actions
        ^fg(Khaki)affecting the title window will be silently discarded
        ^fg(Khaki)in this mode.



^fg(#6fbf47)(4) Option '-u', Simultaneous updates
^fg(#6fbf47)-------------------------------------

This option provides facilities to update the title and slave window at
the same time.

The way it works is best described by an example:

  Motivation:

  We want to display an updating clock in the title and some log
  output in the slave window.

  Solution:

  ^fg(grey70)while true; do
        ^fg(grey70)date                # output goes to the title window
        ^fg(grey70)dmesg | tail -n 10  # output goes to the slave window
        ^fg(grey70)sleep 1
  ^fg(grey70)done | dzen2 -l 10 -u

For this to work correctly it is essential to provide exactly the number
of lines to the slave window as defined by the parameter to '-l'.



^fg(#6fbf47)(5) In-text formating language:
^fg(#6fbf47)-------------------------------

This feature allows to dynamically (at runtime) format the text dzen
displays.

Currently the following commands are supported:


Colors:
-------

    ^^fg(color)         set foreground color
    ^^fg()              without arguments, sets default fg color
    ^^bg(color)         set background color
    ^^bg()              without arguments, sets default bg color

Graphics:
---------

    ^^i(path)           draw icon specified by path
                       Supported formats: XBM and optionally XPM

    ^^r(WIDTHxHEIGHT)   draw a rectangle with the dimensions 
                       WIDTH and HEIGHT
    ^^ro(WIDTHxHEIGHT)  rectangle outline

    ^^c(RADIUS)         draw a circle with size RADIUS pixels
    ^^co(RADIUS)        circle outline

Positioning:
------------

    ^^p(PIXEL)          position next input amount of PIXELs to the right
                       or left of the current position
                       a.k.a. relative positioning

    ^^pa(PIXEL)         position next input at PIXEL
                       a.k.a. absolute positioning
                       For maximum predictability ^^pa() should only be
                       used with '-ta l' or '-sa l'
Other:
------

    ^^tw()              draw to title window
                       This command has some annoyances, as only 
                       the input after the command will be drawn
                       to the title window, so it is best used 
                       only once and as first command per line
                       Subject to be improved in the future.

    ^^cs()              clear slave window
                       This command must be the first and only command
                       per line.

    ^^ib(VALUE)         ignore background setting, VALUE can be either
                       1 to ignore or 0 to not ignore the bg color set
                       with ^^bg(color)
                       This command is useful in combination with ^^pa()
                       in order to position the input inside other already
                       drawn input.

                       Example: 
                         ^^ib(1)^^fg(red)^^ro(100x15)^^p(-98)^^fg(blue)^^r(20x10)^^fg(orange)^^p(3)^^r(40x10)^^p(4)^^fg(darkgreen)^^co(12)^^p(2)^^c(10)
                       Giving:
                         ^ib(1)^fg(red)^ro(100x15)^p(-98)^fg(blue)^r(20x10)^fg(orange)^p(3)^r(40x10)^p(4)^fg(darkgreen)^co(12)^p(2)^c(10)



These commands can appear anywhere and in any combination in dzen's
input. 

The color can be specified either as symbolic name (e.g. red,
darkgreen, etc.) or as #rrggbb hex-value (e.g. #ffffaa).

Icons must be in the XBM or optionally XPM format, see the "bitmaps"
directory for some sample icons. With the standard "bitmap" application
you can easily draw your own icons.

^fg(Khaki)Note:   Displaying XPM (pixmap) files imposes a somewhat
        ^fg(Khaki)higher load than lightweight XBM files, so use
        ^fg(Khaki)them with care in tight loops.


Doubling the '^^' character removes the special meaning from it.


Some examples:

   Input:  
          ^^fg(red)I'm red text ^^fg(blue)I am blue

   Resulting in: 
          ^fg(red)I'm red text ^fg(blue)I am blue


   Input:
          ^^bg(#ffaaaa)The ^^fg(yellow)text to ^^bg(blue)^^fg(orange)colorize

   Resulting in:
          ^bg(#ffaaaa)The ^fg(yellow)text to ^bg(blue)^fg(orange)colorize


   Input:
          ^^fg(white)Some text containing ^^^^ characters

   Resulting in:
          ^fg(white)Some text containing ^^ characters


   Input for icons:
          ^^i(bitmaps/envelope.xbm) I am an envelope ^^fg(yellow)and ^^i(bitmaps/battery.xbm) I'm a baterry.

   Resulting in:
          ^i(bitmaps/envelope.xbm) I am an envelope ^fg(yellow)and ^i(bitmaps/battery.xbm) I'm a baterry.


   Input for rectangles:
          6x4 rectangle ^^r(6x4) ^^fg(red)12x8 ^^r(12x8) ^^fg(yellow)and finally 100x15 ^^r(100x15)

   Resulting in:
          6x4 rectangle ^r(6x4) ^fg(red)12x8 ^r(12x8) ^fg(yellow)and finally 100x15 ^r(100x15)


   Input for relative positioning:
          Some text^^p(100)^^fg(yellow)100 pixels to the right^^p(50)^^fg(red)50 more pixels to the right

   Resulting in:
          Some text^p(100)^fg(yellow)100 pixels to the right^p(50)^fg(red)50 more pixels to the right





^fg(#6fbf47)Examples:
^fg(#6fbf47)---------

^co(4x4) Display message and timeout after 10 seconds:
^fg(grey85)    (echo "This is a message"; sleep 10) | dzen2 -bg darkred -fg grey85 -fn fixed 


^co(4x4) Display message and never timeout:
^fg(grey85)    echo "This is a message"| dzen2 -p


^co(4x4) Display updating single line message:
^fg(grey85)    for i in $(seq 1 20); do A=${A}'='; print $A; sleep 1; done | dzen2


^co(4x4) Display header and a message with multiple lines:
^fg(grey85)    (echo Header; cal; sleep 20) | dzen2 -l 8

    Displays "Header" in the title window and the output of cal in the
    8 lines high slave window.


^co(4x4) Display updating messages:
^fg(grey85)    (echo Header; while true; do echo test$((i++)); sleep 1; done) | dzen2 -l 12

    The slave window will update contents if new input has arrived.


^co(4x4) Display log files:
^fg(grey85)    (su -c "echo LOGFILENAME; tail -f /var/log/messages") | dzen2 -l 20 -x 100 -y 300 -w 500


^co(4x4) Monthly schedule with remind:
^fg(grey85)    (echo Monthly Schedule; remind -c1 -m) | dzen2 -l 52 -w 410 -p -fn lime -bg '#e0e8ea' -fg black -x 635


^co(4x4) Simple menu:
^fg(grey85)    echo "Applications" | dzen2 -l 4 -p -m < menufile


^co(4x4) Horizontal menu without any files:
^fg(grey85)    {echo Menu; echo -e "xterm\nxclock\nxeyes\nxfontsel"} | dzen2 -l 4 -m h -p


^co(4x4) Extract PIDs from the process table:

^fg(grey85)    {echo Procs; ps -a} | dzen2 -m -l 12 -p \
^fg(grey85)    -e 'button1=menuprint;button3=exit;button4=scrollup:3;button5=scrolldown:3;entertitle=uncollapse;leaveslave=collapse' \
^fg(grey85)            | awk '{print $1}'


^co(4x4) Dzen as xmonad (see http://xmonad.org) statusbar:

^fg(grey85)    status.sh | dzen2 -ta r -fn '-*-profont-*-*-*-*-11-*-*-*-*-*-iso8859' -bg '#aecf96' -fg black \
^fg(grey85)        -p -e 'sigusr1=raise;sigusr2=lower;onquit=exec:rm /tmp/dzen2-pid;button3=exit' & echo $! > /tmp/dzen2-pid




Have fun.
070701303F14D9000081A40000420C00000032000000015240109300000262000000080000001100000000000000000000001E00000000dzen2-1379930259.488ab66/TODO#  documentation

          o `-dock' and `-geometry' options are undocumented


#  X related

          o XRandR support (MEDIUM PRIORITY)
          o cache XPM files in order to improve drawing
            performace (HIGH PRIORITY, done in svn trunk)


#  extend available actions

          o set font action (LOW PRIORITY)
          o any other useful action (LOW PRIORITY)


# user interface

          o improve in-text command to draw
            to the title window (MEDIUM PRIORITY, done in svn trunk)
          o auto fit window width to
            text length (MEDIUM PRIORITY, done in svn trunk)
070701303F14DA000081A40000420C00000032000000015240109300002B5E000000080000001100000000000000000000002200000000dzen2-1379930259.488ab66/action.c/*
* (C)opyright 2007-2009 Robert Manea <rob dot manea at gmail dot com>
* See LICENSE file for license details.
*
*/

#include "dzen.h"
#include "action.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


struct event_lookup ev_lookup_table[] = {
	{ "onstart",        onstart},
	{ "onexit",         onexit},
	{ "onnewinput",     onnewinput},
	{ "button1",        button1},
	{ "button2",        button2},
	{ "button3",        button3},
	{ "button4",        button4},
	{ "button5",        button5},
	{ "button6",        button6},
	{ "button7",        button7},
	{ "entertitle",     entertitle},
	{ "leavetitle",     leavetitle},
	{ "enterslave",     enterslave},
	{ "leaveslave",     leaveslave},
	{ "sigusr1",        sigusr1},
	{ "sigusr2",        sigusr2},
	{ "keymarker",      keymarker},
	{ 0, 0 }
};

struct action_lookup  ac_lookup_table[] = {
	{ "print",          a_print },
	{ "exec",           a_exec},
	{ "exit",           a_exit},
	{ "collapse",       a_collapse},
	{ "uncollapse",     a_uncollapse},
	{ "togglecollapse",	a_togglecollapse},
	{ "stick",          a_stick},
	{ "unstick",        a_unstick},
	{ "togglestick",    a_togglestick},
	{ "hide",           a_hide},
	{ "unhide",         a_unhide},
	{ "togglehide",     a_togglehide},
	{ "scrollup",       a_scrollup},
	{ "scrolldown",     a_scrolldown},
	{ "menuprint",      a_menuprint},
	{ "menuprint_noparse",      a_menuprint_noparse},
	{ "menuexec",       a_menuexec},
	{ "raise",          a_raise},
	{ "lower",          a_lower},
	{ "scrollhome",     a_scrollhome},
	{ "scrollend",      a_scrollend},
	{ "grabkeys",       a_grabkeys},
	{ "ungrabkeys",     a_ungrabkeys},
	{ "grabmouse",       a_grabmouse},
	{ "ungrabmouse",     a_ungrabmouse},
	{ 0, 0 }
};

ev_list *head = NULL;

static int
new_event(long evid) {
	ev_list *item, *newitem;

	if(!head) {
		head = emalloc(sizeof (ev_list));
		head->id = evid;
		head->next = NULL;
	}
	else {
		item = head;
		/* check if we already handle this event */
		while(item) {
			if(item->id == evid)
				return 0;
			item = item->next;
		}
		item = head;
		while(item->next)
			item = item->next;

		newitem = emalloc(sizeof (ev_list));
		newitem->id = evid;
		item->next = newitem;
		newitem->next = NULL;
	}
	return 0;
}

static void
add_handler(long evid, int hpos, handlerf* hcb) {
	ev_list *item;

	item = head;
	while(item) {
		if(item->id == evid) {
			if(hpos < MAXACTIONS) {
				item->action[hpos] = emalloc(sizeof(As));
				item->action[hpos]->handler = hcb;
			}
			break;
		}
		item = item->next;
	}
}

static void
add_option(long evid, int hpos, int opos, char* opt) {
	ev_list *item;

	item = head;
	while(item) {
		if(item->id == evid) {
			if(opos < MAXOPTIONS) {
				item->action[hpos]->options[opos] = estrdup(opt);
				item->action[hpos]->options[opos+1] = NULL;
			}
			break;
		}
		item = item->next;
	}
}

int
find_event(long evid) {
	ev_list *item;

	item = head;
	while(item) {
		if(item->id == evid)
			return item->id;
		item = item->next;
	}

	return -1;
}

void
do_action(long evid) {
	int i;
	ev_list *item;

	item = head;
	while(item) {
		if(item->id == evid)
			break;
		item = item->next;
	}

	if(item) {
		for(i=0; item->action[i]->handler; i++) {
			item->action[i]->handler(item->action[i]->options);
		}
	}
}

int
get_ev_id(const char *evname) {
	int i;
	KeySym ks;

	/* check for keyboard event */
	if((!strncmp(evname, "key_", 4))
			&& ((ks = XStringToKeysym(evname+4)) != NoSymbol)) {
		return ks+keymarker;
	}

	/* own events */
	for(i=0; ev_lookup_table[i].name; i++) {
		if(strncmp(ev_lookup_table[i].name, evname, strlen(ev_lookup_table[i].name)) == 0)
			return ev_lookup_table[i].id;
	}
	return -1;
}

handlerf *
get_action_handler(const char *acname) {
	int i;

	for(i=0; ac_lookup_table[i].name; i++) {
		if(strcmp(ac_lookup_table[i].name, acname) == 0)
			return ac_lookup_table[i].handler;
	}
	return NULL;
}


void
free_event_list(void) {
	int i;
	ev_list *item;

	item = head;
	while(item) {
		for(i=0; item->action[i]->handler; i++)
			free(item->action[i]);
		item = item->next;
	}
}

void
fill_ev_table(char *input) {
	char *str1, *str2, *str3, *str4,
		 *token, *subtoken, *kommatoken, *dptoken;
	char *saveptr1=NULL,
		 *saveptr2=NULL,
		 *saveptr3=NULL,
		 *saveptr4=NULL;
	int j, i=0, k=0;
	long eid=0;
	handlerf *ah=0;

	for (j = 1, str1 = input; ; j++, str1 = NULL) {
		token = strtok_r(str1, ";", &saveptr1);
		if (token == NULL)
			break;

		for (str2 = token; ; str2 = NULL) {
			subtoken = strtok_r(str2, "=", &saveptr2);
			if (subtoken == NULL)
				break;
			if( (str2 == token) && ((eid = get_ev_id(subtoken)) != -1))
				;
			else if(eid == -1)
				break;

			for (str3 = subtoken; ; str3 = NULL) {
				kommatoken = strtok_r(str3, ",", &saveptr3);
				if (kommatoken == NULL)
					break;

				for (str4 = kommatoken; ; str4 = NULL) {
					dptoken = strtok_r(str4, ":", &saveptr4);
					if (dptoken == NULL) {
						break;
					}
					if(str4 == kommatoken && str4 != token && eid != -1) {
						if((ah = get_action_handler(dptoken)) != NULL) {
							new_event(eid);
							add_handler(eid, i, ah);
							i++;
						}
					}
					else if(str4 != token && eid != -1 && ah) {
						add_option(eid, i-1, k, dptoken);
						k++;
					}
					else if(!ah)
						break;
				}
				k=0;
			}
			new_event(eid);
			add_handler(eid, i, NULL);
			i=0;
		}
	}
}


/* actions */
int
a_exit(char * opt[]) {
	if(opt[0])
		dzen.ret_val = atoi(opt[0]);
	dzen.running = False;
	return 0;
}

int
a_collapse(char * opt[]){
	(void)opt;
	if(!dzen.slave_win.ishmenu
			&& dzen.slave_win.max_lines
			&& !dzen.slave_win.issticky) {
		XUnmapWindow(dzen.dpy, dzen.slave_win.win);
	}
	return 0;
}

int
a_uncollapse(char * opt[]){
	int i;
	(void)opt;
	if(!dzen.slave_win.ishmenu
			&& dzen.slave_win.max_lines
			&& !dzen.slave_win.issticky) {
		XMapRaised(dzen.dpy, dzen.slave_win.win);
		for(i=0; i < dzen.slave_win.max_lines; i++)
			XMapWindow(dzen.dpy, dzen.slave_win.line[i]);
	}
	return 0;
}

int
a_togglecollapse(char * opt[]){
	XWindowAttributes wa;
	(void)opt;

	if(dzen.slave_win.max_lines &&
			(XGetWindowAttributes(dzen.dpy, dzen.slave_win.win, &wa), wa.map_state == IsUnmapped))
		a_uncollapse(NULL);
	else
		a_collapse(NULL);

	return 0;
}

int
a_stick(char * opt[]) {
	(void)opt;
	if(!dzen.slave_win.ishmenu
			&& dzen.slave_win.max_lines)
		dzen.slave_win.issticky = True;
	return 0;
}

int
a_unstick(char * opt[]) {
	(void)opt;
	if(!dzen.slave_win.ishmenu
			&& dzen.slave_win.max_lines)
		dzen.slave_win.issticky = False;
	return 0;
}

int
a_togglestick(char * opt[]) {
	(void)opt;
	if(!dzen.slave_win.ishmenu
			&& dzen.slave_win.max_lines)
		dzen.slave_win.issticky = dzen.slave_win.issticky ? False : True;
	return 0;
}

static void
scroll(int n) {
	if(dzen.slave_win.tcnt <= dzen.slave_win.max_lines)
		return;
	if(dzen.slave_win.first_line_vis + n < 0) {
		dzen.slave_win.first_line_vis = 0;
		dzen.slave_win.last_line_vis = dzen.slave_win.max_lines;
	}
	else if(dzen.slave_win.last_line_vis + n > dzen.slave_win.tcnt) {
		dzen.slave_win.first_line_vis = dzen.slave_win.tcnt - dzen.slave_win.max_lines;
		dzen.slave_win.last_line_vis = dzen.slave_win.tcnt;
	}
	else {
		dzen.slave_win.first_line_vis += n;
		dzen.slave_win.last_line_vis  += n;
	}

	x_draw_body();
}

int
a_scrollup(char * opt[]) {
	int n=1;

	if(opt[0])
		n = atoi(opt[0]);
	if(dzen.slave_win.max_lines)
			scroll(-1*n);

	return 0;
}

int
a_scrolldown(char * opt[]) {
	int n=1;

	if(opt[0])
		n = atoi(opt[0]);
	if(dzen.slave_win.max_lines)
		scroll(n);

	return 0;
}

int
a_hide(char * opt[]) {
	int n=1;
	
	
	printf("n:%d\n", n);
	if(!dzen.title_win.ishidden) {
		if(!dzen.slave_win.ishmenu)
			XResizeWindow(dzen.dpy, dzen.title_win.win, dzen.title_win.width, 1);
		else
			XResizeWindow(dzen.dpy, dzen.slave_win.win, dzen.title_win.width, 1);

		dzen.title_win.ishidden = True;
	}
	return 0;
}

int
a_unhide(char * opt[]) {
	(void)opt;
	if(dzen.title_win.ishidden) {
		if(!dzen.slave_win.ishmenu)
			XResizeWindow(dzen.dpy, dzen.title_win.win, dzen.title_win.width, dzen.line_height);
		else
			XResizeWindow(dzen.dpy, dzen.slave_win.win, dzen.title_win.width, dzen.line_height);

		dzen.title_win.ishidden = False;
	}
	return 0;
}

int
a_togglehide(char * opt[]) {

	dzen.title_win.ishidden ?
		a_unhide(NULL) :
		a_hide(opt);

	return 0;
}

int
a_exec(char * opt[]) {
	int i;

	if(opt)
		for(i=0; opt[i]; i++)
			if(opt[i]) spawn(opt[i]);
	return 0;
}

int
a_print(char * opt[]) {
	int i;

	if(opt)
		for(i=0; opt[i]; i++)
			puts(opt[i]);
	fflush(stdout);
	return 0;
}

int
a_menuprint(char * opt[]) {
	char *text;
	int i;

	if(dzen.slave_win.ismenu && dzen.slave_win.sel_line != -1
			&& (dzen.slave_win.sel_line + dzen.slave_win.first_line_vis) < dzen.slave_win.tcnt) {
		text = parse_line(NULL, dzen.slave_win.sel_line, 0, 0, 1);
		printf("%s", text);
		if(opt)
			for(i=0; opt[i]; ++i)
				printf("%s", opt[i]);
		puts("");
		fflush(stdout);
		dzen.slave_win.sel_line = -1;
		free(text);
	}
	return 0;
}

int
a_menuprint_noparse(char * opt[]) {
	int i;

	if(dzen.slave_win.ismenu && dzen.slave_win.sel_line != -1
			&& (dzen.slave_win.sel_line + dzen.slave_win.first_line_vis) < dzen.slave_win.tcnt) {
		printf("%s", dzen.slave_win.tbuf[dzen.slave_win.sel_line]);
		if(opt)
			for(i=0; opt[i]; ++i)
				printf("%s", opt[i]);
		puts("");
		fflush(stdout);
		dzen.slave_win.sel_line = -1;
	}
	return 0;
}

int
a_menuexec(char * opt[]) {
	char *text;
	(void)opt;

	if(dzen.slave_win.ismenu && dzen.slave_win.sel_line != -1
			&& (dzen.slave_win.sel_line + dzen.slave_win.first_line_vis) < dzen.slave_win.tcnt) {
		text = parse_line(NULL, dzen.slave_win.sel_line, 0, 0, 1);
		spawn(text);
		dzen.slave_win.sel_line = -1;
		free(text);
	}
	return 0;
}

int
a_raise(char * opt[]) {
	(void)opt;
	XRaiseWindow(dzen.dpy, dzen.title_win.win);

	if(dzen.slave_win.max_lines)
		XRaiseWindow(dzen.dpy, dzen.slave_win.win);
	return 0;
}

int
a_lower(char * opt[]) {
	(void)opt;
	XLowerWindow(dzen.dpy, dzen.title_win.win);

	if(dzen.slave_win.max_lines)
		XLowerWindow(dzen.dpy, dzen.slave_win.win);
	return 0;
}

int
a_scrollhome(char * opt[]) {
	(void)opt;
	if(dzen.slave_win.max_lines) {
		dzen.slave_win.first_line_vis = 0;
		dzen.slave_win.last_line_vis  = dzen.slave_win.max_lines;

		x_draw_body();
	}
	return 0;
}

int
a_scrollend(char * opt[]) {
	(void)opt;
	if(dzen.slave_win.max_lines) {
		dzen.slave_win.first_line_vis = dzen.slave_win.tcnt - dzen.slave_win.max_lines ;
		dzen.slave_win.last_line_vis  = dzen.slave_win.tcnt;

		x_draw_body();
	}
	return 0;
}

int
a_grabkeys(char * opt[]) {
	(void)opt;
	XGrabKeyboard(dzen.dpy, RootWindow(dzen.dpy, dzen.screen),
			True, GrabModeAsync, GrabModeAsync, CurrentTime);
	return 0;
}

int
a_ungrabkeys(char * opt[]) {
	(void)opt;
	XUngrabKeyboard(dzen.dpy, CurrentTime);
	return 0;
}

int
a_grabmouse(char * opt[]) {
	(void)opt;
	XGrabPointer(dzen.dpy, RootWindow(dzen.dpy, dzen.screen),
			True, ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
	return 0;
}

int
a_ungrabmouse(char * opt[]) {
	(void)opt;
	XUngrabPointer(dzen.dpy, CurrentTime);
	return 0;
}

070701303F14DB000081A40000420C000000320000000152401093000006F0000000080000001100000000000000000000002200000000dzen2-1379930259.488ab66/action.h/*  
 * (C)opyright 2007-2009 Robert Manea <rob dot manea at gmail dot com>
 * See LICENSE file for license details.
 *
 */

#define MAXACTIONS 64
#define MAXOPTIONS 64

/* Event, Action data structures */
typedef struct AS As;
typedef struct _ev_list ev_list;
typedef int handlerf(char **);

enum ev_id {
	/* startup, exit, input */
	onstart, onexit, onnewinput,
	/* mouse buttons */
	button1, button2, button3, button4, button5,  button6,  button7,
	/* entering/leaving windows */
	entertitle, leavetitle, enterslave, leaveslave, 
	/* external signals */
	sigusr1, sigusr2,
	/* key event marker 
	 * must always be the last entry
	 */
	keymarker
};

struct _ev_list {
	long id;
	As *action[MAXACTIONS];
	ev_list *next;
};

struct event_lookup {
	const char *name;
	long id;
};

struct action_lookup {
	const char *name;
	int (*handler)(char **);
};

struct AS {
	char *options[MAXOPTIONS];
	int (*handler)(char **);
};


/* utility functions */
void do_action(long);
int get_ev_id(const char *);
handlerf *get_action_handler(const char *);
void fill_ev_table(char *);
void free_event_list(void);
int find_event(long);

/* action handlers */
int a_print(char **);
int a_exit(char **);
int a_exec(char **);
int a_collapse(char **);
int a_uncollapse(char **);
int a_togglecollapse(char **);
int a_stick(char **);
int a_unstick(char **);
int a_togglestick(char **);
int a_scrollup(char **);
int a_scrolldown(char **);
int a_hide(char **);
int a_unhide(char **);
int a_togglehide(char **);
int a_menuprint(char **);
int a_menuprint_noparse(char **);
int a_menuexec(char **);
int a_raise(char **);
int a_lower(char **);
int a_scrollhome(char **);
int a_scrollend(char **);
int a_grabkeys(char **);
int a_ungrabkeys(char **);
int a_grabmouse(char **);
int a_ungrabmouse(char **);

07070121B50EA2000041ED0000420C00000032000000025240109300000000000000080000001100000000000000000000002100000000dzen2-1379930259.488ab66/bitmaps07070121B50EA3000081A40000420C0000003200000001524010930000011F000000080000001100000000000000000000002B00000000dzen2-1379930259.488ab66/bitmaps/alert.xbm#define alert_width 16
#define alert_height 16
static unsigned char alert_bits[] = {
   0xff, 0xff, 0x01, 0xf8, 0xf1, 0xf9, 0xe1, 0xc1, 0xe1, 0xc1, 0xe1, 0xc1,
   0xe1, 0xc1, 0xe1, 0xc1, 0xe1, 0xc1, 0xe1, 0xc1, 0x01, 0xc0, 0xe1, 0xc1,
   0xe1, 0xc1, 0x01, 0xc0, 0xff, 0xff, 0xff, 0xff};
07070121B50EA4000081A40000420C000000320000000152401093000001B5000000080000001100000000000000000000002A00000000dzen2-1379930259.488ab66/bitmaps/ball.xbm#define ball_width 19
#define ball_height 19
static unsigned char ball_bits[] = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0xe0, 0x3f, 0x00,
  0xf0, 0x7f, 0x00, 0x78, 0xfc, 0x00, 0x38, 0xf8, 0x00, 0x7c, 0xfe, 0x01,
  0xfc, 0xff, 0x01, 0xfc, 0xff, 0x01, 0xfc, 0xff, 0x01, 0xfc, 0xff, 0x01,
  0xf8, 0xff, 0x00, 0xf8, 0xff, 0x00, 0xf0, 0x7f, 0x00, 0xe0, 0x3f, 0x00,
  0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
07070121B50EA5000081A40000420C00000032000000015240109300000119000000080000001100000000000000000000002D00000000dzen2-1379930259.488ab66/bitmaps/battery.xbm#define battery_width 15
#define battery_height 15
static unsigned char battery_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f,
   0xfc, 0x08, 0xfc, 0x38, 0xfc, 0x38, 0xfc, 0x08, 0xfc, 0x0f, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
07070121B50EA6000081A40000420C0000003200000001524010930000011C000000080000001100000000000000000000002E00000000dzen2-1379930259.488ab66/bitmaps/envelope.xbm#define envelope_width 15
#define envelope_height 15
static unsigned char envelope_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x1f, 0x0c, 0x18, 0x1c, 0x1c,
   0x34, 0x16, 0xc4, 0x11, 0x84, 0x10, 0x04, 0x10, 0xfc, 0x1f, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
07070121B50EA7000081A40000420C00000032000000015240109300000121000000080000001100000000000000000000002B00000000dzen2-1379930259.488ab66/bitmaps/music.xbm#define music_width 16
#define music_height 16
static unsigned char music_bits[] = {
   0x00, 0x00, 0xe0, 0x00, 0xe0, 0x03, 0x20, 0x1f, 0x20, 0x1c, 0x20, 0x10,
   0x20, 0x10, 0x20, 0x10, 0x20, 0x10, 0x2c, 0x10, 0x3e, 0x10, 0x1e, 0x16,
   0x0c, 0x1f, 0x00, 0x0f, 0x00, 0x06, 0x00, 0x00 };

07070121B50EA8000081A40000420C00000032000000015240109300000121000000080000001100000000000000000000002B00000000dzen2-1379930259.488ab66/bitmaps/pause.xbm#define pause_width 16
#define pause_height 16
static unsigned char pause_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1e, 0x78, 0x1e, 0x78, 0x1e,
   0x78, 0x1e, 0x78, 0x1e, 0x78, 0x1e, 0x78, 0x1e, 0x78, 0x1e, 0x78, 0x1e,
   0x78, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

07070121B50EA9000081A40000420C0000003200000001524010930000011E000000080000001100000000000000000000002A00000000dzen2-1379930259.488ab66/bitmaps/play.xbm#define play_width 16
#define play_height 16
static unsigned char play_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x78, 0x00, 0xf8, 0x01,
   0xf8, 0x07, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x07, 0xf8, 0x01, 0x78, 0x00,
   0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

07070121B50EAA000081A40000420C00000032000000015240109300000122000000080000001100000000000000000000002C00000000dzen2-1379930259.488ab66/bitmaps/volume.xbm#define volume_width 16
#define volume_height 16
static unsigned char volume_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x1b, 0x60, 0x1b, 0x60, 0x1b,
   0x6c, 0x1b, 0x6c, 0x1b, 0x6c, 0x1b, 0x60, 0x1b, 0x60, 0x1b, 0x00, 0x1b,
   0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
070701303F14DC000081A40000420C000000320000000152401093000009CF000000080000001100000000000000000000002300000000dzen2-1379930259.488ab66/config.mk# dzen version
VERSION = 0.9.5-svn

# Customize below to fit your system

# paths
PREFIX = /usr/local
MANPREFIX = ${PREFIX}/share/man

X11INC = /usr/X11R6/include
X11LIB = /usr/X11R6/lib
INCS = -I. -I/usr/include -I${X11INC}

# Configure the features you want to be supported
# Only one of the following options has to be uncommented,
# all others must be commented!
#
# Uncomment: Remove # from the beginning of respective lines
# Comment  : Add # to the beginning of the respective lines

## Option 1: No Xinerama no XPM no XFT
#LIBS = -L/usr/lib -lc -L${X11LIB} -lX11
#CFLAGS = -Wall -Os ${INCS} -DVERSION=\"${VERSION}\"


## Option 2: No Xinerama with XPM
#LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -lXpm
#CFLAGS = -Wall -Os ${INCS} -DVERSION=\"${VERSION}\" -DDZEN_XPM


# Option 3: With Xinerama no XPM
#LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -lXinerama
#CFLAGS = -Wall -Os ${INCS} -DVERSION=\"${VERSION}\" -DDZEN_XINERAMA


## Option 4: With Xinerama and XPM
#LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -lXinerama -lXpm
#CFLAGS = -Wall -Os ${INCS} -DVERSION=\"${VERSION}\" -DDZEN_XINERAMA -DDZEN_XPM


## Option 5: With XFT
LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 `pkg-config --libs xft`
CFLAGS = -Wall -Os ${INCS} -DVERSION=\"${VERSION}\" -DDZEN_XFT `pkg-config --cflags xft`


## Option 6: With XPM and XFT
#LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -lXpm `pkg-config --libs xft`
#CFLAGS = -Wall -Os ${INCS} -DVERSION=\"${VERSION}\" -DDZEN_XPM -DDZEN_XFT `pkg-config --cflags xft`


## Option 7: With Xinerama and XFT
#LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -lXinerama `pkg-config --libs xft`
#CFLAGS = -Wall -Os ${INCS} -DVERSION=\"${VERSION}\" -DDZEN_XINERAMA -DDZEN_XFT `pkg-config --cflags xft`


## Option 8: With Xinerama and XPM and XFT
#LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -lXinerama -lXpm `pkg-config --libs xft`
#CFLAGS = -Wall -Os ${INCS} -DVERSION=\"${VERSION}\" -DDZEN_XINERAMA -DDZEN_XPM -DDZEN_XFT `pkg-config --cflags xft`



# END of feature configuration


LDFLAGS = ${LIBS}

# Solaris, uncomment for Solaris
#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\"
#LDFLAGS = ${LIBS}
#CFLAGS += -xtarget=ultra

# Debugging
#CFLAGS = ${INCS} -DVERSION=\"${VERSION}\" -std=gnu89 -pedantic -Wall -W -Wundef -Wendif-labels -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-align -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline -Wdisabled-optimization -O2 -pipe -DDZEN_XFT `pkg-config --cflags xft`
#LDFLAGS = ${LIBS}

# compiler and linker
CC = gcc
LD = ${CC}
070701303F14DD000081A40000420C000000320000000152401093000063EF000000080000001100000000000000000000002000000000dzen2-1379930259.488ab66/draw.c
/*
* (C)opyright 2007-2009 Robert Manea <rob dot manea at gmail dot com>
* See LICENSE file for license details.
*
*/

#include "dzen.h"
#include "action.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef DZEN_XPM
#include <X11/xpm.h>
#endif

#define ARGLEN 256
#define MAX_ICON_CACHE 32

#define MAX(a,b) ((a)>(b)?(a):(b))
#define LNR2WINDOW(lnr) lnr==-1?0:1

typedef struct ICON_C {
	char name[ARGLEN];
	Pixmap p;

	int w, h;
} icon_c;

icon_c icons[MAX_ICON_CACHE];
int icon_cnt;
int otx;

int xorig[2];
sens_w window_sens[2];

/* command types for the in-text parser */
enum ctype  {bg, fg, icon, rect, recto, circle, circleo, pos, abspos, titlewin, ibg, fn, fixpos, ca, ba};

struct command_lookup {
	const char *name;
	int id;
	int off;
};

struct command_lookup cmd_lookup_table[] = {
	{ "fg(",        fg,			3},
	{ "bg(",        bg,			3},
	{ "i(",			icon,		2},
	{ "r(",	        rect,		2},
	{ "ro(",        recto,		3},
	{ "c(",	        circle,		2},
	{ "co(",        circleo,	3},
	{ "p(",	        pos,		2},
	{ "pa(",        abspos,		3},
	{ "tw(",        titlewin,	3},
	{ "ib(",        ibg,		3},
	{ "fn(",        fn,			3},
	{ "ca(",        ca,			3},
	{ "ba(",		ba,			3},
	{ 0,			0,			0}
};


/* positioning helpers */
enum sctype {LOCK_X, UNLOCK_X, TOP, BOTTOM, CENTER, LEFT, RIGHT};

int get_tokval(const char* line, char **retdata);
int get_token(const char*  line, int * t, char **tval);

static unsigned int
textnw(Fnt *font, const char *text, unsigned int len) {
#ifndef DZEN_XFT
	XRectangle r;

	if(font->set) {
		XmbTextExtents(font->set, text, len, NULL, &r);
		return r.width;
	}
	return XTextWidth(font->xfont, text, len);
#else
	XftTextExtentsUtf8(dzen.dpy, dzen.font.xftfont, (unsigned const char *) text, strlen(text), dzen.font.extents);
	if(dzen.font.extents->height > dzen.font.height)
		dzen.font.height = dzen.font.extents->height;
	return dzen.font.extents->xOff;
#endif
}


void
drawtext(const char *text, int reverse, int line, int align) {
	if(!reverse) {
		XSetForeground(dzen.dpy, dzen.gc, dzen.norm[ColBG]);
		XFillRectangle(dzen.dpy, dzen.slave_win.drawable[line], dzen.gc, 0, 0, dzen.w, dzen.h);
		XSetForeground(dzen.dpy, dzen.gc, dzen.norm[ColFG]);
	}
	else {
		XSetForeground(dzen.dpy, dzen.rgc, dzen.norm[ColFG]);
		XFillRectangle(dzen.dpy, dzen.slave_win.drawable[line], dzen.rgc, 0, 0, dzen.w, dzen.h);
		XSetForeground(dzen.dpy, dzen.rgc, dzen.norm[ColBG]);
	}

	parse_line(text, line, align, reverse, 0);
}

long
getcolor(const char *colstr) {
	Colormap cmap = DefaultColormap(dzen.dpy, dzen.screen);
	XColor color;

	if(!XAllocNamedColor(dzen.dpy, cmap, colstr, &color, &color))
		return -1;

	return color.pixel;
}

void
setfont(const char *fontstr) {
#ifndef DZEN_XFT
	char *def, **missing;
	int i, n;

	missing = NULL;
	if(dzen.font.set)
		XFreeFontSet(dzen.dpy, dzen.font.set);

	dzen.font.set = XCreateFontSet(dzen.dpy, fontstr, &missing, &n, &def);
	if(missing)
		XFreeStringList(missing);

	if(dzen.font.set) {
		XFontSetExtents *font_extents;
		XFontStruct **xfonts;
		char **font_names;
		dzen.font.ascent = dzen.font.descent = 0;
		font_extents = XExtentsOfFontSet(dzen.font.set);
		n = XFontsOfFontSet(dzen.font.set, &xfonts, &font_names);
		for(i = 0, dzen.font.ascent = 0, dzen.font.descent = 0; i < n; i++) {
			if(dzen.font.ascent < (*xfonts)->ascent)
				dzen.font.ascent = (*xfonts)->ascent;
			if(dzen.font.descent < (*xfonts)->descent)
				dzen.font.descent = (*xfonts)->descent;
			xfonts++;
		}
	}
	else {
		if(dzen.font.xfont)
			XFreeFont(dzen.dpy, dzen.font.xfont);
		dzen.font.xfont = NULL;
		if(!(dzen.font.xfont = XLoadQueryFont(dzen.dpy, fontstr)))
			eprint("dzen: error, cannot load font: '%s'\n", fontstr);
		dzen.font.ascent = dzen.font.xfont->ascent;
		dzen.font.descent = dzen.font.xfont->descent;
	}
	dzen.font.height = dzen.font.ascent + dzen.font.descent;
#else
        if(dzen.font.xftfont)
           XftFontClose(dzen.dpy, dzen.font.xftfont);
	dzen.font.xftfont = XftFontOpenXlfd(dzen.dpy, dzen.screen, fontstr);
	if(!dzen.font.xftfont)
	   dzen.font.xftfont = XftFontOpenName(dzen.dpy, dzen.screen, fontstr);
	if(!dzen.font.xftfont)
	   eprint("error, cannot load font: '%s'\n", fontstr);
	dzen.font.extents = malloc(sizeof(XGlyphInfo));
	XftTextExtentsUtf8(dzen.dpy, dzen.font.xftfont, (unsigned const char *) fontstr, strlen(fontstr), dzen.font.extents);
	dzen.font.height = dzen.font.xftfont->ascent + dzen.font.xftfont->descent;
	dzen.font.width = (dzen.font.extents->width)/strlen(fontstr);
#endif
}


int
get_tokval(const char* line, char **retdata) {
	int i;
	char tokval[ARGLEN];

	for(i=0; i < ARGLEN && (*(line+i) != ')'); i++)
		tokval[i] = *(line+i);

	tokval[i] = '\0';
	*retdata = strdup(tokval);

	return i+1;
}

int
get_token(const char *line, int * t, char **tval) {
	int off=0, next_pos=0, i;
	char *tokval = NULL;

	if(*(line+1) == ESC_CHAR)
		return 0;
	line++;

	for(i=0; cmd_lookup_table[i].name; ++i) {
		if( off=cmd_lookup_table[i].off,
				!strncmp(line, cmd_lookup_table[i].name, off) ) {
			next_pos = get_tokval(line+off, &tokval);
			*t = cmd_lookup_table[i].id;
			break;
		}
	}


	*tval = tokval;
	return next_pos+off;
}

static void
setcolor(Drawable *pm, int x, int width, long tfg, long tbg, int reverse, int nobg) {

	if(nobg)
		return;

	XSetForeground(dzen.dpy, dzen.tgc, reverse ? tfg : tbg);
	XFillRectangle(dzen.dpy, *pm, dzen.tgc, x, 0, width, dzen.line_height);

	XSetForeground(dzen.dpy, dzen.tgc, reverse ? tbg : tfg);
	XSetBackground(dzen.dpy, dzen.tgc, reverse ? tfg : tbg);
}

int 
get_sens_area(char *s, int *b, char *cmd) {
	memset(cmd, 0, 1024);
    sscanf(s, "%5d", b);
    char *comma = strchr(s, ',');
    if (comma != NULL)
        strncpy(cmd, comma+1, 1024);

	return 0;
}

static int
get_rect_vals(char *s, int *w, int *h, int *x, int *y) {
	*w=*h=*x=*y=0;

	return sscanf(s, "%5dx%5d%5d%5d", w, h, x, y);
}

static int
get_circle_vals(char *s, int *d, int *a) {
	int ret;
	*d=*a=ret=0;

	return  sscanf(s, "%5d%5d", d, a);
}

static int
get_pos_vals(char *s, int *d, int *a) {
	int i=0, ret=3, onlyx=1;
	char buf[128];
	*d=*a=0;

	if(s[0] == '_') {
		if(!strncmp(s, "_LOCK_X", 7)) {
			*d = LOCK_X;
		}
		if(!strncmp(s, "_UNLOCK_X", 8)) {
			*d = UNLOCK_X;
		}
		if(!strncmp(s, "_LEFT", 5)) {
			*d = LEFT;
		}
		if(!strncmp(s, "_RIGHT", 6)) {
			*d = RIGHT;
		}
		if(!strncmp(s, "_CENTER", 7)) {
			*d = CENTER;
		}
		if(!strncmp(s, "_BOTTOM", 7)) {
			*d = BOTTOM;
		}
		if(!strncmp(s, "_TOP", 4)) {
			*d = TOP;
		}

		return 5;
	} else {
		for(i=0; s[i] && i<128; i++) {
			if(s[i] == ';') {
				onlyx=0;
				break;
			} else
				buf[i]=s[i];
		}

		if(i) {
			buf[i]='\0';
			*d=atoi(buf);
		} else
			ret=2;

		if(s[++i]) {
			*a=atoi(s+i);
		} else
			ret = 1;

		if(onlyx) ret=1;

		return ret;
	}
}

static int
get_block_align_vals(char *s, int *a, int *w)
{
	char buf[32];
	int r;
	*w = -1;
	r = sscanf(s, "%d,%31s", w, buf);
	if(!strcmp(buf, "_LEFT"))
		*a = ALIGNLEFT;
	else if(!strcmp(buf, "_RIGHT"))
		*a = ALIGNRIGHT;
	else if(!strcmp(buf, "_CENTER"))
		*a = ALIGNCENTER;
	else
		*a = -1;

	return r;
}


static int
search_icon_cache(const char* name) {
	int i;

	for(i=0; i < MAX_ICON_CACHE; i++)
		if(!strncmp(icons[i].name, name, ARGLEN))
			return i;

	return -1;
}

#ifdef DZEN_XPM
static void
cache_icon(const char* name, Pixmap pm, int w, int h) {
	if(icon_cnt >= MAX_ICON_CACHE)
		icon_cnt = 0;

	if(icons[icon_cnt].p)
		XFreePixmap(dzen.dpy, icons[icon_cnt].p);

	strncpy(icons[icon_cnt].name, name, ARGLEN);
	icons[icon_cnt].w = w;
	icons[icon_cnt].h = h;
	icons[icon_cnt].p = pm;
	icon_cnt++;
}
#endif


char *
parse_line(const char *line, int lnr, int align, int reverse, int nodraw) {
	/* bitmaps */
	unsigned int bm_w, bm_h;
	int bm_xh, bm_yh;
	/* rectangles, cirlcles*/
	int rectw, recth, rectx, recty;
	/* positioning */
	int n_posx, n_posy, set_posy=0;
	int px=0, py=0, opx=0;
	int i, next_pos=0, j=0, h=0, tw=0;
	/* buffer pos */
	const char *linep=NULL;
	/* fonts */
	int font_was_set=0;
	/* position */
	int pos_is_fixed = 0;
	/* block alignment */
	int block_align = -1;
	int block_width = -1;
	/* clickable area y tracking */
	int max_y=-1;

	/* temp buffers */
	char lbuf[MAX_LINE_LEN], *rbuf = NULL;

	/* parser state */
	int t=-1, nobg=0;
	char *tval=NULL;

	/* X stuff */
	long lastfg = dzen.norm[ColFG], lastbg = dzen.norm[ColBG];
	Fnt *cur_fnt = NULL;
#ifndef DZEN_XFT
	XGCValues gcv;
#endif
	Drawable pm=0, bm;
#ifdef DZEN_XPM
	int free_xpm_attrib = 0;
	Pixmap xpm_pm;
	XpmAttributes xpma;
	XpmColorSymbol xpms;
#endif

#ifdef DZEN_XFT
	XftDraw *xftd=NULL;
	XftColor xftc;
	char *xftcs;
	int xftcs_f=0;
	char *xftcs_bg;
	int xftcs_bgf=0;

	xftcs    = (char *)dzen.fg;
    xftcs_bg = (char *)dzen.bg;
#endif

	/* icon cache */
	int ip;

	/* parse line and return the text without control commands */
	if(nodraw) {
		rbuf = emalloc(MAX_LINE_LEN);
		rbuf[0] = '\0';
		if( (lnr + dzen.slave_win.first_line_vis) >= dzen.slave_win.tcnt)
			line = NULL;
		else
			line = dzen.slave_win.tbuf[dzen.slave_win.first_line_vis+lnr];

	}
	/* parse line and render text */
	else {
		h = dzen.font.height;
		py = (dzen.line_height - h) / 2;
		xorig[LNR2WINDOW(lnr)] = 0;
		
		if(lnr != -1) {
			pm = XCreatePixmap(dzen.dpy, RootWindow(dzen.dpy, DefaultScreen(dzen.dpy)), dzen.slave_win.width,
					dzen.line_height, DefaultDepth(dzen.dpy, dzen.screen));
		}
		else {
			pm = XCreatePixmap(dzen.dpy, RootWindow(dzen.dpy, DefaultScreen(dzen.dpy)), dzen.title_win.width,
					dzen.line_height, DefaultDepth(dzen.dpy, dzen.screen));
		}

#ifdef DZEN_XFT
		xftd = XftDrawCreate(dzen.dpy, pm, DefaultVisual(dzen.dpy, dzen.screen), 
				DefaultColormap(dzen.dpy, dzen.screen));
#endif

		if(!reverse) {
			XSetForeground(dzen.dpy, dzen.tgc, dzen.norm[ColBG]);
#ifdef DZEN_XPM
			xpms.pixel = dzen.norm[ColBG];
#endif
#ifdef DZEN_XFT
			xftcs_bg = (char *)dzen.bg;
			xftcs_bgf = 0;
#endif
		}
		else {
			XSetForeground(dzen.dpy, dzen.tgc, dzen.norm[ColFG]);
#ifdef DZEN_XPM
			xpms.pixel = dzen.norm[ColFG];
#endif
		}
		XFillRectangle(dzen.dpy, pm, dzen.tgc, 0, 0, dzen.w, dzen.h);

		if(!reverse) {
			XSetForeground(dzen.dpy, dzen.tgc, dzen.norm[ColFG]);
		}
		else {
			XSetForeground(dzen.dpy, dzen.tgc, dzen.norm[ColBG]);
		}

#ifdef DZEN_XPM
		xpms.name = NULL;
		xpms.value = (char *)"none";

		xpma.colormap = DefaultColormap(dzen.dpy, dzen.screen);
		xpma.depth = DefaultDepth(dzen.dpy, dzen.screen);
		xpma.visual = DefaultVisual(dzen.dpy, dzen.screen);
		xpma.colorsymbols = &xpms;
		xpma.numsymbols = 1;
		xpma.valuemask = XpmColormap|XpmDepth|XpmVisual|XpmColorSymbols;
#endif

#ifndef DZEN_XFT 
		if(!dzen.font.set){
			gcv.font = dzen.font.xfont->fid;
			XChangeGC(dzen.dpy, dzen.tgc, GCFont, &gcv);
		}
#endif
		cur_fnt = &dzen.font;

		if( lnr != -1 && (lnr + dzen.slave_win.first_line_vis >= dzen.slave_win.tcnt)) {
			XCopyArea(dzen.dpy, pm, dzen.slave_win.drawable[lnr], dzen.gc,
					0, 0, px, dzen.line_height, xorig[LNR2WINDOW(lnr)], 0);
			XFreePixmap(dzen.dpy, pm);
			return NULL;
		}
	}

	linep = line;
	while(1) {
		if(*linep == ESC_CHAR || *linep == '\0') {
			lbuf[j] = '\0';

			/* clear _lock_x at EOL so final width is correct */
			if(*linep=='\0')
				pos_is_fixed=0;

			if(nodraw) {
				strcat(rbuf, lbuf);
			}
			else {
				if(t != -1 && tval) {
					switch(t) {
						case icon:
							if(MAX_ICON_CACHE && (ip=search_icon_cache(tval)) != -1) {
								int y;
								XCopyArea(dzen.dpy, icons[ip].p, pm, dzen.tgc,
										0, 0, icons[ip].w, icons[ip].h, px, y=(set_posy ? py :
										(dzen.line_height >= (signed)icons[ip].h ?
										(dzen.line_height - icons[ip].h)/2 : 0)));
								px += !pos_is_fixed ? icons[ip].w : 0;
								max_y = MAX(max_y, y+icons[ip].h);
							} else {
								int y;
								if(XReadBitmapFile(dzen.dpy, pm, tval, &bm_w,
											&bm_h, &bm, &bm_xh, &bm_yh) == BitmapSuccess
										&& (h/2 + px + (signed)bm_w < dzen.w)) {
									setcolor(&pm, px, bm_w, lastfg, lastbg, reverse, nobg);

									XCopyPlane(dzen.dpy, bm, pm, dzen.tgc,
											0, 0, bm_w, bm_h, px, y=(set_posy ? py :
											(dzen.line_height >= (int)bm_h ?
												(dzen.line_height - (int)bm_h)/2 : 0)), 1);
									XFreePixmap(dzen.dpy, bm);
									px += !pos_is_fixed ? bm_w : 0;
									max_y = MAX(max_y, y+bm_h);
								}
#ifdef DZEN_XPM
								else if(XpmReadFileToPixmap(dzen.dpy, dzen.title_win.win, tval, &xpm_pm, NULL, &xpma) == XpmSuccess) {
									setcolor(&pm, px, xpma.width, lastfg, lastbg, reverse, nobg);

									if(MAX_ICON_CACHE)
										cache_icon(tval, xpm_pm, xpma.width, xpma.height);

									XCopyArea(dzen.dpy, xpm_pm, pm, dzen.tgc,
											0, 0, xpma.width, xpma.height, px, y=(set_posy ? py :
											(dzen.line_height >= (int)xpma.height ?
												(dzen.line_height - (int)xpma.height)/2 : 0)));
									px += !pos_is_fixed ? xpma.width : 0;
									max_y = MAX(max_y, y+xpma.height);

									/* freed by cache_icon() */
									//XFreePixmap(dzen.dpy, xpm_pm);
									free_xpm_attrib = 1;
								}
#endif
							}
							break;


						case rect:
							get_rect_vals(tval, &rectw, &recth, &rectx, &recty);
							recth = recth > dzen.line_height ? dzen.line_height : recth;
							if(set_posy)
								py += recty;
							recty =	recty == 0 ? (dzen.line_height - recth)/2 :
								(dzen.line_height - recth)/2 + recty;
							px += !pos_is_fixed ? rectx : 0;
							setcolor(&pm, px, rectw, lastfg, lastbg, reverse, nobg);

							XFillRectangle(dzen.dpy, pm, dzen.tgc, px,
									set_posy ? py :
									((int)recty < 0 ? dzen.line_height + recty : recty),
									rectw, recth);

							px += !pos_is_fixed ? rectw : 0;
							break;

						case recto:
							get_rect_vals(tval, &rectw, &recth, &rectx, &recty);
							if (!rectw) break;

							recth = recth > dzen.line_height ? dzen.line_height-2 : recth-1;
							if(set_posy)
								py += recty;
							recty =	recty == 0 ? (dzen.line_height - recth)/2 :
								(dzen.line_height - recth)/2 + recty;
							px = (rectx == 0) ? px : rectx+px;
							/* prevent from stairs effect when rounding recty */
							if (!((dzen.line_height - recth) % 2)) recty--;
							setcolor(&pm, px, rectw, lastfg, lastbg, reverse, nobg);
							XDrawRectangle(dzen.dpy, pm, dzen.tgc, px,
									set_posy ? py :
									((int)recty<0 ? dzen.line_height + recty : recty), rectw-1, recth);
							px += !pos_is_fixed ? rectw : 0;
							break;

						case circle:
							rectx = get_circle_vals(tval, &rectw, &recth);
							setcolor(&pm, px, rectw, lastfg, lastbg, reverse, nobg);
							XFillArc(dzen.dpy, pm, dzen.tgc, px, set_posy ? py :(dzen.line_height - rectw)/2,
									rectw, rectw, 90*64, rectx>1?recth*64:64*360);
							px += !pos_is_fixed ? rectw : 0;
							break;

						case circleo:
							rectx = get_circle_vals(tval, &rectw, &recth);
							setcolor(&pm, px, rectw, lastfg, lastbg, reverse, nobg);
							XDrawArc(dzen.dpy, pm, dzen.tgc, px, set_posy ? py : (dzen.line_height - rectw)/2,
									rectw, rectw, 90*64, rectx>1?recth*64:64*360);
							px += !pos_is_fixed ? rectw : 0;
							break;

						case pos:
							if(tval[0]) {
								int r=0;
								r = get_pos_vals(tval, &n_posx, &n_posy);
								if( (r == 1 && !set_posy))
									set_posy=0;
								else if (r == 5) {
									switch(n_posx) {
										case LOCK_X:
											pos_is_fixed = 1;
											break;
										case UNLOCK_X:
											pos_is_fixed = 0;
											break;
										case LEFT:
											px = 0;
											break;
										case RIGHT:
											px = dzen.w;
											break;
										case CENTER:
											px = dzen.w/2;
											break;
										case BOTTOM:
											set_posy = 1;
											py = dzen.line_height;
											break;
										case TOP:
											set_posy = 1;
											py = 0;
											break;
									}
								} else
									set_posy=1;

								if(r != 2)
									px = px+n_posx<0? 0 : px + n_posx;
								if(r != 1) 
									py += n_posy;
							} else {
								set_posy = 0;
								py = (dzen.line_height - dzen.font.height) / 2;
							}
							break;

						case abspos:
							if(tval[0]) {
								int r=0;
								if( (r=get_pos_vals(tval, &n_posx, &n_posy)) == 1 && !set_posy)
									set_posy=0;
								else
									set_posy=1;

								n_posx = n_posx < 0 ? n_posx*-1 : n_posx;
								if(r != 2)
									px = n_posx;
								if(r != 1)
									py = n_posy;
							} else {
								set_posy = 0;
								py = (dzen.line_height - dzen.font.height) / 2;
							}
							break;

						case ibg:
							nobg = atoi(tval);
							break;

						case bg:
							lastbg = tval[0] ? (unsigned)getcolor(tval) : dzen.norm[ColBG];
#ifdef DZEN_XFT
							if(xftcs_bgf) free(xftcs_bg);				
							if(tval[0]) {
								xftcs_bg = estrdup(tval);
								xftcs_bgf = 1;
							} else {
								xftcs_bg = (char *)dzen.bg;
								xftcs_bgf = 0;
							}
#endif							

							break;

						case fg:
							lastfg = tval[0] ? (unsigned)getcolor(tval) : dzen.norm[ColFG];
							XSetForeground(dzen.dpy, dzen.tgc, lastfg);
#ifdef DZEN_XFT
							if(tval[0]) {
								xftcs = estrdup(tval);
								xftcs_f = 1;
							} else {
								xftcs = (char *)dzen.fg;
								xftcs_f = 0;
							}
#endif							
							break;

						case fn:
							if(tval[0]) {
#ifndef DZEN_XFT		
								if(!strncmp(tval, "dfnt", 4)) {
									cur_fnt = &(dzen.fnpl[atoi(tval+4)]);

									if(!cur_fnt->set) {
										gcv.font = cur_fnt->xfont->fid;
										XChangeGC(dzen.dpy, dzen.tgc, GCFont, &gcv);
									}
								}
								else
#endif					
									setfont(tval);
							}
							else {
								cur_fnt = &dzen.font;
#ifndef DZEN_XFT		
								if(!cur_fnt->set){
									gcv.font = cur_fnt->xfont->fid;
									XChangeGC(dzen.dpy, dzen.tgc, GCFont, &gcv);
								}
#else
							setfont(dzen.fnt ? dzen.fnt : FONT);
#endif								
							}
							py = set_posy ? py : (dzen.line_height - cur_fnt->height) / 2;
							font_was_set = 1;
							break;
						case ca:
							; //nop to keep gcc happy
							sens_w *w = &window_sens[LNR2WINDOW(lnr)];
							
							if(tval[0]) {
								click_a *area = &((*w).sens_areas[(*w).sens_areas_cnt]);
								if((*w).sens_areas_cnt < MAX_CLICKABLE_AREAS) {
									get_sens_area(tval, 
											&(*area).button, 
											(*area).cmd);
									(*area).start_x = px;
									(*area).start_y = py;
									(*area).end_y = py;
									max_y = py;
									(*area).active = 0;
									if(lnr == -1) {
										(*area).win = dzen.title_win.win;
									} else {
										(*area).win = dzen.slave_win.line[lnr];
									}
									(*w).sens_areas_cnt++;
								}
							} else {
									//find most recent unclosed area
									for(i = (*w).sens_areas_cnt - 1; i >= 0; i--)
										if(!(*w).sens_areas[i].active)
											break;
									if(i >= 0 && i < MAX_CLICKABLE_AREAS) {
										(*w).sens_areas[i].end_x = px;
										(*w).sens_areas[i].end_y = max_y;
										(*w).sens_areas[i].active = 1;
								}
							}
							break;
						case ba:
							if(tval[0])
								get_block_align_vals(tval, &block_align, &block_width);
							else
								block_align=block_width=-1;
							break;
					}
					free(tval);
				}

				/* check if text is longer than window's width */
				tw = textnw(cur_fnt, lbuf, strlen(lbuf));
				while((((tw + px) > (dzen.w)) || (block_align!=-1 && tw>block_width)) && j>=0) {
					lbuf[--j] = '\0';
					tw = textnw(cur_fnt, lbuf, strlen(lbuf));
				}
				
				opx = px;

				/* draw background for block */
				if(block_align!=-1 && !nobg) {
					setcolor(&pm, px, rectw, lastbg, lastbg, 0, nobg);
					XFillRectangle(dzen.dpy, pm, dzen.tgc, px, 0, block_width, dzen.line_height);
				}

				if(block_align==ALIGNRIGHT)
					px += (block_width - tw);
				else if(block_align==ALIGNCENTER)
					px += (block_width/2) - (tw/2);

				if(!nobg)
					setcolor(&pm, px, tw, lastfg, lastbg, reverse, nobg);
				
#ifndef DZEN_XFT
				if(cur_fnt->set)
					XmbDrawString(dzen.dpy, pm, cur_fnt->set,
							dzen.tgc, px, py + cur_fnt->ascent, lbuf, strlen(lbuf));
				else
					XDrawString(dzen.dpy, pm, dzen.tgc, px, py+dzen.font.ascent, lbuf, strlen(lbuf));
#else
				if(reverse) {
				XftColorAllocName(dzen.dpy, DefaultVisual(dzen.dpy, dzen.screen),
						DefaultColormap(dzen.dpy, dzen.screen),  xftcs_bg,  &xftc);
				} else {
				XftColorAllocName(dzen.dpy, DefaultVisual(dzen.dpy, dzen.screen),
						DefaultColormap(dzen.dpy, dzen.screen),  xftcs,  &xftc);
				}

				XftDrawStringUtf8(xftd, &xftc, 
						cur_fnt->xftfont, px, py + dzen.font.xftfont->ascent, (const FcChar8 *)lbuf, strlen(lbuf));

				if(xftcs_f) {
					free(xftcs);
					xftcs_f = 0;
				}
				if(xftcs_bgf) {
					free(xftcs_bg);
					xftcs_bgf = 0;
				}

#endif

				max_y = MAX(max_y, py+dzen.font.height);

				if(block_align==-1) {
					if(!pos_is_fixed || *linep =='\0')
						px += tw;
				} else {
					if(pos_is_fixed)
						px = opx;
					else
						px = opx+block_width;
				}

				block_align=block_width=-1;
			}

			if(*linep=='\0')
				break;

			j=0; t=-1; tval=NULL;
			next_pos = get_token(linep, &t, &tval);
			linep += next_pos;

			/* ^^ escapes */
			if(next_pos == 0)
				lbuf[j++] = *linep++;
		}
		else
			lbuf[j++] = *linep;

		linep++;
	}

	if(!nodraw) {
		/* expand/shrink dynamically */
		if(dzen.title_win.expand && lnr == -1){
			i = px;
			switch(dzen.title_win.expand) {
				case left:
					/* grow left end */
					otx = dzen.title_win.x_right_corner - i > dzen.title_win.x ?
						dzen.title_win.x_right_corner - i : dzen.title_win.x;
					XMoveResizeWindow(dzen.dpy, dzen.title_win.win, otx, dzen.title_win.y, px, dzen.line_height);
					break;
				case right:
					XResizeWindow(dzen.dpy, dzen.title_win.win, px, dzen.line_height);
					break;
			}

		} else {
			if(align == ALIGNLEFT)
				xorig[LNR2WINDOW(lnr)] = 0;
			if(align == ALIGNCENTER) {
				xorig[LNR2WINDOW(lnr)] = (lnr != -1) ?
					(dzen.slave_win.width - px)/2 :
					(dzen.title_win.width - px)/2;
			}
			else if(align == ALIGNRIGHT) {
				xorig[LNR2WINDOW(lnr)] = (lnr != -1) ?
					(dzen.slave_win.width - px) :
					(dzen.title_win.width - px);
			}
		}


		if(lnr != -1) {
			XCopyArea(dzen.dpy, pm, dzen.slave_win.drawable[lnr], dzen.gc,
                    0, 0, dzen.w, dzen.line_height, xorig[LNR2WINDOW(lnr)], 0);
		}
		else {
			XCopyArea(dzen.dpy, pm, dzen.title_win.drawable, dzen.gc,
					0, 0, dzen.w, dzen.line_height, xorig[LNR2WINDOW(lnr)], 0);
		}
		XFreePixmap(dzen.dpy, pm);

		/* reset font to default */
		if(font_was_set)
			setfont(dzen.fnt ? dzen.fnt : FONT);

#ifdef DZEN_XPM
		if(free_xpm_attrib) {
			XFreeColors(dzen.dpy, xpma.colormap, xpma.pixels, xpma.npixels, xpma.depth);
			XpmFreeAttributes(&xpma);
		}
#endif

#ifdef DZEN_XFT
		XftDrawDestroy(xftd);
#endif
	}

	return nodraw ? rbuf : NULL;
}

int
parse_non_drawing_commands(char * text) {

	if(!text)
		return 1;

	if(!strncmp(text, "^togglecollapse()", strlen("^togglecollapse()"))) {
		a_togglecollapse(NULL);
		return 0;
	}
	if(!strncmp(text, "^collapse()", strlen("^collapse()"))) {
		a_collapse(NULL);
		return 0;
	}
	if(!strncmp(text, "^uncollapse()", strlen("^uncollapse()"))) {
		a_uncollapse(NULL);
		return 0;
	}

	if(!strncmp(text, "^togglestick()", strlen("^togglestick()"))) {
		a_togglestick(NULL);
		return 0;
	}
	if(!strncmp(text, "^stick()", strlen("^stick()"))) {
		a_stick(NULL);
		return 0;
	}
	if(!strncmp(text, "^unstick()", strlen("^unstick()"))) {
		a_unstick(NULL);
		return 0;
	}

	if(!strncmp(text, "^togglehide()", strlen("^togglehide()"))) {
		a_togglehide(NULL);
		return 0;
	}
	if(!strncmp(text, "^hide()", strlen("^hide()"))) {
		a_hide(NULL);
		return 0;
	}
	if(!strncmp(text, "^unhide()", strlen("^unhide()"))) {
		a_unhide(NULL);
		return 0;
	}

	if(!strncmp(text, "^raise()", strlen("^raise()"))) {
		a_raise(NULL);
		return 0;
	}

	if(!strncmp(text, "^lower()", strlen("^lower()"))) {
		a_lower(NULL);
		return 0;
	}

	if(!strncmp(text, "^scrollhome()", strlen("^scrollhome()"))) {
		a_scrollhome(NULL);
		return 0;
	}

	if(!strncmp(text, "^scrollend()", strlen("^scrollend()"))) {
		a_scrollend(NULL);
		return 0;
	}

	if(!strncmp(text, "^exit()", strlen("^exit()"))) {
		a_exit(NULL);
		return 0;
	}

	return 1;
}


void
drawheader(const char * text) {
	if(parse_non_drawing_commands((char *)text)) {
		if (text){
			dzen.w = dzen.title_win.width;
			dzen.h = dzen.line_height;
			
			window_sens[TOPWINDOW].sens_areas_cnt = 0;
			
			XFillRectangle(dzen.dpy, dzen.title_win.drawable, dzen.rgc, 0, 0, dzen.w, dzen.h);
			parse_line(text, -1, dzen.title_win.alignment, 0, 0);
		}
	} else {
		dzen.slave_win.tcnt = -1;
		dzen.cur_line = 0;
	}

	XCopyArea(dzen.dpy, dzen.title_win.drawable, dzen.title_win.win,
			dzen.gc, 0, 0, dzen.title_win.width, dzen.line_height, 0, 0);
}

void
drawbody(char * text) {
	char *ec;
	int i, write_buffer=1;
	

	if(dzen.slave_win.tcnt == -1) {
		dzen.slave_win.tcnt = 0;
		drawheader(text);
		return;
	}

	
	if((ec = strstr(text, "^tw()")) && (*(ec-1) != '^')) {
		drawheader(ec+5);
		return;
	}

	if(dzen.slave_win.tcnt == dzen.slave_win.tsize)
		free_buffer();

	write_buffer = parse_non_drawing_commands(text);


	if(text[0] == '^' && text[1] == 'c' && text[2] == 's') {
		free_buffer();

		for(i=0; i < dzen.slave_win.max_lines; i++)
			XFillRectangle(dzen.dpy, dzen.slave_win.drawable[i], dzen.rgc, 0, 0, dzen.slave_win.width, dzen.line_height);
		x_draw_body();
		return;
	}

	if( write_buffer && (dzen.slave_win.tcnt < dzen.slave_win.tsize) ) {
		dzen.slave_win.tbuf[dzen.slave_win.tcnt] = estrdup(text);
		dzen.slave_win.tcnt++;
	}
}
070701303F14DE000081A40000420C00000032000000015240109300000DA2000000080000001100000000000000000000002000000000dzen2-1379930259.488ab66/dzen.h/* 
 * (C)opyright 2007-2009 Robert Manea <rob dot manea at gmail dot com>
 * See LICENSE file for license details.
 *
 */

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xresource.h>
#ifdef DZEN_XINERAMA
#include <X11/extensions/Xinerama.h>
#endif
#ifdef DZEN_XFT
#include <X11/Xft/Xft.h>
#endif

#define FONT		"-*-fixed-*-*-*-*-*-*-*-*-*-*-*-*"
#define BGCOLOR		"#111111"
#define FGCOLOR		"grey70"
#define ESC_CHAR    '^'

#define ALIGNCENTER 0
#define ALIGNLEFT   1
#define ALIGNRIGHT  2

#define TOPWINDOW   0
#define SLAVEWINDOW 1

#define MIN_BUF_SIZE   1024
#define MAX_LINE_LEN   8192

#define MAX_CLICKABLE_AREAS 256

#ifndef Button6
# define Button6 6
#endif

#ifndef Button7
# define Button7 7
#endif

enum { ColFG, ColBG, ColLast };

/* exapansion directions */
enum { noexpand, left, right, both };

typedef struct DZEN Dzen;
typedef struct Fnt Fnt;
typedef struct TW TWIN;
typedef struct SW SWIN;
typedef struct _Sline Sline;

struct Fnt {
	XFontStruct *xfont;
	XFontSet set;
	int ascent;
	int descent;
	int height;
#ifdef DZEN_XFT
	XftFont *xftfont;
	XGlyphInfo *extents;
	int width;
#endif
};

/* clickable areas */
typedef struct _CLICK_A {
    int active;
	int button;
	int start_x;
	int end_x;
	int start_y;
	int end_y;
	Window win;		//(line)window to which the action is attached
	char cmd[1024];
} click_a;

typedef struct _SENS_PER_WINDOW {
	click_a sens_areas[MAX_CLICKABLE_AREAS];
	int sens_areas_cnt;
} sens_w;

//0: top window, 1: slave window
extern int xorig[2];
extern sens_w window_sens[2];


/* title window */
struct TW {
	int x, y, width, height;

	char *name;
	Window win;
	Drawable drawable;
	char alignment;
	int expand;
	int x_right_corner;
	Bool ishidden;
};

/* slave window */
struct SW {
	int x, y, width, height;

	char *name;
	Window win;
	Window *line;
	Drawable *drawable;

	/* input buffer */
	char **tbuf; 
	int tsize;
	int tcnt;
	/* line fg colors */
	unsigned long *tcol;

	int max_lines;
	int first_line_vis;
	int last_line_vis;
	int sel_line;

	char alignment;
	Bool ismenu;
	Bool ishmenu;
	Bool issticky;
	Bool ismapped;
};

struct DZEN {
	int x, y, w, h;
	Bool running;
	unsigned long norm[ColLast];

	TWIN title_win;
	SWIN slave_win;

	/* sensitive areas */
	Window sa_win;

	const char *fnt;
	const char *bg;
	const char *fg;
	int line_height;

	Display *dpy;
	int screen;
	unsigned int depth;

	Visual *visual;
	GC gc, rgc, tgc;
	Fnt font;
	Fnt fnpl[64];

	Bool ispersistent;
	Bool tsupdate;
	Bool colorize;
	unsigned long timeout;
	long cur_line;
	int ret_val;

	/* should always be 0 if DZEN_XINERAMA not defined */
	int xinescreen;
};

extern Dzen dzen;

void free_buffer(void);
void x_draw_body(void);

/* draw.c */
extern void drawtext(const char *text,
		int reverse,
		int line,
		int align);
extern char * parse_line(const char * text, 
		int linenr, 
		int align, 
		int reverse, 
		int nodraw);
extern long getcolor(const char *colstr);		/* returns color of colstr */
extern void setfont(const char *fontstr);		/* sets global font */
extern unsigned int textw(const char *text);	/* returns width of text in px */
extern void drawheader(const char *text);
extern void drawbody(char *text);

/* util.c */
extern void *emalloc(unsigned int size);		/* allocates memory, exits on error */
extern void eprint(const char *errstr, ...);	/* prints errstr and exits with 1 */
extern char *estrdup(const char *str);			/* duplicates str, exits on allocation error */
extern void spawn(const char *arg);				/* execute arg */
070701303F14DF000041ED0000420C00000032000000025240109300000000000000080000001100000000000000000000002100000000dzen2-1379930259.488ab66/gadgets070701304160CB000081A40000420C0000003200000001524010930000069A000000080000001100000000000000000000002A00000000dzen2-1379930259.488ab66/gadgets/Makefile# dzen2 gadgets
# (c) 2007 Robert Manea

include config.mk

SRC = dbar.c dbar-main.c gdbar.c gcpubar.c textwidth.c
OBJ = ${SRC:.c=.o}

all: options dbar gdbar gcpubar textwidth

options:
	@echo dzen2 gadgets build options:
	@echo "CFLAGS   = ${CFLAGS}"
	@echo "LDFLAGS  = ${LDFLAGS}"
	@echo "CC       = ${CC}"
	@echo "LD       = ${LD}"

.c.o:
	@echo CC $<
	@${CC} -c ${CFLAGS} $<

${OBJ}: dbar.h config.mk

dbar: ${OBJ}
	@echo LD $@
	@${LD} -o $@ dbar-main.o dbar.o ${LDFLAGS}
	@strip $@

gdbar: ${OBJ}
	@echo LD $@
#	@${LD} -o $@ gdbar.o dbar.o ${LDFLAGS} -L${X11LIB} -lX11
	@${LD} -o $@ gdbar.o dbar.o ${LDFLAGS}
	@strip $@

gcpubar: ${OBJ}
	@echo LD $@
#	@${LD} -o $@ gcpubar.o dbar.o ${LDFLAGS} -L${X11LIB}
	@${LD} -o $@ gcpubar.o dbar.o ${LDFLAGS}
	@strip $@

textwidth: ${OBJ}
	@echo LD $@
	@${LD} -o $@ textwidth.o ${LDFLAGS} -L${X11LIB} -lX11
	@strip $@

clean:
	@echo cleaning
	@rm -f ${OBJ} dbar
	@rm -f ${OBJ} gdbar
	@rm -f ${OBJ} gcpubar
	@rm -f ${OBJ} textwidth

install: all
	@echo installing executable file to ${DESTDIR}${PREFIX}/bin
	@mkdir -p ${DESTDIR}${PREFIX}/bin
	@cp -f dbar ${DESTDIR}${PREFIX}/bin
	@chmod 755 ${DESTDIR}${PREFIX}/bin/dbar
	@cp -f gdbar ${DESTDIR}${PREFIX}/bin
	@chmod 755 ${DESTDIR}${PREFIX}/bin/gdbar
	@cp -f gcpubar ${DESTDIR}${PREFIX}/bin
	@chmod 755 ${DESTDIR}${PREFIX}/bin/gcpubar
	@cp -f textwidth ${DESTDIR}${PREFIX}/bin
	@chmod 755 ${DESTDIR}${PREFIX}/bin/textwidth

uninstall:
	@echo removing executable file from ${DESTDIR}${PREFIX}/bin
	@rm -f ${DESTDIR}${PREFIX}/bin/dbar
	@rm -f ${DESTDIR}${PREFIX}/bin/gdbar
	@rm -f ${DESTDIR}${PREFIX}/bin/gcpubar
	@rm -f ${DESTDIR}${PREFIX}/bin/textwidth

.PHONY: all options clean install uninstall
0707013066BB26000081A40000420C00000032000000015240109300000822000000080000001100000000000000000000002D00000000dzen2-1379930259.488ab66/gadgets/README.dbar==============================
dbar, (c) 2007 by Robert Manea
==============================

dbar is an application that generates semi graphical progress meters,
from some values you supply to it.

See the usage examples for a description of the expected input format.

Options:
--------

     -max :  Value to be considered 100%   (default: 100)
     -min :  Value to be considered   0%   (default: 0  )
     -w   :  Number of charcaters to be 
             considered 100% in the meter  (default: 25 )
     -s   :  Symbol represeting the 
             percentage value in the meter (default: =  )
     -l   :  label to be prepended to 
             the bar                       (default: '' )
     -nonl:  no new line, don't put 
             '\n' at the end of the bar    (default: do print '\n')

dbar lets you define static 0% and 100% marks with the '-min' and '-max'
options or you can provide these marks dynamically at runtime.  Static
and dynamic marks can be mixed, in this case the value specified at
runtime will override the comandline value.

You can specify ranges of numbers, negative, positive or ranges with a
negative min value and positive max value.

All numbers are treated as double precision floating point, i.e. the
input is NOT limited to integers.


Usage examples:

 1) Static 0% and 100% mark or single value input:

   echo 25 | dbar -m 100 -l Sometext

   Output: Sometext  25% [======                   ]

 2) If your 100% mark changes dynamically or 2-values input:

   echo "50 150" | dbar
         ^   ^
         |   |__ max. value
         |
         |__ value to display

   Output: 33% [========                 ]

 3) If your value range is not between [0, maxval] or 3-values input:

   echo "50 -25 150" | dbar
         ^   ^  ^
         |   |  |__ max. value 100% mark
         |   |
         |   |_____ min. value 0% mark
         |
         |________ value to display

   Output: 43% [===========              ]


 4) Multiple runs:

   for i in 2 20 50 75 80; do echo $i; sleep 1; done | dbar | dzen2

   Output: Find out yourself.

070701331C015D000081A40000420C00000032000000015240109300000484000000080000001100000000000000000000003000000000dzen2-1379930259.488ab66/gadgets/README.gcpubar====================================
 gcpubar, (c) 20007 by Robert Manea
====================================

gcpubar is a CPU utilization meter for Linux. It relies on the existence
of the "/proc/stat" file and generateѕ fully graphical meters viewable with
dzen >= 0.7.0.

Command line options:
---------------------


  -i  :  Update interval in seconds    (default:   1)
         You can use positive values
         less than 1 for intervals 
         shorter than a second

  -c  :  Number of times to display    (default: infinite)
         the meter

  -w  :  Width of the meter in pixels  (default: 100)

  -h  :  Height of the meter in pixels (default:  10)

  -fg :  Meter foreground color        (default: white)

  -bg :  Meter background color        (default: darkgrey)

  -s  :  Style, can be either o(utlined)
         v(ertical), g(raph) or the default
		 gauge if no parameter is specified

  -gw :  Width of the graph elements    (default: 1)

  -gs :  Space between the graph 
         elemements                     (default: 0)

  -nonl:  no new line, don't put
          '\n' at the end of the bar    (default: do print '\n')




070701331C015E000081A40000420C000000320000000152401093000004FE000000080000001100000000000000000000002E00000000dzen2-1379930259.488ab66/gadgets/README.gdbar=================================
 gdbar, (c) 2007 by Robert Manea
=================================

gdbar is an application that generates fully graphical progress meters,
from some values you supply to it.

It has the same input semantics as dbar (see README.dbar). In contrast
to dbar, gdbar draws fully graphical meters which are only useful in
combination with dzen >= 0.7.0.

Options:
--------

     -fg  :  foreground color of the meter (default: white)
     -bg  :  background color of the meter (default: darkgrey)
     -s   :  Style, can be either o(utlined), v(ertical),
             or the default gauge if no parameter is specified
     -sw  :  Width of the segments
     -sh  :  Height of the vertical segments
     -ss  :  Space between the segments
     -max :  Value to be considered 100%   (default: 100)
     -min :  Value to be considered   0%   (default: 0  )
     -w   :  Size in pixels to be 
             considered 100% in the meter  (default: 80 )
     -h   :  bar height
     -l   :  label to be prepended to 
             the bar                       (default: '' )
     -o   :  Draw conky style meters
     -nonl:  no new line, don't put 
             '\n' at the end of the bar    (default: do print '\n')


See README.dbar for further details!

070701331C015F000081A40000420C000000320000000152401093000001A0000000080000001100000000000000000000003400000000dzen2-1379930259.488ab66/gadgets/README.kittscanner========================================
 kitt-scanner, (c) 2007 by Robert Manea
========================================

This is just a fun gadget and wants to show what can be done with dzen
other than just displaying text ;).

It implements sort of a KITT (Knight Rider, TV series) scanner in shell
script.

There are some settings that you can tweak to your likings, see
"kittscanner.sh" for further details.


070701335BDB20000081A40000420C000000320000000152401093000000DD000000080000001100000000000000000000003200000000dzen2-1379930259.488ab66/gadgets/README.textwidth===================================
textwidth, (c) 2007 by Robert Manea
===================================

Simple utility to calculate the width in pixels of text with a given
font.

Usage: textwidth <fontname> <text>

070701335BDB21000081A40000420C00000032000000015240109300000125000000080000001100000000000000000000002B00000000dzen2-1379930259.488ab66/gadgets/config.mk# Customize below to fit your system

# paths
PREFIX = /usr/local
MANPREFIX = ${PREFIX}/share/man

X11INC = /usr/X11R6/include
INCS = -I. -I/usr/include -I${X11INC}

X11LIB = /usr/X11R6/lib
LIBS = -L/usr/lib 

CFLAGS = -Os ${INCS} 
LDFLAGS = ${LIBS}

# compiler and linker
CC = gcc
LD = ${CC}
070701335BDB22000081A40000420C00000032000000015240109300000A06000000080000001100000000000000000000002D00000000dzen2-1379930259.488ab66/gadgets/dbar-main.c/*  
	dbar - ascii percentage meter

	Copyright (c) 2007 by Robert Manea  <rob dot manea at gmail dot com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/


#include <stdio.h>
#include "dbar.h"

#define MAXLEN 512

int main(int argc, char *argv[]) {
  int i, nv;
  char aval[MAXLEN], *endptr;
  Dbar dbar;

  dbardefaults(&dbar, textual);
  
  for(i=1; i < argc; i++) {
    if(!strncmp(argv[i], "-w", 3)) {
      if(++i < argc)
	dbar.width = atoi(argv[i]);
    }
    else if(!strncmp(argv[i], "-s", 3)) {
      if(++i < argc)
	dbar.sym = argv[i][0];
    }
    else if(!strncmp(argv[i], "-max", 5)) {
      if(++i < argc) {
	dbar.maxval = strtod(argv[i], &endptr);
	if(*endptr) {
	  fprintf(stderr, "dbar: '%s' incorrect number format", argv[i]);
	  return EXIT_FAILURE;
	}
      }
    }
    else if(!strncmp(argv[i], "-min", 5)) {
      if(++i < argc) {
	dbar.minval = strtod(argv[i], &endptr);
	if(*endptr) {
	  fprintf(stderr, "dbar: '%s' incorrect number format", argv[i]);
	  return EXIT_FAILURE;
	}
      }
    }
    else if(!strncmp(argv[i], "-l", 3)) {
      if(++i < argc)
	dbar.label = argv[i];
    }
    else if(!strncmp(argv[i], "-nonl", 6)) {
      dbar.pnl = 0;
    }
    else {
      fprintf(stderr, "usage: dbar [-w <characters>] [-s <symbol>] [-min <minvalue>] [-max <maxvalue>] [-l <string>] [-nonl]\n");
      return EXIT_FAILURE;
    }
  }

  while(fgets(aval, MAXLEN, stdin)) {
    nv = sscanf(aval, "%lf %lf %lf", &dbar.val, &dbar.minval, &dbar.maxval);
    if(nv == 2) {
      dbar.maxval = dbar.minval;
      dbar.minval = 0;
    }
    fdbar(&dbar, stdout);
  }
}
070701335BDB23000081A40000420C0000003200000001524010930000171F000000080000001100000000000000000000002800000000dzen2-1379930259.488ab66/gadgets/dbar.c#include "dbar.h"

void
dbardefaults(Dbar *dbar, int mode) {
	dbar->bg	= "darkgrey";
	dbar->fg	= "white";
	dbar->label	= NULL;
	dbar->sym	= '=';
	dbar->val	= 0;
	dbar->minval	= 0;
	dbar->maxval	= 100.0;
	dbar->mode	= mode ? graphical : textual;
	dbar->style	= norm;
	dbar->width	= mode ? 80 : 25;
	dbar->height	= 10;
	dbar->segw	= 6;
	dbar->segh	= 2;
	dbar->segb	= 0;
	dbar->gs	= 0;
	dbar->gw	= 1;
	dbar->gc	= 0;
	dbar->pnl	= 1;
	memset(dbar->gb, '\0', MAX_GRAPH_VALS);
}

void
fdbar(Dbar *dbar, FILE *stream) {
	int i, rp, p, t;
	int segs, segsa;
	double l, perc;

	perc = (100 * (dbar->val - dbar->minval)) / (dbar->maxval - dbar->minval);

	switch(dbar->style) {
		case outlined:
			l = perc * ((double)(dbar->width-2) / 100);
			break;
		case vertical:
			l = perc * ((double)dbar->height / 100);
			break;
		case graph:
			l = perc * ((double)dbar->height / 100);
			break;
		default:
			l = perc * ((double)dbar->width / 100);
			break;
	}

	l=(int)(l + 0.5) >= (int)l ? l+0.5 : l;
	rp=(int)(perc + 0.5) >= (int)perc ? (int)(perc + 0.5) : (int)perc;

	if(dbar->mode == textual) {
		fprintf(stream, "%s%3d%% [", dbar->label ? dbar->label : "", rp);
		for(i=0; i < (int)l; i++)
			if(i == dbar->width) {
				fputc('>', stream);
				break;
			} else
				fputc(dbar->sym, stream);
			for(; i < dbar->width; i++)
				fputc(' ', stream);
			fprintf(stream, "]%s", dbar->pnl ? "\n" : "");
	} else {
		switch(dbar->style) {
			case outlined:
				if(dbar->segb == 0) {
					fprintf(stream, "%s^ib(1)^fg(%s)^ro(%dx%d)^p(%d)^fg(%s)^r(%dx%d)^p(%d)^ib(0)^fg()%s", 
							dbar->label ? dbar->label : "",
							dbar->bg, (int)dbar->width, dbar->height, -1*(dbar->width-2),
							dbar->fg, (int)l>dbar->width-4?dbar->width-4:(int)l, dbar->height-4>0?dbar->height-4:1,
							dbar->width-(int)l-1, dbar->pnl ? "\n" : "");
				} else {
					segs  = dbar->width / (dbar->segw + dbar->segb);
					segsa = rp * segs / 100;

					fprintf(stream, "%s^ib(1)^fg(%s)^ro(%dx%d)^p(%d)", 
							dbar->label ? dbar->label : "",
							dbar->bg, (int)dbar->width, dbar->height, -1*(dbar->width-2));
					for(i=0; i < segs; i++) {
						if(i<segsa)
							fprintf(stream, "^fg(%s)^r(%dx%d+%d+%d')", dbar->fg, dbar->segw, dbar->height-4>0?dbar->height-4:1, i?dbar->segb:0, 0);
						else
							break;
					}
					printf("^fg()^ib(0)^p(%d)%s", dbar->width - i*(dbar->segw + dbar->segb), dbar->pnl ? "\n" : "");
				}
				break;

			case vertical:
				segs  = dbar->height / (dbar->segh + dbar->segb);
				segsa = rp * segs / 100;
				fprintf(stream, "%s^ib(1)", dbar->label ? dbar->label : "");
				if(dbar->segb == 0) {
					//fprintf(stream, "^fg(%s)^r(%dx%d+%d-%d)^fg(%s)^p(-%d)^r(%dx%d+%d-%d)",
					//		dbar->bg, dbar->segw, dbar->height, 0, dbar->height+1,
					//		dbar->fg, dbar->segw, dbar->segw, (int)l, 0, (int)l+1);
					fprintf(stream, "^fg(%s)^r(%dx%d)^fg(%s)^r(%dx%d-%d+%d)",
							dbar->bg, dbar->segw, dbar->height,
							dbar->fg,  
							dbar->segw, (int)l, dbar->segw, (int)((dbar->height-l)/2.0 + .5));
				} else {
					for(i=0; i < segs; i++) {
						t = dbar->height/2-(dbar->segh+dbar->segb)*i;
						//if(i<segsa)
							fprintf(stream, "^fg(%s)^r(%dx%d-%d%c%d)",
									i < segsa ? dbar->fg : dbar->bg, dbar->segw, dbar->segh, 
									i?dbar->segw:0, t > 0 ? '+' : '-', abs(t));
							//fprintf(stream, "^fg(%s)^p(-%d)^r(%dx%d+%d-%d)",
							//		dbar->fg, i?dbar->segw:0, dbar->segw,
							//		dbar->segh, 0, (dbar->segh+dbar->segb)*(i+1));
						//else
							//fprintf(stream, "^fg(%s)^r(%dx%d-%d-%d)",
							//		dbar->bg, dbar->segw,
							//		dbar->segh,i?dbar->segw:0, (dbar->segh+dbar->segb)*i);
							//fprintf(stream, "^fg(%s)^p(-%d)^r(%dx%d+%d-%d)",
							//		dbar->bg, i?dbar->segw:0, dbar->segw,
							//		dbar->segh, 0, (dbar->segh+dbar->segb)*(i+1));
					}
				}
				fprintf(stream, "^ib(0)^fg()%s", dbar->pnl ? "\n" : "");
				break;

			case graph:
				dbar->gc = dbar->gc < MAX_GRAPH_VALS && 
					(dbar->gs == 0 ? dbar->gc : dbar->gc * dbar->gs + dbar->gc * dbar->gw)
					< dbar->width ? ++dbar->gc : 0;
				dbar->gb[dbar->gc] = l;

				printf("%s", dbar->label ? dbar->label : "");
				for(i=dbar->gc+1; i<MAX_GRAPH_VALS && (i*(dbar->gs+dbar->gw)) < dbar->width; ++i) {
					p=100*dbar->gb[i]/dbar->height;
					p=(int)p+0.5 >= (int)p ? (int)(p+0.5) : (int)p;
					fprintf(stream, "^fg(%s)^p(%d)^r(%dx%d+0-%d)", 
							dbar->fg, dbar->gs, dbar->gw, (int)dbar->gb[i], (int)dbar->gb[i]+1);
				}

				for(i=0; i < dbar->gc; ++i) {
					p=100*dbar->gb[i]/dbar->height;
					p=(int)p+0.5 >= (int)p ? (int)(p+0.5) : (int)p;
					fprintf(stream, "^fg(%s)^p(%d)^r(%dx%d+0-%d)", 
							dbar->fg, dbar->gs, dbar->gw, (int)dbar->gb[i], (int)dbar->gb[i]+1); 
				}
				fprintf(stream, "^fg()%s", dbar->pnl ? "\n" : "");
				break;

			case pie:
				fprintf(stream, "^ib(1)^fg(%s)^c(%d)^p(-%d)^fg(%s)^c(%d-%d)%s",
						dbar->bg, dbar->width, dbar->width, 
						dbar->fg, dbar->width, (int)(rp*360/100),
						dbar->pnl ? "\n" : "");
				break;

			default:
				if(dbar->segb == 0)
					//printf("%s%3d%% ^fg(%s)^r(%dx%d)^fg(%s)^r(%dx%d)^fg()%s", 
					printf("%s^fg(%s)^r(%dx%d)^fg(%s)^r(%dx%d)^fg()%s", 
							dbar->label ? dbar->label : "", 
							dbar->fg, (int)l, dbar->height,
							dbar->bg, dbar->width-(int)l, dbar->height,
							dbar->pnl ? "\n" : "");
				else {
					segs  = dbar->width / (dbar->segw + dbar->segb);
					segsa = rp * segs / 100;

					//printf("%s%3d%% ", dbar->label ? dbar->label : "", rp);
					printf("%s", dbar->label ? dbar->label : "");
					for(i=0; i < segs; i++) {
						if(i<segsa)
							fprintf(stream, "^fg(%s)^r(%dx%d+%d+%d)",
									dbar->fg, dbar->segw, dbar->height, i?dbar->segb:0, 0);
						else
							fprintf(stream, "^fg(%s)^r(%dx%d+%d+%d)",
									dbar->bg, dbar->segw, dbar->height, i?dbar->segb:0, 0);
					}
					fprintf(stream, "^p(%d)^fg()%s", dbar->segb, dbar->pnl ? "\n" : "");
				}
				break;
		}
	}
	fflush(stream);
}
070701335BDB24000081A40000420C0000003200000001524010930000027C000000080000001100000000000000000000002800000000dzen2-1379930259.488ab66/gadgets/dbar.h#ifndef __DBAR_H
#define __DBAR_H

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define MAX_GRAPH_VALS 1024

typedef struct {
  const char *bg;
  const char *fg; 
  const char *label;
  char sym;
  double val;
  double minval;
  double maxval;
  int mode;
  int style;
  int width;
  int height;
  int segw;
  int segh;
  int segb;
  int gs;
  int gw;
  int gc;
  char gb[MAX_GRAPH_VALS];
  int pnl;
} Dbar; 

enum mode  { textual, graphical };
enum style { norm, outlined, vertical, graph, pie };

void fdbar(Dbar *dbar, FILE *stream);
void dbardefaults(Dbar *dbar, int mode);

#endif /* __DBAR_H */
070701335BDB25000081A40000420C000000320000000152401093000012CB000000080000001100000000000000000000002B00000000dzen2-1379930259.488ab66/gadgets/gcpubar.c/*  
	gcpubar - graphical cpu usage bar, to be used with dzen

	Copyright (C) 2007 by Robert Manea, <rob dot manea at gmail dot com>

	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	THE SOFTWARE.
	*/

#include "dbar.h"

/* critical % value, color */
#define CPUCRIT 75
#define CRITCOL "#D56F6C"
/* medium % value, color */
#define CPUMED 50
#define MEDCOL "#EBA178"

struct cpu_info {
	unsigned long long user;
	unsigned long long sys;
	unsigned long long idle;
	unsigned long long iowait;
} ncpu, ocpu;

int main(int argc, char *argv[]) {
	int i, t;
	double total;
	struct cpu_info mcpu;
	FILE *statfp;
	char buf[256], *ep;
	Dbar dbar;

	int counts = 0;
	double ival = 1.0;

	dbardefaults(&dbar, graphical);
	dbar.mode = graphical;

	for(i=1; i < argc; i++) {
		if(!strncmp(argv[i], "-i", 3)) {
			if(i+1 < argc) {
				ival = strtod(argv[i+1], &ep);
				if(*ep) {
					fprintf(stderr, "%s: '-i'  Invalid interval value\n", argv[0]);
					return EXIT_FAILURE;
				}
				else
					i++;
			}
		}
		else if(!strncmp(argv[i], "-s", 3)) {
			if(++i < argc) {
				switch(argv[i][0]) {
					case 'o':
						dbar.style = outlined;
						break;
					case 'g':
						dbar.style = graph;
						break;
					case 'v':
						dbar.style = vertical;
						break;
					case 'p':
						dbar.style = pie;
						break;
					default:
						dbar.style = norm;
						break;
				}
			}
		}
		else if(!strncmp(argv[i], "-c", 3)) {
			if(++i < argc)
				counts = atoi(argv[i]);
		}
		else if(!strncmp(argv[i], "-gs", 4)) {
			if(++i < argc)
				dbar.gs = atoi(argv[i]);
		}
		else if(!strncmp(argv[i], "-gw", 4)) {
			if(++i < argc)
				dbar.gw = atoi(argv[i]);
		}
		else if(!strncmp(argv[i], "-w", 3)) {
			if(++i < argc)
				dbar.width = atoi(argv[i]);
		}
		else if(!strncmp(argv[i], "-h", 3)) {
			if(++i < argc)
				dbar.height = atoi(argv[i]);
		}
		else if(!strncmp(argv[i], "-sw", 4)) {
			if(++i < argc)
				dbar.segw = atoi(argv[i]);
		}
		else if(!strncmp(argv[i], "-sh", 4)) {
			if(++i < argc)
				dbar.segh = atoi(argv[i]);
		}
		else if(!strncmp(argv[i], "-ss", 4)) {
			if(++i < argc)
				dbar.segb = atoi(argv[i]);
		}
		else if(!strncmp(argv[i], "-fg", 4)) {
			if(++i < argc)
				dbar.fg = argv[i];
		}
		else if(!strncmp(argv[i], "-bg", 4)) {
			if(++i < argc)
				dbar.bg = argv[i];
		}
		else if(!strncmp(argv[i], "-l", 3)) {
			if(++i < argc)
				dbar.label = argv[i];
		}
		else if(!strncmp(argv[i], "-nonl", 6)) {
			dbar.pnl = 0;
		}
		else {
			printf("usage: %s [-l <label>] [-i <interval>] [-c <count>] [-fg <color>] [-bg <color>] [-w <pixel>] [-h <pixel>] [-s <o|g|v>] [-sw <pixel>] [-sh <pixel>] [-ss <pixel>] [-gs <pixel>] [-gw <pixel>] [-nonl]\n", argv[0]);
			return EXIT_FAILURE;
		}
	}

	if(!(statfp = fopen("/proc/stat", "r"))) {
		printf("%s: error opening '/proc/stat'\n", argv[0]);
		return EXIT_FAILURE;
	}

	t = counts > 0 ? counts : 1;
	while(t) {
		rewind(statfp); 
		while(fgets(buf, sizeof buf, statfp)) {
			if(!strncmp(buf, "cpu ", 4)) {
				unsigned long long unice;
				double myload;
				/* linux >= 2.6 */
				if((sscanf(buf, "cpu %llu %llu %llu %llu %llu", 
								&ncpu.user, &unice, &ncpu.sys, &ncpu.idle, &ncpu.iowait)) < 5) {
					printf("%s: wrong field count in /proc/stat\n", argv[0]);
					return EXIT_FAILURE;
				}
				ncpu.user += unice;

				mcpu.user   = ncpu.user - ocpu.user;
				mcpu.sys = ncpu.sys - ocpu.sys;
				mcpu.idle   = ncpu.idle - ocpu.idle;
				mcpu.iowait = ncpu.iowait - ocpu.iowait;

				dbar.maxval  = mcpu.user + mcpu.sys + mcpu.idle + mcpu.iowait;
				dbar.val = mcpu.user + mcpu.sys + mcpu.iowait;

				fdbar(&dbar, stdout);
				ocpu = ncpu;
			}
		}
		if((counts > 0) && (t-1 > 0)) {
			--t;
			usleep((unsigned long)(ival * 1000000.0));
		}
		else if((counts == 0) && (t == 1))
			usleep((unsigned long)(ival * 1000000.0));
		else 
			break;
	}

	return EXIT_SUCCESS;
}
070701335BDB26000081A40000420C000000320000000152401093000008E1000000080000001100000000000000000000002900000000dzen2-1379930259.488ab66/gadgets/gdbar.c#include <stdio.h>
#include "dbar.h"

#define MAXLEN 1024

int main(int argc, char *argv[]) {
  int i, nv;
  char aval[MAXLEN], *endptr;
  Dbar dbar;

  dbardefaults(&dbar, graphical);

  for(i=1; i < argc; i++) {
    if(!strncmp(argv[i], "-w", 3)) {
      if(++i < argc)
	dbar.width = atoi(argv[i]);
    }
    else if(!strncmp(argv[i], "-h", 3)) {
      if(++i < argc)
	dbar.height = atoi(argv[i]);
    }
    else if(!strncmp(argv[i], "-sw", 4)) {
      if(++i < argc)
	dbar.segw = atoi(argv[i]);
    }
    else if(!strncmp(argv[i], "-sh", 4)) {
      if(++i < argc)
	dbar.segh = atoi(argv[i]);
    }
    else if(!strncmp(argv[i], "-ss", 4)) {
      if(++i < argc)
	dbar.segb = atoi(argv[i]);
    }
    else if(!strncmp(argv[i], "-s", 3)) {
      if(++i < argc) {
	switch(argv[i][0]) {
	case 'o':
	  dbar.style = outlined;
	  break;
	case 'v':
	  dbar.style = vertical;
	  break;
	case 'p':
	  dbar.style = pie;
	  break;
	default:
	  dbar.style = norm;
	  break;
	}
      }
    }
    else if(!strncmp(argv[i], "-fg", 4)) {
      if(++i < argc)
	dbar.fg = argv[i];
    }
    else if(!strncmp(argv[i], "-bg", 4)) {
      if(++i < argc)
	dbar.bg = argv[i];
    }
    else if(!strncmp(argv[i], "-max", 5)) {
      if(++i < argc) {
	dbar.maxval = strtod(argv[i], &endptr);
	if(*endptr) {
	  fprintf(stderr, "gdbar: '%s' incorrect number format", argv[i]);
	  return EXIT_FAILURE;
	}
      }
    }
    else if(!strncmp(argv[i], "-min", 5)) {
      if(++i < argc) {
	dbar.minval = strtod(argv[i], &endptr);
	if(*endptr) {
	  fprintf(stderr, "gdbar: '%s' incorrect number format", argv[i]);
	  return EXIT_FAILURE;
	}
      }
    }
    else if(!strncmp(argv[i], "-l", 3)) {
      if(++i < argc)
	dbar.label = argv[i];
    }
    else if(!strncmp(argv[i], "-nonl", 6)) {
      dbar.pnl = 0;
    }
    else {
      fprintf(stderr, "usage: gdbar [-s <o|v>] [-w <pixel>] [-h <pixel>] [-sw <pixel>] [-ss <pixel>] [-sw <pixel>] [-fg <color>] [-bg <color>] [-min <minvalue>] [-max <maxvalue>] [-l <string>] [-nonl] \n");
      return EXIT_FAILURE;
    }
  }

  while(fgets(aval, MAXLEN, stdin)) {
    nv = sscanf(aval, "%lf %lf %lf", &dbar.val, &dbar.minval, &dbar.maxval);
    if(nv == 2) {
      dbar.maxval = dbar.minval;
      dbar.minval = 0;
    }
    fdbar(&dbar, stdout);
  }

}
070701335BDB27000081ED0000420C0000003200000001524010930000052B000000080000001100000000000000000000003000000000dzen2-1379930259.488ab66/gadgets/kittscanner.sh#!/bin/sh
#
# (c) 2007 by Robert Manea <rob dot manea at gmail dot com>
#
# KITT Scanner for dzen - a man, a car, a dzen
#


#---[ KITT configuration ]----------------------------------------------

SCANNER_LEDS=17 
LED_SPACING=3
LED_WIDTH=25
LED_HEIGHT=10

INACTIVE_LED_COLOR=darkred
ACTIVE_LED_COLOR=red
BG=black

SLEEP=0.1

DZEN=dzen2
DZENOPTS="-bg $BG -fg $INACTIVE_LED_COLOR"

#-----------------------------------------------------------------------

DFG="^fg(${INACTIVE_LED_COLOR})"
LFG="^fg(${ACTIVE_LED_COLOR})"

RECT="^r(${LED_WIDTH}x${LED_HEIGHT})"

i=; j=1; SIGN='+'

# build a number list "1 2 ... $SCANNER_LEDS"
nr_list_leds() {
	l=1
	lnr=$1

	while [ $l -le $lnr ]; do
		NRLIST=${NRLIST}' '${l}
		l=`expr $l + 1`
	done

	echo $NRLIST
}
LED_LIST=`nr_list_leds $SCANNER_LEDS`

while :; do
    for i in $LED_LIST; do
        if [ "$i" -eq "$j" ]; then
            KBAR=${KBAR}"^p(${LED_SPACING})"${LFG}${RECT}${DFG}
        else
            KBAR=${KBAR}"^p(${LED_SPACING})"${RECT}
        fi

    done

    echo $KBAR; KBAR=
    
    if [ $SIGN = '+' ] && [ $j -ge $SCANNER_LEDS ]; then
        j=$SCANNER_LEDS
        SIGN='-'
    elif [ $SIGN = '-' ] && [ $j -eq 1 ]; then
        j=1
        SIGN='+'
    fi
        
    j=`expr $j $SIGN 1`

    sleep $SLEEP;
done | $DZEN $DZENOPTS -h `expr $LED_HEIGHT + 4`
070701335BDB28000081A40000420C00000032000000015240109300000196000000080000001100000000000000000000002F00000000dzen2-1379930259.488ab66/gadgets/noisyalert.sh#!/bin/sh
#
# (c) 2007 by Robert Manea
#
# A noisy alert for dzen
# 
# Syntax noisyalert.sh [Message] [TIMEOUT in seconds] | dzen2

ALERTMSG=${1:-"Alert"}
ALERTSEC=${2:-10}

RECTW=10
RECTH=10


while [ $ALERTSEC -ne 0 ]; do

	if [ `expr $ALERTSEC % 2` -eq 0 ]; then
		echo "^r(${RECTW}x${RECTH}) $ALERTMSG"
	else
		echo "^ro(${RECTW}x${RECTH}) $ALERTMSG"
	fi

	ALERTSEC=`expr $ALERTSEC - 1`
	sleep 1
done

070701335BDB29000081A40000420C00000032000000015240109300000BD5000000080000001100000000000000000000002D00000000dzen2-1379930259.488ab66/gadgets/textwidth.c/*
    textwidth - calculate width in pixels of text with a given font

    Copyright (C) 2007 by Robert Manea  <rob dot manea at gmail dot com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<X11/Xlib.h>

typedef struct _Fnt {
	XFontStruct *xfont;
	XFontSet set;
	int ascent;
	int descent;
	int height;
} Fnt;

Fnt font;
Display *dpy;

unsigned int
textw(const char *text, unsigned int len) {
	XRectangle r;

	if(font.set) {
		XmbTextExtents(font.set, text, len, NULL, &r);
		return r.width;
	}
	return XTextWidth(font.xfont, text, len);
}

void
setfont(const char *fontstr) {
	char *def, **missing;
	int i, n;

	missing = NULL;
	if(font.set)
		XFreeFontSet(dpy, font.set);
	font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
	if(missing)
		XFreeStringList(missing);
	if(font.set) {
		XFontSetExtents *font_extents;
		XFontStruct **xfonts;
		char **font_names;
		font.ascent = font.descent = 0;
		font_extents = XExtentsOfFontSet(font.set);
		n = XFontsOfFontSet(font.set, &xfonts, &font_names);
		for(i = 0, font.ascent = 0, font.descent = 0; i < n; i++) {
			if(font.ascent < (*xfonts)->ascent)
				font.ascent = (*xfonts)->ascent;
			if(font.descent < (*xfonts)->descent)
				font.descent = (*xfonts)->descent;
			xfonts++;
		}
	}
	else {
		if(font.xfont)
			XFreeFont(dpy, font.xfont);
		font.xfont = NULL;
		if(!(font.xfont = XLoadQueryFont(dpy, fontstr))) {
			fprintf(stderr, "error, cannot load font: '%s'\n", fontstr);
			exit(EXIT_FAILURE);
		}
		font.ascent = font.xfont->ascent;
		font.descent = font.xfont->descent;
	}
	font.height = font.ascent + font.descent;
}

int
main(int argc, char *argv[])
{
	char *myfont, *text;

	if(argc < 3) {
		fprintf(stderr, "usage: %s <font> <string>\n", argv[0]);
		return EXIT_FAILURE;
	}

	myfont = argv[1];
	text   = argv[2];

	dpy = XOpenDisplay(0);
	if(!dpy) {
		fprintf(stderr, "cannot open display\n");
		return EXIT_FAILURE;
	}

	setfont(myfont);
	printf("%u\n", textw(text, strlen(text)));

	return EXIT_SUCCESS;
}

070701335BDB2A000081ED0000420C00000032000000015240109300000253000000080000001100000000000000000000001E00000000dzen2-1379930259.488ab66/help#!/bin/sh
#
# (c) 2007, by Robert Manea

OPTS='-bg #111111 -fg grey70 -p -l 30 -e onstart=uncollapse,scrollhome;button5=scrolldown;key_Down=scrolldown;button4=scrollup;key_Up=scrollup;key_Page_Down=scrolldown:30;key_Page_Up=scrollup:30;key_Escape=exit;button3=exit;entertitle=grabkeys;enterslave=grabkeys;leaveslave=ungrabkeys'

if  test -x ./dzen2 ; then
	(echo "^fg(#323232)^bg(#5FBF77) Documentation (use: scrollwheel, arrow keys, PgUP/PgDown to scroll. Escape or right mouse button to quit) "; cat README.dzen) | ./dzen2 $OPTS
else
	echo "Please type 'make' to build dzen and rerun help"
fi
070701335BDB2B000081A40000420C0000003200000001524010930000751B000000080000001100000000000000000000002000000000dzen2-1379930259.488ab66/main.c/*
 * (C)opyright 2007-2009 Robert Manea <rob dot manea at gmail dot com>
 * See LICENSE file for license details.
 *
 */

#include "dzen.h"
#include "action.h"

#include <ctype.h>
#include <locale.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>

#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 255
#endif

Dzen dzen = {0};
static int last_cnt = 0;
typedef void sigfunc(int);

static void
clean_up(void) {
	int i;

	free_event_list();
#ifndef DZEN_XFT
	if(dzen.font.set)
		XFreeFontSet(dzen.dpy, dzen.font.set);
	else
		XFreeFont(dzen.dpy, dzen.font.xfont);
#endif

	XFreePixmap(dzen.dpy, dzen.title_win.drawable);
	if(dzen.slave_win.max_lines) {
		for(i=0; i < dzen.slave_win.max_lines; i++) {
			XFreePixmap(dzen.dpy, dzen.slave_win.drawable[i]);
			XDestroyWindow(dzen.dpy, dzen.slave_win.line[i]);
		}
		free(dzen.slave_win.line);
		XDestroyWindow(dzen.dpy, dzen.slave_win.win);
	}
	XFreeGC(dzen.dpy, dzen.gc);
	XFreeGC(dzen.dpy, dzen.rgc);
	XFreeGC(dzen.dpy, dzen.tgc);
	XDestroyWindow(dzen.dpy, dzen.title_win.win);
	XCloseDisplay(dzen.dpy);
}

static void
catch_sigusr1(int s) {
	(void)s;
	do_action(sigusr1);
}

static void
catch_sigusr2(int s) {
	(void)s;
	do_action(sigusr2);
}

static void
catch_sigterm(int s) {
	(void)s;
	do_action(onexit);
}

static void
catch_alrm(int s) {
	(void)s;
	do_action(onexit);
	clean_up();
	exit(0);
}

static sigfunc *
setup_signal(int signr, sigfunc *shandler) {
	struct sigaction nh, oh;

	nh.sa_handler = shandler;
	sigemptyset(&nh.sa_mask);
	nh.sa_flags = 0;

	if(sigaction(signr, &nh, &oh) < 0)
		return SIG_ERR;

	return NULL;
}

char *rem=NULL;
static int
chomp(char *inbuf, char *outbuf, int start, int len) {
	int i=0;
	int off=start;

	if(rem) {
		strncpy(outbuf, rem, strlen(rem));
		i += strlen(rem);
		free(rem);
		rem = NULL;
	}
	while(off < len) {
		if(i >= MAX_LINE_LEN) {
			outbuf[MAX_LINE_LEN-1] = '\0';
			return ++off;
		}
		if(inbuf[off] != '\n') {
			 outbuf[i++] = inbuf[off++];
		}
		else if(inbuf[off] == '\n') {
			outbuf[i] = '\0';
			return ++off;
		}
	}

	outbuf[i] = '\0';
	rem = estrdup(outbuf);
	return 0;
}

void
free_buffer(void) {
	int i;
	for(i=0; i<dzen.slave_win.tcnt; i++) {
		free(dzen.slave_win.tbuf[i]);
		dzen.slave_win.tbuf[i] = NULL;
	}
	dzen.slave_win.tcnt =
		dzen.slave_win.last_line_vis =
		last_cnt = 0;
}

static int
read_stdin(void) {
	char buf[MAX_LINE_LEN],
		 retbuf[MAX_LINE_LEN];
	ssize_t n, n_off=0;

	if(!(n = read(STDIN_FILENO, buf, sizeof buf))) {
		if(!dzen.ispersistent) {
			dzen.running = False;
			return -1;
		}
		else
			return -2;
	}
	else {
		while((n_off = chomp(buf, retbuf, n_off, n))) {
			if(!dzen.slave_win.ishmenu
					&& dzen.tsupdate
					&& dzen.slave_win.max_lines
					&& ((dzen.cur_line == 0) || !(dzen.cur_line % (dzen.slave_win.max_lines+1))))
				drawheader(retbuf);
			else if(!dzen.slave_win.ishmenu
					&& !dzen.tsupdate
					&& ((dzen.cur_line == 0) || !dzen.slave_win.max_lines))
				drawheader(retbuf);
			else
				drawbody(retbuf);
			dzen.cur_line++;
		}
	}
	return 0;
}

static void
x_hilight_line(int line) {
	drawtext(dzen.slave_win.tbuf[line + dzen.slave_win.first_line_vis], 1, line, dzen.slave_win.alignment);
	XCopyArea(dzen.dpy, dzen.slave_win.drawable[line], dzen.slave_win.line[line], dzen.gc,
			0, 0, dzen.slave_win.width, dzen.line_height, 0, 0);
}

static void
x_unhilight_line(int line) {
	drawtext(dzen.slave_win.tbuf[line + dzen.slave_win.first_line_vis], 0, line, dzen.slave_win.alignment);
	XCopyArea(dzen.dpy, dzen.slave_win.drawable[line], dzen.slave_win.line[line], dzen.rgc,
			0, 0, dzen.slave_win.width, dzen.line_height, 0, 0);
}

void
x_draw_body(void) {
	int i;
	dzen.x = 0;
	dzen.y = 0;
	dzen.w = dzen.slave_win.width;
	dzen.h = dzen.line_height;
	
	window_sens[SLAVEWINDOW].sens_areas_cnt = 0;

	if(!dzen.slave_win.last_line_vis) {
		if(dzen.slave_win.tcnt < dzen.slave_win.max_lines) {
			dzen.slave_win.first_line_vis = 0;
			dzen.slave_win.last_line_vis  = dzen.slave_win.tcnt;
		}
		else {
			dzen.slave_win.first_line_vis = dzen.slave_win.tcnt - dzen.slave_win.max_lines;
			dzen.slave_win.last_line_vis  = dzen.slave_win.tcnt;
		}
	}

	for(i=0; i < dzen.slave_win.max_lines; i++) {
		if(i < dzen.slave_win.last_line_vis)
			drawtext(dzen.slave_win.tbuf[i + dzen.slave_win.first_line_vis],
					0, i, dzen.slave_win.alignment);
	}
	for(i=0; i < dzen.slave_win.max_lines; i++)
		XCopyArea(dzen.dpy, dzen.slave_win.drawable[i], dzen.slave_win.line[i], dzen.gc,
				0, 0, dzen.slave_win.width, dzen.line_height, 0, 0);
}

static void
x_check_geometry(XRectangle scr) {
	TWIN *t = &dzen.title_win;
	SWIN *s = &dzen.slave_win;

	t->x = t->x < 0 ? scr.width  + t->x + scr.x : t->x + scr.x;
	t->y = t->y < 0 ? scr.height + t->y + scr.y : t->y + scr.y;

	if(t->x < scr.x || scr.x + scr.width < t->x)
		t->x = scr.x;

	if(!t->width)
		t->width = scr.width;

	if((t->x + t->width) > (scr.x + scr.width) && (t->expand != left))
		t->width = scr.width - (t->x - scr.x);

	if(t->expand == left) {
		t->x_right_corner = t->x + t->width;
		t->x = t->width ? t->x_right_corner - t->width : scr.x;
	}

	if(!s->width) {
		s->x = scr.x;
		s->width = scr.width;
	}
	if(t->width == s->width)
		s->x = t->x;

	if(s->width != scr.width) {
		s->x = t->x + (t->width - s->width)/2;
		if(s->x < scr.x)
			s->x = scr.x;
		if(s->x + s->width > scr.x + scr.width)
			s->x = scr.x + (scr.width - s->width);
	}

	if(!dzen.line_height)
		dzen.line_height = dzen.font.height + 2;

	if(t->y + dzen.line_height > scr.y + scr.height)
		t->y = scr.y + scr.height - dzen.line_height;
}

static void
qsi_no_xinerama(Display *dpy, XRectangle *rect) {
	rect->x = 0;
	rect->y = 0;
	rect->width  = DisplayWidth( dpy, DefaultScreen(dpy));
	rect->height = DisplayHeight(dpy, DefaultScreen(dpy));
}

#ifdef DZEN_XINERAMA
static void
queryscreeninfo(Display *dpy, XRectangle *rect, int screen) {
	XineramaScreenInfo *xsi = NULL;
	int nscreens = 1;

	if(XineramaIsActive(dpy))
		xsi = XineramaQueryScreens(dpy, &nscreens);

	if(xsi == NULL || screen > nscreens || screen <= 0) {
		qsi_no_xinerama(dpy, rect);
	}
	else {
		rect->x      = xsi[screen-1].x_org;
		rect->y      = xsi[screen-1].y_org;
		rect->width  = xsi[screen-1].width;
		rect->height = xsi[screen-1].height;
	}
}
#endif

static void
set_docking_ewmh_info(Display *dpy, Window w, int dock) {
	unsigned long strut[12] = { 0 };
	unsigned long strut_s[4] = { 0 };
	XWindowAttributes wa;
	Atom type;
	unsigned int desktop;
	pid_t cur_pid;
	char *host_name;
	XTextProperty txt_prop;
	XRectangle si;
#ifdef DZEN_XINERAMA
	XineramaScreenInfo *xsi;
	int screen_count,i,max_height;
#endif

	host_name = emalloc(HOST_NAME_MAX);
	if( (gethostname(host_name, HOST_NAME_MAX) > -1) &&
			(cur_pid = getpid()) ) {

		XStringListToTextProperty(&host_name, 1, &txt_prop);
		XSetWMClientMachine(dpy, w, &txt_prop);
		XFree(txt_prop.value);

		XChangeProperty(
				dpy,
				w,
				XInternAtom(dpy, "_NET_WM_PID", False),
				XInternAtom(dpy, "CARDINAL", False),
				32,
				PropModeReplace,
				(unsigned char *)&cur_pid,
				1
				);

	}
	free(host_name);


	XGetWindowAttributes(dpy, w, &wa);
#ifdef DZEN_XINERAMA
	queryscreeninfo(dpy,&si,dzen.xinescreen);
#else
	qsi_no_xinerama(dpy,&si);
#endif
	if(wa.y - si.y == 0) {
		strut[2] = si.y + wa.height;
		strut[8] = wa.x;
		strut[9] = wa.x + wa.width - 1;

		strut_s[2] = strut[2];
	}
	else if((wa.y - si.y + wa.height) == si.height) {
#ifdef DZEN_XINERAMA
		max_height = si.height;
		xsi = XineramaQueryScreens(dpy,&screen_count);
		for(i=0; i < screen_count; i++) {
			if(xsi[i].height > max_height)
				max_height = xsi[i].height;
		}
		XFree(xsi);
		/* Adjust strut value if there is a larger screen */ 
		strut[3] = max_height - (si.height + si.y) + wa.height;
#else
		strut[3] = wa.height;
#endif
		strut[10] = wa.x;
		strut[11] = wa.x + wa.width - 1;

		strut_s[3] = strut[3];
	}

	if(strut[2] != 0 || strut[3] != 0) {
		XChangeProperty(
				dpy,
				w,
				XInternAtom(dpy, "_NET_WM_STRUT_PARTIAL", False),
				XInternAtom(dpy, "CARDINAL", False),
				32,
				PropModeReplace,
				(unsigned char *)&strut,
				12
				);
		XChangeProperty(
				dpy,
				w,
				XInternAtom(dpy, "_NET_WM_STRUT", False),
				XInternAtom(dpy, "CARDINAL", False),
				32,
				PropModeReplace,
				(unsigned char *)&strut,
				4
				);
	}

	if(dock) {
		type = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
		XChangeProperty(
				dpy,
				w,
				XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False),
				XInternAtom(dpy, "ATOM", False),
				32,
				PropModeReplace,
				(unsigned char *)&type,
				1
				);

		/* some window managers honor this properties*/
		type = XInternAtom(dpy, "_NET_WM_STATE_ABOVE", False);
		XChangeProperty(
				dpy,
				w,
				XInternAtom(dpy, "_NET_WM_STATE", False),
				XInternAtom(dpy, "ATOM", False),
				32,
				PropModeReplace,
				(unsigned char *)&type,
				1
				);

		type = XInternAtom(dpy, "_NET_WM_STATE_STICKY", False);
		XChangeProperty(
				dpy,
				w,
				XInternAtom(dpy, "_NET_WM_STATE", False),
				XInternAtom(dpy, "ATOM", False),
				32,
				PropModeAppend,
				(unsigned char *)&type,
				1
				);


		desktop = 0xffffffff;
		XChangeProperty(
				dpy,
				w,
				XInternAtom(dpy, "_NET_WM_DESKTOP", False),
				XInternAtom(dpy, "CARDINAL", False),
				32,
				PropModeReplace,
				(unsigned char *)&desktop,
				1
				);
	}

}

static void
x_create_gcs(void) {
	XGCValues gcv;
	gcv.graphics_exposures = 0;

	/* normal GC */
	dzen.gc  = XCreateGC(dzen.dpy, RootWindow(dzen.dpy, dzen.screen), GCGraphicsExposures, &gcv);
	XSetForeground(dzen.dpy, dzen.gc, dzen.norm[ColFG]);
	XSetBackground(dzen.dpy, dzen.gc, dzen.norm[ColBG]);
	/* reverse color GC */
	dzen.rgc = XCreateGC(dzen.dpy, RootWindow(dzen.dpy, dzen.screen), GCGraphicsExposures, &gcv);
	XSetForeground(dzen.dpy, dzen.rgc, dzen.norm[ColBG]);
	XSetBackground(dzen.dpy, dzen.rgc, dzen.norm[ColFG]);
	/* temporary GC */
	dzen.tgc = XCreateGC(dzen.dpy, RootWindow(dzen.dpy, dzen.screen), GCGraphicsExposures, &gcv);
}

static void
x_connect(void) {
	dzen.dpy = XOpenDisplay(0);
	if(!dzen.dpy)
		eprint("dzen: cannot open display\n");
	dzen.screen = DefaultScreen(dzen.dpy);
}

/* Read display styles from X resources. */
static void
x_read_resources(void) {
	XrmDatabase xdb;
	char* xrm;
	char* datatype[20];
	XrmValue xvalue;

	XrmInitialize();
	xrm = XResourceManagerString(dzen.dpy);
	if( xrm != NULL ) {
		xdb = XrmGetStringDatabase(xrm);
		if( XrmGetResource(xdb, "dzen2.font", "*", datatype, &xvalue) == True )
			dzen.fnt = estrdup(xvalue.addr);
		if( XrmGetResource(xdb, "dzen2.foreground", "*", datatype, &xvalue) == True )
			dzen.fg  = estrdup(xvalue.addr);
		if( XrmGetResource(xdb, "dzen2.background", "*", datatype, &xvalue) == True )
			dzen.bg  = estrdup(xvalue.addr);
		if( XrmGetResource(xdb, "dzen2.titlename", "*", datatype, &xvalue) == True )
			dzen.title_win.name  = estrdup(xvalue.addr);
		if( XrmGetResource(xdb, "dzen2.slavename", "*", datatype, &xvalue) == True )
			dzen.slave_win.name  = estrdup(xvalue.addr);
		XrmDestroyDatabase(xdb);
	}
}

static void
x_create_windows(int use_ewmh_dock) {
	XSetWindowAttributes wa;
	Window root;
	int i;
	XRectangle si;
	XClassHint *class_hint;

	root = RootWindow(dzen.dpy, dzen.screen);

	/* style */
	if((dzen.norm[ColBG] = getcolor(dzen.bg)) == ~0lu)
		eprint("dzen: error, cannot allocate color '%s'\n", dzen.bg);
	if((dzen.norm[ColFG] = getcolor(dzen.fg)) == ~0lu)
		eprint("dzen: error, cannot allocate color '%s'\n", dzen.fg);
	setfont(dzen.fnt);

	x_create_gcs();

	/* window attributes */
	wa.override_redirect = (use_ewmh_dock ? 0 : 1);
	wa.background_pixmap = ParentRelative;
	wa.event_mask = ExposureMask | ButtonReleaseMask | ButtonPressMask | ButtonMotionMask | EnterWindowMask | LeaveWindowMask | KeyPressMask;

#ifdef DZEN_XINERAMA
	queryscreeninfo(dzen.dpy, &si, dzen.xinescreen);
#else
	qsi_no_xinerama(dzen.dpy, &si);
#endif
	x_check_geometry(si);

	/* title window */
	dzen.title_win.win = XCreateWindow(dzen.dpy, root,
			dzen.title_win.x, dzen.title_win.y, dzen.title_win.width, dzen.line_height, 0,
			DefaultDepth(dzen.dpy, dzen.screen), CopyFromParent,
			DefaultVisual(dzen.dpy, dzen.screen),
			CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
	/* set class property */
	class_hint = XAllocClassHint();
	class_hint->res_name  = "dzen2";
	class_hint->res_class = "dzen";
	XSetClassHint(dzen.dpy, dzen.title_win.win, class_hint);
	XFree(class_hint);

	/* title */
	XStoreName(dzen.dpy, dzen.title_win.win, dzen.title_win.name);

	dzen.title_win.drawable = XCreatePixmap(dzen.dpy, root, dzen.title_win.width,
			dzen.line_height, DefaultDepth(dzen.dpy, dzen.screen));
	XFillRectangle(dzen.dpy, dzen.title_win.drawable, dzen.rgc, 0, 0, dzen.title_win.width, dzen.line_height);

	/* set some hints for windowmanagers*/
	set_docking_ewmh_info(dzen.dpy, dzen.title_win.win, use_ewmh_dock);

	/* TODO: Smarter approach to window creation so we can reduce the
	 *       size of this function.
	 */

	if(dzen.slave_win.max_lines) {
		dzen.slave_win.first_line_vis = 0;
		dzen.slave_win.last_line_vis  = 0;
		dzen.slave_win.line     = emalloc(sizeof(Window) * dzen.slave_win.max_lines);
		dzen.slave_win.drawable =  emalloc(sizeof(Drawable) * dzen.slave_win.max_lines);

		/* horizontal menu mode */
		if(dzen.slave_win.ishmenu) {
			/* calculate width of menuentries - this is a very simple
			 * approach but works well for general cases.
			 */
			int ew = dzen.slave_win.width / dzen.slave_win.max_lines;
			int r = dzen.slave_win.width - ew * dzen.slave_win.max_lines;
			dzen.slave_win.issticky = True;
			dzen.slave_win.y = dzen.title_win.y;

			dzen.slave_win.win = XCreateWindow(dzen.dpy, root,
					dzen.slave_win.x, dzen.slave_win.y, dzen.slave_win.width, dzen.line_height, 0,
					DefaultDepth(dzen.dpy, dzen.screen), CopyFromParent,
					DefaultVisual(dzen.dpy, dzen.screen),
					CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
			XStoreName(dzen.dpy, dzen.slave_win.win, dzen.slave_win.name);

			for(i=0; i < dzen.slave_win.max_lines; i++) {
				dzen.slave_win.drawable[i] = XCreatePixmap(dzen.dpy, root, ew+r,
						dzen.line_height, DefaultDepth(dzen.dpy, dzen.screen));
			XFillRectangle(dzen.dpy, dzen.slave_win.drawable[i], dzen.rgc, 0, 0,
					ew+r, dzen.line_height);
			}


			/* windows holding the lines */
			for(i=0; i < dzen.slave_win.max_lines; i++)
				dzen.slave_win.line[i] = XCreateWindow(dzen.dpy, dzen.slave_win.win,
						i*ew, 0, (i == dzen.slave_win.max_lines-1) ? ew+r : ew, dzen.line_height, 0,
						DefaultDepth(dzen.dpy, dzen.screen), CopyFromParent,
						DefaultVisual(dzen.dpy, dzen.screen),
						CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);

			/* As we don't use the title window in this mode,
			 * we reuse its width value
			 */
			dzen.title_win.width = dzen.slave_win.width;
			dzen.slave_win.width = ew+r;
		}

		/* vertical slave window */
		else {
			dzen.slave_win.issticky = False;
			dzen.slave_win.y = dzen.title_win.y + dzen.line_height;

			if(dzen.title_win.y + dzen.line_height*dzen.slave_win.max_lines > si.y + si.height)
				dzen.slave_win.y = (dzen.title_win.y - dzen.line_height) - dzen.line_height*(dzen.slave_win.max_lines) + dzen.line_height;

			dzen.slave_win.win = XCreateWindow(dzen.dpy, root,
					dzen.slave_win.x, dzen.slave_win.y, dzen.slave_win.width, dzen.slave_win.max_lines * dzen.line_height, 0,
					DefaultDepth(dzen.dpy, dzen.screen), CopyFromParent,
					DefaultVisual(dzen.dpy, dzen.screen),
					CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
			XStoreName(dzen.dpy, dzen.slave_win.win, dzen.slave_win.name);

			for(i=0; i < dzen.slave_win.max_lines; i++) {
				dzen.slave_win.drawable[i] = XCreatePixmap(dzen.dpy, root, dzen.slave_win.width,
						dzen.line_height, DefaultDepth(dzen.dpy, dzen.screen));
				XFillRectangle(dzen.dpy, dzen.slave_win.drawable[i], dzen.rgc, 0, 0,
						dzen.slave_win.width, dzen.line_height);
			}

			/* windows holding the lines */
			for(i=0; i < dzen.slave_win.max_lines; i++)
				dzen.slave_win.line[i] = XCreateWindow(dzen.dpy, dzen.slave_win.win,
						0, i*dzen.line_height, dzen.slave_win.width, dzen.line_height, 0,
						DefaultDepth(dzen.dpy, dzen.screen), CopyFromParent,
						DefaultVisual(dzen.dpy, dzen.screen),
						CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
		}
	}

}

static void
x_map_window(Window win) {
	XMapRaised(dzen.dpy, win);
	XSync(dzen.dpy, False);
}

static void
x_redraw(Window w) {
	int i;

	if(!dzen.slave_win.ishmenu
			&& w == dzen.title_win.win)
		drawheader(NULL);
	if(!dzen.tsupdate && w == dzen.slave_win.win) {
		for(i=0; i < dzen.slave_win.max_lines; i++)
			XCopyArea(dzen.dpy, dzen.slave_win.drawable[i], dzen.slave_win.line[i], dzen.gc,
					0, 0, dzen.slave_win.width, dzen.line_height, 0, 0);
	}
	else {
		for(i=0; i < dzen.slave_win.max_lines; i++)
			if(w == dzen.slave_win.line[i]) {
				XCopyArea(dzen.dpy, dzen.slave_win.drawable[i], dzen.slave_win.line[i], dzen.gc,
						0, 0, dzen.slave_win.width, dzen.line_height, 0, 0);
			}
	}
}

static void
handle_xev(void) {
	XEvent ev;
	int i, sa_clicked=0;
	char buf[32];
	KeySym ksym;

	XNextEvent(dzen.dpy, &ev);
	switch(ev.type) {
		case Expose:
			if(ev.xexpose.count == 0)
				x_redraw(ev.xexpose.window);
			break;
		case EnterNotify:
			if(dzen.slave_win.ismenu) {
				for(i=0; i < dzen.slave_win.max_lines; i++)
					if(ev.xcrossing.window == dzen.slave_win.line[i])
						x_hilight_line(i);
			}
			if(!dzen.slave_win.ishmenu
					&& ev.xcrossing.window == dzen.title_win.win)
				do_action(entertitle);
			if(ev.xcrossing.window == dzen.slave_win.win)
				do_action(enterslave);
			break;
		case LeaveNotify:
			if(dzen.slave_win.ismenu) {
				for(i=0; i < dzen.slave_win.max_lines; i++)
					if(ev.xcrossing.window == dzen.slave_win.line[i])
						x_unhilight_line(i);
			}
			if(!dzen.slave_win.ishmenu
					&& ev.xcrossing.window == dzen.title_win.win)
				do_action(leavetitle);
			if(ev.xcrossing.window == dzen.slave_win.win) {
				do_action(leaveslave);
			}
			break;
		case ButtonRelease:
			if(dzen.slave_win.ismenu) {
				for(i=0; i < dzen.slave_win.max_lines; i++)
					if(ev.xbutton.window == dzen.slave_win.line[i])
						dzen.slave_win.sel_line = i;
			}

			/* clickable areas */
			int w_id = ev.xbutton.window == dzen.title_win.win ? 0 : 1;
			sens_w w = window_sens[w_id];
			for(i=w.sens_areas_cnt; i>=0; i--) {
				if(ev.xbutton.window == w.sens_areas[i].win &&
						ev.xbutton.button == w.sens_areas[i].button &&
						(ev.xbutton.x >=  w.sens_areas[i].start_x+xorig[w_id] &&
						ev.xbutton.x <=  w.sens_areas[i].end_x+xorig[w_id]) &&
						(ev.xbutton.y >=  w.sens_areas[i].start_y &&
						ev.xbutton.y <=  w.sens_areas[i].end_y) &&
						w.sens_areas[i].active) {
					spawn(w.sens_areas[i].cmd);
					sa_clicked++;
					break;
				}
			}
			if(!sa_clicked) {
				switch(ev.xbutton.button) {
					case Button1:
						do_action(button1);
						break;
					case Button2:
						do_action(button2);
						break;
					case Button3:
						do_action(button3);
						break;
					case Button4:
						do_action(button4);
						break;
					case Button5:
						do_action(button5);
						break;
					case Button6:
						do_action(button6);
						break;
					case Button7:
						do_action(button7);
						break;
				}
			}
			break;
		case KeyPress:
			XLookupString(&ev.xkey, buf, sizeof buf, &ksym, 0);
			do_action(ksym+keymarker);
			break;

		/* TODO: XRandR rotation and size  */
	}
}

static void
handle_newl(void) {
	XWindowAttributes wa;


	if(dzen.slave_win.max_lines && (dzen.slave_win.tcnt > last_cnt)) {
		do_action(onnewinput);

		if (XGetWindowAttributes(dzen.dpy, dzen.slave_win.win, &wa),
				wa.map_state != IsUnmapped
				/* autoscroll and redraw only if  we're
				 * currently viewing the last line of input
				 */
				&& (dzen.slave_win.last_line_vis == last_cnt)) {
			dzen.slave_win.first_line_vis = 0;
			dzen.slave_win.last_line_vis = 0;
			x_draw_body();
		}
		/* needed for a_scrollhome */
		else if(wa.map_state != IsUnmapped
				&& dzen.slave_win.last_line_vis == dzen.slave_win.max_lines)
			x_draw_body();
		/* forget state if window was unmapped */
		else if(wa.map_state == IsUnmapped || !dzen.slave_win.last_line_vis) {
			dzen.slave_win.first_line_vis = 0;
			dzen.slave_win.last_line_vis = 0;
			x_draw_body();
		}
		last_cnt = dzen.slave_win.tcnt;
	}
}

static void
event_loop(void) {
	int xfd, ret, dr=0;
	fd_set rmask;

	xfd = ConnectionNumber(dzen.dpy);
	while(dzen.running) {
		FD_ZERO(&rmask);
		FD_SET(xfd, &rmask);
		if(dr != -2)
			FD_SET(STDIN_FILENO, &rmask);

		while(XPending(dzen.dpy))
			handle_xev();

		ret = select(xfd+1, &rmask, NULL, NULL, NULL);
		if(ret) {
			if(dr != -2 && FD_ISSET(STDIN_FILENO, &rmask)) {
				if((dr = read_stdin()) == -1)
					return;
				handle_newl();
			}
			if(dr == -2 && dzen.timeout > 0) {
				/* set an alarm to kill us after the timeout */
				struct itimerval t;
				memset(&t, 0, sizeof t);
				t.it_value.tv_sec = dzen.timeout;
				t.it_value.tv_usec = 0;
				setitimer(ITIMER_REAL, &t, NULL);
			}
			if(FD_ISSET(xfd, &rmask))
				handle_xev();
		}
	}
	return;
}

static void
x_preload(const char *fontstr, int p) {
	char *def, **missing;
	int i, n;

	missing = NULL;

	dzen.fnpl[p].set = XCreateFontSet(dzen.dpy, fontstr, &missing, &n, &def);
	if(missing)
		XFreeStringList(missing);

	if(dzen.fnpl[p].set) {
		XFontSetExtents *font_extents;
		XFontStruct **xfonts;
		char **font_names;
		dzen.fnpl[p].ascent = dzen.fnpl[p].descent = 0;
		font_extents = XExtentsOfFontSet(dzen.fnpl[p].set);
		n = XFontsOfFontSet(dzen.fnpl[p].set, &xfonts, &font_names);
		for(i = 0, dzen.fnpl[p].ascent = 0, dzen.fnpl[p].descent = 0; i < n; i++) {
			if(dzen.fnpl[p].ascent < (*xfonts)->ascent)
				dzen.fnpl[p].ascent = (*xfonts)->ascent;
			if(dzen.fnpl[p].descent < (*xfonts)->descent)
				dzen.fnpl[p].descent = (*xfonts)->descent;
			xfonts++;
		}
	}
	else {
		if(dzen.fnpl[p].xfont)
			XFreeFont(dzen.dpy, dzen.fnpl[p].xfont);
		dzen.fnpl[p].xfont = NULL;
		if(!(dzen.fnpl[p].xfont = XLoadQueryFont(dzen.dpy, fontstr)))
			eprint("dzen: error, cannot load font: '%s'\n", fontstr);
		dzen.fnpl[p].ascent = dzen.fnpl[p].xfont->ascent;
		dzen.fnpl[p].descent = dzen.fnpl[p].xfont->descent;
	}
	dzen.fnpl[p].height = dzen.fnpl[p].ascent + dzen.fnpl[p].descent;
}

static void
font_preload(char *s) {
	int k = 0;
	char *buf = strtok(s,",");
	while( buf != NULL ) {
		if(k<64)
			x_preload(buf, k++);
		buf = strtok(NULL,",");
	}
}

/* Get alignment from character 'l'eft, 'r'ight and 'c'enter */
static char
alignment_from_char(char align) {
	switch(align) {
		case 'l' : return ALIGNLEFT;
		case 'r' : return ALIGNRIGHT;
		case 'c' : return ALIGNCENTER;
		default  : return ALIGNCENTER;
	}
}

static void
init_input_buffer(void) {
	if(MIN_BUF_SIZE % dzen.slave_win.max_lines)
		dzen.slave_win.tsize = MIN_BUF_SIZE + (dzen.slave_win.max_lines - (MIN_BUF_SIZE % dzen.slave_win.max_lines));
	else
		dzen.slave_win.tsize = MIN_BUF_SIZE;

	dzen.slave_win.tbuf = emalloc(dzen.slave_win.tsize * sizeof(char *));
}

int
main(int argc, char *argv[]) {
	int i, use_ewmh_dock=0;
	char *action_string = NULL;
	char *endptr, *fnpre = NULL;

	/* default values */
	dzen.title_win.name = "dzen title";
	dzen.slave_win.name = "dzen slave";
	dzen.cur_line  = 0;
	dzen.ret_val   = 0;
	dzen.title_win.x = dzen.slave_win.x = 0;
	dzen.title_win.y = 0;
	dzen.title_win.width = dzen.slave_win.width = 0;
	dzen.title_win.alignment = ALIGNCENTER;
	dzen.slave_win.alignment = ALIGNLEFT;
	dzen.fnt = FONT;
	dzen.bg  = BGCOLOR;
	dzen.fg  = FGCOLOR;
	dzen.slave_win.max_lines  = 0;
	dzen.running = True;
	dzen.xinescreen = 0;
	dzen.tsupdate = 0;
	dzen.line_height = 0;
	dzen.title_win.expand = noexpand;

	/* Connect to X server */
	x_connect();
	x_read_resources();

	/* cmdline args */
	for(i = 1; i < argc; i++)
		if(!strncmp(argv[i], "-l", 3)){
			if(++i < argc) {
				dzen.slave_win.max_lines = atoi(argv[i]);
				if(dzen.slave_win.max_lines)
					init_input_buffer();
			}
		}
		else if(!strncmp(argv[i], "-geometry", 10)) {
			if(++i < argc) {
				int t;
				int tx, ty;
				unsigned int tw, th;

				t = XParseGeometry(argv[i], &tx, &ty, &tw, &th);

				if(t & XValue)
					dzen.title_win.x = tx;
				if(t & YValue) {
					dzen.title_win.y = ty;
					if(!ty && (t & YNegative))
						/* -0 != +0 */
						dzen.title_win.y = -1;
				}
				if(t & WidthValue)
					dzen.title_win.width = (signed int) tw;
				if(t & HeightValue)
					dzen.line_height = (signed int) th;
			}
		}
		else if(!strncmp(argv[i], "-u", 3)){
			dzen.tsupdate = True;
		}
		else if(!strncmp(argv[i], "-expand", 8)){
			if(++i < argc) {
				switch(argv[i][0]){
					case 'l':
						dzen.title_win.expand = left;
						break;
					case 'c':
						dzen.title_win.expand = both;
						break;
					case 'r':
						dzen.title_win.expand = right;
						break;
					default:
						dzen.title_win.expand = noexpand;
				}
			}
		}
		else if(!strncmp(argv[i], "-p", 3)) {
			dzen.ispersistent = True;
			if (i+1 < argc) {
				dzen.timeout = strtoul(argv[i+1], &endptr, 10);
				if(*endptr)
					dzen.timeout = 0;
				else
					i++;
			}
		}
		else if(!strncmp(argv[i], "-ta", 4)) {
			if(++i < argc) dzen.title_win.alignment = alignment_from_char(argv[i][0]);
		}
		else if(!strncmp(argv[i], "-sa", 4)) {
			if(++i < argc) dzen.slave_win.alignment = alignment_from_char(argv[i][0]);
		}
		else if(!strncmp(argv[i], "-m", 3)) {
			dzen.slave_win.ismenu = True;
			if(i+1 < argc) {
				if( argv[i+1][0] == 'v') {
					++i;
					break;
				}
				dzen.slave_win.ishmenu = (argv[i+1][0] == 'h') ? ++i, True : False;
			}
		}
		else if(!strncmp(argv[i], "-fn", 4)) {
			if(++i < argc) dzen.fnt = argv[i];
		}
		else if(!strncmp(argv[i], "-e", 3)) {
			if(++i < argc) action_string = argv[i];
		}
		else if(!strncmp(argv[i], "-title-name", 12)) {
			if(++i < argc) dzen.title_win.name = argv[i];
		}
		else if(!strncmp(argv[i], "-slave-name", 12)) {
			if(++i < argc) dzen.slave_win.name = argv[i];
		}
		else if(!strncmp(argv[i], "-bg", 4)) {
			if(++i < argc) dzen.bg = argv[i];
		}
		else if(!strncmp(argv[i], "-fg", 4)) {
			if(++i < argc) dzen.fg = argv[i];
		}
		else if(!strncmp(argv[i], "-x", 3)) {
			if(++i < argc) dzen.title_win.x = dzen.slave_win.x = atoi(argv[i]);
		}
		else if(!strncmp(argv[i], "-y", 3)) {
			if(++i < argc) dzen.title_win.y = atoi(argv[i]);
		}
		else if(!strncmp(argv[i], "-w", 3)) {
			if(++i < argc) dzen.slave_win.width = atoi(argv[i]);
		}
		else if(!strncmp(argv[i], "-h", 3)) {
			if(++i < argc) dzen.line_height= atoi(argv[i]);
		}
		else if(!strncmp(argv[i], "-tw", 4)) {
			if(++i < argc) dzen.title_win.width = atoi(argv[i]);
		}
		else if(!strncmp(argv[i], "-fn-preload", 12)) {
			if(++i < argc) {
				fnpre = estrdup(argv[i]);
			}
		}
#ifdef DZEN_XINERAMA
		else if(!strncmp(argv[i], "-xs", 4)) {
			if(++i < argc) dzen.xinescreen = atoi(argv[i]);
		}
#endif
		else if(!strncmp(argv[i], "-dock", 6))
			use_ewmh_dock = 1;
		else if(!strncmp(argv[i], "-v", 3)) {
			printf("dzen-"VERSION", (C)opyright 2007-2009 Robert Manea\n");
			printf(
			"Enabled optional features: "
#ifdef DZEN_XMP
			" XPM "
#endif
#ifdef DZEN_XFT
			" XFT"
#endif
#ifdef DZEN_XINERAMA
			" XINERAMA "
#endif
			"\n"
			);
			return EXIT_SUCCESS;
		}
		else
			eprint("usage: dzen2 [-v] [-p [seconds]] [-m [v|h]] [-ta <l|c|r>] [-sa <l|c|r>]\n"
                   "             [-x <pixel>] [-y <pixel>] [-w <pixel>] [-h <pixel>] [-tw <pixel>] [-u]\n"
				   "             [-e <string>] [-l <lines>]  [-fn <font>] [-bg <color>] [-fg <color>]\n"
				   "             [-geometry <geometry string>] [-expand <left|right>] [-dock]\n"
				   "             [-title-name <string>] [-slave-name <string>]\n"
#ifdef DZEN_XINERAMA
				   "             [-xs <screen>]\n"
#endif
				  );

	if(dzen.tsupdate && !dzen.slave_win.max_lines)
		dzen.tsupdate = False;

	if(!dzen.title_win.width)
		dzen.title_win.width = dzen.slave_win.width;

	if(!setlocale(LC_ALL, "") || !XSupportsLocale())
		puts("dzen: locale not available, expect problems with fonts.\n");

	if(action_string)
		fill_ev_table(action_string);
	else {
		if(!dzen.slave_win.max_lines) {
			char edef[] = "button3=exit:13";
			fill_ev_table(edef);
		}
		else if(dzen.slave_win.ishmenu) {
			char edef[] = "enterslave=grabkeys;leaveslave=ungrabkeys;"
				"button4=scrollup;button5=scrolldown;"
				"key_Left=scrollup;key_Right=scrolldown;"
				"button1=menuexec;button3=exit:13;"
				"key_Escape=ungrabkeys,exit";
			fill_ev_table(edef);
		}
		else {
			char edef[]  = "entertitle=uncollapse,grabkeys;"
				"enterslave=grabkeys;leaveslave=collapse,ungrabkeys;"
				"button1=menuexec;button2=togglestick;button3=exit:13;"
				"button4=scrollup;button5=scrolldown;"
				"key_Up=scrollup;key_Down=scrolldown;"
				"key_Escape=ungrabkeys,exit";
			fill_ev_table(edef);
		}
	}

	if((find_event(onexit) != -1)
			&& (setup_signal(SIGTERM, catch_sigterm) == SIG_ERR))
		fprintf(stderr, "dzen: error hooking SIGTERM\n");

	if((find_event(sigusr1) != -1)
			&& (setup_signal(SIGUSR1, catch_sigusr1) == SIG_ERR))
		fprintf(stderr, "dzen: error hooking SIGUSR1\n");

	if((find_event(sigusr2) != -1)
		&& (setup_signal(SIGUSR2, catch_sigusr2) == SIG_ERR))
		fprintf(stderr, "dzen: error hooking SIGUSR2\n");

	if(setup_signal(SIGALRM, catch_alrm) == SIG_ERR)
		fprintf(stderr, "dzen: error hooking SIGALARM\n");

	if(dzen.slave_win.ishmenu &&
			!dzen.slave_win.max_lines)
		dzen.slave_win.max_lines = 1;


	x_create_windows(use_ewmh_dock);

	if(!dzen.slave_win.ishmenu)
		x_map_window(dzen.title_win.win);
	else {
		XMapRaised(dzen.dpy, dzen.slave_win.win);
		for(i=0; i < dzen.slave_win.max_lines; i++)
			XMapWindow(dzen.dpy, dzen.slave_win.line[i]);
	}

	if( fnpre != NULL )
		font_preload(fnpre);

	do_action(onstart);

	/* main loop */
	event_loop();

	do_action(onexit);
	clean_up();

	if(dzen.ret_val)
		return dzen.ret_val;

	return EXIT_SUCCESS;
}

070701335BDB2C000081A40000420C00000032000000015240109300000502000000080000001100000000000000000000002000000000dzen2-1379930259.488ab66/util.c/* 
 * (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
 * (C)opyright MMVII Robert Manea <rob dot manea  at gmail dot com>
 * See LICENSE file for license details.
 *
 */

#include "dzen.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>

#define ONEMASK ((size_t)(-1) / 0xFF)

void *
emalloc(unsigned int size) {
	void *res = malloc(size);

	if(!res)
		eprint("fatal: could not malloc() %u bytes\n", size);
	return res;
}

void
eprint(const char *errstr, ...) {
	va_list ap;

	va_start(ap, errstr);
	vfprintf(stderr, errstr, ap);
	va_end(ap);
	exit(EXIT_FAILURE);
}

char *
estrdup(const char *str) {
	void *res = strdup(str);

	if(!res)
		eprint("fatal: could not malloc() %u bytes\n", strlen(str));
	return res;
}
void
spawn(const char *arg) {
	static const char *shell = NULL;

	if(!shell && !(shell = getenv("SHELL")))
		shell = "/bin/sh";
	if(!arg)
		return;
	/* The double-fork construct avoids zombie processes and keeps the code
	* clean from stupid signal handlers. */
	if(fork() == 0) {
		if(fork() == 0) {
			setsid();
			execl(shell, shell, "-c", arg, (char *)NULL);
			fprintf(stderr, "dzen: execl '%s -c %s'", shell, arg);
			perror(" failed");
		}
		exit(0);
	}
	wait(0);
}

07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!306 blocks
openSUSE Build Service is sponsored by