[gromit: 1/13] First version of gromit.
- From: Simon Budig <simon src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gromit: 1/13] First version of gromit.
- Date: Tue, 16 Mar 2010 22:23:32 +0000 (UTC)
commit a1ff753c63f61d83d5fab3059694e4177ed85add
Author: Simon Budig <simon budig de>
Date: Mon Aug 28 12:00:00 2000 +0200
First version of gromit.
COPYING | 339 ++++++++++++++++++++++++
Makefile | 6 +
README | 85 ++++++
gromit.c | 701 +++++++++++++++++++++++++++++++++++++++++++++++++
gromitconf | 14 +
paint_cursor.xbm | 16 ++
paint_cursor_mask.xbm | 16 ++
parser.c | 107 ++++++++
parsertest | 4 +
sawfish-config | 24 ++
10 files changed, 1312 insertions(+), 0 deletions(-)
---
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..4189933
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..8ff0477
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,6 @@
+all: parser gromit
+
+gromit: gromit.c
+ gcc -o gromit gromit.c `gtk-config --libs --cflags`
+parser: parser.c
+ gcc -o parser parser.c `gtk-config --libs --cflags`
diff --git a/README b/README
new file mode 100644
index 0000000..bf5457b
--- /dev/null
+++ b/README
@@ -0,0 +1,85 @@
+Gromit
+----------
+
+Gromit (GRaphics Over MIscellaneous Things) is a small tool to make
+annotations on the screen.
+
+When making presentations of the Gimp I found myself often moving the
+mousepointer around the point of interest until hopefully everybody
+noticed it. This annoyed me, since it is a very vague way to highlight
+something. I dreamt of a small programm which allows me to simply draw
+on the screen, ignoring any window-borders.
+
+Gromit is a first implementation of this program.
+
+The main usage problem of gromit is its activation. You need a special
+command to make gromit grab the mouse, since you typically want to use
+the program you are demonstrating and highlighting something is a short
+interruption of your workflow. It should work *always*, regardless of
+the currently focused window. X11 does not have an easy way to make a
+program sensible for all events of a certain kind. You have to iterate
+over all windows and tell X that you are interested in the events of
+this window. However, this does not affect windows opened later, so you
+have to reiterate this permanently. At this point I decided to use
+another way: You can invoke gromit with various arguments to control an
+already running gromit (see below). Configure your favourite
+windowmanager to invoke these commands on your favourite
+key-combination. I included a script that reconfigures the
+sawfish-windowmanager. (If you are interested: Internally this is done
+via a special X-Selection)
+
+Gromit is pressure sensitive, if you are using properly configured
+XInput-Devices you can draw lines with different thickness. It is
+possible to erase something with the other end of the (Wacom) pen.
+
+
+Usage:
+ gromit --quit
+ will cause the main gromit process to quit (or "-q")
+ gromit --toggle
+ will toggle the grabbing of the cursor (or "-t")
+ gromit --clear
+ will clear the screen (or "-c")
+
+ If activated gromit prevents you from using other programs with the
+ mouse. You can press the button and paint on the screen. Key presses
+ will still reach the currently active window but it may be difficult
+ to change the window-focus without mouse...
+ The next "gromit --toggle" will deactivate gromit and you can use your
+ programs as usual - only the painted regions will be obscured.
+
+I included the (shell-)script "sawfish-config". If you are using the
+sawfish-windowmanager you can simply start this script. The "Pause"-Key
+will be bound to the (de)activation, the "Break"-Key (probably
+Shift+Pause) will clear the screen. If you have config-files for other
+window-managers I'd be happy to include them. Please send them to me.
+
+
+Building;
+
+Gromit is small and lightwight. It needs Gtk to build and the Makefile
+is straightforward. No need for autoconf/automake yet :-)
+Simply type "make" and copy the resulting binary to a convenient place.
+Stripping the binary can reduce its size. I just tested it on
+Linux/XFree86, reports from other platforms are welcome.
+
+
+Problems:
+
+Gromit does not have a configuration-file yet. This is definitely an
+important thing, but probably the code to handle this is bigger than the
+drawing-code. So at the moment gromit is configurable via source :-)
+
+Gromit may drastically slow down your X-Server. It makes heavily use of
+the shape extension, which is quite expensive if you paint a complex
+pattern on screen. Especially terminal-programs tend to scroll
+incredibly slow if something is painted over their window. There is
+nothing I can do about this.
+
+
+This Program is distributed under the Gnu General Public License. See
+the file COPYING for details.
+
+
+Have Fun,
+ Simon Budig <Simon Budig unix-ag org>
diff --git a/gromit.c b/gromit.c
new file mode 100644
index 0000000..07c2112
--- /dev/null
+++ b/gromit.c
@@ -0,0 +1,701 @@
+/* Gromit -- a program for painting on the screen
+ * Copyright (C) 2000 Simon Budig <Simon Budig unix-ag org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <glib.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+
+#include "paint_cursor.xbm"
+#include "paint_cursor_mask.xbm"
+
+#define GROMIT_PAINT_AREA_EVENTS ( GDK_EXPOSURE_MASK | \
+ GDK_LEAVE_NOTIFY_MASK | \
+ GDK_BUTTON_PRESS_MASK | \
+ GDK_BUTTON_MOTION_MASK \
+ /* | GDK_POINTER_MOTION_HINT_MASK */ )
+
+/* Atoms used to control Gromit */
+#define GA_CONTROL gdk_atom_intern ("Gromit/control", FALSE)
+#define GA_STATUS gdk_atom_intern ("Gromit/status", FALSE)
+#define GA_QUIT gdk_atom_intern ("Gromit/quit", FALSE)
+#define GA_ACTIVATE gdk_atom_intern ("Gromit/activate", FALSE)
+#define GA_DEACTIVATE gdk_atom_intern ("Gromit/deactivate", FALSE)
+#define GA_TOGGLE gdk_atom_intern ("Gromit/toggle", FALSE)
+#define GA_CLEAR gdk_atom_intern ("Gromit/clear", FALSE)
+
+typedef enum
+{
+ GROMIT_PEN,
+ GROMIT_ERASER,
+ GROMIT_RECOLOR
+} GromitPaintType;
+
+typedef struct
+{
+ GromitPaintType type;
+ guint width;
+ GdkColor *fg_color;
+ GdkGC *paint_gc;
+ GdkGC *shape_gc;
+} GromitPaintContext;
+
+typedef struct
+{
+ GtkWidget *win;
+ GtkWidget *area;
+ GtkWidget *panel;
+ GtkWidget *button;
+ GdkCursor *paint_cursor;
+ GdkCursor *erase_cursor;
+ GdkPixmap *pixmap;
+ GdkColormap *cm;
+ GdkColor *white;
+ GdkColor *black;
+ GdkColor *red;
+ GdkColor *blue;
+
+ GromitPaintContext *contexts[6];
+ GromitPaintContext *cur_context;
+
+ GdkBitmap *shape;
+ GdkGC *shape_gc;
+ GdkGCValues *shape_gcv;
+ GdkColor *transparent;
+ GdkColor *opaque;
+
+ gdouble lastx;
+ gdouble lasty;
+ guint32 motion_time;
+ gdouble count;
+ guint timeout_id;
+ guint modified;
+ guint delayed;
+ guint maxwidth;
+ guint width;
+ guint height;
+ guint hard_grab;
+ guint client;
+} GromitData;
+
+
+GromitPaintContext *
+gromit_paint_context_new (GdkDrawable *pixmap,
+ GdkDrawable *shape, GromitPaintType type,
+ GdkColor *fg_color, guint width)
+{
+ GromitPaintContext *context;
+ GdkGCValues shape_gcv;
+
+ context = g_malloc (sizeof (GromitPaintContext));
+
+ context->type = type;
+ context->width = width;
+ context->fg_color = fg_color;
+
+ if (type == GROMIT_ERASER)
+ context->paint_gc = NULL;
+ else {
+ /* GROMIT_PEN || GROMIT_RECOLOR */
+ context->paint_gc = gdk_gc_new (pixmap);
+ gdk_gc_set_foreground (context->paint_gc, fg_color);
+ gdk_gc_set_line_attributes (context->paint_gc, width, GDK_LINE_SOLID,
+ GDK_CAP_ROUND, GDK_JOIN_ROUND);
+ }
+
+ if (type == GROMIT_RECOLOR)
+ context->shape_gc = NULL;
+ else {
+ /* GROMIT_PEN || GROMIT_ERASER */
+ context->shape_gc = gdk_gc_new (shape);
+ gdk_gc_get_values (context->shape_gc, &shape_gcv);
+
+ if (type == GROMIT_ERASER)
+ gdk_gc_set_foreground (context->shape_gc, &(shape_gcv.foreground));
+ else
+ /* GROMIT_PEN */
+ gdk_gc_set_foreground (context->shape_gc, &(shape_gcv.background));
+ gdk_gc_set_line_attributes (context->shape_gc, width, GDK_LINE_SOLID,
+ GDK_CAP_ROUND, GDK_JOIN_ROUND);
+ }
+
+ return context;
+}
+
+
+void
+gromit_paint_context_free (GromitPaintContext *context)
+{
+ gdk_gc_unref (context->paint_gc);
+ gdk_gc_unref (context->shape_gc);
+ g_free (context);
+}
+
+
+void
+gromit_toggle_grab (GromitData *data)
+{
+ if (data->hard_grab)
+ {
+ data->hard_grab = 0;
+ /* gtk_grab_remove (gtk_grab_get_current ()); */
+ g_printerr ("Ungrabbing pointer\n");
+ gdk_pointer_ungrab (GDK_CURRENT_TIME);
+ /* gdk_pointer_grab (data->area->window, FALSE, GDK_POINTER_MOTION_MASK,
+ 0, NULL, GDK_CURRENT_TIME); */
+ } else {
+ int foo;
+ /* gtk_grab_add (data->area); */
+ g_printerr ("Grabbing pointer: ");
+ foo = gdk_pointer_grab (data->area->window, FALSE,
+ /* GDK_POINTER_MOTION_MASK | */
+ GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK,
+ 0, data->paint_cursor, GDK_CURRENT_TIME);
+ switch (foo) {
+ case Success:
+ data->hard_grab = 1;
+ g_printerr ("Success\n");
+ break;
+ case GrabNotViewable:
+ g_printerr ("GrabNotViewable\n");
+ break;
+ case AlreadyGrabbed:
+ g_printerr ("AlreadyGrabbed\n");
+ break;
+ case GrabFrozen:
+ g_printerr ("GrabFrozen\n");
+ break;
+ case GrabInvalidTime:
+ g_printerr ("GrabInvalidTime\n");
+ break;
+ default:
+ g_printerr ("Huh?\n");
+ }
+ }
+}
+
+
+void
+gromit_clear_screen (GromitData *data)
+{
+ gdk_gc_set_foreground (data->shape_gc, data->transparent);
+ gdk_draw_rectangle (data->shape, data->shape_gc, 1,
+ 0, 0, data->width, data->height);
+ gtk_widget_shape_combine_mask (data->win, data->shape, 0,0);
+}
+
+
+gint
+reshape (gpointer user_data)
+{
+ GromitData *data = (GromitData *) user_data;
+ static delay_count = 0;
+
+ if (data->modified) {
+ if (gtk_events_pending () && data->delayed < 5) {
+ data->delayed++ ;
+ } else {
+ gtk_widget_shape_combine_mask (data->win, data->shape, 0,0);
+ data->modified = 0;
+ data->delayed = 0;
+ }
+ }
+
+ return 1;
+}
+
+
+void
+gromit_draw_line (GromitData *data, gint x1, gint y1,
+ gint x2, gint y2)
+{
+ GdkRectangle rect;
+
+ rect.x = MIN (x1,x2) - data->maxwidth / 2;
+ rect.y = MIN (y1,y2) - data->maxwidth / 2;
+ rect.width = ABS (x1-x2) + data->maxwidth;
+ rect.height = ABS (y1-y2) + data->maxwidth;
+
+ if (data->cur_context->paint_gc)
+ gdk_gc_set_line_attributes (data->cur_context->paint_gc,
+ data->maxwidth,
+ GDK_LINE_SOLID, GDK_CAP_ROUND,
+ GDK_JOIN_ROUND);
+ if (data->cur_context->shape_gc)
+ gdk_gc_set_line_attributes (data->cur_context->shape_gc,
+ data->maxwidth,
+ GDK_LINE_SOLID, GDK_CAP_ROUND,
+ GDK_JOIN_ROUND);
+
+ if (data->cur_context->paint_gc)
+ gdk_draw_line (data->pixmap, data->cur_context->paint_gc,
+ x1, y1, x2, y2);
+
+ if (data->cur_context->shape_gc) {
+ gdk_draw_line (data->shape, data->cur_context->shape_gc,
+ x1, y1, x2, y2);
+ data->modified = 1;
+ }
+
+ if (data->cur_context->paint_gc)
+ gtk_widget_draw (data->area, &rect);
+
+}
+
+
+/*
+ * Event-Handlers that perform the drawing
+ */
+
+gboolean
+paint (GtkWidget *win, GdkEventButton *ev, gpointer user_data)
+{
+ GromitData *data = (GromitData *) user_data;
+
+#if 0
+ if (ev->button == 1) {
+ if (ev->state & GDK_SHIFT_MASK)
+ data->cur_context = data->contexts[1];
+ else
+ data->cur_context = data->contexts[0];
+ } else if (ev->button == 2) {
+ if (ev->state & GDK_SHIFT_MASK)
+ data->cur_context = data->contexts[3];
+ else
+ data->cur_context = data->contexts[2];
+ } else if (ev->button == 3) {
+ if (ev->state & GDK_SHIFT_MASK)
+ data->cur_context = data->contexts[5];
+ else
+ data->cur_context = data->contexts[4];
+ } else if (ev->button == 4) {
+ gromit_clear_screen (data);
+ } else if (ev->button == 5) {
+ gtk_main_quit ();
+ }
+#endif
+
+ g_printerr ("Source: %d\n", ev->source);
+ switch (ev->source) {
+ case GDK_SOURCE_MOUSE:
+ case GDK_SOURCE_CURSOR:
+ data->cur_context = data->contexts[1];
+ break;
+ case GDK_SOURCE_PEN:
+ gdk_window_set_cursor (data->win->window, data->paint_cursor);
+ data->cur_context = data->contexts[0];
+ break;
+ case GDK_SOURCE_ERASER:
+ gdk_window_set_cursor (data->win->window, data->erase_cursor);
+ data->cur_context = data->contexts[4];
+ break;
+ default:
+ data->cur_context = data->contexts[0];
+ }
+
+ gdk_window_set_background (data->area->window,
+ data->cur_context->fg_color);
+
+ data->lastx = ev->x;
+ data->lasty = ev->y;
+ data->motion_time = ev->time;
+
+ if (ev->source == GDK_SOURCE_MOUSE)
+ data->maxwidth = data->cur_context->width;
+ else
+ data->maxwidth = (CLAMP (ev->pressure * ev->pressure,0,1) *
+ (double) data->cur_context->width);
+
+ if (ev->button <= 3)
+ gromit_draw_line (data, ev->x, ev->y, ev->x, ev->y);
+
+ /* if (data->cur_context->shape_gc && !gtk_events_pending ())
+ gtk_widget_shape_combine_mask (data->win, data->shape, 0,0); */
+
+ return 1;
+}
+
+
+gboolean
+paintto (GtkWidget *win, GdkEventMotion *ev, gpointer user_data)
+{
+ GromitData *data = (GromitData *) user_data;
+ GdkTimeCoord *coords;
+ int nevents;
+ int i;
+
+ coords = gdk_input_motion_events (ev->window, ev->deviceid,
+ data->motion_time, ev->time, &nevents);
+ // g_printerr ("Got %d coords\n", nevents);
+ if (coords)
+ {
+ for (i=0; i<nevents; i++) {
+ if (ev->source == GDK_SOURCE_MOUSE)
+ data->maxwidth = data->cur_context->width;
+ else
+ data->maxwidth = (CLAMP (coords[i].pressure*coords[i].pressure,0,1)*
+ (double) data->cur_context->width);
+ gromit_draw_line (data, data->lastx, data->lasty,
+ coords[i].x, coords[i].y);
+ data->lastx = coords[i].x;
+ data->lasty = coords[i].y;
+ }
+ data->motion_time = coords[nevents-1].time;
+ g_free (coords);
+ } else {
+ if (ev->is_hint) {
+ g_printerr ("Hint\n");
+ gdk_input_window_get_pointer (ev->window, ev->deviceid,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ }
+ if (ev->source == GDK_SOURCE_MOUSE)
+ data->maxwidth = data->cur_context->width;
+ else
+ data->maxwidth = (CLAMP (ev->pressure * ev->pressure,0,1) *
+ (double) data->cur_context->width);
+ gromit_draw_line (data, data->lastx, data->lasty, ev->x, ev->y);
+ data->lastx = ev->x;
+ data->lasty = ev->y;
+ }
+
+ data->lastx=ev->x;
+ data->lasty=ev->y;
+
+ return 0;
+}
+
+
+/*
+ * Functions for handling various (GTK+)-Events
+ */
+
+void
+quiet_print_handler (const gchar *string)
+{
+ return;
+}
+
+
+guint
+event_key_snoop (GtkWidget *grab_widget,
+ GdkEventKey *event,
+ gpointer func_data)
+{
+ g_printerr ("Got Key!\n");
+ return 0;
+}
+
+
+gboolean
+event_configure (GtkWidget *widget,
+ GdkEventExpose *event,
+ gpointer user_data)
+{
+ GromitData *data = (GromitData *) user_data;
+
+ data->pixmap = gdk_pixmap_new (data->area->window, data->width,
+ data->height, -1);
+ gdk_draw_rectangle (data->pixmap, data->area->style->black_gc,
+ 1, 0, 0, data->width, data->height);
+ gdk_window_set_transient_for (data->area->window, data->win->window);
+
+ return 1;
+}
+
+
+gboolean
+event_expose (GtkWidget *widget,
+ GdkEventExpose *event,
+ gpointer user_data)
+{
+ GromitData *data = (GromitData *) user_data;
+
+ gdk_draw_pixmap (data->area->window,
+ data->area->style->fg_gc[GTK_WIDGET_STATE (data->area)],
+ data->pixmap, event->area.x, event->area.y,
+ event->area.x, event->area.y, event->area.width,
+ event->area.height);
+ return 0;
+}
+
+
+/* Remote control */
+
+void
+event_selection_get (GtkWidget *widget,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ gpointer data)
+{
+ gchar *uri = "OK";
+
+ if (selection_data->target == GA_TOGGLE)
+ gromit_toggle_grab (data);
+ else if (selection_data->target == GA_CLEAR)
+ gromit_clear_screen (data);
+ else if (selection_data->target == GA_QUIT)
+ gtk_main_quit ();
+ else
+ uri = "NOK";
+
+ gtk_selection_data_set (selection_data,
+ selection_data->target,
+ 8, uri, strlen (uri));
+}
+
+
+void
+event_selection_received (GtkWidget *widget,
+ GtkSelectionData *selection_data,
+ guint time,
+ gpointer user_data)
+{
+ GromitData *data = (GromitData *) user_data;
+
+ /* If someone has a selection for us, Gromit is already running. */
+
+ if (selection_data->type == GDK_NONE)
+ data->client = 0;
+ else
+ data->client = 1;
+
+ gtk_main_quit ();
+}
+
+
+/*
+ * Functions for setting up (parts of) the application
+ */
+
+void
+setup_input_devices ()
+{
+ GList *tmp_list;
+
+ tmp_list = gdk_input_list_devices ();
+ while (tmp_list)
+ {
+ GdkDeviceInfo *info = (GdkDeviceInfo *) tmp_list->data;
+ if (strstr (info->name, "raser")) /* Guess "Eraser"-Type devices */
+ gdk_input_set_source (info->deviceid, GDK_SOURCE_ERASER);
+ g_printerr ("Enabling No. %d: \"%s\" (Type: %d)\n",
+ info->deviceid, info->name, info->source);
+ gdk_input_set_mode (info->deviceid, GDK_MODE_SCREEN);
+ tmp_list = tmp_list->next;
+ }
+}
+
+
+void
+setup_client_app (GromitData *data)
+{
+ data->width = gdk_screen_width ();
+ data->height = gdk_screen_height ();
+ data->count = 0;
+ data->hard_grab = 0;
+
+ data->win = gtk_window_new (GTK_WINDOW_POPUP);
+ gtk_widget_set_usize (GTK_WIDGET (data->win), data->width, data->height);
+ gtk_widget_set_uposition (GTK_WIDGET (data->win), 0, 0);
+
+ gtk_signal_connect (GTK_OBJECT (data->win), "delete-event",
+ GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
+ gtk_signal_connect (GTK_OBJECT (data->win), "destroy",
+ GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
+ gtk_signal_connect (GTK_OBJECT (data->win), "motion_notify_event",
+ GTK_SIGNAL_FUNC (paintto), (gpointer) data);
+ gtk_signal_connect (GTK_OBJECT (data->win), "button_press_event",
+ GTK_SIGNAL_FUNC (paint), (gpointer) data);
+ gtk_signal_connect (GTK_OBJECT (data->win), "selection_get",
+ GTK_SIGNAL_FUNC (event_selection_get), (gpointer) data);
+ gtk_signal_connect (GTK_OBJECT (data->win), "selection_received",
+ GTK_SIGNAL_FUNC (event_selection_received),
+ (gpointer) data);
+}
+
+
+void
+setup_main_app (GromitData *data)
+{
+ GdkPixmap *cursor_src, *cursor_mask;
+
+ /* COLORMAP */
+ data->cm = gdk_colormap_get_system ();
+ data->white = g_malloc (sizeof (GdkColor));
+ data->black = g_malloc (sizeof (GdkColor));
+ data->red = g_malloc (sizeof (GdkColor));
+ data->blue = g_malloc (sizeof (GdkColor));
+ gdk_color_white (data->cm, data->white);
+ gdk_color_black (data->cm, data->black);
+ gdk_color_parse ("#FF0000", data->red);
+ gdk_colormap_alloc_color (data->cm, data->red, 0, 1);
+ gdk_color_parse ("#2266FF", data->blue);
+ gdk_colormap_alloc_color (data->cm, data->blue, 0, 1);
+
+ /* CURSORS */
+ cursor_src = gdk_bitmap_create_from_data (NULL, paint_cursor_bits,
+ paint_cursor_width,
+ paint_cursor_height);
+ cursor_mask = gdk_bitmap_create_from_data (NULL, paint_cursor_mask_bits,
+ paint_cursor_width,
+ paint_cursor_height);
+ data->paint_cursor = gdk_cursor_new_from_pixmap (cursor_src, cursor_mask,
+ data->white, data->black,
+ paint_cursor_x_hot,
+ paint_cursor_y_hot);
+ gdk_pixmap_unref (cursor_src);
+ gdk_pixmap_unref (cursor_mask);
+
+ /* data->paint_cursor = gdk_cursor_new (GDK_PLUS); */
+ data->erase_cursor = gdk_cursor_new (GDK_RTL_LOGO);
+
+ /* SHAPE PIXMAP */
+ data->shape = gdk_pixmap_new (NULL, data->width, data->height, 1);
+ data->shape_gc = gdk_gc_new (data->shape);
+ data->shape_gcv = g_malloc (sizeof (GdkGCValues));
+ gdk_gc_get_values (data->shape_gc, data->shape_gcv);
+ data->transparent = gdk_color_copy (&(data->shape_gcv->foreground));
+ data->opaque = gdk_color_copy (&(data->shape_gcv->background));
+ gdk_gc_set_foreground (data->shape_gc, data->transparent);
+ gdk_draw_rectangle (data->shape, data->shape_gc,
+ 1, 0, 0, data->width, data->height);
+
+ /* DRAWING AREA */
+ data->area = gtk_drawing_area_new ();
+ gtk_drawing_area_size (GTK_DRAWING_AREA (data->area),
+ data->width, data->height);
+
+ gtk_widget_set_events (data->area, GROMIT_PAINT_AREA_EVENTS);
+ gtk_widget_set_extension_events (data->area, GDK_EXTENSION_EVENTS_CURSOR);
+ gtk_signal_connect (GTK_OBJECT (data->area), "expose_event",
+ (GtkSignalFunc) event_expose, (gpointer) data);
+ gtk_signal_connect (GTK_OBJECT (data->area),"configure_event",
+ (GtkSignalFunc) event_configure, (gpointer) data);
+
+ gtk_container_add (GTK_CONTAINER (data->win), data->area);
+
+ gtk_widget_shape_combine_mask (data->win, data->shape, 0,0);
+
+ gtk_widget_show_all (data->win);
+
+ data->timeout_id = gtk_timeout_add (20, reshape, data);
+ data->modified = 0;
+
+ data->contexts[0] = gromit_paint_context_new (data->pixmap, data->shape,
+ GROMIT_PEN, data->red, 7);
+ data->contexts[1] = gromit_paint_context_new (data->pixmap, data->shape,
+ GROMIT_PEN, data->blue, 7);
+ data->contexts[2] = gromit_paint_context_new (data->pixmap, data->shape,
+ GROMIT_RECOLOR, data->red,
+ 10);
+ data->contexts[3] = gromit_paint_context_new (data->pixmap, data->shape,
+ GROMIT_RECOLOR, data->blue,
+ 10);
+ data->contexts[4] = gromit_paint_context_new (data->pixmap, data->shape,
+ GROMIT_ERASER, data->white,
+ 150);
+ data->contexts[5] = gromit_paint_context_new (data->pixmap, data->shape,
+ GROMIT_ERASER, data->white,
+ 50);
+
+ gtk_key_snooper_install ((GtkKeySnoopFunc) event_key_snoop, NULL);
+
+ gtk_selection_owner_set (data->win, GA_CONTROL, GDK_CURRENT_TIME);
+
+ gtk_selection_add_target (data->win, GA_CONTROL, GA_STATUS, 0);
+ gtk_selection_add_target (data->win, GA_CONTROL, GA_QUIT, 1);
+ gtk_selection_add_target (data->win, GA_CONTROL, GA_ACTIVATE, 2);
+ gtk_selection_add_target (data->win, GA_CONTROL, GA_DEACTIVATE, 3);
+ gtk_selection_add_target (data->win, GA_CONTROL, GA_TOGGLE, 4);
+ gtk_selection_add_target (data->win, GA_CONTROL, GA_CLEAR, 5);
+
+ setup_input_devices ();
+}
+
+
+/*
+ * Main programs
+ */
+
+int
+main_client (int argc, char **argv, GromitData *data)
+{
+ GdkAtom action = GDK_NONE;
+ gint i;
+ gchar *arg;
+
+ for (i=1; i < argc ; i++)
+ {
+ arg = argv[i];
+ action = GDK_NONE;
+ if (strcmp (arg, "-t") == 0 ||
+ strcmp (arg, "--toggle") == 0)
+ action = GA_TOGGLE;
+ else if (strcmp (arg, "-q") == 0 ||
+ strcmp (arg, "--quit") == 0)
+ action = GA_QUIT;
+ else if (strcmp (arg, "-c") == 0 ||
+ strcmp (arg, "--clear") == 0)
+ action = GA_CLEAR;
+
+ if (action != GDK_NONE)
+ {
+ gtk_selection_convert (data->win, GA_CONTROL,
+ action, GDK_CURRENT_TIME);
+ gtk_main (); /* Wait for the response */
+ }
+ }
+
+ return 0;
+}
+
+int
+main (int argc, char **argv)
+{
+ GromitData *data;
+
+ data = g_malloc (sizeof (GromitData));
+ gtk_init (&argc, &argv);
+
+ /* g_set_printerr_handler (quiet_print_handler); */
+
+ setup_client_app (data);
+
+ /* Try to get a status message. If there is a response gromit
+ * is already acive.
+ */
+
+ gtk_selection_convert (data->win, GA_CONTROL, GA_STATUS,
+ GDK_CURRENT_TIME);
+ gtk_main (); /* Wait for the response */
+
+ if (data->client)
+ return main_client (argc, argv, data);
+
+ /* Main application */
+ setup_main_app (data);
+ gtk_main ();
+ gdk_pointer_ungrab (GDK_CURRENT_TIME);
+ gdk_cursor_destroy (data->paint_cursor);
+ gdk_cursor_destroy (data->erase_cursor);
+ g_free (data);
+ return 0;
+}
+
+/* vim: sw=3 ts=8 cindent noai bs=2 cinoptions=(0 */
diff --git a/gromitconf b/gromitconf
new file mode 100644
index 0000000..fd514c8
--- /dev/null
+++ b/gromitconf
@@ -0,0 +1,14 @@
+# Configuration file for gromit
+
+# Tools
+
+"roter Stift" = PEN ( size = 12, color = "red" )
+"Radierer" = Eraser ( size = 50 )
+
+"Pen1" = "roter Stift"
+
+"Pen1"[SHIFT,CTRL] = "Radierer"
+"Pen1"[SHIFT+CTRL] = PEN ( SIZE=30, color="red" )
+"Eraser" = ERASER ( color="#0000ff", siZE=50 )
+"Mouse" = NULL
+
diff --git a/paint_cursor.xbm b/paint_cursor.xbm
new file mode 100644
index 0000000..fe19815
--- /dev/null
+++ b/paint_cursor.xbm
@@ -0,0 +1,16 @@
+#define paint_cursor_width 31
+#define paint_cursor_height 31
+#define paint_cursor_x_hot 14
+#define paint_cursor_y_hot 14
+static unsigned char paint_cursor_bits[] = {
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0xf0, 0x1f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00};
diff --git a/paint_cursor_mask.xbm b/paint_cursor_mask.xbm
new file mode 100644
index 0000000..98c092f
--- /dev/null
+++ b/paint_cursor_mask.xbm
@@ -0,0 +1,16 @@
+#define paint_cursor_mask_width 31
+#define paint_cursor_mask_height 31
+#define paint_cursor_mask_x_hot 14
+#define paint_cursor_mask_y_hot 14
+static unsigned char paint_cursor_mask_bits[] = {
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00,
+ 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00,
+ 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0xf0, 0x1f,
+ 0xfe, 0x03, 0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00,
+ 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00,
+ 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00};
diff --git a/parser.c b/parser.c
new file mode 100644
index 0000000..d50370a
--- /dev/null
+++ b/parser.c
@@ -0,0 +1,107 @@
+#include <glib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#undef DEBUG
+
+gint main (void) {
+ GScanner *scanner;
+ GTokenType token;
+ int file;
+
+ scanner = g_scanner_new (NULL);
+ scanner->config->case_sensitive = 0;
+ scanner->config->scan_octal = 0;
+ scanner->config->identifier_2_string = 1;
+ scanner->config->char_2_token = 1;
+ scanner->config->numbers_2_int = 1;
+ scanner->config->int_2_float = 1;
+
+ g_scanner_scope_add_symbol (scanner, 1, "size", NULL);
+ g_scanner_scope_add_symbol (scanner, 1, "color", NULL);
+ g_scanner_scope_add_symbol (scanner, 0, "PEN", NULL);
+ g_scanner_scope_add_symbol (scanner, 0, "RECOLOR", NULL);
+ g_scanner_scope_add_symbol (scanner, 0, "ERASER", NULL);
+
+ g_scanner_set_scope (scanner, 1);
+ scanner->config->scope_0_fallback = 1;
+
+ file = open ("./gromitconf", O_RDONLY);
+ g_scanner_input_file (scanner, file);
+
+ while ((token = g_scanner_get_next_token (scanner)) != G_TOKEN_EOF) {
+ switch (token) {
+ case G_TOKEN_LEFT_PAREN:
+ printf (" (\n"); break;
+ case G_TOKEN_RIGHT_PAREN:
+ printf (" )\n"); break;
+ case G_TOKEN_LEFT_BRACE:
+ printf (" [\n"); break;
+ case G_TOKEN_RIGHT_BRACE:
+ printf (" ]\n"); break;
+ case G_TOKEN_EQUAL_SIGN:
+ printf (" =\n"); break;
+ case G_TOKEN_COMMA:
+ printf (" ,\n"); break;
+
+ case G_TOKEN_INT:
+ printf ("Integer: %d\n", scanner->value.v_int); break;
+ case G_TOKEN_FLOAT:
+ printf ("Float : %f\n", scanner->value.v_float); break;
+
+ case G_TOKEN_STRING:
+ printf ("String : %s\n", scanner->value.v_string); break;
+
+ case G_TOKEN_IDENTIFIER:
+ case G_TOKEN_IDENTIFIER_NULL:
+ printf ("Ident : %s\n", scanner->value.v_identifier); break;
+
+ case G_TOKEN_SYMBOL:
+ printf (" SYMBOL!\n"); break;
+
+ case G_TOKEN_CHAR:
+ printf ("Char : %c\n", scanner->value.v_char); break;
+
+ case G_TOKEN_ERROR:
+ printf ("*** Error!\n"); break;
+
+#ifdef DEBUG
+ case G_TOKEN_LAST:
+ printf ("G_TOKEN_LAST\n"); break;
+
+ case G_TOKEN_LEFT_CURLY:
+ printf ("G_TOKEN_LEFT_CURLY\n"); break;
+ case G_TOKEN_RIGHT_CURLY:
+ printf ("G_TOKEN_RIGHT_CURLY\n"); break;
+ case G_TOKEN_LEFT_BRACE:
+ printf ("G_TOKEN_LEFT_BRACE\n"); break;
+ case G_TOKEN_RIGHT_BRACE:
+ printf ("G_TOKEN_RIGHT_BRACE\n"); break;
+ case G_TOKEN_NONE:
+ printf ("G_TOKEN_NONE\n"); break;
+ case G_TOKEN_BINARY:
+ printf ("G_TOKEN_BINARY\n"); break;
+ case G_TOKEN_OCTAL:
+ printf ("G_TOKEN_OCTAL\n"); break;
+ case G_TOKEN_HEX:
+ printf ("G_TOKEN_HEX\n"); break;
+ case G_TOKEN_COMMENT_SINGLE:
+ printf ("G_TOKEN_COMMENT_SINGLE\n"); break;
+ case G_TOKEN_COMMENT_MULTI:
+ printf ("G_TOKEN_COMMENT_MULTI\n"); break;
+ case G_TOKEN_EOF:
+ printf ("G_TOKEN_EOF\n"); break;
+
+#endif
+ default:
+ printf ("Unknown Token: %d, '%s'!\n", scanner->token, scanner->value);
+
+ }
+ }
+ close (file);
+ g_scanner_destroy (scanner);
+}
+
+
diff --git a/parsertest b/parsertest
new file mode 100644
index 0000000..0fe03d5
--- /dev/null
+++ b/parsertest
@@ -0,0 +1,4 @@
+(Hallo /* C-Style Comment */ Welt)
+# This line is uninteresting!
+("Hallo Welt")
+(1 2 'nochn string' 00100101 3 1.2 0xa7, 012 12 "#ffaa99" )
diff --git a/sawfish-config b/sawfish-config
new file mode 100755
index 0000000..8d6a55d
--- /dev/null
+++ b/sawfish-config
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+sawfish-client -- >/dev/null <<ENDOFSAWFISHCONFIG
+
+(defun gromit-toggle-grab ()
+ (interactive)
+ (ungrab-pointer)
+ (ungrab-keyboard)
+ (sync-server)
+ (system "/home/simon/src/gromit/gromit --toggle &")
+)
+
+(defun gromit-clear-screen ()
+ (interactive)
+ (ungrab-pointer)
+ (ungrab-keyboard)
+ (sync-server)
+ (system "/home/simon/src/gromit/gromit --clear &")
+)
+
+(bind-keys global-keymap "Pause" 'gromit-toggle-grab)
+(bind-keys global-keymap "Break" 'gromit-clear-screen)
+
+ENDOFSAWFISHCONFIG
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]