[Xfce4-commits] <mousepad:master> * Import my Mousepad rewrite
Nick Schermer
noreply at xfce.org
Sat May 5 21:30:02 CEST 2012
Updating branch refs/heads/master
to 8a402ec2206b15649d4bc1a50621d3a52f11dd2b (commit)
from 1bd002d711d108435b12b0cf7aa694b908cd63ed (commit)
commit 8a402ec2206b15649d4bc1a50621d3a52f11dd2b
Author: Nick Schermer <nick at xfce.org>
Date: Tue Feb 27 17:02:14 2007 +0000
* Import my Mousepad rewrite
(Old svn revision: 25036)
AUTHORS | 3 +
COPYING | 340 ++++++++
INSTALL | 231 +++++
Makefile.am | 40 +
Mousepad.desktop.in.in | 13 +
NEWS | 29 +
TODO | 27 +
autogen.sh | 37 +
configure.in.in | 238 +++++
icons/16x16/Makefile.am | 10 +
icons/16x16/Mousepad.png | Bin 0 -> 574 bytes
icons/24x24/Makefile.am | 10 +
icons/24x24/Mousepad.png | Bin 0 -> 972 bytes
icons/Makefile.am | 21 +
icons/scalable/Makefile.am | 10 +
icons/scalable/Mousepad.svg | 552 ++++++++++++
mousepad/Makefile.am | 93 ++
mousepad/main.c | 182 ++++
mousepad/mousepad-application.c | 239 +++++
mousepad/mousepad-application.h | 52 ++
mousepad/mousepad-dbus-infos.xml | 15 +
mousepad/mousepad-dbus.c | 247 ++++++
mousepad/mousepad-dbus.h | 44 +
mousepad/mousepad-file.c | 331 +++++++
mousepad/mousepad-file.h | 46 +
mousepad/mousepad-preferences.c | 544 ++++++++++++
mousepad/mousepad-preferences.h | 43 +
mousepad/mousepad-private.h | 75 ++
mousepad/mousepad-screen.c | 607 +++++++++++++
mousepad/mousepad-screen.h | 67 ++
mousepad/mousepad-tab-label.c | 265 ++++++
mousepad/mousepad-tab-label.h | 41 +
mousepad/mousepad-view.c | 554 ++++++++++++
mousepad/mousepad-view.h | 45 +
mousepad/mousepad-window-ui.xml | 65 ++
mousepad/mousepad-window.c | 1779 ++++++++++++++++++++++++++++++++++++++
mousepad/mousepad-window.h | 48 +
po/LINGUAS | 1 +
po/Mousepad.pot | 225 +++++
po/POTFILES.in | 6 +
40 files changed, 7175 insertions(+), 0 deletions(-)
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..e39278b
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,3 @@
+Erik Harrison <erikharrison at xfce.org>
+Nick Schermer <nick at xfce.org>
+Benedikt Meurer <benny at xfce.org>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..d60c31a
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
+
+ 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) <year> <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-1307 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) year 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/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e69de29
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..095b1eb
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,231 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004 Free
+Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about. Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory. After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+Installation Names
+==================
+
+By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PREFIX'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PREFIX', the package will
+use PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+will cause the specified gcc to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+ Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..039c6a0
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,40 @@
+# $Id$
+
+SUBDIRS = \
+ icons \
+ mousepad \
+ po
+
+distclean-local:
+ rm -rf *.spec *.cache *~
+
+rpm: dist
+ rpmbuild -ta $(PACKAGE)-$(VERSION).tar.gz
+ @rm -f $(PACKAGE)-$(VERSION).tar.gz
+
+desktopdir = $(datadir)/applications
+desktop_in_in_files = \
+ Mousepad.desktop.in.in
+desktop_in_files = $(desktop_in_in_files:.desktop.in.in=.desktop.in)
+%.desktop.in: %.desktop.in.in
+ sed -e "s,\@libexecdir\@,$(libexecdir),g" < $< > $@
+desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
+ at INTLTOOL_DESKTOP_RULE@
+
+EXTRA_DIST = \
+ intltool-extract.in \
+ intltool-merge.in \
+ intltool-update.in \
+ $(desktop_in_in_files)
+
+DISTCLEANFILES = \
+ intltool-extract \
+ intltool-merge \
+ intltool-update \
+ $(desktop_in_files) \
+ $(desktop_DATA)
+
+DISTCHECK_CONFIGURE_FLAGS = \
+ --enable-gtk-doc
+
+# vi:set ts=8 sw=8 noet ai nocindent syntax=automake:
diff --git a/Mousepad.desktop.in.in b/Mousepad.desktop.in.in
new file mode 100644
index 0000000..875f1b7
--- /dev/null
+++ b/Mousepad.desktop.in.in
@@ -0,0 +1,13 @@
+
+[Desktop Entry]
+Encoding=UTF-8
+_Name=Mousepad
+_Comment=Simple Text Editor
+_GenericName=Text Editor
+Exec=Mousepad %F
+Icon=Mousepad
+Terminal=false
+StartupNotify=true
+Type=Application
+Categories=Application;Office;
+
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..4109058
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,29 @@
+Mousepad 0.3.x
+==============
+New core features:
+ - Everything is written in GObjects.
+ - Run multiple windows in one instance.
+ - Tab support.
+ - Loading multiple files at once (in new tabs). Both multiple
+ select in the open dialog and by using the command line is supported.
+ - Hidden settings
+ - Set the recent menu limit.
+ - Support for editable menu accelerators.
+ - Using MMAP for loading files.
+ - Items in the recent menu are removed when Mousepad was unable
+ to open it.
+
+
+Bug that can be closed:
+ 2941 - Save button is now default response in the dialog.
+ 2720 - No font is set as long the user doesn't defined any.
+ 1697 - No compiler warnings.
+ 2945 - Windows geometry is now properly saved.
+ 2896 - Hidden option to show to full path in the window title.
+ 2397 - Basic command line options.
+ 2786 - The MousepadPreferences object uses XfceRc for saving the settings.
+ 2784 - No crashes when there is no rc file.
+
+Bug that won't be fixed:
+ 956 - Xfce About dialog. This allows us to depend on libxfcegui4 for one
+ dialog, so we're going to do that and use the Gtk about dialog.
diff --git a/README b/README
new file mode 100644
index 0000000..e69de29
diff --git a/THANKS b/THANKS
new file mode 100644
index 0000000..e69de29
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..a6464bb
--- /dev/null
+++ b/TODO
@@ -0,0 +1,27 @@
+- Interface
+ - Implement the Go menu and acceleartors.
+ - Dialog when closing multiple (modified) tabs.
+ - Statusbar (not a priority).
+ - Right-click menu for the tab label.
+ - Credits dialog.
+ - Change tabs position.
+
+- Text View
+ - Search and Replace. Maybe also text highlighting.
+ - GObject for undo/redo that is used by MousepadView.
+ - Support for encoding.
+
+- Saving and loading
+ - Save All option.
+ - Reload option. Maybe also stat the source file when switching
+ tabs and tell the user if the source was modified.
+
+- Other
+ - Implement Gtk print support.
+ - Maybe add support for gtksourceview and/or gtkspell.
+
+- Testing
+ - Profiling the startup time.
+ - Profiling loading large files (Gtk has a problem here). This also
+ locks some dialogs.
+ - Checking for memory leaks.
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..ef7bfb2
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# $Id$
+#
+# Copyright (c) 2007
+# The Xfce development team. All rights reserved.
+#
+
+(type xdt-autogen) >/dev/null 2>&1 || {
+ cat >&2 <<EOF
+autogen.sh: You don't seem to have the Xfce development tools installed on
+ your system, which are required to build this software.
+ Please install the xfce4-dev-tools package first, it is available
+ from http://www.xfce.org/.
+EOF
+ exit 1
+}
+
+# verify that po/LINGUAS is present
+(test -f po/LINGUAS) >/dev/null 2>&1 || {
+ cat >&2 <<EOF
+autogen.sh: The file po/LINGUAS could not be found. Please check your snapshot
+ or try to checkout again.
+EOF
+ exit 1
+}
+
+# substitute
+linguas=`sed -e '/^#/d' po/LINGUAS`
+revision=`LC_ALL=C svn info | awk '/^Revision: / {printf "%d\n", $2}'`
+sed -e "s/@LINGUAS@/${linguas}/g" \
+ -e "s/@REVISION@/${revision}/g" \
+ < "configure.in.in" > "configure.in"
+
+exec xdt-autogen $@
+
+# vi:set ts=2 sw=2 et ai:
diff --git a/configure.in.in b/configure.in.in
new file mode 100644
index 0000000..6cbd2a5
--- /dev/null
+++ b/configure.in.in
@@ -0,0 +1,238 @@
+dnl $Id$
+dnl
+dnl Copyright (c) 2007
+dnl The Xfce development team. All rights reserved.
+dnl
+
+dnl ***************************
+dnl *** Version information ***
+dnl ***************************
+m4_define([mousepad_version_major], [0])
+m4_define([mousepad_version_minor], [3])
+m4_define([mousepad_version_micro], [0])
+m4_define([mousepad_version_build], [r at REVISION@])
+m4_define([mousepad_version_tag], [svn])
+m4_define([mousepad_version], [mousepad_version_major().mousepad_version_minor().mousepad_version_micro()ifelse(mousepad_version_tag(), [svn], [mousepad_version_tag()-mousepad_version_build()], [mousepad_version_tag()])])
+
+dnl *******************************************
+dnl *** Debugging support for SVN snapshots ***
+dnl *******************************************
+m4_define([mousepad_debug_default], [ifelse(mousepad_version_tag(), [svn], [yes], [minimum])])
+
+dnl ***************************
+dnl *** Initialize autoconf ***
+dnl ***************************
+AC_COPYRIGHT([Copyright (c) 2007
+ The Xfce development team. All rights reserved.])
+AC_INIT([Mousepad], [mousepad_version()], [http://bugzilla.xfce.org/], [Mousepad])
+AC_PREREQ([2.50])
+AC_CANONICAL_TARGET()
+AC_REVISION([$Id$])
+
+dnl ***************************
+dnl *** Initialize automake ***
+dnl ***************************
+AM_INIT_AUTOMAKE([1.8 dist-bzip2 tar-ustar])
+AM_CONFIG_HEADER([config.h])
+AM_MAINTAINER_MODE()
+
+dnl *******************************
+dnl *** Check for UNIX variants ***
+dnl *******************************
+AC_AIX()
+AC_ISC_POSIX()
+AC_MINIX()
+
+dnl ********************************
+dnl *** Check for basic programs ***
+dnl ********************************
+AC_PROG_CC()
+AC_PROG_LD()
+AC_PROG_INSTALL()
+AC_PROG_INTLTOOL()
+
+dnl **************************
+dnl *** Initialize libtool ***
+dnl **************************
+AC_PROG_LIBTOOL()
+
+dnl **************************************
+dnl *** Substitute version information ***
+dnl **************************************
+MOUSEPAD_VERSION_MAJOR=mousepad_version_major()
+MOUSEPAD_VERSION_MINOR=mousepad_version_minor()
+MOUSEPAD_VERSION_MICRO=mousepad_version_micro()
+AC_SUBST([MOUSEPAD_VERSION_MAJOR])
+AC_SUBST([MOUSEPAD_VERSION_MINOR])
+AC_SUBST([MOUSEPAD_VERSION_MICRO])
+
+dnl **********************************
+dnl *** Check for standard headers ***
+dnl **********************************
+AC_CHECK_HEADERS([errno.h fcntl.h memory.h stdlib.h string.h \
+ sys/mman.h sys/types.h sys/stat.h time.h unistd.h])
+
+dnl ************************************
+dnl *** Check for standard functions ***
+dnl ************************************
+AC_FUNC_MMAP()
+AC_CHECK_FUNCS([posix_madvise])
+
+dnl ******************************
+dnl *** Check for i18n support ***
+dnl ******************************
+XDT_I18N([@LINGUAS@])
+
+dnl ***********************************
+dnl *** Check for required packages ***
+dnl ***********************************
+XDT_CHECK_PACKAGE([EXO], [exo-0.3], [0.3.2])
+XDT_CHECK_PACKAGE([GLIB], [glib-2.0], [2.12.0])
+XDT_CHECK_PACKAGE([GTHREAD], [gthread-2.0], [2.12.0])
+XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [2.10.0])
+XDT_CHECK_PACKAGE([LIBXFCE4UTIL], [libxfce4util-1.0], [4.4.0])
+
+dnl ********************************************
+dnl *** Check for session management support ***
+dnl ********************************************
+XDT_CHECK_LIBSM()
+
+dnl **********************************
+dnl *** Optional support for D-BUS ***
+dnl **********************************
+XDT_CHECK_OPTIONAL_PACKAGE([DBUS], [dbus-glib-1],
+ [0.34], [dbus], [D-BUS support])
+
+dnl *************************************************
+dnl *** Optional support for startup notification ***
+dnl *************************************************
+XDT_CHECK_OPTIONAL_PACKAGE([LIBSTARTUP_NOTIFICATION],
+ [libstartup-notification-1.0],
+ [0.4], [startup-notification],
+ [startup notification library])
+
+dnl *************************
+dnl *** Check for gtk-doc ***
+dnl *************************
+GTK_DOC_CHECK([1.0])
+
+dnl ***********************************
+dnl *** Check for debugging support ***
+dnl ***********************************
+AC_ARG_ENABLE([debug],
+AC_HELP_STRING([--enable-debug=@<:@no/minimum/yes/full@:>@], [Turn on debugging @<:@default=mousepad_debug_default@:>@]),
+ [], [enable_debug=mousepad_debug_default])
+AC_MSG_CHECKING([whether to enable debugging support])
+if test x"$enable_debug" = x"full" -o x"$enable_debug" = x"yes"; then
+ dnl Print the result
+ AC_MSG_RESULT([$enable_debug])
+
+ dnl Make sure we detect possible errors (if supported)
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Wall -Werror"
+ AC_MSG_CHECKING([whether $CC accepts -Wall -Werror])
+ AC_COMPILE_IFELSE(AC_LANG_SOURCE([int x;]), [
+ AC_MSG_RESULT([yes])
+ PLATFORM_CFLAGS="$PLATFORM_CFLAGS -Wall -Werror"
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+ CFLAGS="$save_CFLAGS"
+
+ dnl Paranoia for --enable-debug=full
+ if test x"$enable_debug" = x"full"; then
+ dnl Enable extensive debugging
+ PLATFORM_CPPFLAGS="$PLATFORM_CPPFLAGS -DG_ENABLE_DEBUG"
+
+ dnl Use -O0 -g3 if the compiler supports it
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -O0 -g3"
+ AC_MSG_CHECKING([whether $CC accepts -O0 -g3])
+ AC_COMPILE_IFELSE(AC_LANG_SOURCE([int x;]), [
+ AC_MSG_RESULT([yes])
+ PLATFORM_CFLAGS="$PLATFORM_CFLAGS -O0 -g3"
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+ CFLAGS="$save_CFLAGS"
+ fi
+else
+ dnl Print the result
+ AC_MSG_RESULT([$enable_debug])
+
+ dnl Disable debugging (release build)
+ PLATFORM_CPPFLAGS="$PLATFORM_CPPFLAGS -DNDEBUG"
+
+ dnl Disable object cast checks
+ PLATFORM_CPPFLAGS="$PLATFORM_CPPFLAGS -DG_DISABLE_CAST_CHECKS"
+
+ dnl Disable all checks for --enable-debug=no
+ if test x"$enable_debug" = x"no"; then
+ PLATFORM_CPPFLAGS="$PLATFORM_CPPFLAGS -DG_DISABLE_ASSERT -DG_DISABLE_CHECKS"
+ fi
+fi
+
+dnl **************************************
+dnl *** Check for linker optimizations ***
+dnl **************************************
+AC_MSG_CHECKING([whether $LD accepts --as-needed])
+case `$LD --as-needed -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ LDFLAGS="$LDFLAGS -Wl,--as-needed"
+ AC_MSG_RESULT([yes])
+ ;;
+*)
+ AC_MSG_RESULT([no])
+ ;;
+esac
+AC_MSG_CHECKING([whether $LD accepts -O1])
+case `$LD -O1 -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -Wl,-O1"
+ AC_MSG_RESULT([yes])
+ ;;
+*)
+ AC_MSG_RESULT([no])
+ ;;
+esac
+
+dnl *********************************
+dnl *** Substitute platform flags ***
+dnl *********************************
+AC_MSG_CHECKING([PLATFORM_CPPFLAGS])
+AC_MSG_RESULT([$PLATFORM_CPPFLAGS])
+AC_SUBST([PLATFORM_CPPFLAGS])
+AC_MSG_CHECKING([PLATFORM_CFLAGS])
+AC_MSG_RESULT([$PLATFORM_CFLAGS])
+AC_SUBST([PLATFORM_CFLAGS])
+AC_MSG_CHECKING([PLATFORM_LDFLAGS])
+AC_MSG_RESULT([$PLATFORM_LDFLAGS])
+AC_SUBST([PLATFORM_LDFLAGS])
+
+AC_OUTPUT([
+Makefile
+icons/Makefile
+icons/16x16/Makefile
+icons/24x24/Makefile
+icons/scalable/Makefile
+mousepad/Makefile
+po/Makefile.in
+])
+
+dnl ***************************
+dnl *** Print configuration ***
+dnl ***************************
+echo
+echo "Build Configuration:"
+echo
+if test x"$DBUS_FOUND" = x"yes"; then
+echo "* D-BUS support: yes"
+else
+echo "* D-BUS support: no"
+fi
+if test x"$LIBSTARTUP_NOTIFICATION_FOUND" = x"yes"; then
+echo "* Startup Notification: yes"
+else
+echo "* Startup Notification: no"
+fi
+echo
diff --git a/icons/16x16/Makefile.am b/icons/16x16/Makefile.am
new file mode 100644
index 0000000..4fe130f
--- /dev/null
+++ b/icons/16x16/Makefile.am
@@ -0,0 +1,10 @@
+# $Id$
+
+appsdir = $(datadir)/icons/hicolor/16x16/apps
+apps_DATA = \
+ Mousepad.png
+
+EXTRA_DIST = \
+ $(apps_DATA)
+
+# vi:set ts=8 sw=8 noet ai nocindent syntax=automake:
diff --git a/icons/16x16/Mousepad.png b/icons/16x16/Mousepad.png
new file mode 100644
index 0000000..188e1c1
Binary files /dev/null and b/icons/16x16/Mousepad.png differ
diff --git a/icons/24x24/Makefile.am b/icons/24x24/Makefile.am
new file mode 100644
index 0000000..2608272
--- /dev/null
+++ b/icons/24x24/Makefile.am
@@ -0,0 +1,10 @@
+# $Id$
+
+iconsdir = $(datadir)/icons/hicolor/24x24/apps
+icons_DATA = \
+ Mousepad.png
+
+EXTRA_DIST = \
+ $(icons_DATA)
+
+# vi:set ts=8 sw=8 noet ai nocindent syntax=automake:
diff --git a/icons/24x24/Mousepad.png b/icons/24x24/Mousepad.png
new file mode 100644
index 0000000..bdbb88e
Binary files /dev/null and b/icons/24x24/Mousepad.png differ
diff --git a/icons/Makefile.am b/icons/Makefile.am
new file mode 100644
index 0000000..e6cdc99
--- /dev/null
+++ b/icons/Makefile.am
@@ -0,0 +1,21 @@
+# $Id$
+
+SUBDIRS = \
+ 16x16 \
+ 24x24 \
+ scalable
+
+gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor
+
+install-data-hook:
+ @-if test -z "$(DESTDIR)"; then \
+ echo "Updating Gtk icon cache."; \
+ $(gtk_update_icon_cache); \
+ else \
+ echo "*** Icon cache not updated. Remember to run:"; \
+ echo "***"; \
+ echo "*** $(gtk_update_icon_cache)"; \
+ echo "***"; \
+ fi
+
+# vi:set ts=8 sw=8 noet ai nocindent syntax=automake:
diff --git a/icons/scalable/Makefile.am b/icons/scalable/Makefile.am
new file mode 100644
index 0000000..305a62c
--- /dev/null
+++ b/icons/scalable/Makefile.am
@@ -0,0 +1,10 @@
+# $Id$
+
+iconsdir = $(datadir)/icons/hicolor/scalable/apps
+icons_DATA = \
+ Mousepad.svg
+
+EXTRA_DIST = \
+ $(icons_DATA)
+
+# vi:set ts=8 sw=8 noet ai nocindent syntax=automake:
diff --git a/icons/scalable/Mousepad.svg b/icons/scalable/Mousepad.svg
new file mode 100644
index 0000000..aa7188e
--- /dev/null
+++ b/icons/scalable/Mousepad.svg
@@ -0,0 +1,552 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ inkscape:export-ydpi="90.000000"
+ inkscape:export-xdpi="90.000000"
+ inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
+ width="48px"
+ height="48px"
+ id="svg11300"
+ sodipodi:version="0.32"
+ inkscape:version="0.43+devel"
+ sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/apps"
+ sodipodi:docname="accessories-text-editor.svg">
+ <defs
+ id="defs3">
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="radialGradient6719"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
+ cx="605.71429"
+ cy="486.64789"
+ fx="605.71429"
+ fy="486.64789"
+ r="117.14286" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient5060">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop5062" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop5064" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="radialGradient6717"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
+ cx="605.71429"
+ cy="486.64789"
+ fx="605.71429"
+ fy="486.64789"
+ r="117.14286" />
+ <linearGradient
+ id="linearGradient5048">
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="0"
+ id="stop5050" />
+ <stop
+ id="stop5056"
+ offset="0.5"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop5052" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5048"
+ id="linearGradient6715"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
+ x1="302.85715"
+ y1="366.64789"
+ x2="302.85715"
+ y2="609.50507" />
+ <linearGradient
+ id="linearGradient2994">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop2996" />
+ <stop
+ style="stop-color:#c9c9c9;stop-opacity:1;"
+ offset="1"
+ id="stop2998" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient2984">
+ <stop
+ style="stop-color:#e7e2b8;stop-opacity:1;"
+ offset="0"
+ id="stop2986" />
+ <stop
+ style="stop-color:#e7e2b8;stop-opacity:0;"
+ offset="1"
+ id="stop2988" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2974">
+ <stop
+ style="stop-color:#c1c1c1;stop-opacity:1;"
+ offset="0"
+ id="stop2976" />
+ <stop
+ style="stop-color:#acacac;stop-opacity:1;"
+ offset="1"
+ id="stop2978" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2966">
+ <stop
+ style="stop-color:#ffd1d1;stop-opacity:1;"
+ offset="0"
+ id="stop2968" />
+ <stop
+ id="stop3006"
+ offset="0.5"
+ style="stop-color:#ff1d1d;stop-opacity:1;" />
+ <stop
+ style="stop-color:#6f0000;stop-opacity:1;"
+ offset="1"
+ id="stop2970" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2919">
+ <stop
+ style="stop-color:#a3a4a0;stop-opacity:1;"
+ offset="0"
+ id="stop2921" />
+ <stop
+ style="stop-color:#888a85;stop-opacity:1;"
+ offset="1"
+ id="stop2923" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2873">
+ <stop
+ style="stop-color:#939393;stop-opacity:1;"
+ offset="0"
+ id="stop2875" />
+ <stop
+ style="stop-color:#424242;stop-opacity:1;"
+ offset="1"
+ id="stop2877" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient2865">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop2867" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop2869" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2855">
+ <stop
+ style="stop-color:#dfdfdf;stop-opacity:1;"
+ offset="0"
+ id="stop2857" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop2859" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2855"
+ id="linearGradient2861"
+ x1="21.043484"
+ y1="42.83337"
+ x2="14.283642"
+ y2="6.8333683"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.137871,0.000000,0.000000,1.000000,-2.660884,0.000000)" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2865"
+ id="radialGradient2871"
+ cx="23.5625"
+ cy="40.4375"
+ fx="23.5625"
+ fy="40.4375"
+ r="19.5625"
+ gradientTransform="matrix(1.000000,0.000000,0.000000,0.348243,0.000000,26.35543)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2873"
+ id="linearGradient2879"
+ x1="26.612417"
+ y1="28.083368"
+ x2="26.228401"
+ y2="42.83337"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2919"
+ id="linearGradient2925"
+ x1="6"
+ y1="7.5624999"
+ x2="40.984375"
+ y2="7.5624999"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2966"
+ id="linearGradient2972"
+ x1="48.90625"
+ y1="17.376184"
+ x2="50.988335"
+ y2="22.250591"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-5.669292,0.000000)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2974"
+ id="linearGradient2980"
+ x1="46"
+ y1="19.8125"
+ x2="47.6875"
+ y2="22.625"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-5.669292,0.000000)" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2984"
+ id="radialGradient2990"
+ cx="29.053354"
+ cy="27.640751"
+ fx="29.053354"
+ fy="27.640751"
+ r="3.2408544"
+ gradientTransform="matrix(2.923565,-3.911409e-24,2.471769e-23,2.029717,-61.55532,-27.88417)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2994"
+ id="linearGradient3000"
+ x1="25.71875"
+ y1="31.046875"
+ x2="25.514589"
+ y2="30.703125"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-5.825542,0.125000)" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2865"
+ id="radialGradient3010"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.000000,0.000000,0.000000,0.348243,1.439818e-16,26.35543)"
+ cx="23.5625"
+ cy="40.4375"
+ fx="23.5625"
+ fy="40.4375"
+ r="19.5625" />
+ </defs>
+ <sodipodi:namedview
+ stroke="#c4a000"
+ fill="#edd400"
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="0.25490196"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1"
+ inkscape:cx="14.928934"
+ inkscape:cy="7.6822472"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:grid-bbox="true"
+ inkscape:document-units="px"
+ inkscape:showpageshadow="false"
+ inkscape:window-width="872"
+ inkscape:window-height="659"
+ inkscape:window-x="195"
+ inkscape:window-y="221" />
+ <metadata
+ id="metadata4">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Jakub Steiner</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:source>http://jimmac.musichall.cz</dc:source>
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
+ <dc:title>Text Editor</dc:title>
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Reproduction" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Distribution" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Notice" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Attribution" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/ShareAlike" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer">
+ <g
+ transform="matrix(2.417561e-2,0,0,2.086758e-2,45.12765,40.1536)"
+ id="g6707">
+ <rect
+ style="opacity:0.40206185;color:black;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect6709"
+ width="1339.6335"
+ height="478.35718"
+ x="-1559.2523"
+ y="-150.69685" />
+ <path
+ style="opacity:0.40206185;color:black;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M -219.61876,-150.68038 C -219.61876,-150.68038 -219.61876,327.65041 -219.61876,327.65041 C -76.744594,328.55086 125.78146,220.48075 125.78138,88.454235 C 125.78138,-43.572302 -33.655436,-150.68036 -219.61876,-150.68038 z "
+ id="path6711"
+ sodipodi:nodetypes="cccc" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path6713"
+ d="M -1559.2523,-150.68038 C -1559.2523,-150.68038 -1559.2523,327.65041 -1559.2523,327.65041 C -1702.1265,328.55086 -1904.6525,220.48075 -1904.6525,88.454235 C -1904.6525,-43.572302 -1745.2157,-150.68036 -1559.2523,-150.68038 z "
+ style="opacity:0.40206185;color:black;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ <path
+ style="color:#000000;fill:url(#linearGradient2861);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient2879);stroke-width:0.99999982;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 7.1638699,4.5063726 L 39.813122,4.5063726 C 40.575699,4.5063726 41.189615,5.0388241 41.189615,5.7002099 C 41.189615,5.7002099 43.590945,39.868907 43.590945,39.868907 C 43.590945,39.868907 43.603403,42.216529 43.603403,42.216529 C 43.603403,42.877915 42.989488,43.410366 42.226911,43.410366 L 4.750081,43.410366 C 3.9875042,43.410366 3.3735887,42.877915 3.3735887,42.216529 L 3.3624173,40.049613 L 5.7873775,5.7002099 C 5.7873775,5.0388241 6.4012931,4.5063726 7.1638699,4.5063726 z "
+ id="rect1975"
+ sodipodi:nodetypes="ccccccccccc" />
+ <path
+ transform="matrix(0.616613,0.000000,0.000000,0.440367,10.61425,13.94266)"
+ d="M 43.125 40.4375 A 19.5625 6.8125 0 1 1 4,40.4375 A 19.5625 6.8125 0 1 1 43.125 40.4375 z"
+ sodipodi:ry="6.8125"
+ sodipodi:rx="19.5625"
+ sodipodi:cy="40.4375"
+ sodipodi:cx="23.5625"
+ id="path3008"
+ style="opacity:0.31578944;color:#000000;fill:url(#radialGradient3010);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ sodipodi:type="arc" />
+ <rect
+ style="opacity:1;color:#000000;fill:#a4a4a4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect2851"
+ width="39.048077"
+ height="3.0714951"
+ x="3.9770372"
+ y="39.868271"
+ rx="0.67937863"
+ ry="0.67937863" />
+ <path
+ style="opacity:1;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 3.9267507,40.442796 C 3.9267507,40.442796 4.0776125,39.912466 4.6307727,39.868272 L 42.195375,39.868272 C 42.949684,39.868272 42.999971,40.619573 42.999971,40.619573 C 42.999971,40.619573 43.02357,39 41.7161,39 L 5.3042159,39 C 4.2984702,39.088388 3.9267507,39.779883 3.9267507,40.442796 z "
+ id="path2853"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="opacity:1;color:#000000;fill:url(#linearGradient2925);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 6.25,5.7343749 L 6,10.125 C 6,10.125 6.3125,8.9999999 7,8.9999999 L 40.125,8.9999999 C 40.828125,8.9843749 40.859375,9.3124999 40.984375,9.8281249 C 40.984375,9.8281249 40.734375,5.9531249 40.734375,5.9531249 C 40.703125,5.4062499 40.515625,4.9999999 39.953125,4.9999999 L 7.0625,4.9999999 C 6.609375,4.9999999 6.296875,5.3437499 6.25,5.7343749 z "
+ id="path2915"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ sodipodi:nodetypes="ccccccccccc"
+ id="path2917"
+ d="M 7.8126474,5.5404503 L 38.944983,5.5404503 C 39.66702,5.5404503 40.2483,5.3883462 40.2483,6.014572 C 40.2483,6.014572 42.521973,39.023077 42.521973,39.023077 C 42.521973,39.023077 42.622156,41.732033 42.622156,41.732033 C 42.622156,42.358259 42.48282,42.376269 41.760782,42.376269 L 4.8620444,42.376269 C 4.4493662,42.376269 4.4426114,42.269871 4.4426114,41.864615 L 4.4320338,39.194177 L 6.7280807,6.045822 C 6.7280807,5.4195962 7.09061,5.5404503 7.8126474,5.5404503 z "
+ style="color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.99999946;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;opacity:0.43859649" />
+ <g
+ id="g2950">
+ <rect
+ ry="1"
+ rx="1"
+ y="2.5"
+ x="8.5"
+ height="5"
+ width="2"
+ id="rect2899"
+ style="opacity:1;color:#000000;fill:#fce94f;fill-opacity:1;fill-rule:evenodd;stroke:#886f00;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <rect
+ style="opacity:1;color:#000000;fill:#fce94f;fill-opacity:1;fill-rule:evenodd;stroke:#886f00;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect2901"
+ width="2"
+ height="5"
+ x="12.5"
+ y="2.5"
+ rx="1"
+ ry="1" />
+ <rect
+ ry="1"
+ rx="1"
+ y="2.5"
+ x="16.5"
+ height="5"
+ width="2"
+ id="rect2903"
+ style="opacity:1;color:#000000;fill:#fce94f;fill-opacity:1;fill-rule:evenodd;stroke:#886f00;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <rect
+ style="opacity:1;color:#000000;fill:#fce94f;fill-opacity:1;fill-rule:evenodd;stroke:#886f00;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect2905"
+ width="2"
+ height="5"
+ x="20.5"
+ y="2.5"
+ rx="1"
+ ry="1" />
+ <rect
+ ry="1"
+ rx="1"
+ y="2.5"
+ x="24.5"
+ height="5"
+ width="2"
+ id="rect2907"
+ style="opacity:1;color:#000000;fill:#fce94f;fill-opacity:1;fill-rule:evenodd;stroke:#886f00;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <rect
+ style="opacity:1;color:#000000;fill:#fce94f;fill-opacity:1;fill-rule:evenodd;stroke:#886f00;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect2909"
+ width="2"
+ height="5"
+ x="28.5"
+ y="2.5"
+ rx="1"
+ ry="1" />
+ <rect
+ ry="1"
+ rx="1"
+ y="2.5"
+ x="32.5"
+ height="5"
+ width="2"
+ id="rect2911"
+ style="opacity:1;color:#000000;fill:#fce94f;fill-opacity:1;fill-rule:evenodd;stroke:#886f00;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <rect
+ style="opacity:1;color:#000000;fill:#fce94f;fill-opacity:1;fill-rule:evenodd;stroke:#886f00;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect2913"
+ width="2"
+ height="5"
+ x="36.5"
+ y="2.5"
+ rx="1"
+ ry="1" />
+ </g>
+ <g
+ id="g2941">
+ <rect
+ y="12"
+ x="9"
+ height="1"
+ width="29"
+ id="rect2927"
+ style="opacity:0.28070175;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <rect
+ style="opacity:0.28070176;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect2929"
+ width="29"
+ height="1"
+ x="9"
+ y="14.981792" />
+ <rect
+ y="18.003939"
+ x="9"
+ height="1"
+ width="13"
+ id="rect2931"
+ style="opacity:0.28070176;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <rect
+ style="opacity:0.28070176;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect2933"
+ width="29"
+ height="1"
+ x="9"
+ y="22.985731" />
+ <rect
+ y="26.007877"
+ x="9"
+ height="1"
+ width="29"
+ id="rect2935"
+ style="opacity:0.28070176;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <rect
+ style="opacity:0.28070176;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect2937"
+ width="29"
+ height="1"
+ x="9"
+ y="29.030024" />
+ <rect
+ y="32.05217"
+ x="9"
+ height="1"
+ width="8"
+ id="rect2939"
+ style="opacity:0.28070176;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ <path
+ style="opacity:1;color:#000000;fill:#cb9022;fill-opacity:1;fill-rule:evenodd;stroke:#5c410c;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 17.34116,32.5 L 22.96616,26.875 L 43.059909,17.125 C 46.309909,15.875 48.247409,20.5 45.372409,22.125 L 25.34116,31.5 L 17.34116,32.5 z "
+ id="path2960"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ sodipodi:nodetypes="czcczcc"
+ id="path2964"
+ d="M 38.330708,20 C 38.330708,20 39.768208,20.09375 40.330708,21.34375 C 40.910201,22.631511 40.330708,24 40.330708,24 L 45.361958,21.53125 C 45.361958,21.53125 46.81399,20.649883 46.018208,18.6875 C 45.233296,16.751923 43.330708,17.53125 43.330708,17.53125 L 38.330708,20 z "
+ style="opacity:1;color:#000000;fill:url(#linearGradient2972);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ style="opacity:1;color:#000000;fill:url(#linearGradient2980);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 38.330708,20 C 38.330708,20 39.768208,20.09375 40.330708,21.34375 C 40.910201,22.631511 40.330708,24 40.330708,24 L 42.330708,23 C 42.330708,23 43.15774,21.681133 42.549458,20.3125 C 41.924458,18.90625 40.330708,19 40.330708,19 L 38.330708,20 z "
+ id="path2962"
+ sodipodi:nodetypes="czcczcc" />
+ <path
+ style="opacity:1;color:#000000;fill:url(#radialGradient2990);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 18.768208,31.78125 L 23.268208,27.28125 C 24.768208,28.09375 25.549458,29.4375 25.143208,31 L 18.768208,31.78125 z "
+ id="path2982"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="opacity:1;color:#000000;fill:url(#linearGradient3000);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 20.111958,30.375 L 18.486958,31.96875 L 20.830708,31.65625 C 21.049458,30.9375 20.643208,30.59375 20.111958,30.375 z "
+ id="path2992"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="opacity:1;color:#000000;fill:#ffffff;fill-opacity:0.36363639;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 23.268208,27.25 L 24.830708,28.5 L 40.218048,21.18133 C 39.773616,20.325286 38.976281,20.096733 38.314669,20.019068 L 23.268208,27.25 z "
+ id="path3002"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="opacity:1;color:#000000;fill:#000000;fill-opacity:0.36363639;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 25.143208,31.0625 L 25.330708,30.3125 L 40.561798,23.1829 C 40.561798,23.1829 40.451638,23.796527 40.345919,23.93225 L 25.143208,31.0625 z "
+ id="path3004"
+ sodipodi:nodetypes="ccccc" />
+ </g>
+</svg>
diff --git a/mousepad/Makefile.am b/mousepad/Makefile.am
new file mode 100644
index 0000000..bb27224
--- /dev/null
+++ b/mousepad/Makefile.am
@@ -0,0 +1,93 @@
+# $Id$
+
+INCLUDES = \
+ -I$(top_builddir) \
+ -I$(top_srcdir) \
+ -DBINDIR=\"$(bindir)\" \
+ -DDATADIR=\"$(datadir)\" \
+ -DLIBDIR=\"$(libdir)\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DG_LOG_DOMAIN=\"Mousepad\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DPACKAGE_LOCALE_DIR=\"$(localedir)\" \
+ $(PLATFORM_CPPFLAGS)
+
+bin_PROGRAMS = \
+ Mousepad
+
+Mousepad_SOURCES = \
+ main.c \
+ mousepad-application.c \
+ mousepad-application.h \
+ mousepad-file.c \
+ mousepad-file.h \
+ mousepad-preferences.c \
+ mousepad-preferences.h \
+ mousepad-private.h \
+ mousepad-screen.c \
+ mousepad-screen.h \
+ mousepad-tab-label.c \
+ mousepad-tab-label.h \
+ mousepad-view.c \
+ mousepad-view.h \
+ mousepad-window.c \
+ mousepad-window.h \
+ mousepad-window-ui.h
+
+Mousepad_CFLAGS = \
+ $(EXO_CFLAGS) \
+ $(GTHREAD_CFLAGS) \
+ $(PLATFORM_CFLAGS)
+
+Mousepad_LDFLAGS = \
+ -no-undefined \
+ $(LIBSM_LDFLAGS) \
+ $(PLATFORM_LDFLAGS)
+
+Mousepad_LDADD = \
+ $(EXO_LIBS) \
+ $(GTHREAD_LIBS)
+
+if HAVE_DBUS
+mousepad_build_sources = \
+ mousepad-dbus-infos.h
+
+Mousepad_SOURCES += \
+ mousepad-dbus.c \
+ mousepad-dbus.h
+
+Mousepad_CFLAGS += \
+ -DDBUS_API_SUBJECT_TO_CHANGE \
+ $(DBUS_CFLAGS)
+
+Mousepad_LDADD += \
+ $(DBUS_LIBS)
+endif
+
+# install symlink to 'mousepad'
+install-data-local:
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ -( cd $(DESTDIR)$(bindir) ; ln -sf Mousepad mousepad )
+
+if MAINTAINER_MODE
+DISTCLEANFILES = \
+ mousepad-window-ui.h
+
+BUILT_SOURCES = \
+ $(mousepad_build_sources) \
+ mousepad-window-ui.h
+
+if HAVE_DBUS
+mousepad-dbus-infos.h: $(srcdir)/mousepad-dbus-infos.xml Makefile
+ dbus-binding-tool --prefix=mousepad_dbus_service --mode=glib-server $(srcdir)/mousepad-dbus-infos.xml > mousepad-dbus-infos.h
+endif
+
+mousepad-window-ui.h: Makefile $(srcdir)/mousepad-window-ui.xml
+ exo-csource --static --name=mousepad_window_ui $(srcdir)/mousepad-window-ui.xml > mousepad-window-ui.h
+endif
+
+EXTRA_DIST = \
+ mousepad-dbus-infos.xml \
+ mousepad-window-ui.xml
+
+# vi:set ts=8 sw=8 noet ai nocindent syntax=automake:
diff --git a/mousepad/main.c b/mousepad/main.c
new file mode 100644
index 0000000..88045b7
--- /dev/null
+++ b/mousepad/main.c
@@ -0,0 +1,182 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <mousepad/mousepad-private.h>
+#include <mousepad/mousepad-application.h>
+
+#ifdef HAVE_DBUS
+#include <mousepad/mousepad-dbus.h>
+#endif
+
+
+/* globals */
+static gchar **filenames = NULL;
+static gboolean opt_version = FALSE;
+#ifdef HAVE_DBUS
+static gboolean opt_disable_server = FALSE;
+#endif
+
+
+
+/* command line options */
+static GOptionEntry option_entries[] =
+{
+#ifdef HAVE_DBUS
+ { "disable-server", '\0', 0, G_OPTION_ARG_NONE, &opt_disable_server, N_ ("Do not register with the D-BUS session message bus"), NULL, },
+#endif
+ { "version", 'v', 0, G_OPTION_ARG_NONE, &opt_version, N_ ("Print version information and exit"), NULL, },
+ { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL, NULL },
+ { NULL, },
+};
+
+
+
+gint
+main (gint argc, gchar **argv)
+{
+ MousepadApplication *application;
+#ifdef HAVE_DBUS
+ MousepadDBusService *dbus_service;
+#endif
+ GError *error = NULL;
+ gchar *working_directory;
+
+ /* translation domain */
+ xfce_textdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8");
+
+ /* default application name */
+ g_set_application_name (_("Mousepad"));
+
+#ifdef G_ENABLE_DEBUG
+ /* crash when something went wrong */
+ g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
+#endif
+
+ /* initialize the GThread system */
+ if (!g_thread_supported ())
+ g_thread_init (NULL);
+
+ /* initialize Gtk+ */
+ if (!gtk_init_with_args (&argc, &argv, _("[FILES...]"), option_entries, GETTEXT_PACKAGE, &error))
+ {
+ /* check if we have an error message */
+ if (G_LIKELY (error == NULL))
+ {
+ /* no error message, the GUI initialization failed */
+ g_error ("%s", _("Failed to open display."));
+ }
+ else
+ {
+ /* print the error message */
+ g_error ("%s", error->message);
+ g_error_free (error);
+ }
+
+ return EXIT_FAILURE;
+ }
+
+ /* check if we should print version information */
+ if (G_UNLIKELY (opt_version))
+ {
+ g_print ("%s %s (Xfce %s)\n\n", PACKAGE_NAME, PACKAGE_VERSION, xfce_version_string ());
+ g_print ("%s\n", "Copyright (c) 2007");
+ g_print ("\t%s\n\n", _("The Xfce development team. All rights reserved."));
+ g_print ("%s\n\n", _("Written by Nick Schermer <nick at xfce.org>."));
+ g_print (_("Please report bugs to <%s>."), PACKAGE_BUGREPORT);
+ g_print ("\n");
+
+ return EXIT_SUCCESS;
+ }
+
+ /* get the current working directory */
+ working_directory = g_get_current_dir ();
+
+#ifdef HAVE_DBUS
+ if (G_LIKELY (!opt_disable_server))
+ {
+ /* check if we can reuse an existing instance */
+ if (mousepad_dbus_client_launch_files (filenames, working_directory, &error))
+ {
+ /* stop any running startup notification */
+ gdk_notify_startup_complete ();
+
+ /* cleanup */
+ g_free (working_directory);
+ g_strfreev (filenames);
+
+ /* print errors, if needed */
+ if (G_UNLIKELY (error))
+ {
+ g_error ("Mousepad: %s\n", error->message);
+ g_error_free (error);
+
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+ }
+ }
+#endif /* !HAVE_DBUS */
+
+ /* use the Mousepad icon as default for new windows */
+ gtk_window_set_default_icon_name ("Mousepad");
+
+ /* create a new mousepad application */
+ application = mousepad_application_get ();
+
+ /* open an empty window or the files */
+ mousepad_application_open_window (application, NULL, working_directory, filenames);
+
+ /* cleanup */
+ g_free (working_directory);
+ g_strfreev (filenames);
+
+ /* do not enter the main loop, unless we have atleast one window */
+ if (G_LIKELY (mousepad_application_has_windows (application)))
+ {
+#ifdef HAVE_DBUS
+ /* register with dbus */
+ dbus_service = g_object_new (MOUSEPAD_TYPE_DBUS_SERVICE, NULL);
+#endif
+
+ /* enter the main loop */
+ gtk_main ();
+
+#ifdef HAVE_DBUS
+ /* release dbus service reference */
+ g_object_unref (G_OBJECT (dbus_service));
+#endif
+ }
+
+ /* release application reference */
+ g_object_unref (G_OBJECT (application));
+
+ return EXIT_SUCCESS;
+}
diff --git a/mousepad/mousepad-application.c b/mousepad/mousepad-application.c
new file mode 100644
index 0000000..755348b
--- /dev/null
+++ b/mousepad/mousepad-application.c
@@ -0,0 +1,239 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <mousepad/mousepad-private.h>
+#include <mousepad/mousepad-application.h>
+#include <mousepad/mousepad-window.h>
+
+
+
+static void mousepad_application_class_init (MousepadApplicationClass *klass);
+static void mousepad_application_init (MousepadApplication *application);
+static void mousepad_application_window_destroyed (GtkWidget *window,
+ MousepadApplication *application);
+static void mousepad_application_finalize (GObject *object);
+
+
+
+struct _MousepadApplicationClass
+{
+ GObjectClass __parent__;
+};
+
+struct _MousepadApplication
+{
+ GObject __parent__;
+
+ GList *windows;
+};
+
+
+
+static GObjectClass *mousepad_application_parent_class;
+
+
+
+MousepadApplication*
+mousepad_application_get (void)
+{
+ static MousepadApplication *application = NULL;
+
+ if (G_UNLIKELY (application == NULL))
+ {
+ application = g_object_new (MOUSEPAD_TYPE_APPLICATION, NULL);
+ }
+ else
+ {
+ g_object_ref (G_OBJECT (application));
+ }
+
+ return application;
+}
+
+
+
+static GObjectClass *mousepad_application_parent_class;
+
+
+
+GType
+mousepad_application_get_type (void)
+{
+ static GType type = G_TYPE_INVALID;
+
+ if (G_UNLIKELY (type == G_TYPE_INVALID))
+ {
+ type = g_type_register_static_simple (G_TYPE_OBJECT,
+ I_("MousepadApplication"),
+ sizeof (MousepadApplicationClass),
+ (GClassInitFunc) mousepad_application_class_init,
+ sizeof (MousepadApplication),
+ (GInstanceInitFunc) mousepad_application_init,
+ 0);
+ }
+
+ return type;
+}
+
+
+
+static void
+mousepad_application_class_init (MousepadApplicationClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ mousepad_application_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = mousepad_application_finalize;
+}
+
+
+
+static void
+mousepad_application_init (MousepadApplication *application)
+{
+ gchar *path;
+
+ /* check if we have a saved accel map */
+ path = xfce_resource_lookup (XFCE_RESOURCE_CONFIG, "Mousepad/accels.scm");
+ if (G_LIKELY (path != NULL))
+ {
+ /* load the accel map */
+ gtk_accel_map_load (path);
+ g_free (path);
+ }
+}
+
+
+
+static void
+mousepad_application_finalize (GObject *object)
+{
+ MousepadApplication *application = MOUSEPAD_APPLICATION (object);
+ GList *li;
+ gchar *path;
+
+ /* save the current accel map */
+ path = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, "Mousepad/accels.scm", TRUE);
+ if (G_LIKELY (path != NULL))
+ {
+ /* save the accel map */
+ gtk_accel_map_save (path);
+ g_free (path);
+ }
+
+ for (li = application->windows; li != NULL; li = li->next)
+ {
+ g_signal_handlers_disconnect_by_func (G_OBJECT (li->data), G_CALLBACK (mousepad_application_window_destroyed), application);
+ gtk_widget_destroy (GTK_WIDGET (li->data));
+ }
+
+ g_list_free (application->windows);
+
+ (*G_OBJECT_CLASS (mousepad_application_parent_class)->finalize) (object);
+}
+
+
+
+GList*
+mousepad_application_get_windows (MousepadApplication *application)
+{
+ GList *windows = NULL;
+ GList *li;
+
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_APPLICATION (application), NULL);
+
+ for (li = application->windows; li != NULL; li = li->next)
+ if (G_LIKELY (MOUSEPAD_IS_WINDOW (li->data)))
+ windows = g_list_prepend (windows, li->data);
+
+ return windows;
+}
+
+
+
+gboolean
+mousepad_application_has_windows (MousepadApplication *application)
+{
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_APPLICATION (application), FALSE);
+
+ return (application->windows != NULL);
+}
+
+
+
+void
+mousepad_application_open_window (MousepadApplication *application,
+ GdkScreen *screen,
+ const gchar *working_directory,
+ gchar **filenames)
+{
+ GtkWidget *window;
+
+ _mousepad_return_if_fail (MOUSEPAD_IS_APPLICATION (application));
+ _mousepad_return_if_fail (screen == NULL || GDK_IS_SCREEN (screen));
+
+ /* create a new window */
+ window = mousepad_window_new ();
+
+ /* get the screen */
+ if (G_UNLIKELY (screen == NULL))
+ screen = gdk_screen_get_default ();
+
+ /* move to the correct screen */
+ gtk_window_set_screen (GTK_WINDOW (window), screen);
+
+ /* open the filenames or an empty tab */
+ if (filenames != NULL && *filenames != NULL)
+ mousepad_window_open_files (MOUSEPAD_WINDOW (window), working_directory, filenames);
+ else
+ mousepad_window_open_tab (MOUSEPAD_WINDOW (window), NULL);
+
+ /* connect to the "destroy" signal */
+ g_signal_connect (G_OBJECT (window), "destroy",
+ G_CALLBACK (mousepad_application_window_destroyed), application);
+
+ /* add the window to our internal list */
+ application->windows = g_list_prepend (application->windows, window);
+
+ gtk_widget_show (window);
+}
+
+
+
+static void
+mousepad_application_window_destroyed (GtkWidget *window,
+ MousepadApplication *application)
+{
+ _mousepad_return_if_fail (GTK_IS_WINDOW (window));
+ _mousepad_return_if_fail (MOUSEPAD_IS_APPLICATION (application));
+ _mousepad_return_if_fail (g_list_find (application->windows, window) != NULL);
+
+ /* remove the window from the list */
+ application->windows = g_list_remove (application->windows, window);
+
+ /* quit if there are no windows opened */
+ if (application->windows == NULL)
+ gtk_main_quit ();
+}
diff --git a/mousepad/mousepad-application.h b/mousepad/mousepad-application.h
new file mode 100644
index 0000000..de4dde9
--- /dev/null
+++ b/mousepad/mousepad-application.h
@@ -0,0 +1,52 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.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
+ */
+
+#ifndef __MOUSEPAD_APPLICATION_H__
+#define __MOUSEPAD_APPLICATION_H__
+
+#include <exo/exo.h>
+
+G_BEGIN_DECLS
+
+typedef struct _MousepadApplicationClass MousepadApplicationClass;
+typedef struct _MousepadApplication MousepadApplication;
+
+#define MOUSEPAD_TYPE_APPLICATION (mousepad_application_get_type ())
+#define MOUSEPAD_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOUSEPAD_TYPE_APPLICATION, MousepadApplication))
+#define MOUSEPAD_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPAD_TYPE_APPLICATION, MousepadApplicationClass))
+#define MOUSEPAD_IS_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOUSEPAD_TYPE_APPLICATION))
+#define MOUSEPAD_IS_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOUSEPAD_TYPE_APPLICATION))
+#define MOUSEPAD_APPLICATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOUSEPAD_TYPE_APPLICATION, MousepadApplicationClass))
+
+GType mousepad_application_get_type (void) G_GNUC_CONST;
+
+MousepadApplication *mousepad_application_get (void);
+
+GList *mousepad_application_get_windows (MousepadApplication *application);
+
+gboolean mousepad_application_has_windows (MousepadApplication *application);
+
+void mousepad_application_open_window (MousepadApplication *application,
+ GdkScreen *screen,
+ const gchar *working_directory,
+ gchar **filenames);
+
+G_END_DECLS
+
+#endif /* !__MOUSEPAD_APPLICATION_H__ */
diff --git a/mousepad/mousepad-dbus-infos.xml b/mousepad/mousepad-dbus-infos.xml
new file mode 100644
index 0000000..27fa116
--- /dev/null
+++ b/mousepad/mousepad-dbus-infos.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<node name="/org/xfce/Mousepad">
+
+ <interface name="org.xfce.Mousepad">
+ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="mousepad_dbus_service" />
+
+ <method name="LaunchFiles">
+ <arg direction="in" name="working-directory" type="s" />
+ <arg direction="in" name="filenames" type="as" />
+ </method>
+
+ </interface>
+
+</node>
diff --git a/mousepad/mousepad-dbus.c b/mousepad/mousepad-dbus.c
new file mode 100644
index 0000000..9c6f6bd
--- /dev/null
+++ b/mousepad/mousepad-dbus.c
@@ -0,0 +1,247 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2004-2007 Benedikt Meurer <benny at xfce.org>
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <dbus/dbus-glib-lowlevel.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus.h>
+
+#include <mousepad/mousepad-dbus.h>
+#include <mousepad/mousepad-private.h>
+
+
+
+static void mousepad_dbus_service_class_init (MousepadDBusServiceClass *klass);
+static void mousepad_dbus_service_init (MousepadDBusService *dbus_service);
+static void mousepad_dbus_service_finalize (GObject *object);
+static gboolean mousepad_dbus_service_launch_files (MousepadDBusService *dbus_service,
+ const gchar *working_directory,
+ gchar **filenames,
+ GError **error);
+
+
+
+struct _MousepadDBusServiceClass
+{
+ GObjectClass __parent__;
+};
+
+struct _MousepadDBusService
+{
+ GObject __parent__;
+
+ DBusGConnection *connection;
+};
+
+
+
+static GObjectClass *mousepad_dbus_service_parent_class;
+
+
+
+GType
+mousepad_dbus_service_get_type (void)
+{
+ static GType type = G_TYPE_INVALID;
+
+ if (G_UNLIKELY (type == G_TYPE_INVALID))
+ {
+ type = g_type_register_static_simple (G_TYPE_OBJECT,
+ I_("MousepadDBusService"),
+ sizeof (MousepadDBusServiceClass),
+ (GClassInitFunc) mousepad_dbus_service_class_init,
+ sizeof (MousepadDBusService),
+ (GInstanceInitFunc) mousepad_dbus_service_init,
+ 0);
+ }
+
+ return type;
+}
+
+
+
+static void
+mousepad_dbus_service_class_init (MousepadDBusServiceClass *klass)
+{
+ extern const DBusGObjectInfo dbus_glib_mousepad_dbus_service_object_info;
+ GObjectClass *gobject_class;
+
+ /* determine the parent type class */
+ mousepad_dbus_service_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = mousepad_dbus_service_finalize;
+
+ /* install the D-BUS info for our class */
+ dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), &dbus_glib_mousepad_dbus_service_object_info);
+}
+
+
+
+static void
+mousepad_dbus_service_init (MousepadDBusService *dbus_service)
+{
+ GError *error = NULL;
+
+ /* try to connect to the session bus */
+ dbus_service->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+
+ if (G_LIKELY (dbus_service->connection != NULL))
+ {
+ /* register the /org/xfce/TextEditor object for Mousepad */
+ dbus_g_connection_register_g_object (dbus_service->connection, "/org/xfce/Mousepad", G_OBJECT (dbus_service));
+
+ /* request the org.xfce.Mousepad name for Mousepad */
+ dbus_bus_request_name (dbus_g_connection_get_connection (dbus_service->connection), "org.xfce.Mousepad", DBUS_NAME_FLAG_REPLACE_EXISTING, NULL);
+ }
+ else
+ {
+#ifdef NDEBUG
+ /* hide this warning when the user is root and debug is disabled */
+ if (geteuid () != 0)
+#endif
+ {
+ /* notify the user that D-BUS service won't be available */
+ g_message ("Failed to connect to the D-BUS session bus: %s\n", error->message);
+ }
+
+ g_error_free (error);
+ }
+}
+
+
+
+static void
+mousepad_dbus_service_finalize (GObject *object)
+{
+ MousepadDBusService *dbus_service = MOUSEPAD_DBUS_SERVICE (object);
+
+ /* release the D-BUS connection object */
+ if (G_LIKELY (dbus_service->connection != NULL))
+ dbus_g_connection_unref (dbus_service->connection);
+
+ (*G_OBJECT_CLASS (mousepad_dbus_service_parent_class)->finalize) (object);
+}
+
+
+
+static gboolean
+mousepad_dbus_service_launch_files (MousepadDBusService *dbus_service,
+ const gchar *working_directory,
+ gchar **filenames,
+ GError **error)
+{
+ MousepadApplication *application;
+ GdkScreen *screen;
+
+ _mousepad_return_val_if_fail (g_path_is_absolute (working_directory), FALSE);
+ _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ screen = gdk_screen_get_default ();
+
+ application = mousepad_application_get ();
+ mousepad_application_open_window (application, screen, working_directory, filenames);
+ g_object_unref (G_OBJECT (application));
+
+ return TRUE;
+}
+
+
+
+gboolean
+mousepad_dbus_client_launch_files (gchar **filenames,
+ const gchar *working_directory,
+ GError **error)
+{
+ DBusConnection *connection;
+ DBusMessage *message;
+ DBusMessage *result;
+ DBusError derror;
+
+ _mousepad_return_val_if_fail (g_path_is_absolute (working_directory), FALSE);
+ _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ dbus_error_init (&derror);
+
+ /* try to connect to the session bus */
+ connection = dbus_bus_get (DBUS_BUS_SESSION, &derror);
+ if (G_UNLIKELY (connection == NULL))
+ {
+ dbus_set_g_error (error, &derror);
+ dbus_error_free (&derror);
+ return FALSE;
+ }
+
+ /* generate the message */
+ message = dbus_message_new_method_call ("org.xfce.Mousepad", "/org/xfce/Mousepad",
+ "org.xfce.Mousepad", "LaunchFiles");
+ dbus_message_set_auto_start (message, FALSE);
+ dbus_message_append_args (message,
+ DBUS_TYPE_STRING, &working_directory,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &filenames, filenames ? g_strv_length (filenames) : 0,
+ DBUS_TYPE_INVALID);
+
+ /* send the message */
+ result = dbus_connection_send_with_reply_and_block (connection, message, -1, &derror);
+
+ /* release ref */
+ dbus_message_unref (message);
+
+ /* check if no reply was received */
+ if (result == NULL)
+ {
+#ifndef NDEBUG
+ /* set the error when debug is enabled */
+ dbus_set_g_error (error, &derror);
+#endif
+ dbus_error_free (&derror);
+ return FALSE;
+ }
+
+ /* but maybe we received an error */
+ if (dbus_message_get_type (result) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ dbus_set_error_from_message (&derror, result);
+ dbus_set_g_error (error, &derror);
+ dbus_message_unref (result);
+ dbus_error_free (&derror);
+ return FALSE;
+ }
+
+ /* it seems everything worked */
+ dbus_message_unref (result);
+
+ return TRUE;
+}
+
+
+
+#include <mousepad/mousepad-dbus-infos.h>
+
diff --git a/mousepad/mousepad-dbus.h b/mousepad/mousepad-dbus.h
new file mode 100644
index 0000000..50e5866
--- /dev/null
+++ b/mousepad/mousepad-dbus.h
@@ -0,0 +1,44 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.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
+ */
+
+#ifndef __MOUSEPAD_DBUS_H__
+#define __MOUSEPAD_DBUS_H__
+
+typedef struct _MousepadDBusServiceClass MousepadDBusServiceClass;
+typedef struct _MousepadDBusService MousepadDBusService;
+
+#include <mousepad/mousepad-application.h>
+
+#define MOUSEPAD_TYPE_DBUS_SERVICE (mousepad_dbus_service_get_type ())
+#define MOUSEPAD_DBUS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOUSEPAD_TYPE_DBUS_SERVICE, MousepadDBusService))
+#define MOUSEPAD_DBUS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPAD_TYPE_DBUS_SERVICE, MousepadDBusServiceClass))
+#define MOUSEPAD_IS_DBUS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOUSEPAD_TYPE_DBUS_SERVICE))
+#define MOUSEPAD_IS_DBUS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOUSEPAD_TYPE_DBUS_BRIGDE))
+#define MOUSEPAD_DBUS_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOUSEPAD_TYPE_DBUS_SERVICE, MousepadDBusServiceClass))
+
+GType mousepad_dbus_service_get_type (void) G_GNUC_CONST;
+
+gboolean
+mousepad_dbus_client_launch_files (gchar **filenames,
+ const gchar *working_directory,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* !__MOUSEPAD_DBUS_H__ */
diff --git a/mousepad/mousepad-file.c b/mousepad/mousepad-file.c
new file mode 100644
index 0000000..6854fa6
--- /dev/null
+++ b/mousepad/mousepad-file.c
@@ -0,0 +1,331 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <mousepad/mousepad-private.h>
+#include <mousepad/mousepad-file.h>
+
+
+
+gboolean
+mousepad_file_get_externally_modified (const gchar *filename,
+ gint mtime,
+ GError **error)
+{
+ gint fd;
+ struct stat statb;
+ gboolean modified = FALSE;
+
+ _mousepad_return_val_if_fail (filename != NULL, FALSE);
+ _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* open the file for reading */
+ fd = open (filename, O_RDONLY);
+ if (G_UNLIKELY (fd < 0))
+ {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_IO,
+ _("Failed to open \"%s\" for reading"), filename);
+ return FALSE;
+ }
+
+ /* check if the file has been modified */
+ if (G_LIKELY (fstat (fd, &statb) == 0))
+ modified = (mtime > 0 && statb.st_mtime != mtime);
+
+ /* close the file */
+ close (fd);
+
+ return modified;
+}
+
+
+
+gboolean
+mousepad_file_save_data (const gchar *filename,
+ const gchar *data,
+ gsize bytes,
+ gint *new_mtime,
+ GError **error)
+{
+ gint fd;
+ struct stat statb;
+ gboolean succeed = FALSE;
+ gint n, m, l;
+
+ _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ _mousepad_return_val_if_fail (filename != NULL, FALSE);
+ _mousepad_return_val_if_fail (data != NULL, FALSE);
+
+ /* try to create the file (this failes if it already exists) */
+ fd = open (filename, O_CREAT | O_EXCL | O_WRONLY, 0666);
+ if (fd < 0)
+ {
+ if (G_LIKELY (errno == EEXIST))
+ {
+ /* try to open an existing file for reading */
+ fd = open (filename, O_RDWR);
+ if (G_UNLIKELY (fd < 0))
+ {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_IO,
+ _("Failed to open \"%s\" for writing"), filename);
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* failed to create a file */
+ g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
+ _("Failed to create new file \"%s\""), filename);
+ return FALSE;
+ }
+ }
+
+ /* get the file information */
+ if (G_UNLIKELY (fstat (fd, &statb) != 0))
+ goto failed;
+
+ /* an extra check if we are allowed to write */
+ if (G_UNLIKELY ((statb.st_mode & 00222) == 0 && access (filename, W_OK) != 0))
+ {
+ g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
+ _("You don't have permission to write to \"%s\""), filename);
+ goto failed;
+ }
+
+ /* make sure the document is empty and we're writing at the beginning of the file */
+ if (G_LIKELY (lseek (fd, 0, SEEK_SET) != -1))
+ if (G_UNLIKELY (ftruncate (fd, 0) != 0))
+ {
+ g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
+ _("Failed to truncate \"%s\" before writing"), filename);
+ goto failed;
+ }
+
+ /* write the content to the file */
+ for (m = 0, n = bytes; m < n; )
+ {
+ /* write the data piece by piece */
+ l = write (fd, data + m, n - m);
+
+ if (G_UNLIKELY (l < 0))
+ {
+ /* just try again on EAGAIN/EINTR */
+ if (G_LIKELY (errno != EAGAIN && errno != EINTR))
+ {
+ g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
+ _("Failed to write data to \"%s\""), filename);
+ goto failed;
+ }
+ }
+ else
+ {
+ /* advance the offset */
+ m += l;
+ }
+ }
+
+ /* re-stat the mtime */
+ if (G_UNLIKELY (fstat (fd, &statb) == 0))
+ *new_mtime = statb.st_mtime;
+
+ /* mm.. it seems everything worked fine */
+ succeed = TRUE;
+
+failed:
+ /* close the file */
+ close (fd);
+
+ return succeed;
+}
+
+
+
+gboolean
+mousepad_file_read_to_buffer (const gchar *filename,
+ GtkTextBuffer *buffer,
+ gint *new_mtime,
+ gboolean *readonly,
+ GError **error)
+{
+ GtkTextIter start_iter;
+ struct stat statb;
+ gchar *content;
+ gint fd;
+ gboolean succeed = FALSE;
+
+ _mousepad_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
+ _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ _mousepad_return_val_if_fail (filename != NULL, FALSE);
+
+ /* get the start point in the buffer */
+ gtk_text_buffer_get_start_iter (buffer, &start_iter);
+
+ /* open the file for reading */
+ fd = open (filename, O_RDONLY);
+ if (G_UNLIKELY (fd < 0))
+ {
+ g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
+ _("Failed to open \"%s\" for reading"), filename);
+ return FALSE;
+ }
+
+ /* read the file information */
+ if (G_UNLIKELY (fstat (fd, &statb) < 0))
+ goto failed;
+
+ /* extra check if we're allowed to read the file */
+ if ((statb.st_mode & 00444) == 0 && access (filename, R_OK) != 0)
+ {
+ g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
+ _("You are not allowed to read \"%s\""), filename);
+ goto failed;
+ }
+
+ /* check if we're allowed to write the file */
+ *readonly = !((statb.st_mode & 00222) != 0 && access (filename, W_OK) == 0);
+
+#ifdef HAVE_MMAP
+ /* try mmap() for files not larger than 8MB */
+ content = (statb.st_size <= 8 * 1024 * 1024)
+ ? (gchar *) mmap (NULL, statb.st_size, PROT_READ, MAP_SHARED, fd, 0)
+ : MAP_FAILED;
+
+ if (G_LIKELY (content != (gchar *) MAP_FAILED))
+ {
+#ifdef HAVE_POSIX_MADVISE
+ /* tell the system that the data will be read sequentially */
+ posix_madvise (content, statb.st_size, POSIX_MADV_SEQUENTIAL);
+#endif
+
+ /* insert the file content */
+ gtk_text_buffer_insert (buffer, &start_iter, content, strlen (content));
+
+ /* unmap */
+ munmap (content, statb.st_size);
+ }
+ else
+#endif /* !HAVE_MMAP */
+ {
+ /* load the file content by using the glib function */
+ if (G_UNLIKELY (g_file_get_contents (filename, &content, NULL, error) == FALSE))
+ goto failed;
+
+ /* insert the file content */
+ gtk_text_buffer_insert (buffer, &start_iter, content, strlen (content));
+
+ /* cleanup */
+ g_free (content);
+ }
+
+ /* set the mtime of the document */
+ *new_mtime = statb.st_mtime;
+
+ /* everything went ok */
+ succeed = TRUE;
+
+failed:
+ /* close the file */
+ close (fd);
+
+ return succeed;
+}
+
+
+
+gboolean
+mousepad_file_is_writable (const gchar *filename,
+ GError **error)
+{
+ struct stat statb;
+ gint fd;
+ gboolean writable = FALSE;
+
+ _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ _mousepad_return_val_if_fail (filename != NULL, FALSE);
+
+ fd = open (filename, O_RDONLY);
+ if (G_UNLIKELY (fd < 0))
+ {
+ g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
+ _("Failed to open \"%s\" for reading"), filename);
+ return FALSE;
+ }
+
+ /* read the file information */
+ if (G_UNLIKELY (fstat (fd, &statb) < 0))
+ goto failed;
+
+ /* get the file information */
+ if (G_UNLIKELY (fstat (fd, &statb) != 0))
+ goto failed;
+
+ /* an extra check if we are allowed to write */
+ if ((statb.st_mode & 00222) != 0 && access (filename, W_OK) == 0)
+ {
+ writable = TRUE;
+ }
+ else
+ {
+ g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
+ _("You don't have permission to write to \"%s\""), filename);
+ goto failed;
+ }
+
+
+failed:
+ /* close the file */
+ close (fd);
+
+ return writable;
+}
+
+
+
diff --git a/mousepad/mousepad-file.h b/mousepad/mousepad-file.h
new file mode 100644
index 0000000..cabfda8
--- /dev/null
+++ b/mousepad/mousepad-file.h
@@ -0,0 +1,46 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.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
+ */
+
+#ifndef __MOUSEPAD_FILE_H__
+#define __MOUSEPAD_FILE_H__
+
+G_BEGIN_DECLS
+
+gboolean mousepad_file_get_externally_modified (const gchar *filename,
+ gint mtime,
+ GError **error);
+
+gboolean mousepad_file_save_data (const gchar *filename,
+ const gchar *data,
+ gsize bytes,
+ gint *new_mtime,
+ GError **error);
+
+gboolean mousepad_file_read_to_buffer (const gchar *filename,
+ GtkTextBuffer *buffer,
+ gint *new_mtime,
+ gboolean *readonly,
+ GError **error);
+
+gboolean mousepad_file_is_writable (const gchar *filename,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* !__MOUSEPAD_FILE_H__ */
diff --git a/mousepad/mousepad-preferences.c b/mousepad/mousepad-preferences.c
new file mode 100644
index 0000000..4a3f1d1
--- /dev/null
+++ b/mousepad/mousepad-preferences.c
@@ -0,0 +1,544 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.org>
+ * Copyright (c) 2007 Benedikt Meurer <benny at xfce.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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <glib-object.h>
+
+#include <mousepad/mousepad-private.h>
+#include <mousepad/mousepad-preferences.h>
+
+
+
+enum
+{
+ PROP_0,
+ PROP_AUTO_INDENT,
+ PROP_FONT_NAME,
+ PROP_LAST_WINDOW_HEIGHT,
+ PROP_LAST_WINDOW_WIDTH,
+ PROP_LINE_NUMBERS,
+ PROP_WORD_WRAP,
+ PROP_MISC_ALWAYS_SHOW_TABS,
+ PROP_MISC_CYCLE_TABS,
+ PROP_MISC_SHOW_FULL_PATH_IN_TITLE,
+ PROP_MISC_RECENT_MENU_LIMIT,
+ PROP_MISC_REMEMBER_GEOMETRY,
+ PROP_MISC_TAB_CLOSE_BUTTONS,
+ N_PROPERTIES,
+};
+
+static void transform_string_to_boolean (const GValue *src,
+ GValue *dst);
+static void transform_string_to_int (const GValue *src,
+ GValue *dst);
+static void mousepad_preferences_class_init (MousepadPreferencesClass *klass);
+static void mousepad_preferences_init (MousepadPreferences *preferences);
+static void mousepad_preferences_finalize (GObject *object);
+static void mousepad_preferences_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void mousepad_preferences_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void mousepad_preferences_queue_store (MousepadPreferences *preferences);
+static gboolean mousepad_preferences_load_idle (gpointer user_data);
+static gboolean mousepad_preferences_store_idle (gpointer user_data);
+static void mousepad_preferences_store_idle_destroy (gpointer user_data);
+
+struct _MousepadPreferencesClass
+{
+ GObjectClass __parent__;
+};
+
+struct _MousepadPreferences
+{
+ GObject __parent__;
+
+ GValue values[N_PROPERTIES];
+
+ gboolean loading_in_progress;
+
+ gint store_idle_id;
+};
+
+
+
+static GObjectClass *mousepad_preferences_parent_class;
+
+
+
+static void
+transform_string_to_boolean (const GValue *src,
+ GValue *dst)
+{
+ g_value_set_boolean (dst, strcmp (g_value_get_string (src), "FALSE") != 0);
+}
+
+
+
+static void
+transform_string_to_int (const GValue *src,
+ GValue *dst)
+{
+ g_value_set_int (dst, (gint) strtol (g_value_get_string (src), NULL, 10));
+}
+
+
+
+GType
+mousepad_preferences_get_type (void)
+{
+ static GType type = G_TYPE_INVALID;
+
+ if (G_UNLIKELY (type == G_TYPE_INVALID))
+ {
+ type = g_type_register_static_simple (G_TYPE_OBJECT,
+ I_("MousepadPreferences"),
+ sizeof (MousepadPreferencesClass),
+ (GClassInitFunc) mousepad_preferences_class_init,
+ sizeof (MousepadPreferences),
+ (GInstanceInitFunc) mousepad_preferences_init,
+ 0);
+ }
+
+ return type;
+}
+
+
+
+static void
+mousepad_preferences_class_init (MousepadPreferencesClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ /* determine the parent type class */
+ mousepad_preferences_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = mousepad_preferences_finalize;
+ gobject_class->get_property = mousepad_preferences_get_property;
+ gobject_class->set_property = mousepad_preferences_set_property;
+
+ /* register transformation functions */
+ if (!g_value_type_transformable (G_TYPE_STRING, G_TYPE_BOOLEAN))
+ g_value_register_transform_func (G_TYPE_STRING, G_TYPE_BOOLEAN, transform_string_to_boolean);
+ if (!g_value_type_transformable (G_TYPE_STRING, G_TYPE_INT))
+ g_value_register_transform_func (G_TYPE_STRING, G_TYPE_INT, transform_string_to_int);
+
+ g_object_class_install_property (gobject_class,
+ PROP_AUTO_INDENT,
+ g_param_spec_boolean ("auto-indent",
+ "auto-indent",
+ "auto-indent",
+ FALSE,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_FONT_NAME,
+ g_param_spec_string ("font-name",
+ "font-name",
+ "font-name",
+ NULL,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_LAST_WINDOW_HEIGHT,
+ g_param_spec_int ("last-window-height",
+ "last-window-height",
+ "last-window-height",
+ 1, G_MAXINT, 480,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_LAST_WINDOW_WIDTH,
+ g_param_spec_int ("last-window-width",
+ "last-window-width",
+ "last-window-width",
+ 1, G_MAXINT, 640,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_LINE_NUMBERS,
+ g_param_spec_boolean ("line-numbers",
+ "line-numbers",
+ "line-numbers",
+ FALSE,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_WORD_WRAP,
+ g_param_spec_boolean ("word-wrap",
+ "word-wrap",
+ "word-wrap",
+ FALSE,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_MISC_ALWAYS_SHOW_TABS,
+ g_param_spec_boolean ("misc-always-show-tabs",
+ "misc-always-show-tabs",
+ "misc-always-show-tabs",
+ FALSE,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_MISC_CYCLE_TABS,
+ g_param_spec_boolean ("misc-cycle-tabs",
+ "misc-cycle-tabs",
+ "misc-cycle-tabs",
+ FALSE,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_MISC_SHOW_FULL_PATH_IN_TITLE,
+ g_param_spec_boolean ("misc-show-full-path-in-title",
+ "misc-show-full-path-in-title",
+ "misc-show-full-path-in-title",
+ FALSE,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_MISC_RECENT_MENU_LIMIT,
+ g_param_spec_int ("misc-recent-menu-limit",
+ "misc-recent-menu-limit",
+ "misc-recent-menu-limit",
+ 1, G_MAXINT, 10,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_MISC_REMEMBER_GEOMETRY,
+ g_param_spec_boolean ("misc-remember-geometry",
+ "misc-remember-geometry",
+ "misc-remember-geometry",
+ TRUE,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_MISC_TAB_CLOSE_BUTTONS,
+ g_param_spec_boolean ("misc-tab-close-buttons",
+ "misc-tab-close-buttons",
+ "misc-tab-close-buttons",
+ TRUE,
+ EXO_PARAM_READWRITE));
+}
+
+
+
+static void
+mousepad_preferences_init (MousepadPreferences *preferences)
+{
+ /* load the settings */
+ mousepad_preferences_load_idle (preferences);
+}
+
+
+
+static void
+mousepad_preferences_finalize (GObject *object)
+{
+ MousepadPreferences *preferences = MOUSEPAD_PREFERENCES (object);
+ guint n;
+
+ /* flush preferences */
+ if (G_UNLIKELY (preferences->store_idle_id != 0))
+ {
+ mousepad_preferences_store_idle (preferences);
+ g_source_remove (preferences->store_idle_id);
+ }
+ /* release the property values */
+ for (n = 1; n < N_PROPERTIES; ++n)
+ if (G_IS_VALUE (preferences->values + n))
+ g_value_unset (preferences->values + n);
+
+ (*G_OBJECT_CLASS (mousepad_preferences_parent_class)->finalize) (object);
+}
+
+
+
+static void
+mousepad_preferences_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ MousepadPreferences *preferences = MOUSEPAD_PREFERENCES (object);
+ GValue *src;
+
+ src = preferences->values + prop_id;
+ if (G_IS_VALUE (src))
+ g_value_copy (src, value);
+ else
+ g_param_value_set_default (pspec, value);
+}
+
+
+
+static void
+mousepad_preferences_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ MousepadPreferences *preferences = MOUSEPAD_PREFERENCES (object);
+ GValue *dst;
+
+ dst = preferences->values + prop_id;
+ if (G_UNLIKELY (!G_IS_VALUE (dst)))
+ g_value_init (dst, pspec->value_type);
+
+ if (g_param_values_cmp (pspec, value, dst) != 0)
+ {
+ g_value_copy (value, dst);
+ mousepad_preferences_queue_store (preferences);
+ }
+}
+
+
+
+static void
+mousepad_preferences_queue_store (MousepadPreferences *preferences)
+{
+ if (preferences->store_idle_id == 0 && !preferences->loading_in_progress)
+ {
+ preferences->store_idle_id = g_idle_add_full (G_PRIORITY_LOW, mousepad_preferences_store_idle,
+ preferences, mousepad_preferences_store_idle_destroy);
+ }
+}
+
+
+
+static gchar*
+property_name_to_option_name (const gchar *property_name)
+{
+ const gchar *s;
+ gboolean upper = TRUE;
+ gchar *option;
+ gchar *t;
+
+ option = g_new (gchar, strlen (property_name) + 1);
+ for (s = property_name, t = option; *s != '\0'; ++s)
+ {
+ if (*s == '-')
+ {
+ upper = TRUE;
+ }
+ else if (upper)
+ {
+ *t++ = g_ascii_toupper (*s);
+ upper = FALSE;
+ }
+ else
+ {
+ *t++ = *s;
+ }
+ }
+ *t = '\0';
+
+ return option;
+}
+
+
+
+static gboolean
+mousepad_preferences_load_idle (gpointer user_data)
+{
+ MousepadPreferences *preferences = MOUSEPAD_PREFERENCES (user_data);
+ const gchar *string;
+ GParamSpec **specs;
+ GParamSpec *spec;
+ XfceRc *rc;
+ GValue dst = { 0, };
+ GValue src = { 0, };
+ gchar *option;
+ guint nspecs;
+ guint n;
+
+ rc = xfce_rc_config_open (XFCE_RESOURCE_CONFIG, "Mousepad/mousepadrc", TRUE);
+ if (G_UNLIKELY (rc == NULL))
+ {
+ g_warning ("Failed to load mousepad preferences.");
+ return FALSE;
+ }
+
+ g_object_freeze_notify (G_OBJECT (preferences));
+
+ xfce_rc_set_group (rc, "Configuration");
+
+ preferences->loading_in_progress = TRUE;
+
+ specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (preferences), &nspecs);
+
+ for (n = 0; n < nspecs; ++n)
+ {
+ spec = specs[n];
+
+ option = property_name_to_option_name (spec->name);
+ string = xfce_rc_read_entry (rc, option, NULL);
+ g_free (option);
+
+ if (G_UNLIKELY (string == NULL))
+ continue;
+
+ g_value_init (&src, G_TYPE_STRING);
+ g_value_set_static_string (&src, string);
+
+ if (spec->value_type == G_TYPE_STRING)
+ {
+ g_object_set_property (G_OBJECT (preferences), spec->name, &src);
+ }
+ else if (g_value_type_transformable (G_TYPE_STRING, spec->value_type))
+ {
+ g_value_init (&dst, spec->value_type);
+ if (g_value_transform (&src, &dst))
+ g_object_set_property (G_OBJECT (preferences), spec->name, &dst);
+ g_value_unset (&dst);
+ }
+ else
+ {
+ g_warning ("Failed to load property \"%s\"", spec->name);
+ }
+
+ g_value_unset (&src);
+ }
+ g_free (specs);
+
+ preferences->loading_in_progress = FALSE;
+
+ xfce_rc_close (rc);
+
+ g_object_thaw_notify (G_OBJECT (preferences));
+
+ return FALSE;
+}
+
+
+
+static gboolean
+mousepad_preferences_store_idle (gpointer user_data)
+{
+ MousepadPreferences *preferences = MOUSEPAD_PREFERENCES (user_data);
+ const gchar *string;
+ GParamSpec **specs;
+ GParamSpec *spec;
+ XfceRc *rc;
+ GValue dst = { 0, };
+ GValue src = { 0, };
+ gchar *option;
+ guint nspecs;
+ guint n;
+
+ rc = xfce_rc_config_open (XFCE_RESOURCE_CONFIG, "Mousepad/mousepadrc", FALSE);
+ if (G_UNLIKELY (rc == NULL))
+ {
+ g_warning ("Failed to store mousepad preferences.");
+ return FALSE;
+ }
+
+ xfce_rc_set_group (rc, "Configuration");
+
+ specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (preferences), &nspecs);
+
+ for (n = 0; n < nspecs; ++n)
+ {
+ spec = specs[n];
+
+ g_value_init (&dst, G_TYPE_STRING);
+
+ if (spec->value_type == G_TYPE_STRING)
+ {
+ g_object_get_property (G_OBJECT (preferences), spec->name, &dst);
+ }
+ else
+ {
+ g_value_init (&src, spec->value_type);
+ g_object_get_property (G_OBJECT (preferences), spec->name, &src);
+ g_value_transform (&src, &dst);
+ g_value_unset (&src);
+ }
+
+ /* determine the option name for the spec */
+ option = property_name_to_option_name (spec->name);
+
+ /* store the setting */
+ string = g_value_get_string (&dst);
+ if (G_LIKELY (string != NULL))
+ xfce_rc_write_entry (rc, option, string);
+
+ /* cleanup */
+ g_value_unset (&dst);
+ g_free (option);
+ }
+
+ /* cleanup */
+ xfce_rc_close (rc);
+ g_free (specs);
+
+ return FALSE;
+}
+
+
+
+static void
+mousepad_preferences_store_idle_destroy (gpointer user_data)
+{
+ MOUSEPAD_PREFERENCES (user_data)->store_idle_id = 0;
+}
+
+
+
+MousepadPreferences*
+mousepad_preferences_get (void)
+{
+ static MousepadPreferences *preferences = NULL;
+
+ if (G_UNLIKELY (preferences == NULL))
+ {
+ preferences = g_object_new (MOUSEPAD_TYPE_PREFERENCES, NULL);
+ g_object_add_weak_pointer (G_OBJECT (preferences),
+ (gpointer) &preferences);
+ }
+ else
+ {
+ g_object_ref (G_OBJECT (preferences));
+ }
+
+ return preferences;
+}
diff --git a/mousepad/mousepad-preferences.h b/mousepad/mousepad-preferences.h
new file mode 100644
index 0000000..c3d9d9b
--- /dev/null
+++ b/mousepad/mousepad-preferences.h
@@ -0,0 +1,43 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.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
+ */
+
+#ifndef __MOUSEPAD_PREFERENCIES_H__
+#define __MOUSEPAD_PREFERENCIES_H__
+
+#include <exo/exo.h>
+
+G_BEGIN_DECLS
+
+#define MOUSEPAD_TYPE_PREFERENCES (mousepad_preferences_get_type ())
+#define MOUSEPAD_PREFERENCES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOUSEPAD_TYPE_PREFERENCES, MousepadPreferences))
+#define MOUSEPAD_PREFERENCES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPAD_TYPE_PREFERENCES, MousepadPreferencesClass))
+#define MOUSEPAD_IS_PREFERENCES(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOUSEPAD_TYPE_PREFERENCES))
+#define MOUSEPAD_IS_PREFERENCES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOUSEPAD_TYPE_PREFERENCES))
+#define MOUSEPAD_PREFERENCES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOUSEPAD_TYPE_PREFERENCES, MousepadPreferencesClass))
+
+typedef struct _MousepadPreferencesClass MousepadPreferencesClass;
+typedef struct _MousepadPreferences MousepadPreferences;
+
+GType mousepad_preferences_get_type (void) G_GNUC_CONST;
+
+MousepadPreferences *mousepad_preferences_get (void);
+
+G_END_DECLS
+
+#endif /* !__MOUSEPAD_PREFERENCIES_H__ */
diff --git a/mousepad/mousepad-private.h b/mousepad/mousepad-private.h
new file mode 100644
index 0000000..7ed596e
--- /dev/null
+++ b/mousepad/mousepad-private.h
@@ -0,0 +1,75 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2006 Benedikt Meurer <benny at xfce.org>
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.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
+ */
+
+#ifndef __MOUSEPAD_PRIVATE_H__
+#define __MOUSEPAD_PRIVATE_H__
+
+#include <exo/exo.h>
+
+G_BEGIN_DECLS
+
+/* support macros for debugging */
+#ifndef NDEBUG
+#define _mousepad_assert(expr) g_assert (expr)
+#define _mousepad_assert_not_reached() g_assert_not_reached ()
+#define _mousepad_return_if_fail(expr) g_return_if_fail (expr)
+#define _mousepad_return_val_if_fail(expr, val) g_return_val_if_fail (expr, (val))
+#else
+#define _mousepad_assert(expr) G_STMT_START{ (void)0; }G_STMT_END
+#define _mousepad_assert_not_reached() G_STMT_START{ (void)0; }G_STMT_END
+#define _mousepad_return_if_fail(expr) G_STMT_START{ (void)0; }G_STMT_END
+#define _mousepad_return_val_if_fail(expr, val) G_STMT_START{ (void)0; }G_STMT_END
+#endif
+
+
+
+/* avoid trivial g_value_get_*() function calls */
+#ifdef NDEBUG
+#define g_value_get_boolean(v) (((const GValue *) (v))->data[0].v_int)
+#define g_value_get_char(v) (((const GValue *) (v))->data[0].v_int)
+#define g_value_get_uchar(v) (((const GValue *) (v))->data[0].v_uint)
+#define g_value_get_int(v) (((const GValue *) (v))->data[0].v_int)
+#define g_value_get_uint(v) (((const GValue *) (v))->data[0].v_uint)
+#define g_value_get_long(v) (((const GValue *) (v))->data[0].v_long)
+#define g_value_get_ulong(v) (((const GValue *) (v))->data[0].v_ulong)
+#define g_value_get_int64(v) (((const GValue *) (v))->data[0].v_int64)
+#define g_value_get_uint64(v) (((const GValue *) (v))->data[0].v_uint64)
+#define g_value_get_enum(v) (((const GValue *) (v))->data[0].v_long)
+#define g_value_get_flags(v) (((const GValue *) (v))->data[0].v_ulong)
+#define g_value_get_float(v) (((const GValue *) (v))->data[0].v_float)
+#define g_value_get_double(v) (((const GValue *) (v))->data[0].v_double)
+#define g_value_get_string(v) (((const GValue *) (v))->data[0].v_pointer)
+#define g_value_get_param(v) (((const GValue *) (v))->data[0].v_pointer)
+#define g_value_get_boxed(v) (((const GValue *) (v))->data[0].v_pointer)
+#define g_value_get_pointer(v) (((const GValue *) (v))->data[0].v_pointer)
+#define g_value_get_object(v) (((const GValue *) (v))->data[0].v_pointer)
+#endif
+
+
+
+/* don't use the invalid property warning since testing in debug builds is enough */
+#ifndef G_ENABLE_DEBUG
+#undef G_OBJECT_WARN_INVALID_PROPERTY_ID
+#define G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec) G_STMT_START{ (void)0; }G_STMT_END
+#endif
+
+G_END_DECLS
+
+#endif /* !__MOUSEPAD_PRIVATE_H__ */
diff --git a/mousepad/mousepad-screen.c b/mousepad/mousepad-screen.c
new file mode 100644
index 0000000..73ad87d
--- /dev/null
+++ b/mousepad/mousepad-screen.c
@@ -0,0 +1,607 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+#include <mousepad/mousepad-private.h>
+#include <mousepad/mousepad-file.h>
+#include <mousepad/mousepad-view.h>
+#include <mousepad/mousepad-screen.h>
+
+
+
+static void mousepad_screen_class_init (MousepadScreenClass *klass);
+static void mousepad_screen_init (MousepadScreen *screen);
+static void mousepad_screen_finalize (GObject *object);
+static void mousepad_screen_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void mousepad_screen_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void mousepad_screen_set_font (MousepadScreen *screen,
+ const gchar *font_name);
+static void mousepad_screen_set_word_wrap (MousepadScreen *screen,
+ gboolean word_wrap);
+static void mousepad_screen_modified_changed (GtkTextBuffer *buffer,
+ MousepadScreen *screen);
+static void mousepad_screen_has_selection (GtkTextBuffer *buffer,
+ GParamSpec *pspec,
+ MousepadScreen *screen);
+
+
+
+enum
+{
+ PROP_0,
+ PROP_AUTO_INDENT,
+ PROP_FILENAME,
+ PROP_FONT_NAME,
+ PROP_LINE_NUMBERS,
+ PROP_TITLE,
+ PROP_WORD_WRAP,
+};
+
+enum
+{
+ SELECTION_CHANGED,
+ MODIFIED_CHANGED,
+ LAST_SIGNAL,
+};
+
+struct _MousepadScreenClass
+{
+ GtkScrolledWindowClass __parent__;
+
+ /* signals */
+ void (*selection_changed) (MousepadScreen *screen,
+ gboolean selected);
+ void (*modified_changed) (MousepadScreen *screen,
+ gboolean modified);
+};
+
+struct _MousepadScreen
+{
+ GtkScrolledWindow __parent__;
+
+ GtkWidget *textview;
+
+ /* file and display name */
+ gchar *filename;
+ gchar *display_name;
+
+ /* last document modified time */
+ time_t mtime;
+};
+
+
+
+static guint screen_signals[LAST_SIGNAL];
+static GObjectClass *mousepad_screen_parent_class;
+
+
+
+GtkWidget *
+mousepad_screen_new (void)
+{
+ return g_object_new (MOUSEPAD_TYPE_SCREEN, NULL);
+}
+
+
+
+GType
+mousepad_screen_get_type (void)
+{
+ static GType type = G_TYPE_INVALID;
+
+ if (G_UNLIKELY (type == G_TYPE_INVALID))
+ {
+ type = g_type_register_static_simple (GTK_TYPE_SCROLLED_WINDOW,
+ I_("MousepadScreen"),
+ sizeof (MousepadScreenClass),
+ (GClassInitFunc) mousepad_screen_class_init,
+ sizeof (MousepadScreen),
+ (GInstanceInitFunc) mousepad_screen_init,
+ 0);
+ }
+
+ return type;
+}
+
+
+
+static void
+mousepad_screen_class_init (MousepadScreenClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ mousepad_screen_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = mousepad_screen_finalize;
+ gobject_class->get_property = mousepad_screen_get_property;
+ gobject_class->set_property = mousepad_screen_set_property;
+
+ g_object_class_install_property (gobject_class,
+ PROP_AUTO_INDENT,
+ g_param_spec_boolean ("auto-indent",
+ "auto-indent",
+ "auto-indent",
+ FALSE,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_FILENAME,
+ g_param_spec_string ("filename",
+ "filename",
+ "filename",
+ NULL,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_FONT_NAME,
+ g_param_spec_string ("font-name",
+ "font-name",
+ "font-name",
+ "Bitstream Vera Sans Mono 10",
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_LINE_NUMBERS,
+ g_param_spec_boolean ("line-numbers",
+ "line-numbers",
+ "line-numbers",
+ FALSE,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_TITLE,
+ g_param_spec_string ("title",
+ "title",
+ "title",
+ NULL,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_WORD_WRAP,
+ g_param_spec_boolean ("word-wrap",
+ "word-wrap",
+ "word-wrap",
+ FALSE,
+ EXO_PARAM_READWRITE));
+
+ screen_signals[SELECTION_CHANGED] =
+ g_signal_new (I_("selection-changed"),
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+
+ screen_signals[MODIFIED_CHANGED] =
+ g_signal_new (I_("modified-changed"),
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+}
+
+
+
+static void
+mousepad_screen_init (MousepadScreen *screen)
+{
+ GtkTextBuffer *buffer;
+
+ /* initialize the variables */
+ screen->filename = NULL;
+ screen->display_name = NULL;
+ screen->mtime = 0;
+
+ /* setup the scolled window */
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (screen),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (screen), NULL);
+ gtk_scrolled_window_set_vadjustment (GTK_SCROLLED_WINDOW (screen), NULL);
+
+ /* setup the textview */
+ screen->textview = g_object_new (MOUSEPAD_TYPE_VIEW, NULL);
+ gtk_container_add (GTK_CONTAINER (screen), screen->textview);
+ gtk_widget_show (screen->textview);
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (screen->textview));
+ g_signal_connect (G_OBJECT (buffer), "modified-changed",
+ G_CALLBACK (mousepad_screen_modified_changed), screen);
+ g_signal_connect (G_OBJECT (buffer), "notify::has-selection",
+ G_CALLBACK (mousepad_screen_has_selection), screen);
+
+}
+
+
+
+static void
+mousepad_screen_finalize (GObject *object)
+{
+ MousepadScreen *screen = MOUSEPAD_SCREEN (object);
+
+ g_free (screen->filename);
+ g_free (screen->display_name);
+
+ (*G_OBJECT_CLASS (mousepad_screen_parent_class)->finalize) (object);
+}
+
+
+
+static void
+mousepad_screen_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ MousepadScreen *screen = MOUSEPAD_SCREEN (object);
+
+ switch (prop_id)
+ {
+ case PROP_FILENAME:
+ g_value_set_static_string (value, mousepad_screen_get_filename (screen));
+ break;
+
+ case PROP_TITLE:
+ g_value_set_static_string (value, mousepad_screen_get_title (screen, FALSE));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+
+static void
+mousepad_screen_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ MousepadScreen *screen = MOUSEPAD_SCREEN (object);
+
+ switch (prop_id)
+ {
+ case PROP_FONT_NAME:
+ mousepad_screen_set_font (screen, g_value_get_string (value));
+ break;
+
+ case PROP_LINE_NUMBERS:
+ mousepad_view_set_show_line_numbers (MOUSEPAD_VIEW (screen->textview),
+ g_value_get_boolean (value));
+ break;
+
+ case PROP_AUTO_INDENT:
+ mousepad_view_set_auto_indent (MOUSEPAD_VIEW (screen->textview),
+ g_value_get_boolean (value));
+ break;
+
+ case PROP_WORD_WRAP:
+ mousepad_screen_set_word_wrap (screen, g_value_get_boolean (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+
+static void
+mousepad_screen_set_font (MousepadScreen *screen,
+ const gchar *font_name)
+{
+ PangoFontDescription *font_desc;
+
+ _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
+
+ if (G_LIKELY (font_name))
+ {
+ font_desc = pango_font_description_from_string (font_name);
+ gtk_widget_modify_font (GTK_WIDGET (screen->textview), font_desc);
+ pango_font_description_free (font_desc);
+ }
+}
+
+
+
+static void
+mousepad_screen_set_word_wrap (MousepadScreen *screen,
+ gboolean word_wrap)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
+
+ gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (screen->textview),
+ word_wrap ? GTK_WRAP_WORD : GTK_WRAP_NONE);
+}
+
+
+
+static void
+mousepad_screen_modified_changed (GtkTextBuffer *buffer,
+ MousepadScreen *screen)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
+
+ g_signal_emit (G_OBJECT (screen), screen_signals[MODIFIED_CHANGED], 0);
+}
+
+
+
+static void
+mousepad_screen_has_selection (GtkTextBuffer *buffer,
+ GParamSpec *pspec,
+ MousepadScreen *screen)
+{
+ gboolean selected;
+
+ _mousepad_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
+ _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
+
+ g_object_get (G_OBJECT (buffer), "has-selection", &selected, NULL);
+
+ g_signal_emit (G_OBJECT (screen), screen_signals[SELECTION_CHANGED], 0, selected);
+}
+
+
+
+void
+mousepad_screen_set_filename (MousepadScreen *screen,
+ const gchar *filename)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
+ _mousepad_return_if_fail (filename != NULL);
+
+ /* cleanup the old names */
+ g_free (screen->filename);
+ g_free (screen->display_name);
+
+ /* create the new names */
+ screen->filename = g_strdup (filename);
+ screen->display_name = g_filename_display_basename (filename);
+
+ /* tell the listeners */
+ g_object_notify (G_OBJECT (screen), "title");
+}
+
+
+
+gboolean
+mousepad_screen_open_file (MousepadScreen *screen,
+ const gchar *filename,
+ GError **error)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter iter;
+ gboolean succeed = FALSE;
+ gboolean readonly;
+ gint new_mtime;
+
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), FALSE);
+ _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ _mousepad_return_val_if_fail (filename != NULL, FALSE);
+
+ /* get the buffer */
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (screen->textview));
+
+ /* we're going to add the file content */
+ gtk_text_buffer_begin_user_action (buffer);
+
+ /* insert the file content */
+ if (mousepad_file_read_to_buffer (filename,
+ buffer,
+ &new_mtime,
+ &readonly,
+ error))
+ {
+ /* set the new filename */
+ mousepad_screen_set_filename (screen, filename);
+
+ /* set the new mtime */
+ screen->mtime = new_mtime;
+
+ /* whether the textview is editable */
+ gtk_text_view_set_editable (GTK_TEXT_VIEW (screen->textview), !readonly);
+
+ /* move the cursors to the first place and pretend nothing happend */
+ gtk_text_buffer_get_start_iter (buffer, &iter);
+ gtk_text_buffer_place_cursor (buffer, &iter);
+ gtk_text_buffer_set_modified (buffer, FALSE);
+ gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (screen->textview), &iter, 0, FALSE, 0, 0);
+
+ /* it worked out very well */
+ succeed = TRUE;
+ }
+
+ /* and we're done */
+ gtk_text_buffer_end_user_action (buffer);
+
+ return succeed;
+}
+
+
+
+gboolean
+mousepad_screen_save_file (MousepadScreen *screen,
+ GError **error)
+{
+ gchar *content;
+ gchar *converted = NULL;
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
+ gsize bytes;
+ gint new_mtime;
+ gboolean succeed = FALSE;
+
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), FALSE);
+ _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ _mousepad_return_val_if_fail (screen->filename != NULL, FALSE);
+
+ /* get the buffer */
+ buffer = mousepad_screen_get_text_buffer (screen);
+
+ /* get the textview content */
+ gtk_text_buffer_get_bounds (buffer, &start, &end);
+ content = gtk_text_buffer_get_slice (buffer, &start, &end, TRUE);
+
+ if (G_LIKELY (content != NULL))
+ {
+ /* TODO: fix the file encoding here, basic utf8 for testing */
+ converted = g_convert (content,
+ strlen (content),
+ "UTF-8",
+ "UTF-8",
+ NULL,
+ &bytes,
+ error);
+
+ /* cleanup */
+ g_free (content);
+
+ if (G_LIKELY (converted != NULL))
+ {
+ succeed = mousepad_file_save_data (screen->filename, converted, bytes,
+ &new_mtime, error);
+
+ /* cleanup */
+ g_free (converted);
+
+ /* saving work w/o problems */
+ if (G_LIKELY (succeed))
+ {
+ /* set the new mtime */
+ screen->mtime = new_mtime;
+
+ /* nothing happend */
+ gtk_text_buffer_set_modified (buffer, FALSE);
+
+ /* we were allowed to write */
+ gtk_text_view_set_editable (GTK_TEXT_VIEW (screen->textview), TRUE);
+
+ /* emit the modified-changed signal */
+ mousepad_screen_modified_changed (NULL, screen);
+ }
+ }
+ }
+
+ return succeed;
+}
+
+
+
+const gchar *
+mousepad_screen_get_title (MousepadScreen *screen,
+ gboolean show_full_path)
+{
+ const gchar *title;
+
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), NULL);
+
+ if (G_UNLIKELY (show_full_path && screen->filename))
+ title = screen->filename;
+ else if (screen->display_name)
+ title = screen->display_name;
+ else
+ title = _("Untitled");
+
+ return title;
+}
+
+
+
+const gchar *
+mousepad_screen_get_filename (MousepadScreen *screen)
+{
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), NULL);
+
+ return screen->filename;
+}
+
+
+
+gboolean
+mousepad_screen_get_externally_modified (MousepadScreen *screen,
+ GError **error)
+{
+ gboolean modified;
+
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), FALSE);
+ _mousepad_return_val_if_fail (screen->filename != NULL, FALSE);
+
+ /* check if the file has been modified */
+ modified = mousepad_file_get_externally_modified (screen->filename, screen->mtime, error);
+
+ return modified;
+}
+
+
+
+gboolean
+mousepad_screen_get_modified (MousepadScreen *screen)
+{
+ GtkTextBuffer *buffer;
+
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), FALSE);
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (screen->textview));
+
+ return gtk_text_buffer_get_modified (buffer);
+}
+
+
+
+GtkTextView *
+mousepad_screen_get_text_view (MousepadScreen *screen)
+{
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), NULL);
+
+ return GTK_TEXT_VIEW (screen->textview);
+}
+
+
+
+GtkTextBuffer *
+mousepad_screen_get_text_buffer (MousepadScreen *screen)
+{
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), NULL);
+
+ return gtk_text_view_get_buffer (GTK_TEXT_VIEW (screen->textview));
+}
diff --git a/mousepad/mousepad-screen.h b/mousepad/mousepad-screen.h
new file mode 100644
index 0000000..9017424
--- /dev/null
+++ b/mousepad/mousepad-screen.h
@@ -0,0 +1,67 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.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
+ */
+
+#ifndef __MOUSEPAD_SCREEN_H__
+#define __MOUSEPAD_SCREEN_H__
+
+G_BEGIN_DECLS
+
+#define MOUSEPAD_SCROLL_MARGIN 0.02
+
+#define MOUSEPAD_TYPE_SCREEN (mousepad_screen_get_type ())
+#define MOUSEPAD_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOUSEPAD_TYPE_SCREEN, MousepadScreen))
+#define MOUSEPAD_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPAD_TYPE_SCREEN, MousepadScreenClass))
+#define MOUSEPAD_IS_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOUSEPAD_TYPE_SCREEN))
+#define MOUSEPAD_IS_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPADL_TYPE_SCREEN))
+#define MOUSEPAD_SCREEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOUSEPAD_TYPE_SCREEN, MousepadScreenClass))
+
+typedef struct _MousepadScreenClass MousepadScreenClass;
+typedef struct _MousepadScreen MousepadScreen;
+
+GType mousepad_screen_get_type (void) G_GNUC_CONST;
+
+GtkWidget *mousepad_screen_new (void);
+
+void mousepad_screen_set_filename (MousepadScreen *screen,
+ const gchar *filename);
+
+gboolean mousepad_screen_open_file (MousepadScreen *screen,
+ const gchar *filename,
+ GError **error);
+
+gboolean mousepad_screen_save_file (MousepadScreen *screen,
+ GError **error);
+
+const gchar *mousepad_screen_get_title (MousepadScreen *screen,
+ gboolean show_full_path);
+
+const gchar *mousepad_screen_get_filename (MousepadScreen *screen);
+
+gboolean mousepad_screen_get_externally_modified (MousepadScreen *screen,
+ GError **error);
+
+GtkTextView *mousepad_screen_get_text_view (MousepadScreen *screen);
+
+GtkTextBuffer *mousepad_screen_get_text_buffer (MousepadScreen *screen);
+
+gboolean mousepad_screen_get_modified (MousepadScreen *screen);
+
+G_END_DECLS
+
+#endif /* !__MOUSEPAD_SCREEN_H__ */
diff --git a/mousepad/mousepad-tab-label.c b/mousepad/mousepad-tab-label.c
new file mode 100644
index 0000000..0a8042f
--- /dev/null
+++ b/mousepad/mousepad-tab-label.c
@@ -0,0 +1,265 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <mousepad/mousepad-private.h>
+#include <mousepad/mousepad-preferences.h>
+#include <mousepad/mousepad-tab-label.h>
+
+static void mousepad_tab_label_class_init (MousepadTabLabelClass *klass);
+static void mousepad_tab_label_init (MousepadTabLabel *window);
+static void mousepad_tab_label_finalize (GObject *object);
+static void mousepad_tab_label_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void mousepad_tab_label_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void mousepad_tab_label_close_tab (GtkWidget *widget,
+ MousepadTabLabel *label);
+
+
+enum
+{
+ PROP_0,
+ PROP_TITLE,
+ PROP_TOOLTIP,
+};
+
+enum
+{
+ CLOSE_TAB,
+ LAST_SIGNAL,
+};
+
+struct _MousepadTabLabelClass
+{
+ GtkHBoxClass __parent__;
+
+ /* signals */
+ void (*close_tab) (MousepadTabLabel *label);
+};
+
+struct _MousepadTabLabel
+{
+ GtkHBox __parent__;
+
+ MousepadPreferences *preferences;
+
+ GtkTooltips *tooltips;
+ GtkWidget *ebox;
+ GtkWidget *label;
+};
+
+
+static GObjectClass *mousepad_tab_label_parent_class;
+static guint label_signals[LAST_SIGNAL];
+
+
+
+GtkWidget *
+mousepad_tab_label_new (void)
+{
+ return g_object_new (MOUSEPAD_TYPE_TAB_LABEL, NULL);
+}
+
+
+
+GType
+mousepad_tab_label_get_type (void)
+{
+ static GType type = G_TYPE_INVALID;
+
+ if (G_UNLIKELY (type == G_TYPE_INVALID))
+ {
+ type = g_type_register_static_simple (GTK_TYPE_HBOX,
+ I_("MousepadTabLabel"),
+ sizeof (MousepadTabLabelClass),
+ (GClassInitFunc) mousepad_tab_label_class_init,
+ sizeof (MousepadTabLabel),
+ (GInstanceInitFunc) mousepad_tab_label_init,
+ 0);
+ }
+
+ return type;
+}
+
+
+
+static void
+mousepad_tab_label_class_init (MousepadTabLabelClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ mousepad_tab_label_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = mousepad_tab_label_finalize;
+ gobject_class->get_property = mousepad_tab_label_get_property;
+ gobject_class->set_property = mousepad_tab_label_set_property;
+
+ g_object_class_install_property (gobject_class,
+ PROP_TITLE,
+ g_param_spec_string ("title",
+ "title",
+ "title",
+ NULL,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_TOOLTIP,
+ g_param_spec_string ("tooltip",
+ "tooltip",
+ "tooltip",
+ NULL,
+ EXO_PARAM_READWRITE));
+
+ label_signals[CLOSE_TAB] =
+ g_signal_new ("close-tab",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (MousepadTabLabelClass, close_tab),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+
+
+static void
+mousepad_tab_label_init (MousepadTabLabel *label)
+{
+ GtkWidget *button;
+ GtkWidget *image;
+
+ label->preferences = mousepad_preferences_get ();
+
+ label->tooltips = gtk_tooltips_new ();
+ g_object_ref (G_OBJECT (label->tooltips));
+ gtk_object_sink (GTK_OBJECT (label->tooltips));
+
+ gtk_widget_push_composite_child ();
+
+ label->ebox = g_object_new (GTK_TYPE_EVENT_BOX, "border-width", 2, NULL);
+ GTK_WIDGET_SET_FLAGS (label->ebox, GTK_NO_WINDOW);
+ gtk_box_pack_start (GTK_BOX (label), label->ebox, TRUE, TRUE, 0);
+ gtk_widget_show (label->ebox);
+
+ label->label = g_object_new (GTK_TYPE_LABEL,
+ "selectable", FALSE,
+ "xalign", 0.0, NULL);
+ gtk_container_add (GTK_CONTAINER (label->ebox), label->label);
+ gtk_widget_show (label->label);
+
+ button = gtk_button_new ();
+ gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+ gtk_container_set_border_width (GTK_CONTAINER (button), 0);
+ gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
+ GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_DEFAULT|GTK_CAN_FOCUS);
+ gtk_tooltips_set_tip (label->tooltips, button, _("Close this tab"), NULL);
+ gtk_box_pack_start (GTK_BOX (label), button, FALSE, FALSE, 0);
+ exo_binding_new (G_OBJECT (label->preferences), "misc-tab-close-buttons", G_OBJECT (button), "visible");
+
+ image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
+ gtk_container_add (GTK_CONTAINER (button), image);
+ gtk_widget_show (image);
+
+ g_signal_connect (G_OBJECT (button), "clicked",
+ G_CALLBACK (mousepad_tab_label_close_tab), label);
+
+ gtk_widget_pop_composite_child ();
+}
+
+
+
+static void
+mousepad_tab_label_finalize (GObject *object)
+{
+ MousepadTabLabel *label = MOUSEPAD_TAB_LABEL (object);
+
+ g_object_unref (G_OBJECT (label->preferences));
+ g_object_unref (G_OBJECT (label->tooltips));
+
+ (*G_OBJECT_CLASS (mousepad_tab_label_parent_class)->finalize) (object);
+}
+
+
+
+static void
+mousepad_tab_label_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ MousepadTabLabel *label = MOUSEPAD_TAB_LABEL (object);
+
+ switch (prop_id)
+ {
+ case PROP_TITLE:
+ g_object_get_property (G_OBJECT (label->label), "label", value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+
+static void
+mousepad_tab_label_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ MousepadTabLabel *label = MOUSEPAD_TAB_LABEL (object);
+ const gchar *title;
+
+ switch (prop_id)
+ {
+ case PROP_TITLE:
+ title = g_value_get_string (value);
+ gtk_label_set_text (GTK_LABEL (label->label), title);
+ break;
+
+ case PROP_TOOLTIP:
+ title = g_value_get_string (value);
+ gtk_tooltips_set_tip (label->tooltips, label->ebox, title, NULL);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+
+static void
+mousepad_tab_label_close_tab (GtkWidget *widget,
+ MousepadTabLabel *label)
+{
+ g_signal_emit (G_OBJECT (label), label_signals[CLOSE_TAB], 0);
+}
diff --git a/mousepad/mousepad-tab-label.h b/mousepad/mousepad-tab-label.h
new file mode 100644
index 0000000..1ce64d5
--- /dev/null
+++ b/mousepad/mousepad-tab-label.h
@@ -0,0 +1,41 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.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
+ */
+
+#ifndef __MOUSEPAD_TAB_LABEL_H__
+#define __MOUSEPAD_TAB_LABEL_H__
+
+G_BEGIN_DECLS
+
+#define MOUSEPAD_TYPE_TAB_LABEL (mousepad_tab_label_get_type ())
+#define MOUSEPAD_TAB_LABEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOUSEPAD_TYPE_TAB_LABEL, MousepadTabLabel))
+#define MOUSEPAD_TAB_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPAD_TYPE_TAB_LABEL, MousepadTabLabelClass))
+#define MOUSEPAD_IS_TAB_LABEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOUSEPAD_TYPE_TAB_LABEL))
+#define MOUSEPAD_IS_TAB_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPADL_TYPE_TAB_LABEL))
+#define MOUSEPAD_TAB_LABEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOUSEPAD_TYPE_TAB_LABEL, MousepadTabLabelClass))
+
+typedef struct _MousepadTabLabelClass MousepadTabLabelClass;
+typedef struct _MousepadTabLabel MousepadTabLabel;
+
+GType mousepad_tab_label_get_type (void) G_GNUC_CONST;
+
+GtkWidget *mousepad_tab_label_new (void);
+
+G_END_DECLS
+
+#endif /* !__MOUSEPAD_TAB_LABEL_H__ */
diff --git a/mousepad/mousepad-view.c b/mousepad/mousepad-view.c
new file mode 100644
index 0000000..d4f3ce0
--- /dev/null
+++ b/mousepad/mousepad-view.c
@@ -0,0 +1,554 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <gdk/gdkkeysyms.h>
+
+#include <mousepad/mousepad-private.h>
+#include <mousepad/mousepad-view.h>
+
+
+
+static void mousepad_view_class_init (MousepadViewClass *klass);
+static void mousepad_view_init (MousepadView *view);
+static void mousepad_view_finalize (GObject *object);
+static gboolean mousepad_view_key_press_event (GtkWidget *widget,
+ GdkEventKey *event);
+static void mousepad_view_indent_lines (MousepadView *view,
+ GtkTextIter *start,
+ GtkTextIter *end,
+ gboolean indent);
+static gchar *mousepad_view_compute_indentation (MousepadView *view,
+ GtkTextIter *iter);
+static gint mousepad_view_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static void mousepad_view_get_lines (GtkTextView *text_view,
+ gint first_y,
+ gint last_y,
+ GArray **pixels,
+ GArray **numbers,
+ gint *countp);
+
+
+
+struct _MousepadViewClass
+{
+ GtkTextViewClass __parent__;
+};
+
+struct _MousepadView
+{
+ GtkTextView __parent__;
+
+ gboolean auto_indent;
+ gboolean line_numbers;
+};
+
+
+
+static GObjectClass *mousepad_view_parent_class;
+
+
+
+GType
+mousepad_view_get_type (void)
+{
+ static GType type = G_TYPE_INVALID;
+
+ if (G_UNLIKELY (type == G_TYPE_INVALID))
+ {
+ type = g_type_register_static_simple (GTK_TYPE_TEXT_VIEW,
+ I_("MousepadView"),
+ sizeof (MousepadViewClass),
+ (GClassInitFunc) mousepad_view_class_init,
+ sizeof (MousepadView),
+ (GInstanceInitFunc) mousepad_view_init,
+ 0);
+ }
+
+ return type;
+}
+
+
+
+static void
+mousepad_view_class_init (MousepadViewClass *klass)
+{
+ GObjectClass *gobject_class;
+ GtkWidgetClass *widget_class;
+
+ mousepad_view_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = mousepad_view_finalize;
+
+ widget_class = GTK_WIDGET_CLASS (klass);
+ widget_class->key_press_event = mousepad_view_key_press_event;
+ widget_class->expose_event = mousepad_view_expose;
+}
+
+
+
+static void
+mousepad_view_init (MousepadView *view)
+{
+ /* empty */
+}
+
+
+
+static void
+mousepad_view_finalize (GObject *object)
+{
+ (*G_OBJECT_CLASS (mousepad_view_parent_class)->finalize) (object);
+}
+
+
+
+static gboolean
+mousepad_view_key_press_event (GtkWidget *widget,
+ GdkEventKey *event)
+{
+ MousepadView *view = MOUSEPAD_VIEW (widget);
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
+ GtkTextMark *mark;
+ guint modifiers;
+ guint key = event->keyval;
+ gchar *string;
+ gboolean has_selection;
+
+ /* get the textview buffer */
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
+
+ /* check if we have to indent when the user pressed enter */
+ if ((key == GDK_Return || key == GDK_KP_Enter) &&
+ !(event->state & GDK_SHIFT_MASK) && view->auto_indent)
+ {
+ /* get the iter */
+ mark = gtk_text_buffer_get_insert (buffer);
+ gtk_text_buffer_get_iter_at_mark (buffer, &start, mark);
+
+ /* get the string of tabs and spaces we're going to indent */
+ string = mousepad_view_compute_indentation (view, &start);
+
+ if (string != NULL)
+ {
+ /* tell others we're going to change the buffer */
+ gtk_text_buffer_begin_user_action (buffer);
+
+ /* insert the indent characters */
+ gtk_text_buffer_insert (buffer, &start, "\n", 1);
+ gtk_text_buffer_insert (buffer, &start, string, strlen (string));
+ g_free (string);
+
+ /* we're finished */
+ gtk_text_buffer_end_user_action (buffer);
+
+ /* make sure the new string is visible for the user */
+ gtk_text_view_scroll_mark_onscreen (GTK_TEXT_VIEW (widget), mark);
+
+ return TRUE;
+ }
+ }
+
+ /* get the modifiers state */
+ modifiers = gtk_accelerator_get_default_mod_mask ();
+
+ /* check if the user pressed the tab button for indenting lines */
+ if ((key == GDK_Tab || key == GDK_KP_Tab || key == GDK_ISO_Left_Tab) &&
+ ((event->state & modifiers) == 0 || (event->state & modifiers) == GDK_SHIFT_MASK))
+ {
+ /* get the selected text */
+ has_selection = gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
+
+ /* Shift + Tab */
+ if (event->state & GDK_SHIFT_MASK)
+ {
+ /* unindent */
+ mousepad_view_indent_lines (view, &start, &end, FALSE);
+
+ return TRUE;
+ }
+
+ if (has_selection &&
+ ((gtk_text_iter_starts_line (&start) && gtk_text_iter_ends_line (&end)) ||
+ (gtk_text_iter_get_line (&start) != gtk_text_iter_get_line (&end))))
+ {
+ /* indent */
+ mousepad_view_indent_lines (view, &start, &end, TRUE);
+
+ return TRUE;
+ }
+ }
+
+ return (*GTK_WIDGET_CLASS (mousepad_view_parent_class)->key_press_event) (widget, event);
+}
+
+
+
+static void
+mousepad_view_indent_lines (MousepadView *view,
+ GtkTextIter *start,
+ GtkTextIter *end,
+ gboolean indent)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter iter, iter2;
+ gint start_line, end_line;
+ gint i, spaces, tabs;
+
+ /* get the textview buffer */
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+ /* get the line numbers for the start and end iter */
+ start_line = gtk_text_iter_get_line (start);
+ end_line = gtk_text_iter_get_line (end);
+
+ /* check if the last line does not exist of 'invisible' characters */
+ if ((gtk_text_iter_get_visible_line_offset (end) == 0) && (end_line > start_line))
+ end_line--;
+
+ /* tell everybody we're going to change the buffer */
+ gtk_text_buffer_begin_user_action (buffer);
+
+ /* insert a tab in front of each line */
+ for (i = start_line; i <= end_line; i++)
+ {
+ /* get the iter of the line we're going to indent */
+ gtk_text_buffer_get_iter_at_line (buffer, &iter, i);
+
+ /* don't (un)indent empty lines */
+ if (gtk_text_iter_ends_line (&iter))
+ continue;
+
+ if (indent)
+ {
+ /* insert the tab */
+ gtk_text_buffer_insert (buffer, &iter, "\t", -1);
+ }
+ else /* unindent */
+ {
+ if (gtk_text_iter_get_char (&iter) == '\t')
+ {
+ /* remove the tab */
+ iter2 = iter;
+ gtk_text_iter_forward_char (&iter2);
+ gtk_text_buffer_delete (buffer, &iter, &iter2);
+ }
+ else if (gtk_text_iter_get_char (&iter) == ' ')
+ {
+ spaces = 0;
+
+ iter2 = iter;
+
+ /* count the number of spaces before the text */
+ while (!gtk_text_iter_ends_line (&iter2))
+ {
+ if (gtk_text_iter_get_char (&iter2) == ' ')
+ spaces++;
+ else
+ break;
+
+ gtk_text_iter_forward_char (&iter2);
+ }
+
+ if (spaces > 0)
+ {
+ /* the number of tabs in the spaces */
+ tabs = spaces / 8;
+
+ /* the number of spaces after the 'tabs' */
+ spaces = spaces - (tabs * 8);
+
+ /* we're going to remove the number of spaces after the 'tabs'
+ * or 1 'tab' */
+ if (spaces == 0)
+ spaces = 8;
+
+ iter2 = iter;
+
+ /* delete the spaces */
+ gtk_text_iter_forward_chars (&iter2, spaces);
+ gtk_text_buffer_delete (buffer, &iter, &iter2);
+ }
+ }
+ }
+ }
+
+ /* we're done */
+ gtk_text_buffer_end_user_action (buffer);
+
+ /* scroll */
+ gtk_text_view_scroll_mark_onscreen (GTK_TEXT_VIEW (view),
+ gtk_text_buffer_get_insert (buffer));
+}
+
+
+
+static gchar *
+mousepad_view_compute_indentation (MousepadView *view,
+ GtkTextIter *iter)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
+ gint line;
+ gunichar ch;
+
+ /* get the buffer */
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+ /* get the line of the iter */
+ line = gtk_text_iter_get_line (iter);
+
+ /* get the iter of the beginning of this line */
+ gtk_text_buffer_get_iter_at_line (buffer, &start, line);
+
+ /* clone baby */
+ end = start;
+
+ /* get the first character */
+ ch = gtk_text_iter_get_char (&end);
+
+ /* keep walking till we hit text or a new line */
+ while (g_unichar_isspace (ch) &&
+ (ch != '\n') && (ch != '\r') &&
+ (gtk_text_iter_compare (&end, iter) < 0))
+ {
+ /* break if we can't step forward */
+ if (!gtk_text_iter_forward_char (&end))
+ break;
+
+ /* get the next character */
+ ch = gtk_text_iter_get_char (&end);
+ }
+
+ /* return NULL if the iters are the same */
+ if (gtk_text_iter_equal (&start, &end))
+ return NULL;
+
+ /* return the text between the iters */
+ return gtk_text_iter_get_slice (&start, &end);
+}
+
+
+
+static void
+mousepad_view_get_lines (GtkTextView *text_view,
+ gint first_y,
+ gint last_y,
+ GArray **pixels,
+ GArray **numbers,
+ gint *countp)
+{
+ GtkTextIter iter;
+ gint count = 0;
+ gint y, height;
+ gint line_number = 0, last_line_number;
+
+ g_array_set_size (*pixels, 0);
+ g_array_set_size (*numbers, 0);
+
+ /* get iter at first y */
+ gtk_text_view_get_line_at_y (text_view, &iter, first_y, NULL);
+
+ /* for each iter, get its location and add it to the arrays.
+ * Stop when we pass last_y */
+ while (!gtk_text_iter_is_end (&iter))
+ {
+ /* get the y position of the iter */
+ gtk_text_view_get_line_yrange (text_view, &iter, &y, &height);
+
+ /* get the number of the line */
+ line_number = gtk_text_iter_get_line (&iter);
+
+ /* append both values to the array */
+ g_array_append_val (*pixels, y);
+ g_array_append_val (*numbers, line_number);
+
+ ++count;
+
+ /* stop when we reached last_y */
+ if ((y + height) >= last_y)
+ break;
+
+ /* jump to the next line */
+ gtk_text_iter_forward_line (&iter);
+ }
+
+ if (gtk_text_iter_is_end (&iter))
+ {
+ gtk_text_view_get_line_yrange (text_view, &iter, &y, &height);
+
+ last_line_number = gtk_text_iter_get_line (&iter);
+
+ if (last_line_number != line_number)
+ {
+ g_array_append_val (*pixels, y);
+ g_array_append_val (*numbers, last_line_number);
+ ++count;
+ }
+ }
+
+ /* not lines in the buffer? weird, there is atleast one... */
+ if (G_UNLIKELY (count == 0))
+ {
+ y = 0;
+ g_array_append_val (*pixels, y);
+ g_array_append_val (*numbers, y);
+
+ ++count;
+ }
+
+ *countp = count;
+}
+
+
+
+static gboolean
+mousepad_view_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GdkWindow *window;
+ GtkTextView *view = GTK_TEXT_VIEW (widget);
+ gint y1, y2;
+ GArray *numbers, *pixels;
+ gint count, i;
+ PangoLayout *layout;
+ gchar str[8]; /* maximum of 10e6 lines */
+ gint width;
+ gint position;
+ gint line_number;
+
+ /* get the left window */
+ window = gtk_text_view_get_window (view, GTK_TEXT_WINDOW_LEFT);
+
+ /* check if the event if for the left window */
+ if (event->window == window)
+ {
+ /* get the expose event area */
+ y1 = event->area.y;
+ y2 = y1 + event->area.height;
+
+ /* correct then to the size of the textview window */
+ gtk_text_view_window_to_buffer_coords (view, GTK_TEXT_WINDOW_LEFT,
+ 0, y1, NULL, &y1);
+ gtk_text_view_window_to_buffer_coords (view, GTK_TEXT_WINDOW_LEFT,
+ 0, y2, NULL, &y2);
+
+ /* create new arrays */
+ pixels = g_array_new (FALSE, FALSE, sizeof (gint));
+ numbers = g_array_new (FALSE, FALSE, sizeof (gint));
+
+ /* get the line numbers and y coordinates. */
+ mousepad_view_get_lines (view,
+ y1, y2,
+ &pixels,
+ &numbers,
+ &count);
+
+ /* create the pango layout */
+ g_snprintf (str, sizeof (str), "%d",
+ MAX (99, gtk_text_buffer_get_line_count (view->buffer)));
+ layout = gtk_widget_create_pango_layout (widget, str);
+ pango_layout_get_pixel_size (layout, &width, NULL);
+ pango_layout_set_width (layout, width);
+ pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT);
+
+ /* set the width of the left window border */
+ gtk_text_view_set_border_window_size (view, GTK_TEXT_WINDOW_LEFT,
+ width + 6);
+
+ for (i = 0; i < count; i++)
+ {
+ gtk_text_view_buffer_to_window_coords (view,
+ GTK_TEXT_WINDOW_LEFT, 0,
+ g_array_index (pixels, gint, i),
+ NULL,
+ &position);
+
+ /* get the line number */
+ line_number = g_array_index (numbers, gint, i) + 1;
+
+ /* create the pango layout */
+ g_snprintf (str, sizeof (str), "%d", line_number);
+ pango_layout_set_markup (layout, str, strlen (str));
+
+ /* time to draw the layout in the window */
+ gtk_paint_layout (widget->style, window,
+ GTK_WIDGET_STATE (widget),
+ FALSE, NULL,
+ widget, NULL,
+ width + 2,
+ position,
+ layout);
+ }
+
+ /* cleanup */
+ g_array_free (pixels, TRUE);
+ g_array_free (numbers, TRUE);
+
+ g_object_unref (G_OBJECT (layout));
+ }
+
+ /* Gtk can draw the text now */
+ return (*GTK_WIDGET_CLASS (mousepad_view_parent_class)->expose_event) (widget, event);
+}
+
+
+
+void
+mousepad_view_set_show_line_numbers (MousepadView *view,
+ gboolean visible)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_VIEW (view));
+
+ if (view->line_numbers != visible)
+ {
+ /* set the boolean */
+ view->line_numbers = visible;
+
+ /* set the left border size */
+ gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (view),
+ GTK_TEXT_WINDOW_LEFT,
+ visible ? 20 : 0);
+
+ /* make sure there is an expose event */
+ gtk_widget_queue_draw (GTK_WIDGET (view));
+ }
+}
+
+
+
+void
+mousepad_view_set_auto_indent (MousepadView *view,
+ gboolean enable)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_VIEW (view));
+
+ /* set the boolean */
+ view->auto_indent = enable;
+}
diff --git a/mousepad/mousepad-view.h b/mousepad/mousepad-view.h
new file mode 100644
index 0000000..f18da6e
--- /dev/null
+++ b/mousepad/mousepad-view.h
@@ -0,0 +1,45 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.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
+ */
+
+#ifndef __MOUSEPAD_VIEW_H__
+#define __MOUSEPAD_VIEW_H__
+
+G_BEGIN_DECLS
+
+#define MOUSEPAD_TYPE_VIEW (mousepad_view_get_type ())
+#define MOUSEPAD_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOUSEPAD_TYPE_VIEW, MousepadView))
+#define MOUSEPAD_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPAD_TYPE_VIEW, MousepadViewClass))
+#define MOUSEPAD_IS_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOUSEPAD_TYPE_VIEW))
+#define MOUSEPAD_IS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPADL_TYPE_VIEW))
+#define MOUSEPAD_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOUSEPAD_TYPE_VIEW, MousepadViewClass))
+
+typedef struct _MousepadViewClass MousepadViewClass;
+typedef struct _MousepadView MousepadView;
+
+GType mousepad_view_get_type (void) G_GNUC_CONST;
+
+void mousepad_view_set_show_line_numbers (MousepadView *view,
+ gboolean visible);
+
+void mousepad_view_set_auto_indent (MousepadView *view,
+ gboolean enable);
+
+G_END_DECLS
+
+#endif /* !__MOUSEPAD_VIEW_H__ */
diff --git a/mousepad/mousepad-window-ui.xml b/mousepad/mousepad-window-ui.xml
new file mode 100644
index 0000000..b1e94b7
--- /dev/null
+++ b/mousepad/mousepad-window-ui.xml
@@ -0,0 +1,65 @@
+<ui>
+ <!--
+ $Id$
+
+ Copyright (c) 2007 Nick Schermer <nick at xfce.org>
+ -->
+
+ <menubar name="main-menu">
+ <menu action="file-menu">
+ <menuitem action="new-tab" />
+ <menuitem action="new-window" />
+ <separator />
+ <menuitem action="open-file" />
+ <menuitem action="recent-menu" />
+ <separator />
+ <menuitem action="save-file" />
+ <menuitem action="save-file-as" />
+ <separator />
+ <menuitem action="close-tab" />
+ <menuitem action="close-window" />
+ <menuitem action="close-all-windows" />
+ </menu>
+
+ <menu action="edit-menu">
+ <menuitem action="undo" />
+ <menuitem action="redo" />
+ <separator />
+ <menuitem action="cut" />
+ <menuitem action="copy" />
+ <menuitem action="paste" />
+ <menuitem action="delete" />
+ <separator />
+ <menuitem action="select-all" />
+ </menu>
+
+ <menu action="search-menu">
+ <menuitem action="find" />
+ <menuitem action="find-next" />
+ <menuitem action="find-previous" />
+ <menuitem action="replace" />
+ <separator />
+ <menuitem action="jump-to" />
+ </menu>
+
+ <menu action="view-menu">
+ <menuitem action="font" />
+ <separator />
+ <menuitem action="word-wrap" />
+ <menuitem action="line-numbers" />
+ <separator />
+ <menuitem action="auto-indent" />
+ </menu>
+
+ <menu action="go-menu">
+ <menuitem action="back" />
+ <menuitem action="forward" />
+ <separator />
+ <placeholder name="placeholder-go-items" />
+ </menu>
+
+ <menu action="help-menu">
+ <menuitem action="about" />
+ </menu>
+ </menubar>
+</ui>
diff --git a/mousepad/mousepad-window.c b/mousepad/mousepad-window.c
new file mode 100644
index 0000000..1f7a669
--- /dev/null
+++ b/mousepad/mousepad-window.c
@@ -0,0 +1,1779 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.org>
+ * Copyright (c) 2007 Benedikt Meurer <benny at xfce.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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <mousepad/mousepad-application.h>
+#include <mousepad/mousepad-preferences.h>
+#include <mousepad/mousepad-private.h>
+#include <mousepad/mousepad-file.h>
+#include <mousepad/mousepad-screen.h>
+#include <mousepad/mousepad-view.h>
+#include <mousepad/mousepad-tab-label.h>
+#include <mousepad/mousepad-window.h>
+#include <mousepad/mousepad-window-ui.h>
+
+
+
+static void mousepad_window_class_init (MousepadWindowClass *klass);
+static void mousepad_window_init (MousepadWindow *window);
+static void mousepad_window_dispose (GObject *object);
+static void mousepad_window_finalize (GObject *object);
+static gboolean mousepad_window_configure_event (GtkWidget *widget,
+ GdkEventConfigure *event);
+static gboolean mousepad_window_save_geometry_timer (gpointer user_data);
+static void mousepad_window_save_geometry_timer_destroy (gpointer user_data);
+static MousepadScreen *mousepad_window_get_active (MousepadWindow *window);
+static gboolean mousepad_window_save_as (MousepadWindow *window,
+ MousepadScreen *screen);
+static void mousepad_window_add (MousepadWindow *window,
+ MousepadScreen *screen);
+static gboolean mousepad_window_close_screen (MousepadWindow *window,
+ MousepadScreen *screen);
+static void mousepad_window_create_recent_menu (MousepadWindow *window);
+static void mousepad_window_add_recent (const gchar *filename);
+static void mousepad_window_set_title (MousepadWindow *window,
+ MousepadScreen *screen);
+static void mousepad_window_notify_title (MousepadScreen *screen,
+ GParamSpec *pspec,
+ MousepadWindow *window);
+static void mousepad_window_page_notified (GtkNotebook *notebook,
+ GParamSpec *pspec,
+ MousepadWindow *window);
+static void mousepad_window_tab_removed (GtkNotebook *notebook,
+ MousepadScreen *screen,
+ MousepadWindow *window);
+static void mousepad_window_error_dialog (GtkWindow *window,
+ GError *error,
+ const gchar *message);
+static void mousepad_window_update_actions (MousepadWindow *window);
+static void mousepad_window_rebuild_gomenu (MousepadWindow *window);
+static void mousepad_window_selection_changed (MousepadScreen *screen,
+ gboolean selected,
+ MousepadWindow *window);
+static void mousepad_window_action_open_new_window (GtkAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_open_file (GtkAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_open_recent (GtkRecentChooser *chooser,
+ MousepadWindow *window);
+static void mousepad_window_action_save_file (GtkAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_save_file_as (GtkAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_close_tab (GtkAction *action,
+ MousepadWindow *window);
+static void mousepad_window_button_close_tab (MousepadScreen *screen);
+static gboolean mousepad_window_delete_event (MousepadWindow *window,
+ GdkEvent *event);
+static void mousepad_window_action_close (GtkAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_close_all_windows (GtkAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_open_new_tab (GtkAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_cut (GtkAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_copy (GtkAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_paste (GtkAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_delete (GtkAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_select_all (GtkAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_jump_to (GtkAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_select_font (GtkAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_prev_tab (GtkAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_next_tab (GtkAction *action,
+ MousepadWindow *window);
+static void mousepad_window_action_about (GtkAction *action,
+ MousepadWindow *window);
+
+
+
+
+struct _MousepadWindowClass
+{
+ GtkWindowClass __parent__;
+};
+
+struct _MousepadWindow
+{
+ GtkWindow __parent__;
+
+ MousepadPreferences *preferences;
+
+ GtkActionGroup *action_group;
+ GtkUIManager *ui_manager;
+
+ GtkWidget *notebook;
+
+ /* support to remember window geometry */
+ gint save_geometry_timer_id;
+};
+
+
+
+static const GtkActionEntry action_entries[] =
+{
+ { "file-menu", NULL, N_ ("_File"), NULL, NULL, NULL, },
+ { "new-tab", "tab-new", N_ ("New _Tab"), "<control>T", N_ ("Open a new Mousepad tab"), G_CALLBACK (mousepad_window_action_open_new_tab), },
+ { "new-window", "window-new", N_ ("_New Window"), "<control>N", N_ ("Open a new Mousepad window"), G_CALLBACK (mousepad_window_action_open_new_window), },
+ { "open-file", GTK_STOCK_OPEN, N_ ("_Open File"), NULL, N_ ("Open a new document"), G_CALLBACK (mousepad_window_action_open_file), },
+ { "recent-menu", NULL, N_ ("Open _Recent"), NULL, NULL, NULL, },
+ { "save-file", GTK_STOCK_SAVE, N_ ("_Save"), NULL, N_ ("Save current document"), G_CALLBACK (mousepad_window_action_save_file), },
+ { "save-file-as", GTK_STOCK_SAVE_AS, N_ ("Save _As"), NULL, N_ ("Save current document as another file"), G_CALLBACK (mousepad_window_action_save_file_as), },
+ { "close-tab", GTK_STOCK_CLOSE, N_ ("C_lose Tab"), "<control>W", N_ ("Close the current Mousepad tab"), G_CALLBACK (mousepad_window_action_close_tab), },
+ { "close-window", GTK_STOCK_QUIT, N_ ("_Close Window"), "<control>Q", N_ ("Close the Mousepad window"), G_CALLBACK (mousepad_window_action_close), },
+ { "close-all-windows", NULL, N_ ("Close _All Windows"), "<control><shift>W", N_ ("Close all Mousepad windows"), G_CALLBACK (mousepad_window_action_close_all_windows), },
+
+ { "edit-menu", NULL, N_ ("_Edit"), NULL, NULL, NULL, },
+ { "undo", GTK_STOCK_UNDO, N_ ("_Undo"), NULL, NULL, NULL, },
+ { "redo", GTK_STOCK_REDO, N_ ("_Redo"), NULL, NULL, NULL, },
+ { "cut", GTK_STOCK_CUT, N_ ("Cu_t"), NULL, NULL, G_CALLBACK (mousepad_window_action_cut), },
+ { "copy", GTK_STOCK_COPY, N_ ("_Copy"), NULL, NULL, G_CALLBACK (mousepad_window_action_copy), },
+ { "paste", GTK_STOCK_PASTE, N_ ("_Paste"), NULL, NULL, G_CALLBACK (mousepad_window_action_paste), },
+ { "delete", GTK_STOCK_DELETE, N_ ("_Delete"), NULL, NULL, G_CALLBACK (mousepad_window_action_delete), },
+ { "select-all", GTK_STOCK_SELECT_ALL, N_ ("Select _All"), NULL, NULL, G_CALLBACK (mousepad_window_action_select_all), },
+
+ { "search-menu", NULL, N_ ("_Search"), NULL, NULL, NULL, },
+ { "find", GTK_STOCK_FIND, N_ ("_Find"), NULL, NULL, NULL, },
+ { "find-next", NULL, N_ ("Find _Next"), NULL, NULL, NULL, },
+ { "find-previous", NULL, N_ ("Find _Previous"), NULL, NULL, NULL, },
+ { "replace", GTK_STOCK_FIND_AND_REPLACE, N_ ("_Replace"), NULL, NULL, NULL, },
+ { "jump-to", GTK_STOCK_JUMP_TO, N_ ("_Jump To"), NULL, NULL, G_CALLBACK (mousepad_window_action_jump_to), },
+
+ { "view-menu", NULL, N_ ("_View"), NULL, NULL, NULL, },
+ { "font", GTK_STOCK_SELECT_FONT, N_ ("_Font"), NULL, N_ ("Choose Mousepad font"), G_CALLBACK (mousepad_window_action_select_font), },
+
+ { "go-menu", NULL, N_ ("_Go"), NULL, },
+ { "back", GTK_STOCK_GO_BACK, N_ ("Back"), NULL, N_ ("Select the previous tab"), G_CALLBACK (mousepad_window_action_prev_tab), },
+ { "forward", GTK_STOCK_GO_FORWARD, N_ ("Forward"), NULL, N_ ("Select the next tab"), G_CALLBACK (mousepad_window_action_next_tab), },
+
+ { "help-menu", NULL, N_ ("_Help"), NULL, },
+ { "about", GTK_STOCK_ABOUT, N_ ("_About"), NULL,N_ ("Display information about Mousepad"), G_CALLBACK (mousepad_window_action_about), },
+};
+
+static const GtkToggleActionEntry toggle_action_entries[] =
+{
+ { "word-wrap", NULL, N_ ("_Word Wrap"), NULL, NULL, NULL, FALSE, },
+ { "line-numbers", NULL, N_ ("_Line Numbers"), NULL, NULL, NULL, FALSE, },
+ { "auto-indent", NULL, N_ ("_Auto Indent"), NULL, NULL, NULL, FALSE, },
+};
+
+
+
+static GObjectClass *mousepad_window_parent_class;
+
+
+
+GtkWidget *
+mousepad_window_new (void)
+{
+ return g_object_new (MOUSEPAD_TYPE_WINDOW, NULL);
+}
+
+
+
+GType
+mousepad_window_get_type (void)
+{
+ static GType type = G_TYPE_INVALID;
+
+ if (G_UNLIKELY (type == G_TYPE_INVALID))
+ {
+ type = g_type_register_static_simple (GTK_TYPE_WINDOW,
+ I_("MousepadWindow"),
+ sizeof (MousepadWindowClass),
+ (GClassInitFunc) mousepad_window_class_init,
+ sizeof (MousepadWindow),
+ (GInstanceInitFunc) mousepad_window_init,
+ 0);
+ }
+
+ return type;
+}
+
+
+
+static void
+mousepad_window_class_init (MousepadWindowClass *klass)
+{
+ GObjectClass *gobject_class;
+ GtkWidgetClass *gtkwidget_class;
+
+ mousepad_window_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->dispose = mousepad_window_dispose;
+ gobject_class->finalize = mousepad_window_finalize;
+
+ gtkwidget_class = GTK_WIDGET_CLASS (klass);
+ gtkwidget_class->configure_event = mousepad_window_configure_event;
+}
+
+
+static void
+mousepad_window_init (MousepadWindow *window)
+{
+ GtkAccelGroup *accel_group;
+ GtkWidget *menubar;
+ GtkWidget *vbox;
+ GtkWidget *label;
+ GtkWidget *separator;
+ GtkWidget *ebox;
+ GtkAction *action;
+ gint width, height;
+
+ window->preferences = mousepad_preferences_get ();
+
+ /* signal for monitoring */
+ g_signal_connect (G_OBJECT (window), "delete-event",
+ G_CALLBACK (mousepad_window_delete_event), NULL);
+
+ /* read settings from the preferences */
+ g_object_get (G_OBJECT (window->preferences),
+ "last-window-width", &width,
+ "last-window-height", &height,
+ NULL);
+
+ /* set the default window size */
+ gtk_window_set_default_size (GTK_WINDOW (window), width, height);
+
+ /* the action group for this window */
+ window->action_group = gtk_action_group_new ("MousepadActionGroup");
+ gtk_action_group_set_translation_domain (window->action_group, GETTEXT_PACKAGE);
+ gtk_action_group_add_actions (window->action_group, action_entries, G_N_ELEMENTS (action_entries), GTK_WIDGET (window));
+ gtk_action_group_add_toggle_actions (window->action_group, toggle_action_entries, G_N_ELEMENTS (toggle_action_entries), GTK_WIDGET (window));
+
+ /* create mutual bindings for the toggle buttons */
+ action = gtk_action_group_get_action (window->action_group, "line-numbers");
+ exo_mutual_binding_new (G_OBJECT (window->preferences), "line-numbers", G_OBJECT (action), "active");
+ action = gtk_action_group_get_action (window->action_group, "auto-indent");
+ exo_mutual_binding_new (G_OBJECT (window->preferences), "auto-indent", G_OBJECT (action), "active");
+ action = gtk_action_group_get_action (window->action_group, "word-wrap");
+ exo_mutual_binding_new (G_OBJECT (window->preferences), "word-wrap", G_OBJECT (action), "active");
+
+ window->ui_manager = gtk_ui_manager_new ();
+ gtk_ui_manager_insert_action_group (window->ui_manager, window->action_group, 0);
+ gtk_ui_manager_add_ui_from_string (window->ui_manager, mousepad_window_ui, mousepad_window_ui_length, NULL);
+
+ /* append the recent-menu items */
+ mousepad_window_create_recent_menu (window);
+
+ accel_group = gtk_ui_manager_get_accel_group (window->ui_manager);
+ gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
+
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), vbox);
+ gtk_widget_show (vbox);
+
+ menubar = gtk_ui_manager_get_widget (window->ui_manager, "/main-menu");
+ gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, FALSE, 0);
+ gtk_widget_show (menubar);
+
+ /* check if we need to add the root warning */
+ if (G_UNLIKELY (geteuid () == 0))
+ {
+ /* install default settings for the root warning text box */
+ gtk_rc_parse_string ("style\"mousepad-window-root-style\"{bg[NORMAL]=\"#b4254b\"\nfg[NORMAL]=\"#fefefe\"}\n"
+ "widget\"MousepadWindow.*.root-warning\"style\"mousepad-window-root-style\"\n"
+ "widget\"MousepadWindow.*.root-warning.GtkLabel\"style\"mousepad-window-root-style\"\n");
+
+ /* add the box for the root warning */
+ ebox = gtk_event_box_new ();
+ gtk_widget_set_name (ebox, "root-warning");
+ gtk_box_pack_start (GTK_BOX (vbox), ebox, FALSE, FALSE, 0);
+ gtk_widget_show (ebox);
+
+ /* add the label with the root warning */
+ label = gtk_label_new (_("Warning, you are using the root account, you may harm your system."));
+ gtk_misc_set_padding (GTK_MISC (label), 6, 3);
+ gtk_container_add (GTK_CONTAINER (ebox), label);
+ gtk_widget_show (label);
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
+ gtk_widget_show (separator);
+ }
+
+ window->notebook = g_object_new (GTK_TYPE_NOTEBOOK,
+ "homogeneous", FALSE,
+ "scrollable", TRUE,
+ "show-border", FALSE,
+ "show-tabs", FALSE,
+ "tab-hborder", 0,
+ "tab-vborder", 0,
+ NULL);
+
+ g_signal_connect (G_OBJECT (window->notebook), "notify::page",
+ G_CALLBACK (mousepad_window_page_notified), window);
+ g_signal_connect (G_OBJECT (window->notebook), "remove",
+ G_CALLBACK (mousepad_window_tab_removed), window);
+
+ gtk_box_pack_start (GTK_BOX (vbox), window->notebook, TRUE, TRUE, 0);
+ gtk_widget_show (window->notebook);
+}
+
+
+
+static void
+mousepad_window_dispose (GObject *object)
+{
+ MousepadWindow *window = MOUSEPAD_WINDOW (object);
+
+ /* destroy the save geometry timer source */
+ if (G_UNLIKELY (window->save_geometry_timer_id > 0))
+ g_source_remove (window->save_geometry_timer_id);
+
+ (*G_OBJECT_CLASS (mousepad_window_parent_class)->dispose) (object);
+}
+
+
+
+static void
+mousepad_window_finalize (GObject *object)
+{
+ MousepadWindow *window = MOUSEPAD_WINDOW (object);
+
+ g_object_unref (G_OBJECT (window->ui_manager));
+ g_object_unref (G_OBJECT (window->action_group));
+
+ /* release the preferences reference */
+ g_object_unref (G_OBJECT (window->preferences));
+
+ (*G_OBJECT_CLASS (mousepad_window_parent_class)->finalize) (object);
+}
+
+
+
+static gboolean
+mousepad_window_configure_event (GtkWidget *widget,
+ GdkEventConfigure *event)
+{
+ MousepadWindow *window = MOUSEPAD_WINDOW (widget);
+
+ /* check if we have a new dimension here */
+ if (widget->allocation.width != event->width || widget->allocation.height != event->height)
+ {
+ /* drop any previous timer source */
+ if (window->save_geometry_timer_id > 0)
+ g_source_remove (window->save_geometry_timer_id);
+
+ /* check if we should schedule another save timer */
+ if (GTK_WIDGET_VISIBLE (widget))
+ {
+ /* save the geometry one second after the last configure event */
+ window->save_geometry_timer_id = g_timeout_add_full (G_PRIORITY_LOW, 1000, mousepad_window_save_geometry_timer,
+ window, mousepad_window_save_geometry_timer_destroy);
+ }
+ }
+
+ /* let Gtk+ handle the configure event */
+ return (*GTK_WIDGET_CLASS (mousepad_window_parent_class)->configure_event) (widget, event);
+}
+
+
+
+static gboolean
+mousepad_window_save_geometry_timer (gpointer user_data)
+{
+ GdkWindowState state;
+ MousepadWindow *window = MOUSEPAD_WINDOW (user_data);
+ gboolean remember_geometry;
+ gint width;
+ gint height;
+
+ GDK_THREADS_ENTER ();
+
+ /* check if we should remember the window geometry */
+ g_object_get (G_OBJECT (window->preferences), "misc-remember-geometry", &remember_geometry, NULL);
+ if (G_LIKELY (remember_geometry))
+ {
+ /* check if the window is still visible */
+ if (GTK_WIDGET_VISIBLE (window))
+ {
+ /* determine the current state of the window */
+ state = gdk_window_get_state (GTK_WIDGET (window)->window);
+
+ /* don't save geometry for maximized or fullscreen windows */
+ if ((state & (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)) == 0)
+ {
+ /* determine the current width/height of the window... */
+ gtk_window_get_size (GTK_WINDOW (window), &width, &height);
+
+ /* ...and remember them as default for new windows */
+ g_object_set (G_OBJECT (window->preferences),
+ "last-window-width", width,
+ "last-window-height", height, NULL);
+ }
+ }
+ }
+
+ GDK_THREADS_LEAVE ();
+
+ return FALSE;
+}
+
+
+
+static void
+mousepad_window_save_geometry_timer_destroy (gpointer user_data)
+{
+ MOUSEPAD_WINDOW (user_data)->save_geometry_timer_id = 0;
+}
+
+
+
+static MousepadScreen *
+mousepad_window_get_active (MousepadWindow *window)
+{
+ GtkNotebook *notebook = GTK_NOTEBOOK (window->notebook);
+ gint page_num;
+
+ page_num = gtk_notebook_get_current_page (notebook);
+
+ if (G_LIKELY (page_num >= 0))
+ return MOUSEPAD_SCREEN (gtk_notebook_get_nth_page (notebook, page_num));
+ else
+ return NULL;
+}
+
+
+
+gboolean
+mousepad_window_open_tab (MousepadWindow *window,
+ const gchar *filename)
+{
+ GtkWidget *screen;
+ GError *error = NULL;
+ gboolean succeed = TRUE;
+ gint npages = 0, i;
+ const gchar *opened_filename;
+
+ /* get the number of page in the notebook */
+ if (filename)
+ npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)) - 1;
+
+ /* walk though the tabs */
+ for (i = 0; i < npages; i++)
+ {
+ screen = gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->notebook), i);
+
+ if (G_LIKELY (screen != NULL))
+ {
+ /* get the filename */
+ opened_filename = mousepad_screen_get_filename (MOUSEPAD_SCREEN (screen));
+
+ /* see if the file is already opened */
+ if (exo_str_is_equal (filename, opened_filename))
+ {
+ /* switch to the tab */
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), i);
+
+ /* and we're done */
+ return TRUE;
+ }
+ }
+ }
+
+ /* new screen */
+ screen = mousepad_screen_new ();
+
+ /* load a file, if there is any */
+ if (filename)
+ succeed = mousepad_screen_open_file (MOUSEPAD_SCREEN (screen), filename, &error);
+
+ if (G_LIKELY (succeed))
+ mousepad_window_add (window, MOUSEPAD_SCREEN (screen));
+ else
+ {
+ /* something went wrong, remove the screen */
+ gtk_widget_destroy (GTK_WIDGET (screen));
+
+ /* show the warning */
+ mousepad_window_error_dialog (GTK_WINDOW (window), error, _("Failed to open file"));
+ g_error_free (error);
+ }
+
+ return succeed;
+}
+
+
+
+void
+mousepad_window_open_files (MousepadWindow *window,
+ const gchar *working_directory,
+ gchar **filenames)
+{
+ gint n;
+ gchar *filename;
+
+ _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+ _mousepad_return_if_fail (working_directory != NULL);
+ _mousepad_return_if_fail (filenames != NULL);
+ _mousepad_return_if_fail (*filenames != NULL);
+
+ /* walk through all the filenames */
+ for (n = 0; filenames[n] != NULL; ++n)
+ {
+ /* check if the filename looks like an uri */
+ if (g_strstr_len (filenames[n], 5, "file:"))
+ {
+ /* convert the uri to an absolute filename */
+ filename = g_filename_from_uri (filenames[n], NULL, NULL);
+ }
+ else if (g_path_is_absolute (filenames[n]) == FALSE)
+ {
+ /* create an absolute file */
+ filename = g_build_filename (working_directory, filenames[n], NULL);
+ }
+
+ /* open a new tab with the file */
+ mousepad_window_open_tab (window, filename ? filename : filenames[n]);
+
+ /* cleanup */
+ g_free (filename);
+ filename = NULL;
+ }
+}
+
+
+
+static GtkFileChooserConfirmation
+mousepad_window_save_as_callback (GtkFileChooser *dialog)
+{
+ gchar *filename;
+ GError *error = NULL;
+ GtkFileChooserConfirmation result;
+
+ /* get the filename */
+ filename = gtk_file_chooser_get_filename (dialog);
+
+ if (mousepad_file_is_writable (filename, &error))
+ {
+ /* show the normal confirmation dialog */
+ result = GTK_FILE_CHOOSER_CONFIRMATION_CONFIRM;
+ }
+ else
+ {
+ /* tell the user he cannot write to this file */
+ mousepad_window_error_dialog (GTK_WINDOW (dialog), error, _("Permission denied"));
+ g_error_free (error);
+
+ /* the user doesn't have permission to write to the file */
+ result = GTK_FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN;
+ }
+
+ /* cleanup */
+ g_free (filename);
+
+ return result;
+}
+
+
+
+static gboolean
+mousepad_window_save_as (MousepadWindow *window,
+ MousepadScreen *screen)
+{
+ GtkWidget *dialog;
+ gboolean succeed = FALSE;
+ gchar *filename;
+
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_WINDOW (window), FALSE);
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), FALSE);
+
+ dialog = gtk_file_chooser_dialog_new (_("Save As"),
+ GTK_WINDOW (window),
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_OK,
+ NULL);
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE);
+ gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+ /* we check if the user is allowed to write to the file */
+ g_signal_connect (G_OBJECT (dialog), "confirm-overwrite",
+ G_CALLBACK (mousepad_window_save_as_callback), NULL);
+
+ /* set the current file, or the temp name */
+ if (mousepad_screen_get_filename (screen) != NULL)
+ gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), mousepad_screen_get_filename (screen));
+ else
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), mousepad_screen_get_title (screen, FALSE));
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
+ {
+ /* get the filename the user has selected */
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+
+ if (G_LIKELY (filename != NULL))
+ {
+ /* set the filename */
+ mousepad_screen_set_filename (screen, filename);
+
+ /* cleanup */
+ g_free (filename);
+
+ /* it worked */
+ succeed = TRUE;
+ }
+ }
+
+ /* destroy the dialog */
+ gtk_widget_destroy (dialog);
+
+ return succeed;
+}
+
+
+
+static void
+mousepad_window_modified_changed (MousepadScreen *screen,
+ MousepadWindow *window)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+ _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
+
+ mousepad_window_set_title (window, screen);
+}
+
+
+
+static void
+mousepad_window_add (MousepadWindow *window,
+ MousepadScreen *screen)
+{
+ GtkWidget *label;
+ gboolean always_show_tabs;
+ gint page, npages;
+ MousepadScreen *active;
+
+ _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+ _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
+
+ /* connect some bindings to the screen */
+ exo_binding_new (G_OBJECT (window->preferences), "line-numbers", G_OBJECT (screen), "line-numbers");
+ exo_binding_new (G_OBJECT (window->preferences), "word-wrap", G_OBJECT (screen), "word-wrap");
+ exo_binding_new (G_OBJECT (window->preferences), "auto-indent", G_OBJECT (screen), "auto-indent");
+ exo_binding_new (G_OBJECT (window->preferences), "font-name", G_OBJECT (screen), "font-name");
+
+ label = mousepad_tab_label_new ();
+ gtk_widget_show (label);
+
+ /* add the window to the screen */
+ g_object_set_data (G_OBJECT (screen), I_("mousepad-window"), window);
+
+ /* connect some bindings and signals to the tab label */
+ exo_binding_new (G_OBJECT (screen), "title", G_OBJECT (label), "title");
+ exo_binding_new (G_OBJECT (screen), "filename", G_OBJECT (label), "tooltip");
+ g_signal_connect_swapped (G_OBJECT (label), "close-tab", G_CALLBACK (mousepad_window_button_close_tab), screen);
+ g_signal_connect (G_OBJECT (screen), "notify::title", G_CALLBACK (mousepad_window_notify_title), window);
+
+ g_signal_connect (G_OBJECT (screen), "selection-changed", G_CALLBACK (mousepad_window_selection_changed), window);
+ g_signal_connect (G_OBJECT (screen), "modified-changed", G_CALLBACK (mousepad_window_modified_changed), window);
+
+ /* append the page to the window */
+ page = gtk_notebook_append_page (GTK_NOTEBOOK (window->notebook),
+ GTK_WIDGET (screen), label);
+
+ /* check if we should always display tabs */
+ g_object_get (G_OBJECT (window->preferences), "misc-always-show-tabs", &always_show_tabs, NULL);
+
+ /* change the visibility of the tabs accordingly */
+ npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook));
+ gtk_notebook_set_show_tabs (GTK_NOTEBOOK (window->notebook), always_show_tabs || (npages > 1));
+
+ /* don't focus the notebook */
+ GTK_WIDGET_UNSET_FLAGS (window->notebook, GTK_CAN_FOCUS);
+
+ /* rebuild the go menu */
+ mousepad_window_rebuild_gomenu (window);
+
+ /* show the screen */
+ gtk_widget_show (GTK_WIDGET (screen));
+
+ /* get the active tab */
+ active = mousepad_window_get_active (window);
+
+ /* switch to the new tab */
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), page);
+
+ /* destroy the (old) active tab if it's empty
+ * and the new tab is not */
+ if (active != NULL &&
+ mousepad_screen_get_modified (active) == FALSE &&
+ mousepad_screen_get_filename (active) == NULL &&
+ mousepad_screen_get_filename (screen) != NULL)
+ gtk_widget_destroy (GTK_WIDGET (active));
+}
+
+
+
+static gboolean
+mousepad_window_close_screen (MousepadWindow *window,
+ MousepadScreen *screen)
+{
+ GtkWidget *dialog;
+ gint response;
+ gboolean succeed = FALSE;
+ GError *error = NULL;
+
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_WINDOW (window), FALSE);
+ _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), FALSE);
+
+ /* check if the document needs to be saved */
+ if (mousepad_screen_get_modified (screen))
+ {
+ /* create the question dialog */
+ dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_NONE,
+ _("Do you want to save changes to this\ndocument before closing?"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("If you don't save, your changes will be lost."));
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ _("_Don't Save"), GTK_RESPONSE_HELP,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_OK,
+ NULL);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+ /* run the dialog */
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ switch (response)
+ {
+ case GTK_RESPONSE_HELP:
+ /* don't save, only destroy the screen */
+ succeed = TRUE;
+ break;
+ case GTK_RESPONSE_CANCEL:
+ /* we do nothing */
+ break;
+ case GTK_RESPONSE_OK:
+ /* save the screen */
+ if (mousepad_screen_get_filename (screen) == NULL)
+ {
+ /* file has no name yet, save as */
+ if (mousepad_window_save_as (window, screen))
+ succeed = mousepad_screen_save_file (screen, &error);
+ }
+ else
+ {
+ succeed = mousepad_screen_save_file (screen, &error);
+ }
+ break;
+ }
+ }
+ else
+ {
+ /* no changes in the screen, safe to destroy it */
+ succeed = TRUE;
+ }
+
+ /* destroy the screen */
+ if (succeed)
+ {
+ gtk_widget_destroy (GTK_WIDGET (screen));
+ }
+ else if (error != NULL)
+ {
+ /* something went wrong with saving the file */
+ mousepad_window_error_dialog (GTK_WINDOW (window), error, _("Failed to save file"));
+ g_error_free (error);
+ }
+
+ return succeed;
+}
+
+
+
+static void
+mousepad_window_create_recent_menu (MousepadWindow *window)
+{
+ GtkRecentFilter *filter;
+ GtkWidget *menu;
+ GtkWidget *item;
+ gint recent_menu_limit;
+
+ _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+
+ /* get the recent menu item */
+ item = gtk_ui_manager_get_widget (window->ui_manager, "/main-menu/file-menu/recent-menu");
+
+ /* create a new recent chooser */
+ menu = gtk_recent_chooser_menu_new ();
+
+ /* show only Mousepad items */
+ filter = gtk_recent_filter_new ();
+ gtk_recent_filter_add_application (filter, "Mousepad Text Editor");
+ gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu), filter);
+
+ /* get the recent menu limit number */
+ g_object_get (G_OBJECT (window->preferences), "misc-recent-menu-limit", &recent_menu_limit, NULL);
+
+ /* set recent menu properties */
+ gtk_recent_chooser_set_local_only (GTK_RECENT_CHOOSER (menu), TRUE);
+ gtk_recent_chooser_set_limit (GTK_RECENT_CHOOSER (menu), recent_menu_limit);
+ gtk_recent_chooser_set_show_tips (GTK_RECENT_CHOOSER (menu), TRUE);
+
+ g_signal_connect (G_OBJECT (menu), "item-activated",
+ G_CALLBACK(mousepad_window_action_open_recent), window);
+
+ /* append the recent menu */
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu);
+}
+
+
+
+static void
+mousepad_window_add_recent (const gchar *filename)
+{
+ GtkRecentData info;
+ gchar *uri;
+ GtkRecentManager *manager = gtk_recent_manager_get_default ();
+
+ _mousepad_return_if_fail (filename != NULL);
+
+ /* create the recent data */
+ info.display_name = NULL;
+ info.description = NULL;
+ info.mime_type = "text/plain";
+ info.app_name = "Mousepad Text Editor";
+ info.app_exec = "Mousepad %F";
+ info.groups = NULL;
+ info.is_private = FALSE;
+
+ /* create an uri from the filename */
+ uri = g_filename_to_uri (filename, NULL, NULL);
+
+ /* add it */
+ if (G_LIKELY (uri != NULL))
+ {
+ gtk_recent_manager_add_full (manager, uri, &info);
+ g_free (uri);
+ }
+}
+
+
+
+static void
+mousepad_window_set_title (MousepadWindow *window,
+ MousepadScreen *screen)
+{
+ gchar *string;
+ const gchar *title;
+ gboolean show_full_path;
+ GtkTextView *textview;
+
+ /* get the active textview */
+ textview = mousepad_screen_get_text_view (screen);
+
+ /* whether to show the full path in the window title */
+ g_object_get (G_OBJECT (window->preferences), "misc-show-full-path-in-title", &show_full_path, NULL);
+
+ /* the window title */
+ title = mousepad_screen_get_title (screen, show_full_path);
+
+ if (!gtk_text_view_get_editable (textview))
+ {
+ string = g_strdup_printf ("%s [%s] - %s",
+ title, _("Read Only"), PACKAGE_NAME);
+ }
+ else
+ {
+ string = g_strdup_printf ("%s%s - %s",
+ mousepad_screen_get_modified (screen) ? "*" : "",
+ title, PACKAGE_NAME);
+ }
+
+ /* get the window title */
+ gtk_window_set_title (GTK_WINDOW (window), string);
+
+ /* cleanup */
+ g_free (string);
+}
+
+
+
+static void
+mousepad_window_notify_title (MousepadScreen *screen,
+ GParamSpec *pspec,
+ MousepadWindow *window)
+{
+ mousepad_window_set_title (window, screen);
+}
+
+
+
+static void
+mousepad_window_page_notified (GtkNotebook *notebook,
+ GParamSpec *pspec,
+ MousepadWindow *window)
+{
+ MousepadScreen *screen;
+
+ screen = mousepad_window_get_active (window);
+ if (G_LIKELY (screen != NULL))
+ {
+ mousepad_window_set_title (window, screen);
+
+ mousepad_window_update_actions (window);
+ }
+}
+
+
+
+static void
+mousepad_window_tab_removed (GtkNotebook *notebook,
+ MousepadScreen *screen,
+ MousepadWindow *window)
+{
+ gboolean always_show_tabs;
+ gint npages;
+
+ npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook));
+
+ if (G_UNLIKELY (npages == 0))
+ {
+ gtk_widget_destroy (GTK_WIDGET (window));
+ }
+ else
+ {
+ /* check tabs should always be visible */
+ g_object_get (G_OBJECT (window->preferences), "misc-always-show-tabs", &always_show_tabs, NULL);
+
+ /* change the visibility of the tabs accordingly */
+ gtk_notebook_set_show_tabs (GTK_NOTEBOOK (window->notebook), always_show_tabs || (npages > 1));
+
+ /* don't focus the notebook */
+ GTK_WIDGET_UNSET_FLAGS (window->notebook, GTK_CAN_FOCUS);
+
+ /* rebuild the go menu */
+ mousepad_window_rebuild_gomenu (window);
+
+ /* update all screen sensitive actions */
+ mousepad_window_update_actions (window);
+ }
+}
+
+
+
+static void
+mousepad_window_error_dialog (GtkWindow *window,
+ GError *error,
+ const gchar *message)
+{
+ GtkWidget *dialog;
+
+ _mousepad_return_if_fail (GTK_IS_WINDOW (window));
+
+ /* create the warning dialog */
+ dialog = gtk_message_dialog_new (window,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ message);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
+
+ /* set the message from GError */
+ if (G_LIKELY (error && error->message))
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ error->message);
+
+ /* run the dialog */
+ gtk_dialog_run (GTK_DIALOG (dialog));
+
+ /* destroy it */
+ gtk_widget_destroy (dialog);
+
+}
+
+
+
+static void
+mousepad_window_selection_changed (MousepadScreen *screen,
+ gboolean selected,
+ MousepadWindow *window)
+{
+ GtkAction *action;
+
+ action = gtk_action_group_get_action (window->action_group, "cut");
+ gtk_action_set_sensitive (action, selected);
+
+ action = gtk_action_group_get_action (window->action_group, "copy");
+ gtk_action_set_sensitive (action, selected);
+
+ action = gtk_action_group_get_action (window->action_group, "delete");
+ gtk_action_set_sensitive (action, selected);
+}
+
+
+
+static void
+mousepad_window_update_actions (MousepadWindow *window)
+{
+ GtkAction *action;
+ GtkNotebook *notebook = GTK_NOTEBOOK (window->notebook);
+ MousepadScreen *screen;
+ GtkTextView *textview;
+ GtkTextBuffer *buffer;
+ GtkWidget *goitem;
+ gboolean cycle_tabs;
+ gint n_pages;
+ gint page_num;
+ gboolean selected;
+
+ /* determine the number of pages */
+ n_pages = gtk_notebook_get_n_pages (notebook);
+
+ /* set sensitivity for the "Close Tab" action */
+ action = gtk_action_group_get_action (window->action_group, "close-tab");
+ gtk_action_set_sensitive (action, (n_pages > 1));
+
+ /* update the actions for the current terminal screen */
+ screen = mousepad_window_get_active (window);
+ if (G_LIKELY (screen != NULL))
+ {
+ page_num = gtk_notebook_page_num (notebook, GTK_WIDGET (screen));
+
+ textview = mousepad_screen_get_text_view (screen);
+ buffer = mousepad_screen_get_text_buffer (screen);
+
+ g_object_get (G_OBJECT (window->preferences), "misc-cycle-tabs", &cycle_tabs, NULL);
+
+ action = gtk_action_group_get_action (window->action_group, "back");
+ gtk_action_set_sensitive (action, (cycle_tabs && n_pages > 1) || (page_num > 0));
+
+ action = gtk_action_group_get_action (window->action_group, "forward");
+ gtk_action_set_sensitive (action, (cycle_tabs && n_pages > 1 ) || (page_num < n_pages - 1));
+
+ action = gtk_action_group_get_action (window->action_group, "save-file");
+ gtk_action_set_sensitive (action, gtk_text_view_get_editable (textview));
+
+ g_object_get (G_OBJECT (buffer), "has-selection", &selected, NULL);
+ mousepad_window_selection_changed (screen, selected, window);
+
+ /* update the "Go" menu */
+ goitem = g_object_get_data (G_OBJECT (screen), "go-menu-item");
+ if (G_LIKELY (goitem != NULL))
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (goitem), TRUE);
+ }
+}
+
+
+static void
+mousepad_window_action_goto (GtkRadioAction *action,
+ GtkNotebook *notebook)
+{
+ gint page = gtk_radio_action_get_current_value (action);
+
+ gtk_notebook_set_current_page (notebook, page);
+}
+
+
+
+static void
+mousepad_window_rebuild_gomenu (MousepadWindow *window)
+{
+ GtkWidget *screen;
+ gint npages;
+ gint n;
+ gchar name[15];
+ gchar accelerator[7];
+ GtkRadioAction *action;
+ GSList *group = NULL;
+ const gchar *go_menu_path;
+ static guint merge_id = 0;
+
+ /* remove the old merge */
+ if (merge_id > 1)
+ gtk_ui_manager_remove_ui (window->ui_manager, merge_id);
+
+ /* create a new merge id */
+ merge_id = gtk_ui_manager_new_merge_id (window->ui_manager);
+
+ /* the path in the ui where the items will be added */
+ go_menu_path = "/main-menu/go-menu/placeholder-go-items";
+
+ /* walk through the notebook pages */
+ npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook));
+ for (n = 0; n < npages; ++n)
+ {
+ screen = gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->notebook), n);
+
+ /* create a new action name */
+ g_snprintf (name, sizeof (name), "document-%d", n);
+
+ /* create the radio action */
+ action = gtk_radio_action_new (name, NULL, NULL, NULL, n);
+ exo_binding_new (G_OBJECT (screen), "title", G_OBJECT (action), "label");
+ gtk_radio_action_set_group (action, group);
+ group = gtk_radio_action_get_group (action);
+ g_signal_connect (G_OBJECT (action), "activate",
+ G_CALLBACK (mousepad_window_action_goto), window->notebook);
+
+ /* connect the action to the screen to we can easily active it when the user toggled the tabs */
+ g_object_set_data (G_OBJECT (screen), I_("go-menu-item"), action);
+
+ if (G_LIKELY (n < 9))
+ {
+ /* create an accelerator and add it to the menu */
+ g_snprintf (accelerator, sizeof (accelerator), "<Alt>%d", n+1);
+ gtk_action_group_add_action_with_accel (window->action_group, GTK_ACTION (action), accelerator);
+ }
+ else
+ /* add a menu item without accelerator */
+ gtk_action_group_add_action (window->action_group, GTK_ACTION (action));
+
+ /* release the action */
+ g_object_unref (G_OBJECT (action));
+
+ /* add the action to the go menu */
+ gtk_ui_manager_add_ui (window->ui_manager, merge_id,
+ go_menu_path, name, name,
+ GTK_UI_MANAGER_MENUITEM, FALSE);
+ }
+
+ /* make sure the ui is up2date to avoid flickering */
+ gtk_ui_manager_ensure_update (window->ui_manager);
+}
+
+
+/**
+ * Menu Actions
+ **/
+static void
+mousepad_window_action_open_new_window (GtkAction *action,
+ MousepadWindow *window)
+{
+ MousepadApplication *application;
+ GdkScreen *screen;
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (window));
+
+ application = mousepad_application_get ();
+ mousepad_application_open_window (application, screen, NULL, NULL);
+ g_object_unref (G_OBJECT (application));
+}
+
+
+
+static void
+mousepad_window_action_open_new_tab (GtkAction *action,
+ MousepadWindow *window)
+{
+ mousepad_window_open_tab (window, NULL);
+}
+
+
+
+static void
+mousepad_window_action_open_file (GtkAction *action,
+ MousepadWindow *window)
+{
+ GtkWidget *chooser;
+ gchar *filename;
+ GSList *filenames, *li;
+
+ /* create new chooser dialog */
+ chooser = gtk_file_chooser_dialog_new (_("Open File"),
+ GTK_WINDOW (window),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+ NULL);
+ gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_ACCEPT);
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser), TRUE);
+ gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (chooser), TRUE);
+
+ /* run the dialog */
+ if (G_LIKELY (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT))
+ {
+ /* open the new file */
+ filenames = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (chooser));
+
+ /* open the selected files */
+ for (li = filenames; li != NULL; li = li->next)
+ {
+ filename = li->data;
+
+ /* open the file in a new tab */
+ mousepad_window_open_tab (window, filename);
+
+ /* add to the recent files */
+ mousepad_window_add_recent (filename);
+
+ /* cleanup */
+ g_free (filename);
+ }
+
+ /* free the list */
+ g_slist_free(filenames);
+ }
+
+ /* destroy dialog */
+ gtk_widget_destroy (chooser);
+}
+
+
+
+static void
+mousepad_window_action_open_recent (GtkRecentChooser *chooser,
+ MousepadWindow *window)
+{
+ gchar *uri;
+ gchar *filename;
+ gboolean succeed;
+ GtkRecentManager *manager;
+
+ /* get the file uri */
+ uri = gtk_recent_chooser_get_current_uri (chooser);
+
+ if (G_LIKELY(uri != NULL))
+ {
+ /* get the filename from the uri */
+ filename = g_filename_from_uri (uri, NULL, NULL);
+
+ if (G_LIKELY (filename != NULL))
+ {
+ /* open a new tab */
+ succeed = mousepad_window_open_tab (window, filename);
+
+ /* remove the file from the recent menu if Mousepad failed to open it */
+ if (G_UNLIKELY (succeed == FALSE))
+ {
+ manager = gtk_recent_manager_get_default ();
+ gtk_recent_manager_remove_item (manager, uri, NULL);
+ }
+
+ /* cleanup */
+ g_free (filename);
+ }
+
+ /* cleanup */
+ g_free (uri);
+ }
+}
+
+
+
+static void
+mousepad_window_action_save_file (GtkAction *action,
+ MousepadWindow *window)
+{
+ MousepadScreen *screen;
+ GError *error = NULL;
+
+ screen = mousepad_window_get_active (window);
+
+ if (G_LIKELY (screen != NULL))
+ {
+ if (mousepad_screen_get_filename (screen) != NULL)
+ mousepad_screen_save_file (screen, &error);
+ else
+ {
+ if (mousepad_window_save_as (window, screen))
+ mousepad_screen_save_file (screen, &error);
+ }
+
+ /* check for errors */
+ if (G_UNLIKELY (error != NULL))
+ {
+ mousepad_window_error_dialog (GTK_WINDOW (window), error, _("Failed to save file"));
+ g_error_free (error);
+ }
+ }
+}
+
+
+
+static void
+mousepad_window_action_save_file_as (GtkAction *action,
+ MousepadWindow *window)
+{
+ MousepadScreen *screen;
+ GError *error = NULL;
+
+ screen = mousepad_window_get_active (window);
+
+ if (G_LIKELY (screen != NULL))
+ {
+ /* popup the save as dialog, if that worked, save the file, if
+ * that worked too, add the (new) file to the recent menu */
+ if (mousepad_window_save_as (window, screen))
+ if (mousepad_screen_save_file (screen, &error))
+ mousepad_window_add_recent (mousepad_screen_get_filename (screen));
+
+ /* check for errors */
+ if (G_UNLIKELY (error != NULL))
+ {
+ mousepad_window_error_dialog (GTK_WINDOW (window), error, _("Failed to save file as"));
+ g_error_free (error);
+ }
+ else
+ {
+ /* make sure save-file is sensitive */
+ action = gtk_action_group_get_action (window->action_group, "save-file");
+ gtk_action_set_sensitive (action, TRUE);
+ }
+ }
+}
+
+
+
+static void
+mousepad_window_action_close_tab (GtkAction *action,
+ MousepadWindow *window)
+{
+ MousepadScreen *screen;
+
+ screen = mousepad_window_get_active (window);
+
+ if (G_LIKELY (screen != NULL))
+ mousepad_window_close_screen (window, screen);
+}
+
+
+
+static void
+mousepad_window_button_close_tab (MousepadScreen *screen)
+{
+ MousepadWindow *window;
+
+ _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
+
+ /* get the mousepad window of this screen */
+ window = g_object_get_data (G_OBJECT (screen), I_("mousepad-window"));
+
+ /* close the screen */
+ if (G_LIKELY (window != NULL))
+ mousepad_window_close_screen (window, screen);
+}
+
+
+
+static gboolean
+mousepad_window_delete_event (MousepadWindow *window,
+ GdkEvent *event)
+{
+ /* try to close the windows */
+ mousepad_window_action_close (NULL, window);
+
+ /* we will close the window when it's time */
+ return TRUE;
+}
+
+
+
+static void
+mousepad_window_action_close (GtkAction *action,
+ MousepadWindow *window)
+{
+ gint npages, i;
+ GtkWidget *screen;
+
+ /* get the number of page in the notebook */
+ npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)) - 1;
+
+ /* close all the tabs, one by one. the window will close
+ * when all the tabs are closed */
+ for (i = npages; i >= 0; --i)
+ {
+ screen = gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->notebook), i);
+
+ if (G_LIKELY (screen != NULL))
+ {
+ /* switch to the tab we're going to close */
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), i);
+
+ /* ask user what to do, break when he/she hits the cancel button */
+ if (!mousepad_window_close_screen (window, MOUSEPAD_SCREEN (screen)))
+ break;
+ }
+ }
+}
+
+
+
+static void
+mousepad_window_action_close_all_windows (GtkAction *action,
+ MousepadWindow *window)
+{
+ MousepadApplication *application;
+ GList *windows, *li;
+
+ /* query the list of currently open windows */
+ application = mousepad_application_get ();
+ windows = mousepad_application_get_windows (application);
+ g_object_unref (G_OBJECT (application));
+
+ /* close all open windows */
+ for (li = windows; li != NULL; li = li->next)
+ mousepad_window_action_close (NULL, MOUSEPAD_WINDOW (li->data));
+
+ g_list_free (windows);
+}
+
+
+
+static void
+mousepad_window_action_cut (GtkAction *action,
+ MousepadWindow *window)
+{
+ MousepadScreen *screen;
+ GtkTextBuffer *buffer;
+ GtkClipboard *clipboard;
+ GtkTextView *textview;
+
+ /* get the active screen */
+ screen = mousepad_window_get_active (window);
+
+ if (G_LIKELY (screen != NULL))
+ {
+ /* get the clipboard, textview and the buffer */
+ buffer = mousepad_screen_get_text_buffer (screen);
+ textview = mousepad_screen_get_text_view (screen);
+ clipboard = gtk_widget_get_clipboard (GTK_WIDGET (textview), GDK_SELECTION_CLIPBOARD);
+
+ /* cut the text */
+ gtk_text_buffer_cut_clipboard (buffer, clipboard,
+ gtk_text_view_get_editable (textview));
+
+ /* scroll to visible area */
+ gtk_text_view_scroll_to_mark (textview,
+ gtk_text_buffer_get_insert (buffer),
+ MOUSEPAD_SCROLL_MARGIN,
+ FALSE, 0.0, 0.0);
+ }
+}
+
+
+
+static void
+mousepad_window_action_copy (GtkAction *action,
+ MousepadWindow *window)
+{
+ MousepadScreen *screen;
+ GtkTextBuffer *buffer;
+ GtkClipboard *clipboard;
+
+ screen = mousepad_window_get_active (window);
+
+ if (G_LIKELY (screen != NULL))
+ {
+ /* get the buffer, textview and the clipboard */
+ buffer = mousepad_screen_get_text_buffer (screen);
+ clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window), GDK_SELECTION_CLIPBOARD);
+
+ /* copy the selected text */
+ gtk_text_buffer_copy_clipboard (buffer, clipboard);
+ }
+}
+
+
+
+static void
+mousepad_window_action_paste (GtkAction *action,
+ MousepadWindow *window)
+{
+ MousepadScreen *screen;
+ GtkTextBuffer *buffer;
+ GtkClipboard *clipboard;
+ GtkTextView *textview;
+
+ screen = mousepad_window_get_active (window);
+
+ if (G_LIKELY (screen != NULL))
+ {
+ /* get the buffer and the clipboard */
+ buffer = mousepad_screen_get_text_buffer (screen);
+ textview = mousepad_screen_get_text_view (screen);
+ clipboard = gtk_widget_get_clipboard (GTK_WIDGET (textview), GDK_SELECTION_CLIPBOARD);
+
+ /* paste the clipboard content */
+ gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL,
+ gtk_text_view_get_editable (textview));
+
+ /* scroll to visible area */
+ gtk_text_view_scroll_to_mark (textview,
+ gtk_text_buffer_get_insert (buffer),
+ MOUSEPAD_SCROLL_MARGIN,
+ FALSE, 0.0, 0.0);
+ }
+}
+
+
+
+static void
+mousepad_window_action_delete (GtkAction *action,
+ MousepadWindow *window)
+{
+ MousepadScreen *screen;
+ GtkTextBuffer *buffer;
+ GtkTextView *textview;
+
+ screen = mousepad_window_get_active (window);
+
+ if (G_LIKELY (screen != NULL))
+ {
+ /* get the buffer */
+ buffer = mousepad_screen_get_text_buffer (screen);
+ textview = mousepad_screen_get_text_view (screen);
+
+ /* delete the selected text */
+ gtk_text_buffer_delete_selection (buffer, TRUE,
+ gtk_text_view_get_editable (textview));
+
+ /* scroll to visible area */
+ gtk_text_view_scroll_to_mark (textview,
+ gtk_text_buffer_get_insert (buffer),
+ MOUSEPAD_SCROLL_MARGIN,
+ FALSE, 0.0, 0.0);
+ }
+}
+
+
+
+static void
+mousepad_window_action_select_all (GtkAction *action,
+ MousepadWindow *window)
+{
+
+ MousepadScreen *screen;
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
+
+ screen = mousepad_window_get_active (window);
+
+ if (G_LIKELY (screen != NULL))
+ {
+ /* get the buffer */
+ buffer = mousepad_screen_get_text_buffer (screen);
+
+ /* get the start and end iter */
+ gtk_text_buffer_get_bounds (buffer, &start, &end);
+
+ /* select everything between those iters */
+ gtk_text_buffer_select_range (buffer, &start, &end);
+ }
+}
+
+
+
+static void
+mousepad_window_action_jump_to (GtkAction *action,
+ MousepadWindow *window)
+{
+ GtkWidget *dialog;
+ GtkWidget *hbox, *label, *button;
+ GtkTextBuffer *buffer;
+ MousepadScreen *screen;
+ gint num, num_max;
+ GtkTextIter iter;
+ GtkAdjustment *adjustment;
+
+
+ screen = mousepad_window_get_active (window);
+
+ if (G_LIKELY (screen != NULL))
+ {
+ buffer = mousepad_screen_get_text_buffer (screen);
+
+ /* get the current line number */
+ gtk_text_buffer_get_iter_at_mark (buffer, &iter, gtk_text_buffer_get_insert (buffer));
+ num = gtk_text_iter_get_line (&iter) + 1;
+
+ /* get the last line number */
+ gtk_text_buffer_get_end_iter (buffer, &iter);
+ num_max = gtk_text_iter_get_line (&iter) + 1;
+
+ /* build the dialog */
+ dialog = gtk_dialog_new_with_buttons (_("Jump To"),
+ GTK_WINDOW (window),
+ GTK_DIALOG_MODAL
+ | GTK_DIALOG_DESTROY_WITH_PARENT
+ | GTK_DIALOG_NO_SEPARATOR,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_JUMP_TO, GTK_RESPONSE_OK,
+ NULL);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+ gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+
+ hbox = gtk_hbox_new (FALSE, 8);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, FALSE, FALSE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
+ gtk_widget_show (hbox);
+
+ label = gtk_label_new_with_mnemonic (_("_Line number:"));
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+ gtk_widget_show (label);
+
+ /* the spin button adjustment */
+ adjustment = (GtkAdjustment *) gtk_adjustment_new (num, 1, num_max, 1, 10, 0);
+
+ /* the spin button */
+ button = gtk_spin_button_new (adjustment, 1, 0);
+ gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (button), TRUE);
+ gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (button), TRUE);
+ gtk_entry_set_width_chars (GTK_ENTRY (button), 8);
+ gtk_entry_set_activates_default (GTK_ENTRY (button), TRUE);
+ gtk_label_set_mnemonic_widget (GTK_LABEL(label), button);
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+ gtk_widget_show (button);
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
+ {
+ /* jump to the line */
+ num = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (button)) - 1;
+ gtk_text_buffer_get_iter_at_line (buffer, &iter, num);
+ gtk_text_buffer_place_cursor (buffer, &iter);
+
+ /* scroll to visible area */
+ gtk_text_view_scroll_to_mark (mousepad_screen_get_text_view (screen),
+ gtk_text_buffer_get_insert (buffer),
+ MOUSEPAD_SCROLL_MARGIN,
+ FALSE, 0.0, 0.0);
+ }
+
+ /* destroy the dialog */
+ gtk_widget_destroy (dialog);
+ }
+}
+
+
+
+static void
+mousepad_window_action_select_font (GtkAction *action,
+ MousepadWindow *window)
+{
+ GtkWidget *dialog;
+ gchar *font_name;
+
+ dialog = gtk_font_selection_dialog_new (_("Choose Mousepad Font"));
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (window));
+
+ /* set the current font */
+ g_object_get (G_OBJECT (window->preferences), "font-name", &font_name, NULL);
+
+ if (G_LIKELY (font_name))
+ {
+ gtk_font_selection_dialog_set_font_name (GTK_FONT_SELECTION_DIALOG (dialog), font_name);
+ g_free (font_name);
+ }
+
+ /* run the dialog */
+ if (G_LIKELY (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK))
+ {
+ /* send the new font to the preferences */
+ font_name = gtk_font_selection_dialog_get_font_name (GTK_FONT_SELECTION_DIALOG (dialog));
+ g_object_set (G_OBJECT (window->preferences), "font-name", font_name, NULL);
+ g_free (font_name);
+ }
+
+ /* destroy dialog */
+ gtk_widget_destroy (dialog);
+}
+
+
+
+static void
+mousepad_window_action_prev_tab (GtkAction *action,
+ MousepadWindow *window)
+{
+ gint page_num;
+ gint n_pages;
+
+ /* get notebook info */
+ page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (window->notebook));
+ n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook));
+
+ /* switch to the previous tab or cycle to the last tab */
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook),
+ (page_num - 1) % n_pages);
+}
+
+
+
+static void
+mousepad_window_action_next_tab (GtkAction *action,
+ MousepadWindow *window)
+{
+ gint page_num;
+ gint n_pages;
+
+ /* get notebook info */
+ page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (window->notebook));
+ n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook));
+
+ /* switch to the next tab or cycle to the first tab */
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook),
+ (page_num + 1) % n_pages);
+}
+
+
+
+static void
+mousepad_window_action_about (GtkAction *action,
+ MousepadWindow *window)
+{
+ static const gchar *authors[] =
+ {
+ "Erik Harrison <erikharrison at xfce.org>",
+ "Nick Schermer <nick at xfce.org>",
+ "Benedikt Meurer <benny at xfce.org>",
+ NULL,
+ };
+
+ /* show the dialog */
+ gtk_about_dialog_set_email_hook (exo_url_about_dialog_hook, NULL, NULL);
+ gtk_about_dialog_set_url_hook (exo_url_about_dialog_hook, NULL, NULL);
+ gtk_show_about_dialog (GTK_WINDOW (window),
+ "authors", authors,
+ "comments", _("Mousepad is a fast text editor for the Xfce Desktop Environment."),
+ "copyright", _("Copyright \302\251 2004-2007 Xfce Development Team"),
+ "destroy-with-parent", TRUE,
+ "license", XFCE_LICENSE_GPL,
+ "logo-icon-name", PACKAGE_NAME,
+ "name", PACKAGE_NAME,
+ "version", PACKAGE_VERSION,
+ "translator-credits", _("translator-credits"),
+ "website", "http://www.xfce.org/projects/mousepad",
+ NULL);
+}
+
diff --git a/mousepad/mousepad-window.h b/mousepad/mousepad-window.h
new file mode 100644
index 0000000..951d020
--- /dev/null
+++ b/mousepad/mousepad-window.h
@@ -0,0 +1,48 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.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
+ */
+
+#ifndef __MOUSEPAD_WINDOW_H__
+#define __MOUSEPAD_WINDOW_H__
+
+G_BEGIN_DECLS
+
+#define MOUSEPAD_TYPE_WINDOW (mousepad_window_get_type ())
+#define MOUSEPAD_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOUSEPAD_TYPE_WINDOW, MousepadWindow))
+#define MOUSEPAD_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPAD_TYPE_WINDOW, MousepadWindowClass))
+#define MOUSEPAD_IS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOUSEPAD_TYPE_WINDOW))
+#define MOUSEPAD_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPADL_TYPE_WINDOW))
+#define MOUSEPAD_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOUSEPAD_TYPE_WINDOW, MousepadWindowClass))
+
+typedef struct _MousepadWindowClass MousepadWindowClass;
+typedef struct _MousepadWindow MousepadWindow;
+
+GType mousepad_window_get_type (void) G_GNUC_CONST;
+
+GtkWidget *mousepad_window_new (void);
+
+gboolean mousepad_window_open_tab (MousepadWindow *window,
+ const gchar *filename);
+
+void mousepad_window_open_files (MousepadWindow *window,
+ const gchar *working_directory,
+ gchar **filenames);
+
+G_END_DECLS
+
+#endif /* !__MOUSEPAD_WINDOW_H__ */
diff --git a/po/ChangeLog b/po/ChangeLog
new file mode 100644
index 0000000..e69de29
diff --git a/po/LINGUAS b/po/LINGUAS
new file mode 100644
index 0000000..a0f7499
--- /dev/null
+++ b/po/LINGUAS
@@ -0,0 +1 @@
+# set of available languages (in alphabetic order)
diff --git a/po/Mousepad.pot b/po/Mousepad.pot
new file mode 100644
index 0000000..ea89984
--- /dev/null
+++ b/po/Mousepad.pot
@@ -0,0 +1,225 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-02-17 12:57+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../mousepad/main.c:47
+msgid "Print version information and exit"
+msgstr ""
+
+#. default application name
+#: ../mousepad/main.c:65
+msgid "Mousepad"
+msgstr ""
+
+#. initialize Gtk+
+#: ../mousepad/main.c:77
+msgid "[FILES...]"
+msgstr ""
+
+#. no error message, the GUI initialization failed
+#: ../mousepad/main.c:83
+msgid "Failed to open display."
+msgstr ""
+
+#: ../mousepad/main.c:100
+msgid "The Xfce development team. All rights reserved."
+msgstr ""
+
+#: ../mousepad/main.c:101
+msgid "Written by Nick Schermer <nick at xfce.org>."
+msgstr ""
+
+#: ../mousepad/main.c:102
+#, c-format
+msgid "Please report bugs to <%s>."
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:29
+msgid "Untitled Document"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:91
+msgid "_File"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:92
+msgid "New _Tab"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:92
+msgid "Open a new Mousepad tab"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:93
+msgid "_New Window"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:93
+msgid "Open a new Mousepad window"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:94
+msgid "_Open File"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:94
+msgid "Open a new document"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:95
+msgid "Open _Recent"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:96
+msgid "_Save"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:96
+msgid "Save current document"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:97
+msgid "Save _As"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:97
+msgid "Save current document as another file"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:98
+msgid "C_lose Tab"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:98
+msgid "Close the current Mousepad tab"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:99
+msgid "_Close Window"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:99
+msgid "Close the Mousepad window"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:100
+msgid "Close _All Windows"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:100
+msgid "Close all Mousepad windows"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:102
+msgid "_Edit"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:103
+msgid "_Undo"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:104
+msgid "_Redo"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:105
+msgid "Cu_t"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:106
+msgid "_Copy"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:107
+msgid "_Paste"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:108
+msgid "_Delete"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:109
+msgid "Select _All"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:111
+msgid "_Search"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:112
+msgid "_Find"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:113
+msgid "Find _Next"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:114
+msgid "Find _Previous"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:115
+msgid "_Replace"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:116
+msgid "_Jump To"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:118
+msgid "_View"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:119
+msgid "_Font"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:121
+msgid "_Go"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:122
+msgid "Back"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:123
+msgid "Forward"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:125
+msgid "_Help"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:126
+msgid "_About"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:126
+msgid "Display information about Mousepad"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:131
+msgid "_Word Wrap"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:132
+msgid "_Line Numbers"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:133
+msgid "_Auto Indent"
+msgstr ""
diff --git a/po/POTFILES.in b/po/POTFILES.in
new file mode 100644
index 0000000..b144c68
--- /dev/null
+++ b/po/POTFILES.in
@@ -0,0 +1,6 @@
+mousepad/main.c
+mousepad/mousepad-application.c
+mousepad/mousepad-dbus.c
+mousepad/mousepad-preferences.c
+mousepad/mousepad-textview.c
+mousepad/mousepad-window.c
More information about the Xfce4-commits
mailing list