Fixed a compiler warning
commit
694ed16f11
|
@ -0,0 +1,57 @@
|
|||
syntax: glob
|
||||
Makefile.in
|
||||
depcomp
|
||||
compile
|
||||
config.guess
|
||||
config.sub
|
||||
configure
|
||||
doc/help.stamp
|
||||
install-sh
|
||||
ltmain.sh
|
||||
test-driver
|
||||
m4/intltool.m4
|
||||
m4/libtool.m4
|
||||
m4/ltoptions.m4
|
||||
m4/ltsugar.m4
|
||||
m4/ltversion.m4
|
||||
m4/lt~obsolete.m4
|
||||
missing
|
||||
po-gsv/Makefile.in.in
|
||||
po/Makefile.in.in
|
||||
build/
|
||||
autom4te.cache/
|
||||
aclocal.m4
|
||||
*~
|
||||
*.orig
|
||||
*.bak
|
||||
*.tmp
|
||||
*.rej
|
||||
*.pyc
|
||||
.goutputstream-*
|
||||
po*/dist
|
||||
po*/pot
|
||||
po/notexist
|
||||
po/missing
|
||||
config.h.in
|
||||
plat/win32/gtk-win/tarballs/
|
||||
plat/win32/gtk-win/debug/
|
||||
plat/win32/gtk-win/release/
|
||||
plat/win32/gtk-win/bdist-debug/
|
||||
plat/win32/gtk-win/bdist-release/
|
||||
api/moo.xml
|
||||
api/gtk.xml
|
||||
moo/plugins/usertools/old/
|
||||
moo/moopython/pygtk/moo-generated.defs
|
||||
moo/moopython/plugins/old/
|
||||
moo/moolua/moo-lua-api.cpp
|
||||
moo/moolua/gtk-lua-api.cpp
|
||||
doc/help/
|
||||
doc/built/
|
||||
po-gsv/po-original/
|
||||
po-gsv/po-stripped/
|
||||
plat/msvs/deps/
|
||||
plat/msvs/Debug/
|
||||
plat/msvs/medit.ncb
|
||||
plat/msvs/medit.suo
|
||||
plat/msvs/medit.vcproj.*.user
|
||||
plat/msvs/medit.sln
|
|
@ -0,0 +1,5 @@
|
|||
Yevgen Muntyan <emuntyan@users.sourceforge.net>
|
||||
Daniel Poelzleithner <mooedit@poelzi.org>
|
||||
Lasse Makholm
|
||||
Ryan Anonymous
|
||||
Ulrich Eckhardt <ulrich.eckhardt@base-42.de>
|
|
@ -0,0 +1,237 @@
|
|||
cmake_minimum_required(VERSION 3.0)
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
|
||||
if(WIN32)
|
||||
include(cmake/PrecompiledHeader.cmake)
|
||||
endif()
|
||||
|
||||
list(APPEND EXTRA_DIST
|
||||
tools/genenums.py
|
||||
tools/glade2c.py
|
||||
tools/xml2h.py
|
||||
plat/win32/installer.iss.in
|
||||
plat/win32/istrans.sh
|
||||
plat/win32/mingw-configure
|
||||
)
|
||||
|
||||
# zzz
|
||||
# if MOO_OS_WIN32
|
||||
# plat/win32/installer.iss: $(top_srcdir)/plat/win32/installer.iss.in $(top_builddir)/config.status
|
||||
# $(AM_V_at)$(MKDIR_P) plat/win32
|
||||
# $(AM_V_GEN)cd $(top_builddir) && ./config.status --silent --file=plat/win32/installer.iss
|
||||
# installer: plat/win32/installer.iss install
|
||||
# $(MEDIT_INNO_COMPILER) plat/win32/installer.iss
|
||||
# copy:
|
||||
# cp moo/medit.exe "/win/Program Files (x86)/medit/bin/"
|
||||
# bd_tmpdir = medit-win-dist-tmp
|
||||
# bd_distdir = $(PACKAGE)-$(VERSION)
|
||||
# bd_pzip = $(PACKAGE)-portable-$(VERSION)
|
||||
# bd_zip = $(PACKAGE)-$(VERSION)
|
||||
# portable: install
|
||||
# rm -fr $(bd_tmpdir)
|
||||
# mkdir $(bd_tmpdir)
|
||||
# cp -lR ${prefix} $(bd_tmpdir)/$(bd_distdir)
|
||||
# cd $(bd_tmpdir) && zip -r9 $(bd_zip).zip $(bd_distdir)
|
||||
# echo "This file enables portable mode for medit" > $(bd_tmpdir)/$(bd_distdir)/bin/$(MEDIT_PORTABLE_MAGIC_FILE_NAME)
|
||||
# cd $(bd_tmpdir) && zip -r9 $(bd_pzip).zip $(bd_distdir)
|
||||
# mv $(bd_tmpdir)/$(bd_pzip).zip $(bd_tmpdir)/$(bd_zip).zip .
|
||||
# rm -fr $(bd_tmpdir)
|
||||
# bdist: installer portable
|
||||
# endif
|
||||
|
||||
# zzz @MOO_PO_SUBDIRS_RULE@
|
||||
|
||||
set(MOO_MAJOR_VERSION 1)
|
||||
set(MOO_MINOR_VERSION 2)
|
||||
set(MOO_MICRO_VERSION 90)
|
||||
set(_moo_version_suffix_ "-devel")
|
||||
set(MOO_MODULE_MAJOR_VERSION 2)
|
||||
set(MOO_MODULE_MINOR_VERSION 0)
|
||||
set(MOO_VERSION "${MOO_MAJOR_VERSION}.${MOO_MINOR_VERSION}.${MOO_MICRO_VERSION}")
|
||||
set(MOO_DISPLAY_VERSION "${MOO_VERSION}${_moo_version_suffix_}")
|
||||
|
||||
project(medit VERSION ${MOO_VERSION})
|
||||
|
||||
# keep in sync with po/maintain
|
||||
set(MOO_PACKAGE_NAME "medit-1")
|
||||
|
||||
set(MOO_WEBSITE "http://mooedit.sourceforge.net/")
|
||||
set(MOO_WEB_CONTACT "http://mooedit.sourceforge.net/contact.html")
|
||||
set(MOO_EMAIL "emuntyan@users.sourceforge.net")
|
||||
set(MOO_COPYRIGHT "2004-2015 Yevgen Muntyan <${MOO_EMAIL}>")
|
||||
|
||||
set(MOO_PREFS_XML_FILE_NAME "prefs.xml")
|
||||
set(MOO_STATE_XML_FILE_NAME "state.xml")
|
||||
set(MOO_NAMED_SESSION_XML_FILE_NAME "session-%s.xml")
|
||||
set(MOO_SESSION_XML_FILE_NAME "session.xml")
|
||||
set(MEDIT_PORTABLE_MAGIC_FILE_NAME "medit-portable")
|
||||
set(MEDIT_PORTABLE_DATA_DIR "medit-portable-data")
|
||||
set(MEDIT_PORTABLE_CACHE_DIR "medit-portable-cache")
|
||||
|
||||
set(MOO_DATA_DIR "share/${MOO_PACKAGE_NAME}")
|
||||
set(MOO_LIB_DIR "lib/${MOO_PACKAGE_NAME}")
|
||||
set(MOO_DOC_DIR "share/doc/${MOO_PACKAGE_NAME}")
|
||||
set(MOO_HELP_DIR "${MOO_DOC_DIR}/help")
|
||||
set(MOO_TEXT_LANG_FILES_DIR "${MOO_DATA_DIR}/language-specs")
|
||||
set(MOO_PYTHON_PLUGIN_DIR "${MOO_DATA_DIR}/plugins")
|
||||
set(MOO_PYTHON_LIB_DIR "${MOO_DATA_DIR}/python")
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
endif()
|
||||
|
||||
if(WIN32 AND CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_CONFIGURATION_TYPES Release Debug)
|
||||
set(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}" CACHE STRING
|
||||
"Reset the configurations to what we need" FORCE)
|
||||
endif()
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
||||
if(WIN32)
|
||||
set(MOO_OS_WIN32 TRUE)
|
||||
else()
|
||||
set(MOO_OS_UNIX TRUE)
|
||||
endif()
|
||||
|
||||
set(MOO_BUILD_FROM_MSVC ${MOO_OS_WIN32} CACHE BOOL "Create a win32 build from MSVC gtk build")
|
||||
set(MOO_BUILD_FROM_MINGW FALSE CACHE BOOL "Create a win32 build from mingw gtk build")
|
||||
|
||||
if(NOT MOO_BUILD_FROM_MINGW AND NOT MOO_BUILD_FROM_MSVC)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(GTK REQUIRED gtk+-2.0)
|
||||
pkg_check_modules(GMODULE REQUIRED gmodule-2.0)
|
||||
#execute_process(
|
||||
# COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=glib_genmarshal glib-2.0
|
||||
# OUTPUT_VARIABLE GLIB_GENMARSHAL
|
||||
# OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
# RESULT_VARIABLE RESULT)
|
||||
#if(NOT RESULT EQUAL 0)
|
||||
# MESSAGE(FATAL_ERROR "Could not find glib-genmarshal")
|
||||
#endif()
|
||||
execute_process(
|
||||
COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=glib_mkenums glib-2.0
|
||||
OUTPUT_VARIABLE GLIB_MKENUMS
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE RESULT)
|
||||
if(NOT RESULT EQUAL 0)
|
||||
MESSAGE(FATAL_ERROR "Could not find glib-mkenums")
|
||||
endif()
|
||||
|
||||
pkg_check_modules(XLIB x11 xext xrender ice sm)
|
||||
pkg_check_modules(LIBXML2 REQUIRED libxml-2.0)
|
||||
else()
|
||||
|
||||
if(MOO_BUILD_FROM_MINGW)
|
||||
set(MOO_GTK_DIR "C:/Projects/gtk/release/target" CACHE PATH "Gtk root dir")
|
||||
set(MOO_GTK_DIST_DIR "C:/Projects/gtk/release/bdist" CACHE PATH "Gtk binary dir")
|
||||
|
||||
set(GTK_LIBRARIES libgtk-win32-2.0-0 libatk-1.0-0 libgdk-win32-2.0-0 libgdk_pixbuf-2.0-0
|
||||
libpango-1.0-0 libpangocairo-1.0-0 libcairo-2
|
||||
libgio-2.0-0 libgobject-2.0-0 libgmodule-2.0-0 libgthread-2.0-0 libglib-2.0-0 libintl-8
|
||||
libmooglib-0)
|
||||
set(LIBXML2_LIBRARIES "libxml2-2")
|
||||
else()
|
||||
set(MOO_GTK_DIR "C:/gtk-build/gtk/x64/release" CACHE PATH "Gtk root dir")
|
||||
set(MOO_GTK_DIST_DIR "C:/gtk-build/gtk/x64/bdist" CACHE PATH "Gtk binary dir")
|
||||
set(MOO_PYTHON_DIST_DIR "C:/projects/python-bdist" CACHE PATH "Python binary dir")
|
||||
|
||||
set(GTK_LIBRARIES atk-1.0 cairo gdk_pixbuf-2.0 gdk-win32-2.0 gio-2.0 glib-2.0 gmodule-2.0 gobject-2.0
|
||||
gthread-2.0 gtk-win32-2.0 iconv intl libffi libpng16 pango-1.0 pangocairo-1.0 pixman-1 zlib1)
|
||||
set(LIBXML2_LIBRARIES libxml2)
|
||||
endif()
|
||||
|
||||
#set(CMAKE_INSTALL_PREFIX ${MOO_GTK_DIR} CACHE PATH "CMake install prefix" FORCE)
|
||||
|
||||
include_directories(SYSTEM "${MOO_GTK_DIR}/include")
|
||||
include_directories(SYSTEM "${MOO_GTK_DIR}/include/glib-2.0")
|
||||
include_directories(SYSTEM "${MOO_GTK_DIR}/lib/glib-2.0/include")
|
||||
include_directories(SYSTEM "${MOO_GTK_DIR}/lib/gtk-2.0/include")
|
||||
include_directories(SYSTEM "${MOO_GTK_DIR}/include/gtk-2.0")
|
||||
include_directories(SYSTEM "${MOO_GTK_DIR}/include/gdk-pixbuf-2.0")
|
||||
include_directories(SYSTEM "${MOO_GTK_DIR}/include/pango-1.0")
|
||||
include_directories(SYSTEM "${MOO_GTK_DIR}/include/atk-1.0")
|
||||
include_directories(SYSTEM "${MOO_GTK_DIR}/include/cairo")
|
||||
include_directories(SYSTEM "${MOO_GTK_DIR}/include/libxml2")
|
||||
|
||||
set(GTK_LIBRARY_DIRS "${MOO_GTK_DIR}/lib")
|
||||
|
||||
set(ENV{PATH} "ENV{PATH};${MOO_GTK_DIR}/bin")
|
||||
|
||||
include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/moo/mooutils/moowin32/ms")
|
||||
|
||||
foreach(var CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
set(${var} "${${var}} /MP /Zo /wd4996")
|
||||
|
||||
# "C4706: assignment within conditional expression" - it's a good warning, it catches
|
||||
# 'if(x = 5)'. Unfortunately it also complains about 'while ((p = x()))' which is fine
|
||||
# and is used a lot. Additional parentheses don't silence it, unlike with gcc.
|
||||
set(${var} "${${var}} /W4 /WX /wd4244 /wd4800 /wd4100 /wd4127 /wd4054 /wd4055 /wd4306 /wd4706 /wd4125 /wd4389 /wd4152 /wd4505")
|
||||
|
||||
set(${var}_RELEASE "${${var}_RELEASE} /Zi")
|
||||
string(REPLACE "/Ob1" "/Ob2" ${var}_RELWITHDEBINFO "${${var}_RELWITHDEBINFO}")
|
||||
|
||||
if (true)
|
||||
# /MDd means link with the debug crt library, which we don't want; and /D_DEBUG forces
|
||||
# that as well because of some includes; turn them off.
|
||||
string(REPLACE "/MDd" "/MD" ${var}_DEBUG "${${var}_DEBUG}")
|
||||
string(REPLACE "/D_DEBUG" "/DENABLE_DEBUG=1 /DDEBUG=1 /DMOO_DEBUG=1" ${var}_DEBUG "${${var}_DEBUG}")
|
||||
else()
|
||||
string(REPLACE "/D_DEBUG" "/DENABLE_DEBUG=1 /DDEBUG=1 /DMOO_DEBUG=1 /D_DEBUG" ${var}_DEBUG "${${var}_DEBUG}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
foreach(mode EXE MODULE SHARED STATIC)
|
||||
set(CMAKE_${mode}_LINKER_FLAGS "${CMAKE_${mode}_LINKER_FLAGS} /DEBUG")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
find_program(GLIB_GENMARSHAL glib-genmarshal HINTS ${MOO_GTK_DIR}/bin/glib-genmarshal.exe)
|
||||
find_program(GDK_PIXBUF_CSOURCE gdk-pixbuf-csource HINTS ${MOO_GTK_DIR}/bin/gdk-pixbuf-csource.exe)
|
||||
|
||||
#find_library(LIBM m)
|
||||
|
||||
find_package(Gettext REQUIRED)
|
||||
set(GETTEXT_PACKAGE "${MOO_PACKAGE_NAME}")
|
||||
set(GETTEXT_PACKAGE_GSV "${MOO_PACKAGE_NAME}-gsv")
|
||||
# MOO_INTL
|
||||
|
||||
set(PythonInterp_FIND_VERSION TRUE)
|
||||
set(PythonInterp_FIND_VERSION_MAJOR 2)
|
||||
find_package(PythonInterp REQUIRED)
|
||||
set(MOO_PYTHON "${PYTHON_EXECUTABLE}")
|
||||
|
||||
set(MOO_ENABLE_PYTHON TRUE CACHE BOOL "Use python")
|
||||
|
||||
add_definitions(-DHAVE_CONFIG_H=1 -DXDG_PREFIX=_moo_edit_xdg -DG_LOG_DOMAIN=\"Moo\")
|
||||
#add_definitions(-DGDK_DISABLE_DEPRECATED=1)
|
||||
#add_definitions(-DGTK_DISABLE_DEPRECATED=1)
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(-DUNICODE=1 -D_UNICODE=1 -D__WIN32__=1 -DSTRICT=1 -D_CRT_SECURE_NO_WARNINGS=1 -D_CRT_NONSTDC_NO_WARNINGS=1)
|
||||
set(MOO_NEED_GETTIMEOFDAY TRUE)
|
||||
set(HAVE_UNISTD_H TRUE)
|
||||
set(HAVE_BIND_TEXTDOMAIN_CODESET TRUE)
|
||||
list(APPEND MEDIT_LIBS Shlwapi.lib)
|
||||
endif(WIN32)
|
||||
|
||||
# zzz SUBDIRS = po po-gsv api doc moo
|
||||
add_subdirectory(api)
|
||||
# add_subdirectory(doc)
|
||||
|
||||
#set(ENABLE_NLS TRUE)
|
||||
#add_subdirectory(po)
|
||||
#add_subdirectory(po-gsv)
|
||||
|
||||
add_subdirectory(moo)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config-cmake.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
|
||||
if(WIN32)
|
||||
install(DIRECTORY plat/win32/medit-data/bin plat/win32/medit-data/etc DESTINATION .)
|
||||
endif(WIN32)
|
||||
|
||||
if(WIN32)
|
||||
include(plat/win32/installer.cmake)
|
||||
endif()
|
|
@ -0,0 +1,504 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
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 and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, 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 library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete 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 distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
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 Library or any portion
|
||||
of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
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 Library, 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 Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you 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.
|
||||
|
||||
If distribution of 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 satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be 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.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library 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.
|
||||
|
||||
9. 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 Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
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 with
|
||||
this License.
|
||||
|
||||
11. 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 Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library 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 Library.
|
||||
|
||||
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.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library 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.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser 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 Library
|
||||
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 Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
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
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "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
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. 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 LIBRARY 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
|
||||
LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. 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 library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
|
@ -0,0 +1,339 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser General
|
||||
Public License instead of this License.
|
|
@ -0,0 +1,28 @@
|
|||
medit uses autotools for the build. Quick build with default options:
|
||||
|
||||
tar xjf medit-x.x.x.tar.bz2
|
||||
cd medit-x.x.x
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
|
||||
This will configure, build, and install medit to /usr/local.
|
||||
|
||||
medit requires development packages of the following: gtk2, libxml2, python2, pygtk2.
|
||||
For example, on Debian you may need to install libgtk2.0-dev, libxml2-dev, python2.7-dev, python-gtk2-dev.
|
||||
|
||||
If you checked out a copy of mercurial repository, then do the following to build:
|
||||
|
||||
./autogen.sh
|
||||
./configure --enable-dev-mode
|
||||
make
|
||||
make install
|
||||
|
||||
Building medit from Mercurial requires the following, in addition to the dependencies
|
||||
listed above: automake, autoconf, libtool, intltool, docbook, xsltproc, txt2tags.
|
||||
Other tools may be required and configure may not check for them, please report those
|
||||
to the author.
|
||||
|
||||
To build a python module which could be used in other programs, use
|
||||
--enable-moo-module --enable-shared --disable-static configure flags in addition
|
||||
to above.
|
|
@ -0,0 +1,85 @@
|
|||
medit is distributed under GPL version 2 licence, its text
|
||||
you can find in COPYING.GPL file. Nevertheless, everything but
|
||||
several lang files (see the list below) is under LGPL version
|
||||
2.1 or "version 2.1 or later", see COPYING file for its text.
|
||||
|
||||
Portions of code are written not by me, those are clearly
|
||||
marked as such (copyright headers in files copied from other
|
||||
projects, or comments in source). Below is the list of
|
||||
third-party files/code with their copyrights and licenses.
|
||||
|
||||
If you want to use my code and LGPL doesn't work for you
|
||||
because you have special clause in your license which is not
|
||||
LGPL-compatible, or other garbage like that, I will gladly
|
||||
release it under double license, or do something like that.
|
||||
Just tell me what exactly is needed.
|
||||
|
||||
If you aren't too picky about legal stuff, then you can simply
|
||||
take code and use it in free software as you like, provided
|
||||
you leave the copyright and project name in there (unless it's a
|
||||
small portion of code of course, simple copy/paste must be free
|
||||
as in WTFPL). This applies to all files (and only to those) which
|
||||
do have copyright notice inside; WTFPL will work fine for the rest.
|
||||
|
||||
|
||||
Third-party stuff, for debian/copyright. Everything below
|
||||
is under LGPL unless noted otherwise.
|
||||
|
||||
moo/moolua/lua/*:
|
||||
Lua, LuaFileSystem. Distributed under MIT
|
||||
license, see moo/moolua/COPYRIGHT, moo/moolua/ext/README.lfs.
|
||||
Copyright (C) 1994-2007 Lua.org, PUC-Rio.
|
||||
Copyright 2003-2007 PUC-Rio
|
||||
|
||||
moo/mooedit/plugins/ctags/readtags.[hc]
|
||||
Exuberant Ctags code, public domain
|
||||
Copyright (c) 1996-2003, Darren Hiebert
|
||||
|
||||
moo/mooutils/moofontsel.h:
|
||||
moo/mooutils/moofontsel.c:
|
||||
GTK font selector modified to show monospace fonts
|
||||
(C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
|
||||
moo/mooutils/mooencodings-data.h:
|
||||
(C) 2002 Red Hat, Inc.
|
||||
(C) 2000-2002 Free Software Foundation, Inc.
|
||||
|
||||
moo/mooapp/smclient/*: - eggsmclient library
|
||||
(C) 2007 Novell, Inc.
|
||||
|
||||
moo/mooutils/pcre/*: pcre library by by Philip Hazel
|
||||
BSD-licensed, (C) 1997-2006 University of Cambridge
|
||||
|
||||
moo/mooedit/gtksourceview/upstream/*:
|
||||
moo/mooedit/language-specs/*:
|
||||
gtksourceview library
|
||||
Written over many years by many people, see the files.
|
||||
|
||||
Among those, GPL'ed files:
|
||||
moo/mooedit/language-specs/gtkrc.lang
|
||||
moo/mooedit/language-specs/ini.lang
|
||||
moo/mooedit/language-specs/lua.lang
|
||||
moo/mooedit/language-specs/msil.lang
|
||||
moo/mooedit/language-specs/nemerle.lang
|
||||
moo/mooedit/language-specs/pascal.lang
|
||||
moo/mooedit/language-specs/php.lang
|
||||
moo/mooedit/language-specs/R.lang
|
||||
moo/mooedit/language-specs/ruby.lang
|
||||
|
||||
moo/moopython/codegen/*: pygtk codegen
|
||||
(C) 2004 Gustavo Carneiro <gjc@gnome.org>
|
||||
(C) ???? James Henstridge <james@daa.com.au>
|
||||
(C) ???? Johan Dahlin <johan@gnome.org>
|
||||
|
||||
moo/mooutils/xdgmime/*: xdgmime library
|
||||
(C) 2003,2004 Red Hat, Inc.
|
||||
(C) 2003,2004 Jonathan Blandford <jrb@alum.mit.edu>
|
||||
|
||||
moo/xdg-utils:
|
||||
Looks like some sort of BSD license
|
||||
(C) 2006 Kevin Krammer <kevin.krammer@gmx.at>
|
||||
(C) 2006 Jeremy White <jwhite@codeweavers.com>
|
||||
|
||||
moo/mooutils/pixmaps/medit.png:
|
||||
xedit.png icon from Crystal Clear icon theme by Everaldo Coelho,
|
||||
http://www.everaldo.com
|
|
@ -0,0 +1,58 @@
|
|||
ACLOCAL_AMFLAGS = -I m4 $(ACLOCAL_FLAGS)
|
||||
|
||||
SUBDIRS = po po-gsv api doc moo
|
||||
|
||||
EXTRA_DIST = \
|
||||
tools/genenums.py \
|
||||
tools/glade2c.py \
|
||||
tools/xml2h.py
|
||||
|
||||
DISTCHECK_CONFIGURE_FLAGS =
|
||||
if MOO_DEV_MODE
|
||||
DISTCHECK_CONFIGURE_FLAGS += MAKEFLAGS=-j3
|
||||
endif
|
||||
if MOO_STRICT_MODE
|
||||
DISTCHECK_CONFIGURE_FLAGS += --enable-strict
|
||||
endif
|
||||
|
||||
CLEANFILES =
|
||||
|
||||
include plat/win32/Makefile.incl
|
||||
|
||||
if MOO_OS_WIN32
|
||||
CLEANFILES += plat/win32/installer.iss
|
||||
plat/win32/installer.iss: $(top_srcdir)/plat/win32/installer.iss.in $(top_builddir)/config.status
|
||||
$(AM_V_at)$(MKDIR_P) plat/win32
|
||||
$(AM_V_GEN)cd $(top_builddir) && ./config.status --silent --file=plat/win32/installer.iss
|
||||
installer: plat/win32/installer.iss install
|
||||
$(MEDIT_INNO_COMPILER) plat/win32/installer.iss
|
||||
copy:
|
||||
cp moo/medit.exe "/win/Program Files (x86)/medit/bin/"
|
||||
bd_tmpdir = medit-win-dist-tmp
|
||||
bd_distdir = $(PACKAGE)-$(VERSION)
|
||||
bd_pzip = $(PACKAGE)-portable-$(VERSION)
|
||||
bd_zip = $(PACKAGE)-$(VERSION)
|
||||
portable: install
|
||||
rm -fr $(bd_tmpdir)
|
||||
mkdir $(bd_tmpdir)
|
||||
cp -lR ${prefix} $(bd_tmpdir)/$(bd_distdir)
|
||||
cd $(bd_tmpdir) && zip -r9 $(bd_zip).zip $(bd_distdir)
|
||||
echo "This file enables portable mode for medit" > $(bd_tmpdir)/$(bd_distdir)/bin/$(MEDIT_PORTABLE_MAGIC_FILE_NAME)
|
||||
cd $(bd_tmpdir) && zip -r9 $(bd_pzip).zip $(bd_distdir)
|
||||
mv $(bd_tmpdir)/$(bd_pzip).zip $(bd_tmpdir)/$(bd_zip).zip .
|
||||
rm -fr $(bd_tmpdir)
|
||||
bdist: installer portable
|
||||
endif
|
||||
|
||||
test:
|
||||
$(MAKE) $(AM_MAKEFLAGS) all
|
||||
$(MAKE) $(AM_MAKEFLAGS) check
|
||||
$(MAKE) $(AM_MAKEFLAGS) uninstall
|
||||
$(MAKE) $(AM_MAKEFLAGS) check
|
||||
$(MAKE) $(AM_MAKEFLAGS) install
|
||||
$(MAKE) $(AM_MAKEFLAGS) installcheck
|
||||
fullcheck:
|
||||
$(MAKE) $(AM_MAKEFLAGS) test
|
||||
$(MAKE) $(AM_MAKEFLAGS) distcheck
|
||||
|
||||
@MOO_PO_SUBDIRS_RULE@
|
|
@ -0,0 +1,651 @@
|
|||
2014-03-20 Yevgen Muntyan <emuntyan@users.sourceforge.net>
|
||||
|
||||
* === Released 1.2.0 ===
|
||||
|
||||
Updated Spanish translation by Eulogio Serradilla.
|
||||
New Polish translation by Piotr Orzechowski.
|
||||
Fixed a bug in parsing grep output for UNC paths on windows.
|
||||
Updated syntax highlighting definitions.
|
||||
Fixed compilation with new glib and gcc.
|
||||
Exposed more functionality, in particular the output pane, to scripts.
|
||||
Finally made file completion case-insensitive on windows.
|
||||
|
||||
2012-11-25 Yevgen Muntyan <emuntyan@users.sourceforge.net>
|
||||
|
||||
* === Released 1.1.2 ===
|
||||
|
||||
Updated Japanese translation from Toshiharu Kudoh.
|
||||
Updated German translation by Debianer.
|
||||
Partial workaround for the Gtk bug with Shift key: make Shift-Fn
|
||||
key combinations work as global shortcuts.
|
||||
|
||||
2012-07-27 Yevgen Muntyan <emuntyan@users.sourceforge.net>
|
||||
|
||||
* === Released 1.1.1 ===
|
||||
|
||||
Fixed some build errors:
|
||||
Check for sys/wait.h, so that HAVE_SYS_WAIT_H is defined when needed.
|
||||
Link with gmodule explicitly.
|
||||
|
||||
2012-03-04 Yevgen Muntyan <emuntyan@users.sourceforge.net>
|
||||
|
||||
* === Released 1.1.0 ===
|
||||
|
||||
Fixed few memory leaks.
|
||||
Improved documentation.
|
||||
Made lua scripts use UTF-8 strings by default.
|
||||
Fixed font selector in terminal pane.
|
||||
Fixed clicks and drags with Shift key pressed.
|
||||
Store 'Show hidden files' setting of file selector in preferences.
|
||||
Added Japanese translation by Toshiharu Kudoh.
|
||||
Updated Spanish translation by Sebikul.
|
||||
Added Finnish translation by Tommi Nieminen.
|
||||
|
||||
2011-10-23 Yevgen Muntyan <emuntyan@users.sourceforge.net>
|
||||
|
||||
* === Released 1.0.5 ===
|
||||
|
||||
Fixed a bug where filename "12d1:1446" was treated as file "12d1"
|
||||
and line number 1446.
|
||||
Unbroke keyboard shortcuts when running under gtk-2.24.7.
|
||||
|
||||
2011-09-11 Yevgen Muntyan <emuntyan@users.sourceforge.net>
|
||||
|
||||
* === Released 1.0.4 ===
|
||||
|
||||
Added protobuf lang file by Pavel Artyomkin.
|
||||
|
||||
2011-04-14 Yevgen Muntyan <emuntyan@users.sourceforge.net>
|
||||
|
||||
* === Released 1.0.3 ===
|
||||
|
||||
Fixed "Move to Split Notebook" command.
|
||||
|
||||
2011-04-04 Yevgen Muntyan <emuntyan@users.sourceforge.net>
|
||||
|
||||
* === Released 1.0.2 ===
|
||||
|
||||
Fixed importing pygobject and pygtk with python-2.7 (at least on
|
||||
openSUSE newer pygtk in medit was broken).
|
||||
|
||||
2011-02-26 Yevgen Muntyan <emuntyan@users.sourceforge.net>
|
||||
|
||||
* === Released 1.0.1 ===
|
||||
|
||||
Updated Russian translation.
|
||||
Fixed a crash on windows when syntax highlighting gets disabled
|
||||
because of very long lines.
|
||||
Updated ini.lang.
|
||||
|
||||
2011-01-29 Yevgen Muntyan <emuntyan@users.sourceforge.net>
|
||||
|
||||
* === Released 1.0.0 ===
|
||||
|
||||
New release which breaks backwards compatibility (which won't be
|
||||
broken again for long time, not until medit-2.0). Bugs have been
|
||||
fixed, features have been implemented, new bugs have been introduced.
|
||||
|
||||
Highlights:
|
||||
|
||||
- Consistent API for Python and Lua scripts, generated from
|
||||
source code, together with documentation. This allows for
|
||||
much more powerful Lua scripts.
|
||||
- Added option to show all spaces, not just Tab characters.
|
||||
- Allow searching in a list of directories instead of just a single one.
|
||||
- Added --geometry command line option.
|
||||
- Added split views - multiple views of the same document in one
|
||||
notebook tab.
|
||||
- Windows can display two notebooks to allow viewing two different
|
||||
documents at the same as well.
|
||||
- Build system uses autotools again. Cmake is nice but not nice enough.
|
||||
|
||||
2010-10-05 Yevgen Muntyan <emuntyan@sourceforge.net>
|
||||
|
||||
* === Released 0.10.5 ===
|
||||
|
||||
Added an option to show spaces, not just tabs.
|
||||
Added linker flags to fix build on some Linux distributions.
|
||||
Fixed bug where Select All menu item wouldn't select text on
|
||||
some builds (found by Andrey Frantsuzov).
|
||||
|
||||
2010-04-29 Yevgen Muntyan <emuntyan@users.sourceforge.net>
|
||||
|
||||
* === Released 0.10.4 ===
|
||||
|
||||
Python plugins are back.
|
||||
|
||||
2010-04-16 Yevgen Muntyan <emuntyan@users.sourceforge.net>
|
||||
|
||||
* === Released 0.10.3 ===
|
||||
|
||||
Fixed crash in Find File command.
|
||||
|
||||
Windows: downgraded gtk to 2.16.6 because of problems with
|
||||
"client-side windows" feature. Fixed a bug with synaptics
|
||||
touchpad where scrolling would stop working after a dialog
|
||||
was shown.
|
||||
|
||||
2010-04-14 Yevgen Muntyan <emuntyan@users.sourceforge.net>
|
||||
|
||||
* === Released 0.10.2 ===
|
||||
|
||||
Added back man page, fixed compilation on systems where cmake
|
||||
builds dynamic libraries by default.
|
||||
|
||||
On windows, made medit use case-insensitive filename comparison
|
||||
and fixed scrolling with a Synaptics touchpad.
|
||||
|
||||
2010-03-19 Yevgen Muntyan <emuntyan@users.sourceforge.net>
|
||||
|
||||
* === Released 0.10.1 ===
|
||||
|
||||
Restored lost ctags plugin. Added simple installation
|
||||
instructions.
|
||||
|
||||
2010-02-28 Yevgen Muntyan <emuntyan@users.sourceforge.net>
|
||||
|
||||
* === Released 0.10.0 ===
|
||||
|
||||
2008-08-29 Yevgen Muntyan <muntyan@tamu.edu>
|
||||
|
||||
* === Released 0.9.4 ===
|
||||
|
||||
Corrected a brain dead logic error which led to data loss:
|
||||
medit did not report a proper error when it could not convert
|
||||
content to requested encoding (e.g. when trying to save text
|
||||
with accented characters in ASCII). Thanks to LoneFox.
|
||||
|
||||
Updated and corrected documentation.
|
||||
Fixed recent files menu where underscore in filenames showed
|
||||
up as mnemonics underline.
|
||||
Added recent files dialog.
|
||||
Fixed saving session on logout.
|
||||
Made open-dialog-follows-doc option apply to Save As too.
|
||||
Much improved Mac OS X port (which requires much improved Mac OS X
|
||||
Gtk port from SVN).
|
||||
Once again fixed document tab icon appearance.
|
||||
Made tilde expansion work in Find in Files dialog.
|
||||
Fixed bug in Preferences dialog caused by a buggy Ubuntu Gtk patch.
|
||||
Worked around freezing when editing a document with very long lines.
|
||||
Added Open With Default Application to file selector menu.
|
||||
Made ctags plugin not try to run ctags on a non-existent file.
|
||||
User data files on windows are now stored in <User>/Application Data
|
||||
instead of the home folder, medit will move old files on startup.
|
||||
Fixed win32 bug with saving session file.
|
||||
Lot of lang files were improved.
|
||||
|
||||
Added Dutch translation by Kris Van Bruwaene.
|
||||
Updated German translation by Christian Dywan.
|
||||
|
||||
2008-02-10 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
|
||||
* === Released 0.9.3 ===
|
||||
|
||||
Fixed double-click glitch in the file selector.
|
||||
Made file list remember expanded and collapsed rows.
|
||||
Implemented Find in Files on windows.
|
||||
Fixed handling UNC paths on windows.
|
||||
GtkRecent*, which caused freezing on load and save,
|
||||
is no longer used.
|
||||
Made ctags plugin enabled by default.
|
||||
Fixed deleting folders on windows.
|
||||
|
||||
Updated German translation by Christian Dywan.
|
||||
|
||||
2008-01-10 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
|
||||
* === Released 0.9.2 ===
|
||||
|
||||
Fixed broken windows build.
|
||||
|
||||
2008-01-09 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
|
||||
* === Released 0.9.1 ===
|
||||
|
||||
Added more editor functions for Lua scripts.
|
||||
Made building with --disable-nls work again.
|
||||
Fixed alternating button order in Find dialog; use it
|
||||
in more dialogs (LoneFox).
|
||||
Fixed a segfault in user tools preferences.
|
||||
Small buttons in the notebook and window panes follow
|
||||
gtk theme.
|
||||
Notebook tabs no longer scroll on closing document.
|
||||
Nicer arrow buttons in notebook.
|
||||
configure doesn't fail to detect pygtk when pycairo-dev
|
||||
is absent.
|
||||
Added a setting to ensure trailing newline character
|
||||
on save.
|
||||
Emacs-like filename:line strings are now recognized by
|
||||
default in shell tools output.
|
||||
File list plugin.
|
||||
Function list plugin (Christian Dywan).
|
||||
File selector allows selecting by dragging the mouse
|
||||
and DND for multiple items.
|
||||
Window panes configurations is now saved and restored
|
||||
properly; panes may be re-arranged by DND.
|
||||
Added color schemes for the terminal.
|
||||
Fixed the bug when the toolbar didn't pick up default gtk
|
||||
style.
|
||||
Fixed all memory leaks found by valgrind.
|
||||
|
||||
Updated French translation by Collilieux.
|
||||
Updated Spanish translation by Arnau Sanchez.
|
||||
Updated German translation by Christian Dywan.
|
||||
Updated Chinese translation by Chaosye.
|
||||
|
||||
Special thanks to Christian Dywan.
|
||||
|
||||
2007-11-29 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
* === Released 0.9.0 ===
|
||||
|
||||
Replaced MooScript with Lua.
|
||||
Improved user-defined tools, made it possible to store
|
||||
tools in separate files instead of creating and editing
|
||||
them via Preferences dialog.
|
||||
Added online help.
|
||||
Rearranged menu items, removed Settings menu.
|
||||
Added a setting for window title format.
|
||||
Made Preferences dialog remember its size to make
|
||||
editing scripts more comfortable.
|
||||
Fixed the bug with storing clipboard contents on exit.
|
||||
Fixed files drag'n'drop on windows.
|
||||
Improved syntax highlighting.
|
||||
medit now reads meditrc files in data directories, so it's
|
||||
possible to have pre-set options different from defaults.
|
||||
Fixed Find in Files and Find File menu items broken on
|
||||
some systems.
|
||||
Fixed highlighting current line and behavior of Home/End
|
||||
keys when line wrapping is enabled.
|
||||
Fixed entries for language extensions and mime types in the
|
||||
Preferences dialog.
|
||||
Added a command-line option to open documents in a new window.
|
||||
|
||||
Czech translation by Vlastimil Ott.
|
||||
Updated German translation by Christian Dywan.
|
||||
|
||||
2007-08-07 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
* === Released 0.8.10 ===
|
||||
|
||||
Fixed numerous memory leaks.
|
||||
Fixed an issue with indentation when pressing Enter key
|
||||
on an empty line.
|
||||
Fixed tooltips on toolbar, once again, now for gtk-2.10.
|
||||
Added a setting for what directory should be shown in the
|
||||
Open dialog.
|
||||
|
||||
2007-07-31 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
* === Released 0.8.9 ===
|
||||
|
||||
Russian translation by Andrey Fedoseev.
|
||||
Spanish translation by Arnau Sanchez.
|
||||
|
||||
Added a setting to disable sessions (Joris_M).
|
||||
Added a setting to draw right margin in text, as in gedit.
|
||||
Unbroke loading old lang files.
|
||||
Fixed some bugs in notebook tabs drawing.
|
||||
Re-added --with-broken-gtk-theme configure option for Suse.
|
||||
Do not ignore displayed tab width when printing.
|
||||
Worked around crash with Export as PDF and gtk-2.10.
|
||||
|
||||
New and improved syntax highlighting:
|
||||
c, css, pkgconfig.
|
||||
|
||||
2007-07-10 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
* === Released 0.8.8 ===
|
||||
|
||||
New command-line option --app-name: instances with different names
|
||||
do not share sessions, and --app-name works as --pid argument when
|
||||
an instance with given name is already running.
|
||||
Added hidden setting for width of displayed Tab characters.
|
||||
Fixed theming bug in the paned widget.
|
||||
Improved Preferences dialog.
|
||||
Updated German translation (Christian Dywan).
|
||||
|
||||
New and improved syntax highlighting:
|
||||
ada, awk, c, changelog, cpp, haskell, html, java, lua, m4,
|
||||
objc, ocl, ruby, scheme, sh.
|
||||
|
||||
2007-06-24 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
* === Released 0.8.7 ===
|
||||
|
||||
Implemented session support.
|
||||
Use xdg-open to open files from file selector.
|
||||
Fixed build on darwin.
|
||||
Added translation for language files.
|
||||
|
||||
Changed license of almost everything to LGPL.
|
||||
|
||||
2007-06-14 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
* === Released 0.8.6 ===
|
||||
|
||||
Chinese translation by Chaosye.
|
||||
German translation by Christian Dywan.
|
||||
|
||||
User config and data files are moved into ~/.config, ~/.share, etc.,
|
||||
according to XDG specification. medit will move old files into new
|
||||
locations on startup, so transition should be smooth and invisible (Oliwer).
|
||||
|
||||
Improved file encodings handling, and fixed some bugs related to it.
|
||||
Made it use more stock items and icons from icon themes.
|
||||
Improved paned widget behavior, no more nasty drawing artifacts.
|
||||
Fixed Find dialog which treated replacement text as a regular
|
||||
expression.
|
||||
Made editor recognize "nxml" emacs mode as xml.
|
||||
freedesktop.org mime type database is used now on windows, so it knows
|
||||
how to highlight files of common types.
|
||||
'medit filename' behaves better when another isntance is already running.
|
||||
Underline character in a filename is no longer treated as mnemonic
|
||||
underline in the Window menu.
|
||||
Fixed tab icons background bug (Christian Dywan).
|
||||
|
||||
Improved syntax highlighting:
|
||||
c csharp css desktop fortran gap gtkrc idl java javascript latex m4
|
||||
ocaml octave pascal perl pkgconfig po ruby scheme sh sql tcl verilog
|
||||
vhdl xml
|
||||
New syntax highlighting:
|
||||
docbook ocaml spec
|
||||
|
||||
2007-04-09 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
* === Released 0.8.5 ===
|
||||
|
||||
Fixed critical win32 bug: editor duplicated line endings on save,
|
||||
screwing up files and everything (Thomas Gilgin).
|
||||
|
||||
Implemented selecting whole lines on click/drag over line numbers
|
||||
margin (stonecrest).
|
||||
Made it save user-chosen encodings in Open and Save dialog.
|
||||
It's now possible to print line numbers.
|
||||
|
||||
Version 0.8.4 broke loading files on unix, and was deleted.
|
||||
|
||||
2007-04-06 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
* === Released 0.8.3 ===
|
||||
|
||||
French translation by Collilieux.
|
||||
Finally made tools written in Python work.
|
||||
Fixed Stop button in replace confirmation dialog.
|
||||
Number following colon after filename on command line is treated as line number,
|
||||
e.g. 'medit /home/user/foo:134'.
|
||||
|
||||
File selector fixes:
|
||||
Use exo-open when running on XFCE.
|
||||
Correctly determine mime type of backup files and text files.
|
||||
Executable files do not get passed to gnome-open and alike, so they are not
|
||||
executed on double-click.
|
||||
Improved performance and memory consumption.
|
||||
|
||||
Improved syntax highlighting: C, C++, po, gtk-doc, Makefile,
|
||||
|
||||
2007-02-03 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
* === Released 0.8.2 ===
|
||||
|
||||
Made medit ask whether to save changes on logout.
|
||||
Fixed build without libxml2.
|
||||
Fixed PHP and Java syntax highlighting.
|
||||
Double-click in file selector now opens text files in the editor,
|
||||
and uses default applications for the rest of files.
|
||||
|
||||
2007-01-20 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
* === Released 0.8.1 ===
|
||||
|
||||
Added syntax highlighting for pkgconfig, libtool, dpatch, dtd.
|
||||
Improved highlighting for shell, python, desktop, m4, xml.
|
||||
Improved compiler and python output views.
|
||||
Added simple python project type.
|
||||
Made Alt-<number> shortcuts switch tabs (stonecrest).
|
||||
All filter settings matching given filename are applied now,
|
||||
in order they are specified, so it's easy to set settings
|
||||
for a folder or single glob, and then tweak them for individual
|
||||
files.
|
||||
Added character encoding selectors to Open and Save dialogs.
|
||||
File permissions are now preserved when using Save As.
|
||||
Input fifo's are created in a separate subdirectory of /tmp,
|
||||
to pollute it less.
|
||||
Windows build uses mime types database from freedesktop.org
|
||||
now.
|
||||
Implemented folder watching on windows: file selector updates
|
||||
automatically when folder content changes.
|
||||
Drag'n'drop in file selector works with Go to Current Doc Folder button.
|
||||
Added bunch of tools for LaTeX documents.
|
||||
|
||||
2006-11-30 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
* === Released 0.8.0 ===
|
||||
|
||||
Added document bookmarks (Dmytro Savchuk).
|
||||
"medit" without arguments opens new file if existing process instance
|
||||
is used (Lontronics).
|
||||
Open dialog remembers its size (Lontronics).
|
||||
|
||||
2006-11-19 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
* === Released 0.7.97 ===
|
||||
|
||||
Added Print Preview and Export as PDF menu items.
|
||||
Improved print preview.
|
||||
Fixed problem with multiple windows on twm (Lontronics).
|
||||
|
||||
2006-11-13 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
* === Released 0.7.96 ===
|
||||
|
||||
Fixed print preview for different page orientations.
|
||||
Made editor use document font to display line numbers.
|
||||
|
||||
2006-11-13 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
* === Released 0.7.95 ===
|
||||
|
||||
Quick fix release for 0.7.9.
|
||||
|
||||
Fixed crash on windows with pygtk older than 2.10.
|
||||
Got drawing tabs and trailing spaces back.
|
||||
|
||||
2006-11-12 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
* === Released 0.7.9 ===
|
||||
|
||||
Beta version of new 0.8 release.
|
||||
|
||||
Syntax highlighting has been replaced with brand new syntax
|
||||
highlighting from GtkSourceView. It supports million different
|
||||
languages, and has much better performance.
|
||||
|
||||
New features and improvements:
|
||||
Win32 installer includes GTK.
|
||||
Implemented print preview; implemented printing with
|
||||
text styles from the document.
|
||||
Implemented customizable output filters, for highlighting
|
||||
errors in commands output and automatic opening appropriate
|
||||
files.
|
||||
Copying file in the file selector copies its URI/path
|
||||
when appropriate.
|
||||
Added "async" mode for running shell commands: output is
|
||||
redirected to medit's parent console and medit does not
|
||||
wait for the command to terminate.
|
||||
|
||||
Fixed bugs include:
|
||||
Problem with new keyboard shortcuts not applied immediately
|
||||
when set in Configure Shortcuts dialog.
|
||||
Build errors with gtk-2.6.
|
||||
Paned widgets can't be covered by document anymore.
|
||||
Lot of other bugs too.
|
||||
|
||||
2006-08-24 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
* === Released 0.7.1 ===
|
||||
|
||||
Quick-fix release: fixed some build errors,
|
||||
removed shell unix tools from win32 build.
|
||||
|
||||
2006-08-23 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
* === Released 0.7.0 ===
|
||||
|
||||
New features and impovements:
|
||||
New and improved user-defined tools.
|
||||
Much improved Find plugin.
|
||||
I18n infrastructure is in place (no translations yet).
|
||||
Reworked plugin system.
|
||||
Experimental project plugin.
|
||||
Printing with gtk-2.10.
|
||||
|
||||
Made it possible to blacklist certain extensions, so no language
|
||||
is picked up for them.
|
||||
Added New File action in file selector.
|
||||
Made displayed tab width configurable.
|
||||
Close editor tabs by middle mouse button click (Thomas Gilgin).
|
||||
Made font selectors show only monospace fonts.
|
||||
Find Current Word action (Thomas Gilgin).
|
||||
Improved terminal drawing.
|
||||
Prettified python console (Geoffrey French).
|
||||
|
||||
Disabled active strings and completion in this version, they will
|
||||
be reenabled and made actually useful in next releases.
|
||||
|
||||
Bug fixes include:
|
||||
Fixed bug with simultaneous dragging icon and reordering tabs in notebook.
|
||||
On opening files prefer locale encoding to builtin ones (Thomas Gilgin).
|
||||
Do not try to open special files both on windows and unix.
|
||||
Fix startup notification protocol handling, so the editor does not steal
|
||||
focus when using single instance mode and does pop up on correct desktop
|
||||
when needed.
|
||||
Color scheme setting applied after opening a document (Thomas Gilgin).
|
||||
Custom shortcuts did not get saved under certain conditions.
|
||||
Fixed tab icon dnd which caused input lock in child windows.
|
||||
Fixed bug in Search/Replace when replacement uses back references.
|
||||
Store clipboard contents on quit (Thomas Gilgin).
|
||||
Fixed crash on paste from another application.
|
||||
Save search history and search options (Thomas Gilgin).
|
||||
|
||||
2006-05-26 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
* === Released 0.6.99 ===
|
||||
|
||||
Added Open With submenu in file selector popup menu.
|
||||
Fixed bug with per-language settings lost on save.
|
||||
Added document list menu in editor windows.
|
||||
Fixed crash on paste from another application.
|
||||
Improved entry completion behaviour.
|
||||
Improved python plugin.
|
||||
Updated printing code for changes in gtk api.
|
||||
Fixed file selector background bug.
|
||||
There is a single win32 installer now, and medit picks up python if it's present
|
||||
on startup: medit is not linked to pythonxx.dll, python support has been moved
|
||||
into pymo2x plugins.
|
||||
Improved build infrastructure (Andreas Hanke).
|
||||
Bug fixes.
|
||||
|
||||
2006-05-04 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
|
||||
* === Released 0.6.98 ===
|
||||
|
||||
Added printing support for gtk-2.9.
|
||||
Printing support in gtk is not stable yet, and will likely change
|
||||
in future, therefore printing in medit must be explicitely enabled by
|
||||
--enable-printing argument to configure.
|
||||
Fixed drawing bug when opening big files.
|
||||
Made window panes save their position after changing it by drag-n-drop.
|
||||
Build fixes on AMD Linux, other bug fixes.
|
||||
|
||||
2006-05-04 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
|
||||
* === Released 0.6.97 ===
|
||||
|
||||
medit now uses system pcre library if present; FAM support is disabled.
|
||||
|
||||
Allow adding tools into different menus.
|
||||
Added gnuplot syntax highlighting.
|
||||
Fixed python output pane: it now jumps to correct line in error
|
||||
messages, and it uses Stop button.
|
||||
Added gui for setting per-language settings in Preferences dialog.
|
||||
Dropping a file into the text area opens file now, instead of pasting uri.
|
||||
"medit filename" from command line creates new file if the argument is not
|
||||
an existing file.
|
||||
|
||||
2006-04-30 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
|
||||
* === Released 0.6.96 ===
|
||||
|
||||
Fixed bugs:
|
||||
Build problems on AMD64 - David Hough.
|
||||
Missing #include <time.h> - Nick Treleaven, David Hough.
|
||||
Problem with hidden toolbar showing up anyway - Andrey Fedoseev.
|
||||
Missing window icon - Andrey Fedoseev.
|
||||
|
||||
2006-04-30 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
|
||||
* === Released 0.6.95 ===
|
||||
|
||||
Greatly improved syntax highlighting, zillion fixes.
|
||||
|
||||
2006-04-20 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
|
||||
* === Released 0.6.9 ===
|
||||
|
||||
User-defined completion, tools, and context menus.
|
||||
|
||||
2006-04-09 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
|
||||
* === Released 0.6.8 ===
|
||||
|
||||
Finally unbroke windows terminal, and finally fixed
|
||||
bug with terminal eating 100% of cpu time.
|
||||
|
||||
Active strings, user-defined commands:
|
||||
Added support for python scripts and shell commands.
|
||||
|
||||
2006-04-06 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
|
||||
* === Released 0.6.7 ===
|
||||
|
||||
Reverted changes in windows terminal.
|
||||
|
||||
2006-04-06 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
|
||||
* === Released 0.6.6 ===
|
||||
|
||||
Lot of bugs fixed, lot of bugs introduced.
|
||||
|
||||
MooEdit:
|
||||
Made quick search work.
|
||||
Line ends type is detected automatically, and
|
||||
used when saving file.
|
||||
|
||||
2006-03-29 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
|
||||
* === Released 0.6.5 ===
|
||||
|
||||
0.6.4 is broken
|
||||
|
||||
2006-03-29 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
|
||||
* === Released 0.6.4 ===
|
||||
|
||||
MooEdit:
|
||||
Implemented printing for gtk-2.10.
|
||||
|
||||
MooTerm:
|
||||
Rewritten drawing.
|
||||
|
||||
MooFileView:
|
||||
Made it work (to some extent) on windows.
|
||||
|
||||
2006-03-15 Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
|
||||
* === Released 0.6.3 ===
|
||||
|
||||
Added customizable menus, with user-defined actions using MooScript.
|
||||
|
||||
MooApp:
|
||||
Fixed input pipe eating all cpu time.
|
||||
Use recursive g_remove on windows for removing directories, to avoid
|
||||
shell api asking user if he wants t remove temporary directory.
|
||||
Custom About dialog.
|
||||
|
||||
MooEdit:
|
||||
Reenabled force-tag-redraw hack in highlighter, due to GTK bug.
|
||||
Fixed unreal slowness of highlighting matching brackets.
|
||||
|
||||
MooTerm:
|
||||
Made moo_term_get_selection_bounds() public.
|
||||
|
||||
MooFileView:
|
||||
Unbroke get_parent_folder
|
||||
|
||||
Python module:
|
||||
Made moo module behave like a package.
|
||||
Made atributes of TermIter and TermTextAttr writable.
|
||||
Added file-like objects which use g_print* for sys.stdout and sys.stderr.
|
|
@ -0,0 +1,40 @@
|
|||
General Information
|
||||
===================
|
||||
|
||||
medit is a text editor.
|
||||
|
||||
medit is free software, released under GNU GPL license. See the LICENSE
|
||||
file in this distribution for details.
|
||||
|
||||
The web site is:
|
||||
http://medit.bitbucket.org/
|
||||
releases are located at:
|
||||
http://sourceforge.net/project/showfiles.php?group_id=167563
|
||||
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
See INSTALL file in this distribution.
|
||||
|
||||
|
||||
Bug reports and contact
|
||||
=======================
|
||||
|
||||
Report bugs and file feature requests in the medit bug tracker at
|
||||
http://sourceforge.net/tracker/?group_id=167563&atid=843451 . You can
|
||||
also send an email to emuntyan@users.sourceforge.net if you don't feel
|
||||
like using the bug tracker, or have any questions/comments.
|
||||
|
||||
|
||||
Sources
|
||||
=======
|
||||
|
||||
medit sources are tracked using mercurial. You can browse medit source
|
||||
repository online at http://bitbucket.org/medit/medit/. To check out a
|
||||
copy of medit repository, install mercurial, and do
|
||||
hg clone http://bitbucket.org/medit/medit/
|
||||
This will create a new directory named 'medit' with medit sources inside.
|
||||
To update them later on, do
|
||||
hg pull; hg update
|
||||
in this directory.
|
|
@ -0,0 +1,48 @@
|
|||
To Sveta and Max Muntyan,
|
||||
|
||||
and to all who contributed, including
|
||||
|
||||
Andreas Hanke
|
||||
Andrey Fedoseev
|
||||
archxyne
|
||||
Arnau Sanchez
|
||||
Chaosye
|
||||
Christian Dywan
|
||||
Collilieux
|
||||
Daniel Butzu
|
||||
Daniel Poelzleithner
|
||||
David Hough
|
||||
Debianer
|
||||
Denis Koryavov
|
||||
Dmytro Savchuk
|
||||
Eulogio Serradilla
|
||||
Everaldo Coelho
|
||||
Federico Mena Quintero
|
||||
Geoffrey French
|
||||
Jeroen Zwartepoorte
|
||||
josgalo
|
||||
Kenneth Prugh
|
||||
Kris Van Bruwaene
|
||||
Lasse Makholm
|
||||
LoneFox
|
||||
Lontronics
|
||||
Malete Partner
|
||||
Marco Barisione
|
||||
Matthias Clasen
|
||||
Nick Treleaven
|
||||
Owen Taylor
|
||||
Paolo Borelli
|
||||
Paolo Maggi
|
||||
Pavel Artyomkin
|
||||
Philip Hazel
|
||||
Ryan Anonymous
|
||||
Scott Wimer
|
||||
Sebikul
|
||||
Thomas Gilgin
|
||||
Tim Janik
|
||||
Tim-Philipp Müller
|
||||
Tommi Nieminen
|
||||
Toshiharu Kudoh
|
||||
Ulrich Eckhardt
|
||||
Vlastimil Ott
|
||||
Yannick Duchêne
|
|
@ -0,0 +1,363 @@
|
|||
SET(docparser_files
|
||||
parsedocs.py
|
||||
mdp/__init__.py
|
||||
mdp/module.py
|
||||
mdp/docparser.py
|
||||
mdp/xmlwriter.py
|
||||
)
|
||||
|
||||
SET(gendefs_files
|
||||
gendefs.py
|
||||
mpi/__init__.py
|
||||
mpi/module.py
|
||||
mpi/defswriter.py
|
||||
)
|
||||
|
||||
SET(genlua_files
|
||||
genlua.py
|
||||
mpi/__init__.py
|
||||
mpi/module.py
|
||||
mpi/luawriter.py
|
||||
)
|
||||
|
||||
SET(gendocs_files
|
||||
gendocs.py
|
||||
gendocbook.py
|
||||
mpi/__init__.py
|
||||
mpi/module.py
|
||||
mpi/docbookwriter.py
|
||||
)
|
||||
|
||||
SET(source_files
|
||||
../moo/moolua/medit-lua.h
|
||||
../moo/moolua/medit-lua.cpp
|
||||
../moo/mooapp/mooappabout.c
|
||||
../moo/mooapp/mooappabout.h
|
||||
../moo/mooapp/mooapp-accels.h
|
||||
../moo/mooapp/mooapp.c
|
||||
../moo/mooapp/mooapp.h
|
||||
../moo/mooapp/mooapp-info.h
|
||||
../moo/mooapp/mooapp-private.h
|
||||
../moo/mooapp/moohtml.c
|
||||
../moo/mooapp/moohtml.h
|
||||
../moo/mooapp/moolinklabel.c
|
||||
../moo/mooapp/moolinklabel.h
|
||||
../moo/mooedit/mooedit-accels.h
|
||||
../moo/mooedit/mooeditaction.c
|
||||
../moo/mooedit/mooeditaction-factory.c
|
||||
../moo/mooedit/mooeditaction-factory.h
|
||||
../moo/mooedit/mooeditaction.h
|
||||
../moo/mooedit/mooeditbookmark.c
|
||||
../moo/mooedit/mooeditbookmark.h
|
||||
../moo/mooedit/mooedit.cpp
|
||||
../moo/mooedit/mooeditconfig.c
|
||||
../moo/mooedit/mooeditconfig.h
|
||||
../moo/mooedit/mooeditdialogs.cpp
|
||||
../moo/mooedit/mooeditdialogs.h
|
||||
../moo/mooedit/mooedit-enum-types.c
|
||||
../moo/mooedit/mooedit-enum-types.h
|
||||
../moo/mooedit/mooedit-enums.h
|
||||
../moo/mooedit/mooeditfileinfo.c
|
||||
../moo/mooedit/mooeditfileinfo.c
|
||||
../moo/mooedit/mooeditfileinfo.h
|
||||
../moo/mooedit/mooedit-fileops.cpp
|
||||
../moo/mooedit/mooedit-fileops.h
|
||||
../moo/mooedit/mooeditfiltersettings.c
|
||||
../moo/mooedit/mooeditfiltersettings.h
|
||||
../moo/mooedit/mooedit.h
|
||||
../moo/mooedit/mooedithistoryitem.c
|
||||
../moo/mooedit/mooedithistoryitem.h
|
||||
../moo/mooedit/mooedit-impl.h
|
||||
../moo/mooedit/mooeditor.cpp
|
||||
../moo/mooedit/mooeditor.h
|
||||
../moo/mooedit/mooeditor-impl.h
|
||||
../moo/mooedit/mooeditor-private.h
|
||||
../moo/mooedit/mooeditor-tests.c
|
||||
../moo/mooedit/mooeditor-tests.h
|
||||
../moo/mooedit/mooeditprefs.c
|
||||
../moo/mooedit/mooeditprefs.h
|
||||
../moo/mooedit/mooeditprefspage.c
|
||||
../moo/mooedit/mooedit-private.h
|
||||
../moo/mooedit/mooedit-script.c
|
||||
../moo/mooedit/mooedit-script.h
|
||||
../moo/mooedit/mooedittab.c
|
||||
../moo/mooedit/mooedittab.h
|
||||
../moo/mooedit/mooedittypes.h
|
||||
../moo/mooedit/mooeditview.c
|
||||
../moo/mooedit/mooeditview.h
|
||||
../moo/mooedit/mooeditview-script.c
|
||||
../moo/mooedit/mooeditview-script.h
|
||||
../moo/mooedit/mooeditwindow.c
|
||||
../moo/mooedit/mooeditwindow.h
|
||||
../moo/mooedit/mooeditwindow-impl.h
|
||||
../moo/mooedit/moofold.c
|
||||
../moo/mooedit/moofold.h
|
||||
../moo/mooedit/mooindenter.c
|
||||
../moo/mooedit/mooindenter.h
|
||||
../moo/mooedit/moolang.c
|
||||
../moo/mooedit/moolang.h
|
||||
../moo/mooedit/moolangmgr.c
|
||||
../moo/mooedit/moolangmgr.h
|
||||
../moo/mooedit/moolangmgr-private.h
|
||||
../moo/mooedit/moolang-private.h
|
||||
../moo/mooedit/moolinebuffer.c
|
||||
../moo/mooedit/moolinebuffer.h
|
||||
../moo/mooedit/moolinemark.c
|
||||
../moo/mooedit/moolinemark.h
|
||||
../moo/mooedit/mooplugin.c
|
||||
../moo/mooedit/mooplugin.h
|
||||
../moo/mooedit/mooplugin-loader.c
|
||||
../moo/mooedit/mooplugin-loader.h
|
||||
../moo/mooedit/mooplugin-macro.h
|
||||
../moo/mooedit/mootextbtree.c
|
||||
../moo/mooedit/mootextbtree.h
|
||||
../moo/mooedit/mootextbuffer.c
|
||||
../moo/mooedit/mootextfind.c
|
||||
../moo/mooedit/mootextfind.h
|
||||
../moo/mooedit/mootextiter.h
|
||||
../moo/mooedit/mootextprint.c
|
||||
../moo/mooedit/mootextprint.h
|
||||
../moo/mooedit/mootextprint-private.h
|
||||
../moo/mooedit/mootext-private.h
|
||||
../moo/mooedit/mootextsearch.c
|
||||
../moo/mooedit/mootextsearch.h
|
||||
../moo/mooedit/mootextsearch-private.h
|
||||
../moo/mooedit/mootextstylescheme.c
|
||||
../moo/mooedit/mootextstylescheme.h
|
||||
../moo/mooedit/mootextview.c
|
||||
../moo/mooedit/mootextview.h
|
||||
../moo/mooedit/mootextview-input.c
|
||||
../moo/mooedit/mootextview-private.h
|
||||
../moo/moofileview/moobookmarkmgr.c
|
||||
../moo/moofileview/moobookmarkmgr.h
|
||||
../moo/moofileview/moobookmarkview.c
|
||||
../moo/moofileview/moobookmarkview.h
|
||||
../moo/moofileview/moofile.c
|
||||
../moo/moofileview/moofileentry.c
|
||||
../moo/moofileview/moofileentry.h
|
||||
../moo/moofileview/moofile.h
|
||||
../moo/moofileview/moofile-private.h
|
||||
../moo/moofileview/moofilesystem.c
|
||||
../moo/moofileview/moofilesystem.h
|
||||
../moo/moofileview/moofileview-accels.h
|
||||
../moo/moofileview/moofileview-aux.h
|
||||
../moo/moofileview/moofileview.c
|
||||
../moo/moofileview/moofileview-dialogs.c
|
||||
../moo/moofileview/moofileview-dialogs.h
|
||||
../moo/moofileview/moofileview.h
|
||||
../moo/moofileview/moofileview-impl.h
|
||||
../moo/moofileview/moofileview-private.h
|
||||
../moo/moofileview/moofileview-tools.c
|
||||
../moo/moofileview/moofileview-tools.h
|
||||
../moo/moofileview/moofolder.c
|
||||
../moo/moofileview/moofolder.h
|
||||
../moo/moofileview/moofoldermodel.c
|
||||
../moo/moofileview/moofoldermodel.h
|
||||
../moo/moofileview/moofoldermodel-private.h
|
||||
../moo/moofileview/moofolder-private.h
|
||||
../moo/moofileview/mooiconview.c
|
||||
../moo/moofileview/mooiconview.h
|
||||
../moo/moofileview/mootreeview.c
|
||||
../moo/moofileview/mootreeview.h
|
||||
../moo/mooutils/mooaccelbutton.c
|
||||
../moo/mooutils/mooaccelbutton.h
|
||||
../moo/mooutils/mooaccel.c
|
||||
../moo/mooutils/mooaccel.h
|
||||
../moo/mooutils/mooaccelprefs.c
|
||||
../moo/mooutils/mooaccelprefs.h
|
||||
../moo/mooutils/mooactionbase.c
|
||||
../moo/mooutils/mooactionbase.h
|
||||
../moo/mooutils/mooactionbase-private.h
|
||||
../moo/mooutils/mooaction.c
|
||||
../moo/mooutils/mooactioncollection.c
|
||||
../moo/mooutils/mooactioncollection.h
|
||||
../moo/mooutils/mooactionfactory.c
|
||||
../moo/mooutils/mooactionfactory.h
|
||||
../moo/mooutils/mooactiongroup.c
|
||||
../moo/mooutils/mooactiongroup.h
|
||||
../moo/mooutils/mooaction.h
|
||||
../moo/mooutils/mooaction-private.h
|
||||
../moo/mooutils/mooappinput-common.c
|
||||
../moo/mooutils/mooappinput.h
|
||||
../moo/mooutils/mooapp-ipc.c
|
||||
../moo/mooutils/mooapp-ipc.h
|
||||
../moo/mooutils/mooarray.h
|
||||
../moo/mooutils/mooatom.h
|
||||
../moo/mooutils/moobigpaned.c
|
||||
../moo/mooutils/moobigpaned.h
|
||||
../moo/mooutils/mooclosure.c
|
||||
../moo/mooutils/mooclosure.h
|
||||
../moo/mooutils/moocombo.c
|
||||
../moo/mooutils/moocombo.h
|
||||
../moo/mooutils/moocompat.h
|
||||
../moo/mooutils/moodialogs.c
|
||||
../moo/mooutils/moodialogs.h
|
||||
../moo/mooutils/mooeditops.c
|
||||
../moo/mooutils/mooeditops.h
|
||||
../moo/mooutils/mooencodings.c
|
||||
../moo/mooutils/mooencodings-data.h
|
||||
../moo/mooutils/mooencodings.h
|
||||
../moo/mooutils/mooentry.cpp
|
||||
../moo/mooutils/mooentry.h
|
||||
../moo/mooutils/moo-environ.h
|
||||
../moo/mooutils/moofiledialog.c
|
||||
../moo/mooutils/moofiledialog.h
|
||||
../moo/mooutils/moofileicon.c
|
||||
../moo/mooutils/moofileicon.h
|
||||
../moo/mooutils/moofilewatch.c
|
||||
../moo/mooutils/moofilewatch.h
|
||||
../moo/mooutils/moofilewriter.c
|
||||
../moo/mooutils/moofilewriter.h
|
||||
../moo/mooutils/moofilewriter-private.h
|
||||
../moo/mooutils/moofiltermgr.c
|
||||
../moo/mooutils/moofiltermgr.h
|
||||
../moo/mooutils/moofontsel.c
|
||||
../moo/mooutils/moofontsel.h
|
||||
../moo/mooutils/mooglade.c
|
||||
../moo/mooutils/mooglade.h
|
||||
../moo/mooutils/moohelp.c
|
||||
../moo/mooutils/moohelp.h
|
||||
../moo/mooutils/moohistorycombo.c
|
||||
../moo/mooutils/moohistorycombo.h
|
||||
../moo/mooutils/moohistorylist.c
|
||||
../moo/mooutils/moohistorylist.h
|
||||
../moo/mooutils/moohistorymgr.c
|
||||
../moo/mooutils/moohistorymgr.h
|
||||
../moo/mooutils/mooi18n.c
|
||||
../moo/mooutils/mooi18n.h
|
||||
../moo/mooutils/moolist.h
|
||||
../moo/mooutils/moomarkup.c
|
||||
../moo/mooutils/moomarkup.h
|
||||
../moo/mooutils/moomenuaction.c
|
||||
../moo/mooutils/moomenuaction.h
|
||||
../moo/mooutils/moomenu.c
|
||||
../moo/mooutils/moomenu.h
|
||||
../moo/mooutils/moomenumgr.c
|
||||
../moo/mooutils/moomenumgr.h
|
||||
../moo/mooutils/moomenutoolbutton.c
|
||||
../moo/mooutils/moomenutoolbutton.h
|
||||
../moo/mooutils/moo-mime.c
|
||||
../moo/mooutils/moo-mime.h
|
||||
../moo/mooutils/moonotebook.c
|
||||
../moo/mooutils/moonotebook.h
|
||||
../moo/mooutils/mooonce.h
|
||||
../moo/mooutils/moopane.c
|
||||
../moo/mooutils/moopaned.c
|
||||
../moo/mooutils/moopaned.h
|
||||
../moo/mooutils/moopane.h
|
||||
../moo/mooutils/mooprefs.c
|
||||
../moo/mooutils/mooprefsdialog.c
|
||||
../moo/mooutils/mooprefsdialog.h
|
||||
../moo/mooutils/mooprefs.h
|
||||
../moo/mooutils/mooprefspage.c
|
||||
../moo/mooutils/mooprefspage.h
|
||||
../moo/mooutils/moospawn.c
|
||||
../moo/mooutils/moospawn.h
|
||||
../moo/mooutils/moostock.c
|
||||
../moo/mooutils/moostock.h
|
||||
../moo/mooutils/moo-test-macros.h
|
||||
../moo/mooutils/moo-test-utils.c
|
||||
../moo/mooutils/moo-test-utils.h
|
||||
../moo/mooutils/mootypedecl-macros.h
|
||||
../moo/mooutils/mootype-macros.h
|
||||
../moo/mooutils/moouixml.c
|
||||
../moo/mooutils/moouixml.h
|
||||
../moo/mooutils/mooundo.c
|
||||
../moo/mooutils/mooundo.h
|
||||
../moo/mooutils/mooutils-debug.h
|
||||
../moo/mooutils/mooutils-enums.c
|
||||
../moo/mooutils/mooutils-enums.h
|
||||
../moo/mooutils/mooutils-file.c
|
||||
../moo/mooutils/mooutils-file.h
|
||||
../moo/mooutils/mooutils-fs.c
|
||||
../moo/mooutils/mooutils-fs.h
|
||||
../moo/mooutils/mooutils-gobject.c
|
||||
../moo/mooutils/mooutils-gobject.h
|
||||
../moo/mooutils/mooutils-gobject-private.h
|
||||
../moo/mooutils/mooutils.h
|
||||
../moo/mooutils/mooutils-macros.h
|
||||
../moo/mooutils/mooutils-mem.h
|
||||
../moo/mooutils/mooutils-messages.h
|
||||
../moo/mooutils/mooutils-misc.cpp
|
||||
../moo/mooutils/mooutils-misc.h
|
||||
../moo/mooutils/mooutils-script.c
|
||||
../moo/mooutils/mooutils-script.h
|
||||
../moo/mooutils/mooutils-tests.h
|
||||
../moo/mooutils/mooutils-thread.cpp
|
||||
../moo/mooutils/mooutils-thread.h
|
||||
../moo/mooutils/mooutils-treeview.c
|
||||
../moo/mooutils/mooutils-treeview.h
|
||||
../moo/mooutils/mooutils-win32.c
|
||||
../moo/mooutils/moowin32/mingw/fnmatch.h
|
||||
../moo/mooutils/moowin32/mingw/netinet/in.h
|
||||
../moo/mooutils/moowin32/ms/sys/time.h
|
||||
../moo/mooutils/moowin32/ms/unistd.h
|
||||
../moo/mooutils/moowindow.c
|
||||
../moo/mooutils/moowindow.h
|
||||
../moo/plugins/support/moocmdview.c
|
||||
../moo/plugins/support/moocmdview.h
|
||||
../moo/plugins/support/mooeditwindowoutput.c
|
||||
../moo/plugins/support/mooeditwindowoutput.h
|
||||
../moo/plugins/support/moolineview.c
|
||||
../moo/plugins/support/moolineview.h
|
||||
../moo/plugins/support/moooutputfilter.c
|
||||
../moo/plugins/support/moooutputfilter.h
|
||||
../moo/plugins/usertools/moocommand.c
|
||||
../moo/plugins/usertools/moocommanddisplay.c
|
||||
../moo/plugins/usertools/moocommanddisplay.h
|
||||
../moo/plugins/usertools/moocommand.h
|
||||
../moo/plugins/usertools/moocommand-private.h
|
||||
../moo/plugins/usertools/moooutputfilterregex.c
|
||||
../moo/plugins/usertools/moooutputfilterregex.h
|
||||
../moo/plugins/usertools/moousertools.c
|
||||
../moo/plugins/usertools/moousertools-enums.c
|
||||
../moo/plugins/usertools/moousertools-enums.h
|
||||
../moo/plugins/usertools/moousertools.h
|
||||
../moo/plugins/usertools/moousertools-prefs.c
|
||||
../moo/plugins/usertools/moousertools-prefs.h
|
||||
)
|
||||
|
||||
FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/genmooxml.cmake
|
||||
"EXECUTE_PROCESS(COMMAND ${MOO_PYTHON} ${CMAKE_CURRENT_SOURCE_DIR}/parsedocs.py
|
||||
--source-dir ${CMAKE_SOURCE_DIR}/moo/mooapp
|
||||
--source-dir ${CMAKE_SOURCE_DIR}/moo/mooedit
|
||||
--source-dir ${CMAKE_SOURCE_DIR}/moo/moofileview
|
||||
--source-dir ${CMAKE_SOURCE_DIR}/moo/mooutils
|
||||
--source-dir ${CMAKE_SOURCE_DIR}/moo/moopython
|
||||
--source-dir ${CMAKE_SOURCE_DIR}/moo/plugins/usertools
|
||||
--source-dir ${CMAKE_SOURCE_DIR}/moo/plugins/support
|
||||
--source-file ${CMAKE_SOURCE_DIR}/moo/moolua/medit-lua.cpp
|
||||
--source-file ${CMAKE_SOURCE_DIR}/moo/moolua/medit-lua.h
|
||||
--skip moofontsel.*
|
||||
--output ${CMAKE_CURRENT_SOURCE_DIR}/moo.xml
|
||||
RESULT_VARIABLE RESULT)
|
||||
if(NOT RESULT EQUAL 0)
|
||||
MESSAGE(FATAL_ERROR \"Error: \${RESULT}\")
|
||||
endif()
|
||||
file(WRITE moo.xml.stamp moo.xml.stamp)
|
||||
")
|
||||
|
||||
add_custom_command(OUTPUT moo.xml.stamp
|
||||
COMMAND ${CMAKE_COMMAND} -P genmooxml.cmake
|
||||
DEPENDS ${docparser_files} ${source_files} ${CMAKE_CURRENT_BINARY_DIR}/genmooxml.cmake ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt)
|
||||
LIST(APPEND built_moo_sources moo.xml.stamp)
|
||||
|
||||
FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/gengtkxml.cmake
|
||||
"EXECUTE_PROCESS(COMMAND ${MOO_PYTHON} ${CMAKE_CURRENT_SOURCE_DIR}/parsedocs.py
|
||||
--source-file ${CMAKE_SOURCE_DIR}/moo/moolua/gtk-api.c
|
||||
--source-file ${CMAKE_SOURCE_DIR}/moo/moolua/gtk-api.h
|
||||
--module Gtk
|
||||
--output ${CMAKE_CURRENT_SOURCE_DIR}/gtk.xml
|
||||
RESULT_VARIABLE RESULT)
|
||||
if(NOT RESULT EQUAL 0)
|
||||
MESSAGE(FATAL_ERROR \"Error: \${RESULT}\")
|
||||
endif()
|
||||
file(WRITE gtk.xml.stamp gtk.xml.stamp)
|
||||
")
|
||||
|
||||
add_custom_command(OUTPUT gtk.xml.stamp
|
||||
COMMAND ${CMAKE_COMMAND} -P gengtkxml.cmake
|
||||
DEPENDS ${docparser_files} ${source_files} ${CMAKE_CURRENT_BINARY_DIR}/gengtkxml.cmake ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt)
|
||||
LIST(APPEND built_moo_sources gtk.xml.stamp)
|
||||
|
||||
add_custom_target(apixml ALL DEPENDS moo.xml.stamp gtk.xml.stamp)
|
|
@ -0,0 +1,72 @@
|
|||
docparser_files = \
|
||||
parsedocs.py \
|
||||
mdp/__init__.py \
|
||||
mdp/module.py \
|
||||
mdp/docparser.py \
|
||||
mdp/xmlwriter.py
|
||||
|
||||
gendefs_files = \
|
||||
gendefs.py \
|
||||
mpi/__init__.py \
|
||||
mpi/module.py \
|
||||
mpi/defswriter.py
|
||||
|
||||
genlua_files = \
|
||||
genlua.py \
|
||||
mpi/__init__.py \
|
||||
mpi/module.py \
|
||||
mpi/luawriter.py
|
||||
|
||||
gendocs_files = \
|
||||
gendocs.py \
|
||||
gendocbook.py \
|
||||
mpi/__init__.py \
|
||||
mpi/module.py \
|
||||
mpi/docbookwriter.py
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(docparser_files) \
|
||||
$(gendefs_files) \
|
||||
$(genlua_files) \
|
||||
$(gendocs_files) \
|
||||
sourcefiles.mak \
|
||||
moo.xml \
|
||||
gtk.xml
|
||||
|
||||
BUILT_SOURCES =
|
||||
|
||||
if MOO_DEV_MODE
|
||||
|
||||
include sourcefiles.mak
|
||||
|
||||
BUILT_SOURCES += moo.xml.stamp
|
||||
moo.xml.stamp: $(docparser_files) $(source_files)
|
||||
$(AM_V_GEN)$(MOO_PYTHON) $(srcdir)/parsedocs.py \
|
||||
--source-dir $(top_srcdir)/moo/mooapp \
|
||||
--source-dir $(top_srcdir)/moo/mooedit \
|
||||
--source-dir $(top_srcdir)/moo/moofileview \
|
||||
--source-dir $(top_srcdir)/moo/mooutils \
|
||||
--source-dir $(top_srcdir)/moo/moopython \
|
||||
--source-dir $(top_srcdir)/moo/plugins/usertools \
|
||||
--source-dir $(top_srcdir)/moo/plugins/support \
|
||||
--source-file $(top_srcdir)/moo/moolua/medit-lua.cpp \
|
||||
--source-file $(top_srcdir)/moo/moolua/medit-lua.h \
|
||||
--skip 'moofontsel.*' \
|
||||
--output moo.xml.tmp
|
||||
$(AM_V_at)cmp -s moo.xml.tmp $(srcdir)/moo.xml || mv moo.xml.tmp $(srcdir)/moo.xml
|
||||
$(AM_V_at)rm -f moo.xml.tmp
|
||||
$(AM_V_at)echo stamp > moo.xml.stamp
|
||||
|
||||
BUILT_SOURCES += gtk.xml.stamp
|
||||
gtk.xml.stamp: $(docparser_files) $(top_srcdir)/moo/moolua/gtk-api.c $(top_srcdir)/moo/moolua/gtk-api.h
|
||||
$(AM_V_at)$(MKDIR_P) moolua
|
||||
$(AM_V_GEN)$(MOO_PYTHON) $(srcdir)/parsedocs.py \
|
||||
--source-file $(top_srcdir)/moo/moolua/gtk-api.c \
|
||||
--source-file $(top_srcdir)/moo/moolua/gtk-api.h \
|
||||
--module Gtk \
|
||||
--output gtk.xml.tmp
|
||||
$(AM_V_at)cmp -s gtk.xml.tmp $(srcdir)/gtk.xml || mv gtk.xml.tmp $(srcdir)/gtk.xml
|
||||
$(AM_V_at)rm -f gtk.xml.tmp
|
||||
$(AM_V_at)echo stamp > gtk.xml.stamp
|
||||
|
||||
endif
|
|
@ -0,0 +1,10 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
from mpi.module import Module
|
||||
from mpi.defswriter import Writer
|
||||
|
||||
for arg in sys.argv[1:]:
|
||||
mod = Module.from_xml(arg)
|
||||
Writer(sys.stdout).write(mod)
|
|
@ -0,0 +1,31 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
import sys
|
||||
import optparse
|
||||
|
||||
from mpi.module import Module
|
||||
from mpi.docbookwriter import Writer
|
||||
|
||||
op = optparse.OptionParser()
|
||||
op.add_option("--python", action="store_true")
|
||||
op.add_option("--lua", action="store_true")
|
||||
op.add_option("--template", action="store")
|
||||
op.add_option("-i", "--import", action="append", dest="import_modules")
|
||||
(opts, args) = op.parse_args()
|
||||
|
||||
assert len(args) == 1
|
||||
assert bool(opts.python) + bool(opts.lua) == 1
|
||||
if opts.python:
|
||||
mode = 'python'
|
||||
elif opts.lua:
|
||||
mode = 'lua'
|
||||
|
||||
import_modules = []
|
||||
if opts.import_modules:
|
||||
for filename in opts.import_modules:
|
||||
import_modules.append(Module.from_xml(filename))
|
||||
|
||||
mod = Module.from_xml(args[0])
|
||||
for im in import_modules:
|
||||
mod.import_module(im)
|
||||
Writer(mode, opts.template, sys.stdout).write(mod)
|
|
@ -0,0 +1,22 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
import sys
|
||||
import optparse
|
||||
|
||||
from mpi.module import Module
|
||||
from mpi.texiwriter import Writer
|
||||
|
||||
op = optparse.OptionParser()
|
||||
op.add_option("--python", action="store_true")
|
||||
op.add_option("--lua", action="store_true")
|
||||
(opts, args) = op.parse_args()
|
||||
|
||||
assert len(args) == 1
|
||||
assert bool(opts.python) + bool(opts.lua) == 1
|
||||
if opts.python:
|
||||
mode = 'python'
|
||||
elif opts.lua:
|
||||
mode = 'lua'
|
||||
|
||||
mod = Module.from_xml(args[0])
|
||||
Writer(mode, sys.stdout).write(mod)
|
|
@ -0,0 +1,36 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
import os
|
||||
import sys
|
||||
import optparse
|
||||
|
||||
from mpi.module import Module
|
||||
from mpi.luawriter import Writer
|
||||
|
||||
op = optparse.OptionParser()
|
||||
op.add_option("-i", "--import", action="append", dest="import_modules")
|
||||
op.add_option("--include-header", action="append", dest="include_headers")
|
||||
op.add_option("--output", dest="output")
|
||||
(opts, args) = op.parse_args()
|
||||
|
||||
import_modules = []
|
||||
if opts.import_modules:
|
||||
for filename in opts.import_modules:
|
||||
import_modules.append(Module.from_xml(filename))
|
||||
|
||||
if opts.output:
|
||||
out_file = open(opts.output + '.tmp', 'w')
|
||||
else:
|
||||
out_file = sys.stdout
|
||||
|
||||
assert len(args) == 1
|
||||
mod = Module.from_xml(args[0])
|
||||
for im in import_modules:
|
||||
mod.import_module(im)
|
||||
Writer(out_file).write(mod, opts.include_headers)
|
||||
|
||||
if opts.output:
|
||||
out_file.close()
|
||||
if os.access(opts.output, os.F_OK):
|
||||
os.remove(opts.output)
|
||||
os.rename(opts.output + '.tmp', opts.output)
|
|
@ -0,0 +1 @@
|
|||
# empty
|
|
@ -0,0 +1,691 @@
|
|||
import re
|
||||
import string
|
||||
import sys
|
||||
import os
|
||||
|
||||
DEBUG = False
|
||||
|
||||
class ParseError(RuntimeError):
|
||||
def __init__(self, message, block=None):
|
||||
if block:
|
||||
RuntimeError.__init__(self, '%s in file %s, around line %d' % \
|
||||
(message, block.filename, block.first_line))
|
||||
else:
|
||||
RuntimeError.__init__(self, message)
|
||||
|
||||
class DoxBlock(object):
|
||||
def __init__(self, block):
|
||||
object.__init__(self)
|
||||
|
||||
self.symbol = None
|
||||
self.annotations = []
|
||||
self.params = []
|
||||
self.attributes = []
|
||||
self.docs = []
|
||||
self.summary = None
|
||||
|
||||
self.__parse(block)
|
||||
|
||||
def __parse(self, block):
|
||||
first_line = True
|
||||
chunks = []
|
||||
cur = [None, None, []]
|
||||
for line in block.lines:
|
||||
if first_line:
|
||||
m = re.match(r'([\w\d_.-]+(:+[\w\d_.-]+)*)(:(\s.*)?)?$', line)
|
||||
if m is None:
|
||||
raise ParseError('bad id line', block)
|
||||
cur[0] = m.group(1)
|
||||
annotations, docs = self.__parse_annotations(m.group(4) or '')
|
||||
cur[1] = annotations
|
||||
cur[2] = [docs] if docs else []
|
||||
elif not line:
|
||||
if cur[0] is not None:
|
||||
chunks.append(cur)
|
||||
cur = [None, None, []]
|
||||
elif cur[2]:
|
||||
cur[2].append(line)
|
||||
else:
|
||||
m = re.match(r'(@[\w\d_.-]+|Returns|Return value|Since):(.*)$', line)
|
||||
if m:
|
||||
if cur[0] or cur[2]:
|
||||
chunks.append(cur)
|
||||
cur = [None, None, []]
|
||||
cur[0] = m.group(1)
|
||||
annotations, docs = self.__parse_annotations(m.group(2) or '')
|
||||
cur[1] = annotations
|
||||
cur[2] = [docs] if docs else []
|
||||
else:
|
||||
cur[2].append(line)
|
||||
first_line = False
|
||||
if cur[0] or cur[2]:
|
||||
chunks.append(cur)
|
||||
|
||||
self.symbol = chunks[0][0]
|
||||
self.annotations = chunks[0][1]
|
||||
self.summary = chunks[0][2]
|
||||
|
||||
for chunk in chunks[1:]:
|
||||
if chunk[0]:
|
||||
if chunk[0].startswith('@'):
|
||||
self.params.append(chunk)
|
||||
else:
|
||||
self.attributes.append(chunk)
|
||||
else:
|
||||
self.docs = chunk[2]
|
||||
|
||||
if not self.symbol:
|
||||
raise ParseError('bad id line', block)
|
||||
|
||||
def __parse_annotations(self, text):
|
||||
annotations = []
|
||||
ann_start = -1
|
||||
for i in xrange(len(text)):
|
||||
c = text[i]
|
||||
if c in ' \t':
|
||||
pass
|
||||
elif c == ':':
|
||||
if ann_start < 0:
|
||||
if annotations:
|
||||
return annotations, text[i+1:].strip()
|
||||
else:
|
||||
return None, text
|
||||
else:
|
||||
pass
|
||||
elif c != '(' and ann_start < 0:
|
||||
if annotations:
|
||||
raise ParseError('bad annotations')
|
||||
return None, text
|
||||
elif c == '(':
|
||||
if ann_start >= 0:
|
||||
raise ParseError('( inside ()')
|
||||
ann_start = i
|
||||
elif c == ')':
|
||||
assert ann_start >= 0
|
||||
if ann_start + 1 < i:
|
||||
annotations.append(text[ann_start+1:i])
|
||||
ann_start = -1
|
||||
if ann_start >= 0:
|
||||
raise ParseError('unterminated annotation')
|
||||
return annotations, None
|
||||
|
||||
class Block(object):
|
||||
def __init__(self, lines, filename, first_line, last_line):
|
||||
object.__init__(self)
|
||||
self.lines = list(lines)
|
||||
self.filename = filename
|
||||
self.first_line = first_line
|
||||
self.last_line = last_line
|
||||
|
||||
class Symbol(object):
|
||||
def __init__(self, name, annotations, docs, block):
|
||||
object.__init__(self)
|
||||
self.name = name
|
||||
self.annotations = annotations or []
|
||||
self.docs = docs
|
||||
self.block = block
|
||||
|
||||
class Class(Symbol):
|
||||
def __init__(self, name, annotations, docs, block):
|
||||
Symbol.__init__(self, name, annotations, docs, block)
|
||||
|
||||
class Boxed(Symbol):
|
||||
def __init__(self, name, annotations, docs, block):
|
||||
Symbol.__init__(self, name, annotations, docs, block)
|
||||
|
||||
class Pointer(Symbol):
|
||||
def __init__(self, name, annotations, docs, block):
|
||||
Symbol.__init__(self, name, annotations, docs, block)
|
||||
|
||||
class EnumBase(Symbol):
|
||||
def __init__(self, name, annotations, docs, values, block):
|
||||
super(EnumBase, self).__init__(name, annotations, docs, block)
|
||||
self.values = values
|
||||
|
||||
class Enum(EnumBase):
|
||||
def __init__(self, name, annotations, docs, values, block):
|
||||
super(Enum, self).__init__(name, annotations, docs, values, block)
|
||||
|
||||
class Flags(EnumBase):
|
||||
def __init__(self, name, annotations, docs, values, block):
|
||||
super(Flags, self).__init__(name, annotations, docs, values, block)
|
||||
|
||||
class EnumValue(object):
|
||||
def __init__(self, name, annotations=None, docs=None):
|
||||
object.__init__(self)
|
||||
self.docs = docs
|
||||
self.annotations = annotations or []
|
||||
self.name = name
|
||||
|
||||
class FunctionBase(Symbol):
|
||||
def __init__(self, name, annotations, params, retval, docs, block):
|
||||
Symbol.__init__(self, name, annotations, docs, block)
|
||||
self.params = params
|
||||
self.retval = retval
|
||||
|
||||
class Signal(FunctionBase):
|
||||
def __init__(self, name, annotations, params, retval, docs, block):
|
||||
FunctionBase.__init__(self, name, annotations, params, retval, docs, block)
|
||||
|
||||
class Function(FunctionBase):
|
||||
def __init__(self, name, annotations, params, retval, docs, block):
|
||||
FunctionBase.__init__(self, name, annotations, params, retval, docs, block)
|
||||
|
||||
class VMethod(Function):
|
||||
def __init__(self, name, annotations, params, retval, docs, block):
|
||||
Function.__init__(self, name, annotations, params, retval, docs, block)
|
||||
|
||||
class ParamBase(object):
|
||||
def __init__(self, annotations=[], docs=None):
|
||||
object.__init__(self)
|
||||
self.docs = docs
|
||||
self.type = None
|
||||
self.annotations = annotations or []
|
||||
|
||||
class Param(ParamBase):
|
||||
def __init__(self, name=None, annotations=None, docs=None):
|
||||
ParamBase.__init__(self, annotations, docs)
|
||||
self.name = name
|
||||
|
||||
class Retval(ParamBase):
|
||||
def __init__(self, annotations=None, docs=None):
|
||||
ParamBase.__init__(self, annotations, docs)
|
||||
|
||||
class Parser(object):
|
||||
def __init__(self):
|
||||
object.__init__(self)
|
||||
self.classes = []
|
||||
self.enums = []
|
||||
self.functions = []
|
||||
self.signals = []
|
||||
self.vmethods = []
|
||||
self.__symbol_dict = {}
|
||||
|
||||
def __split_block(self, block):
|
||||
chunks = []
|
||||
current_prefix = None
|
||||
current_annotations = None
|
||||
current_text = None
|
||||
first_line = True
|
||||
|
||||
re_id = re.compile(r'([\w\d._-]+:(((\s*\([^()]\)\s*)+):)?')
|
||||
re_special = re.compile(r'(@[\w\d._-]+|(SECTION|PROPERTY|SIGNAL)-[\w\d._-]+||Since|Returns|Return value):(((\s*\([^()]\)\s*)+):)?')
|
||||
|
||||
for line in block.lines:
|
||||
if first_line:
|
||||
line = re.sub(r'^SECTION:([\w\d_-]+):?', r'SECTION-\1:', line)
|
||||
line = re.sub(r'^([\w\d_-]+):([\w\d_-]+):?', r'PROPERTY-\1-\2:', line)
|
||||
line = re.sub(r'^([\w\d_-]+)::([\w\d_-]+):?', r'SIGNAL-\1-\2:', line)
|
||||
first_line = False
|
||||
if not line:
|
||||
if current_prefix is not None:
|
||||
chunks.append([current_prefix, current_annotations, current_text])
|
||||
current_prefix = None
|
||||
current_annotations = None
|
||||
current_text = None
|
||||
elif current_text is not None:
|
||||
current_text.append(line)
|
||||
else:
|
||||
m = re_special.match(line)
|
||||
if m:
|
||||
if current_prefix is not None or current_text is not None:
|
||||
chunks.append([current_prefix, current_annotations, current_text])
|
||||
current_prefix = None
|
||||
current_annotations = None
|
||||
current_text = None
|
||||
current_prefix = m.group(1)
|
||||
suffix = m.group(4) or ''
|
||||
annotations, text = self.__parse_annotations(suffix)
|
||||
current_annotations = annotations
|
||||
current_text = [text] if text else []
|
||||
else:
|
||||
if current_text is not None:
|
||||
current_text.append(line)
|
||||
else:
|
||||
current_text = [line]
|
||||
if current_text is not None:
|
||||
chunks.append([current_prefix, current_annotations, current_text])
|
||||
|
||||
return chunks
|
||||
|
||||
def __parse_annotations(self, text):
|
||||
annotations = []
|
||||
ann_start = -1
|
||||
for i in xrange(len(text)):
|
||||
c = text[i]
|
||||
if c in ' \t':
|
||||
pass
|
||||
elif c == ':':
|
||||
if ann_start < 0:
|
||||
if annotations:
|
||||
return annotations, text[i+1:].strip()
|
||||
else:
|
||||
return None, text
|
||||
else:
|
||||
pass
|
||||
elif c != '(' and ann_start < 0:
|
||||
if annotations:
|
||||
raise ParseError('bad annotations')
|
||||
return None, text
|
||||
elif c == '(':
|
||||
if ann_start >= 0:
|
||||
raise ParseError('( inside ()')
|
||||
ann_start = i
|
||||
elif c == ')':
|
||||
assert ann_start >= 0
|
||||
if ann_start + 1 < i:
|
||||
annotations.append(text[ann_start+1:i])
|
||||
ann_start = -1
|
||||
if ann_start >= 0:
|
||||
raise ParseError('unterminated annotation')
|
||||
if annotations:
|
||||
return annotations, None
|
||||
else:
|
||||
return None, None
|
||||
|
||||
def __parse_function(self, block):
|
||||
db = DoxBlock(block)
|
||||
|
||||
params = []
|
||||
retval = None
|
||||
|
||||
for p in db.params:
|
||||
params.append(Param(p[0][1:], p[1], p[2]))
|
||||
for attr in db.attributes:
|
||||
if attr[0] in ('Returns', 'Return value'):
|
||||
retval = Retval(attr[1], attr[2])
|
||||
elif attr[0] in ('Since'):
|
||||
pass
|
||||
else:
|
||||
raise ParseError('unknown attribute %s' % (attr[0],), block)
|
||||
|
||||
if '::' in db.symbol:
|
||||
What = Signal
|
||||
db.symbol = 'signal:' + db.symbol.replace('_', '-').replace('::', ':')
|
||||
symbol_list = self.signals
|
||||
elif ':' in db.symbol:
|
||||
What = Property
|
||||
db.symbol = 'property:' + db.symbol.replace('_', '-')
|
||||
symbol_list = self.properties
|
||||
else:
|
||||
What = Function
|
||||
symbol_list = self.functions
|
||||
|
||||
func = What(db.symbol, db.annotations, params, retval, db.docs, block)
|
||||
func.summary = db.summary
|
||||
if DEBUG:
|
||||
print 'func.name:', func.name
|
||||
if func.name in self.__symbol_dict:
|
||||
raise ParseError('duplicated symbol %s' % (func.name,), block)
|
||||
self.__symbol_dict[func.name] = func
|
||||
symbol_list.append(func)
|
||||
|
||||
def __parse_class(self, block):
|
||||
db = DoxBlock(block)
|
||||
|
||||
name = db.symbol
|
||||
if name.startswith('class:'):
|
||||
name = name[len('class:'):]
|
||||
|
||||
if db.params:
|
||||
raise ParseError('class params', block)
|
||||
if db.attributes:
|
||||
raise ParseError('class attributes', block)
|
||||
|
||||
cls = Class(name, db.annotations, db.docs, block)
|
||||
cls.summary = db.summary
|
||||
self.classes.append(cls)
|
||||
|
||||
def __parse_boxed(self, block):
|
||||
What = None
|
||||
db = DoxBlock(block)
|
||||
|
||||
name = db.symbol
|
||||
if name.startswith('boxed:'):
|
||||
What = Boxed
|
||||
name = name[len('boxed:'):]
|
||||
elif name.startswith('pointer:'):
|
||||
What = Pointer
|
||||
name = name[len('pointer:'):]
|
||||
else:
|
||||
raise ParseError('bad id', block)
|
||||
|
||||
if db.params:
|
||||
raise ParseError('boxed params', block)
|
||||
if db.attributes:
|
||||
raise ParseError('boxed attributes', block)
|
||||
|
||||
cls = What(name, db.annotations, db.docs, block)
|
||||
cls.summary = db.summary
|
||||
self.classes.append(cls)
|
||||
|
||||
def __parse_enum_or_flags(self, block, What):
|
||||
db = DoxBlock(block)
|
||||
|
||||
name = db.symbol
|
||||
prefix = 'enum:' if What is Enum else 'flags:'
|
||||
if name.startswith(prefix):
|
||||
name = name[len(prefix):]
|
||||
|
||||
if db.attributes:
|
||||
raise ParseError('enum attributes', block)
|
||||
|
||||
values = []
|
||||
if db.params:
|
||||
for p in db.params:
|
||||
values.append(EnumValue(p[0][1:], p[1], p[2]))
|
||||
|
||||
enum = What(name, db.annotations, db.docs, values, block)
|
||||
enum.summary = db.summary
|
||||
self.enums.append(enum)
|
||||
|
||||
def __parse_enum(self, block):
|
||||
return self.__parse_enum_or_flags(block, Enum)
|
||||
|
||||
def __parse_flags(self, block):
|
||||
return self.__parse_enum_or_flags(block, Flags)
|
||||
|
||||
def __parse_block(self, block):
|
||||
line = block.lines[0]
|
||||
if line.startswith('class:'):
|
||||
self.__parse_class(block)
|
||||
elif line.startswith('boxed:'):
|
||||
self.__parse_boxed(block)
|
||||
elif line.startswith('pointer:'):
|
||||
self.__parse_boxed(block)
|
||||
elif line.startswith('enum:'):
|
||||
self.__parse_enum(block)
|
||||
elif line.startswith('flags:'):
|
||||
self.__parse_flags(block)
|
||||
elif line.startswith('SECTION:'):
|
||||
pass
|
||||
else:
|
||||
self.__parse_function(block)
|
||||
|
||||
def __add_block(self, block, filename, first_line, last_line):
|
||||
lines = []
|
||||
for line in block:
|
||||
if line.startswith('*'):
|
||||
line = line[1:].strip()
|
||||
if line or lines:
|
||||
lines.append(line)
|
||||
else:
|
||||
first_line += 1
|
||||
i = len(lines) - 1
|
||||
while i >= 0:
|
||||
if not lines[i]:
|
||||
del lines[i]
|
||||
i -= 1
|
||||
last_line -= 1
|
||||
else:
|
||||
break
|
||||
if lines:
|
||||
assert last_line >= first_line
|
||||
self.__parse_block(Block(lines, filename, first_line, last_line))
|
||||
|
||||
def __read_comments(self, filename):
|
||||
block = None
|
||||
first_line = 0
|
||||
line_no = 0
|
||||
for line in open(filename):
|
||||
line = line.strip()
|
||||
if not block:
|
||||
if line.startswith('/**'):
|
||||
line = line[3:]
|
||||
if not line.startswith('*') and not '*/' in line:
|
||||
block = [line]
|
||||
first_line = line_no
|
||||
else:
|
||||
end = line.find('*/')
|
||||
if end >= 0:
|
||||
line = line[:end]
|
||||
block.append(line)
|
||||
self.__add_block(block, filename, first_line, line_no)
|
||||
block = None
|
||||
else:
|
||||
block.append(line)
|
||||
line_no += 1
|
||||
if block:
|
||||
raise ParseError('unterminated block in file %s' % (filename,))
|
||||
|
||||
def read_files(self, filenames):
|
||||
sys.stderr.write('parsing gtk-doc comments... ')
|
||||
sys.stderr.flush()
|
||||
for f in filenames:
|
||||
self.__read_comments(f)
|
||||
sys.stderr.write('done\n')
|
||||
sys.stderr.write('parsing declarations... ')
|
||||
sys.stderr.flush()
|
||||
for f in filenames:
|
||||
if f.endswith('.h'):
|
||||
self.__read_declarations(f)
|
||||
sys.stderr.write('done\n')
|
||||
|
||||
# Code copied from h2def.py by Toby D. Reeves <toby@max.rl.plh.af.mil>
|
||||
|
||||
def __strip_comments(self, buf):
|
||||
parts = []
|
||||
lastpos = 0
|
||||
while 1:
|
||||
pos = string.find(buf, '/*', lastpos)
|
||||
if pos >= 0:
|
||||
if buf[pos:pos+len('/**vtable:')] == '/**vtable:':
|
||||
parts.append(buf[lastpos:pos+len('/**vtable:')])
|
||||
lastpos = pos + len('/**vtable:')
|
||||
elif buf[pos:pos+len('/**signal:')] == '/**signal:':
|
||||
parts.append(buf[lastpos:pos+len('/**signal:')])
|
||||
lastpos = pos + len('/**signal:')
|
||||
else:
|
||||
parts.append(buf[lastpos:pos])
|
||||
pos = string.find(buf, '*/', pos)
|
||||
if pos >= 0:
|
||||
lastpos = pos + 2
|
||||
else:
|
||||
break
|
||||
else:
|
||||
parts.append(buf[lastpos:])
|
||||
break
|
||||
return string.join(parts, '')
|
||||
|
||||
# Strips the dll API from buffer, for example WEBKIT_API
|
||||
def __strip_dll_api(self, buf):
|
||||
pat = re.compile("[A-Z]*_API ")
|
||||
buf = pat.sub("", buf)
|
||||
return buf
|
||||
|
||||
def __clean_func(self, buf):
|
||||
"""
|
||||
Ideally would make buf have a single prototype on each line.
|
||||
Actually just cuts out a good deal of junk, but leaves lines
|
||||
where a regex can figure prototypes out.
|
||||
"""
|
||||
# bulk comments
|
||||
buf = self.__strip_comments(buf)
|
||||
|
||||
# dll api
|
||||
buf = self.__strip_dll_api(buf)
|
||||
|
||||
# compact continued lines
|
||||
pat = re.compile(r"""\\\n""", re.MULTILINE)
|
||||
buf = pat.sub('', buf)
|
||||
|
||||
# Preprocess directives
|
||||
pat = re.compile(r"""^[#].*?$""", re.MULTILINE)
|
||||
buf = pat.sub('', buf)
|
||||
|
||||
#typedefs, stucts, and enums
|
||||
pat = re.compile(r"""^(typedef|struct|enum)(\s|.|\n)*?;\s*""",
|
||||
re.MULTILINE)
|
||||
buf = pat.sub('', buf)
|
||||
|
||||
#strip DECLS macros
|
||||
pat = re.compile(r"""G_(BEGIN|END)_DECLS|(BEGIN|END)_LIBGTOP_DECLS""", re.MULTILINE)
|
||||
buf = pat.sub('', buf)
|
||||
|
||||
#extern "C"
|
||||
pat = re.compile(r"""^\s*(extern)\s+\"C\"\s+{""", re.MULTILINE)
|
||||
buf = pat.sub('', buf)
|
||||
|
||||
#multiple whitespace
|
||||
pat = re.compile(r"""\s+""", re.MULTILINE)
|
||||
buf = pat.sub(' ', buf)
|
||||
|
||||
#clean up line ends
|
||||
pat = re.compile(r""";\s*""", re.MULTILINE)
|
||||
buf = pat.sub('\n', buf)
|
||||
buf = buf.lstrip()
|
||||
|
||||
#associate *, &, and [] with type instead of variable
|
||||
#pat = re.compile(r'\s+([*|&]+)\s*(\w+)')
|
||||
pat = re.compile(r' \s* ([*|&]+) \s* (\w+)', re.VERBOSE)
|
||||
buf = pat.sub(r'\1 \2', buf)
|
||||
pat = re.compile(r'\s+ (\w+) \[ \s* \]', re.VERBOSE)
|
||||
buf = pat.sub(r'[] \1', buf)
|
||||
|
||||
buf = string.replace(buf, '/** vtable:', '/**vtable:')
|
||||
pat = re.compile(r'(\w+) \s* \* \s* \(', re.VERBOSE)
|
||||
buf = pat.sub(r'\1* (', buf)
|
||||
|
||||
# make return types that are const work.
|
||||
buf = re.sub(r'\s*\*\s*G_CONST_RETURN\s*\*\s*', '** ', buf)
|
||||
buf = string.replace(buf, 'G_CONST_RETURN ', 'const-')
|
||||
buf = string.replace(buf, 'const ', 'const-')
|
||||
|
||||
#strip GSEAL macros from the middle of function declarations:
|
||||
pat = re.compile(r"""GSEAL""", re.VERBOSE)
|
||||
buf = pat.sub('', buf)
|
||||
|
||||
return buf
|
||||
|
||||
def __read_declarations_in_buf(self, buf, filename):
|
||||
vproto_pat=re.compile(r"""
|
||||
/\*\*\s*(?P<what>(vtable|signal)):(?P<vtable>[\w\d_]+)\s*\*\*/\s*
|
||||
(?P<ret>(-|\w|\&|\*)+\s*) # return type
|
||||
\s+ # skip whitespace
|
||||
\(\s*\*\s*(?P<vfunc>\w+)\s*\)
|
||||
\s*[(] # match the function name until the opening (
|
||||
\s*(?P<args>.*?)\s*[)] # group the function arguments
|
||||
""", re.IGNORECASE|re.VERBOSE)
|
||||
proto_pat=re.compile(r"""
|
||||
(?P<ret>(-|\w|\&|\*)+\s*) # return type
|
||||
\s+ # skip whitespace
|
||||
(?P<func>\w+)\s*[(] # match the function name until the opening (
|
||||
\s*(?P<args>.*?)\s*[)] # group the function arguments
|
||||
""", re.IGNORECASE|re.VERBOSE)
|
||||
arg_split_pat = re.compile("\s*,\s*")
|
||||
|
||||
buf = self.__clean_func(buf)
|
||||
buf = string.split(buf,'\n')
|
||||
|
||||
for p in buf:
|
||||
if not p:
|
||||
continue
|
||||
|
||||
if DEBUG:
|
||||
print 'matching line', repr(p)
|
||||
|
||||
fname = None
|
||||
vfname = None
|
||||
is_signal = False
|
||||
m = proto_pat.match(p)
|
||||
if m is None:
|
||||
if DEBUG:
|
||||
print 'proto_pat not matched'
|
||||
m = vproto_pat.match(p)
|
||||
if m is None:
|
||||
if DEBUG:
|
||||
print 'vproto_pat not matched'
|
||||
if p.find('vtable:') >= 0:
|
||||
print "oops", repr(p)
|
||||
if p.find('moo_file_enc_new') >= 0:
|
||||
print '***', repr(p)
|
||||
continue
|
||||
else:
|
||||
vfname = m.group('vfunc')
|
||||
if m.group('what') == 'signal':
|
||||
is_signal = True
|
||||
if DEBUG:
|
||||
print 'proto_pat matched', repr(m.group(0))
|
||||
print '+++ ', ('vfunc', 'signal')[is_signal], vfname
|
||||
else:
|
||||
if DEBUG:
|
||||
print 'proto_pat matched', repr(m.group(0))
|
||||
fname = m.group('func')
|
||||
ret = m.group('ret')
|
||||
if ret in ('return', 'else', 'if', 'switch'):
|
||||
continue
|
||||
if fname:
|
||||
func = self.__symbol_dict.get(fname)
|
||||
if func is None:
|
||||
continue
|
||||
if DEBUG:
|
||||
print 'match:|%s|' % fname
|
||||
elif not is_signal:
|
||||
symbol_name = 'vfunc:%s:%s' % (m.group('vtable'), m.group('vfunc'))
|
||||
func = self.__symbol_dict.get(symbol_name)
|
||||
if func is None:
|
||||
func = VMethod(symbol_name, None, None, None, None, None)
|
||||
self.__symbol_dict[symbol_name] = func
|
||||
self.vmethods.append(func)
|
||||
if DEBUG:
|
||||
print 'match:|%s|' % func.name
|
||||
else:
|
||||
symbol_name = ('signal:%s:%s' % (m.group('vtable'), m.group('vfunc'))).replace('_', '-')
|
||||
func = self.__symbol_dict.get(symbol_name)
|
||||
if func is None:
|
||||
func = Signal(symbol_name, None, None, None, None, None)
|
||||
self.__symbol_dict[symbol_name] = func
|
||||
self.signals.append(func)
|
||||
if DEBUG:
|
||||
print 'match:|%s|' % func.name
|
||||
|
||||
args = m.group('args')
|
||||
args = arg_split_pat.split(args)
|
||||
for i in range(len(args)):
|
||||
spaces = string.count(args[i], ' ')
|
||||
if spaces > 1:
|
||||
args[i] = string.replace(args[i], ' ', '-', spaces - 1).replace('gchar', 'char')
|
||||
|
||||
if ret != 'void':
|
||||
ret = ret.replace('gchar', 'char')
|
||||
if func.retval is None:
|
||||
func.retval = Retval()
|
||||
if func.retval.type is None:
|
||||
func.retval.type = ret
|
||||
if ret in ('char*', 'strv', 'char**'):
|
||||
func.retval.annotations.insert(0, 'transfer full')
|
||||
|
||||
is_varargs = 0
|
||||
has_args = len(args) > 0
|
||||
for arg in args:
|
||||
if arg == '...':
|
||||
is_varargs = 1
|
||||
elif arg in ('void', 'void '):
|
||||
has_args = 0
|
||||
if DEBUG:
|
||||
print 'func ', ', '.join([p.name for p in func.params] if func.params else '')
|
||||
if has_args and not is_varargs:
|
||||
if func.params is None:
|
||||
func.params = []
|
||||
elif func.params:
|
||||
assert len(func.params) == len(args)
|
||||
for i in range(len(args)):
|
||||
if DEBUG:
|
||||
print 'arg:', args[i]
|
||||
argtype, argname = string.split(args[i])
|
||||
if DEBUG:
|
||||
print argtype, argname
|
||||
if len(func.params) <= i:
|
||||
func.params.append(Param())
|
||||
if func.params[i].name is None:
|
||||
func.params[i].name = argname
|
||||
if func.params[i].type is None:
|
||||
func.params[i].type = argtype
|
||||
if DEBUG:
|
||||
print 'func ', ', '.join([p.name for p in func.params])
|
||||
|
||||
def __read_declarations(self, filename):
|
||||
if DEBUG:
|
||||
print filename
|
||||
buf = open(filename).read()
|
||||
self.__read_declarations_in_buf(buf, filename)
|
|
@ -0,0 +1,631 @@
|
|||
import sys
|
||||
import re
|
||||
|
||||
import mdp.docparser as dparser
|
||||
|
||||
DEBUG = False
|
||||
|
||||
def split_camel_case_name(name):
|
||||
comps = []
|
||||
cur = ''
|
||||
for c in name:
|
||||
if c.islower() or not cur:
|
||||
cur += c
|
||||
else:
|
||||
comps.append(cur)
|
||||
cur = c
|
||||
if cur:
|
||||
comps.append(cur)
|
||||
return comps
|
||||
|
||||
def get_class_method_c_name_prefix(cls):
|
||||
comps = split_camel_case_name(cls)
|
||||
return '_'.join([c.lower() for c in comps]) + '_'
|
||||
|
||||
def strip_class_prefix(name, cls):
|
||||
prefix = get_class_method_c_name_prefix(cls)
|
||||
if name.startswith(prefix):
|
||||
return name[len(prefix):]
|
||||
else:
|
||||
return name
|
||||
|
||||
def strip_module_prefix(name, mod):
|
||||
prefix = get_class_method_c_name_prefix(mod)
|
||||
if name.startswith(prefix):
|
||||
return name[len(prefix):]
|
||||
else:
|
||||
return name
|
||||
|
||||
def strip_module_prefix_from_class(name, mod):
|
||||
mod = mod.lower()
|
||||
mod = mod[0].upper() + mod[1:]
|
||||
if name.startswith(mod):
|
||||
return name[len(mod):]
|
||||
else:
|
||||
return name
|
||||
|
||||
def make_gtype_id(cls):
|
||||
comps = split_camel_case_name(cls)
|
||||
comps = [comps[0]] + ['TYPE'] + comps[1:]
|
||||
return '_'.join([c.upper() for c in comps])
|
||||
|
||||
class Type(object):
|
||||
def __init__(self, name):
|
||||
object.__init__(self)
|
||||
self.name = name
|
||||
|
||||
class BasicType(Type):
|
||||
def __init__(self, name):
|
||||
Type.__init__(self, name)
|
||||
|
||||
class _GTypedType(Type):
|
||||
def __init__(self, name, short_name, gtype_id, docs):
|
||||
Type.__init__(self, name)
|
||||
self.docs = docs
|
||||
self.methods = []
|
||||
self.static_methods = []
|
||||
self.gtype_id = gtype_id
|
||||
self.short_name = short_name
|
||||
self.annotations = {}
|
||||
|
||||
class EnumBase(_GTypedType):
|
||||
def __init__(self, name, short_name, gtype_id, docs):
|
||||
super(EnumBase, self).__init__(name, short_name, gtype_id, docs)
|
||||
self.values = []
|
||||
|
||||
class EnumValue(object):
|
||||
def __init__(self, name, attributes, docs):
|
||||
super(EnumValue, self).__init__()
|
||||
self.name = name
|
||||
self.attributes = attributes
|
||||
self.docs = docs
|
||||
|
||||
class Enum(EnumBase):
|
||||
def __init__(self, name, short_name, gtype_id, docs):
|
||||
super(Enum, self).__init__(name, short_name, gtype_id, docs)
|
||||
|
||||
class Flags(EnumBase):
|
||||
def __init__(self, name, short_name, gtype_id, docs):
|
||||
super(Flags, self).__init__(name, short_name, gtype_id, docs)
|
||||
|
||||
class _InstanceType(_GTypedType):
|
||||
def __init__(self, name, short_name, gtype_id, docs):
|
||||
_GTypedType.__init__(self, name, short_name, gtype_id, docs)
|
||||
self.constructor = None
|
||||
|
||||
class Class(_InstanceType):
|
||||
def __init__(self, name, short_name, parent, gtype_id, docs):
|
||||
_InstanceType.__init__(self, name, short_name, gtype_id, docs)
|
||||
self.parent = parent
|
||||
self.vmethods = []
|
||||
self.signals = []
|
||||
|
||||
class Boxed(_InstanceType):
|
||||
def __init__(self, name, short_name, gtype_id, docs):
|
||||
_InstanceType.__init__(self, name, short_name, gtype_id, docs)
|
||||
|
||||
class Pointer(_InstanceType):
|
||||
def __init__(self, name, short_name, gtype_id, docs):
|
||||
_InstanceType.__init__(self, name, short_name, gtype_id, docs)
|
||||
|
||||
class Symbol(object):
|
||||
def __init__(self, name, c_name, docs):
|
||||
object.__init__(self)
|
||||
self.name = name
|
||||
self.c_name = c_name
|
||||
self.docs = docs
|
||||
self.summary = None
|
||||
self.annotations = {}
|
||||
|
||||
class FunctionBase(Symbol):
|
||||
def __init__(self, name, c_name, params, retval, docs):
|
||||
Symbol.__init__(self, name, c_name, docs)
|
||||
self.params = params
|
||||
self.retval = retval
|
||||
|
||||
class Function(FunctionBase):
|
||||
def __init__(self, name, c_name, params, retval, docs):
|
||||
FunctionBase.__init__(self, name, c_name, params, retval, docs)
|
||||
|
||||
class Method(FunctionBase):
|
||||
def __init__(self, name, c_name, cls, params, retval, docs):
|
||||
FunctionBase.__init__(self, name, c_name, params, retval, docs)
|
||||
self.cls = cls
|
||||
|
||||
class StaticMethod(FunctionBase):
|
||||
def __init__(self, name, c_name, cls, params, retval, docs):
|
||||
FunctionBase.__init__(self, name, c_name, params, retval, docs)
|
||||
self.cls = cls
|
||||
|
||||
class Constructor(FunctionBase):
|
||||
def __init__(self, name, c_name, cls, params, retval, docs):
|
||||
FunctionBase.__init__(self, name, c_name, params, retval, docs)
|
||||
self.cls = cls
|
||||
|
||||
class VMethod(FunctionBase):
|
||||
def __init__(self, name, cls, params, retval, docs):
|
||||
FunctionBase.__init__(self, name, name, params, retval, docs)
|
||||
self.cls = cls
|
||||
|
||||
class Signal(FunctionBase):
|
||||
def __init__(self, name, cls, params, retval, docs):
|
||||
FunctionBase.__init__(self, name, name, params, retval, docs)
|
||||
self.cls = cls
|
||||
|
||||
class ParamBase(object):
|
||||
def __init__(self, typ, docs):
|
||||
object.__init__(self)
|
||||
self.type = typ
|
||||
self.docs = docs
|
||||
self.attributes = {}
|
||||
self.transfer_mode = None
|
||||
self.element_type = None
|
||||
self.array = False
|
||||
self.array_fixed_len = None
|
||||
self.array_len_param = None
|
||||
self.array_zero_terminated = None
|
||||
|
||||
class Param(ParamBase):
|
||||
def __init__(self, name, typ, docs):
|
||||
ParamBase.__init__(self, typ, docs)
|
||||
self.name = name
|
||||
self.out = False
|
||||
self.caller_allocates = False
|
||||
self.callee_allocates = False
|
||||
self.in_ = False
|
||||
self.inout = False
|
||||
self.allow_none = False
|
||||
self.default_value = None
|
||||
self.scope = 'call'
|
||||
|
||||
class Retval(ParamBase):
|
||||
def __init__(self, typ, docs):
|
||||
ParamBase.__init__(self, typ, docs)
|
||||
|
||||
class Module(object):
|
||||
def __init__(self, name):
|
||||
object.__init__(self)
|
||||
self.name = name
|
||||
self.classes = []
|
||||
self.boxed = []
|
||||
self.__class_dict = {}
|
||||
self.functions = []
|
||||
self.__methods = {}
|
||||
self.__constructors = {}
|
||||
self.__vmethods = {}
|
||||
self.__signals = {}
|
||||
self.types = {}
|
||||
self.enums = []
|
||||
|
||||
def __add_class(self, pcls):
|
||||
name = pcls.name
|
||||
short_name = getattr(pcls, 'short_name', strip_module_prefix_from_class(pcls.name, self.name))
|
||||
gtype_id = getattr(pcls, 'gtype_id', make_gtype_id(pcls.name))
|
||||
docs = pcls.docs
|
||||
parent = None
|
||||
constructable = False
|
||||
annotations = {}
|
||||
for a in pcls.annotations:
|
||||
pieces = a.split()
|
||||
prefix = pieces[0]
|
||||
if prefix == 'parent':
|
||||
assert len(pieces) == 2
|
||||
parent = pieces[1]
|
||||
elif prefix == 'constructable':
|
||||
assert len(pieces) == 1
|
||||
constructable = True
|
||||
elif prefix.find('.') >= 0:
|
||||
annotations[prefix] = ' '.join(pieces[1:])
|
||||
else:
|
||||
raise RuntimeError("unknown annotation '%s' in class %s" % (a, name))
|
||||
cls = Class(name, short_name, parent, gtype_id, docs)
|
||||
cls.summary = pcls.summary
|
||||
cls.annotations = annotations
|
||||
cls.constructable = constructable
|
||||
self.classes.append(cls)
|
||||
self.__class_dict[name] = cls
|
||||
|
||||
def __add_boxed_or_pointer(self, pcls, What):
|
||||
name = pcls.name
|
||||
short_name = getattr(pcls, 'short_name', strip_module_prefix_from_class(pcls.name, self.name))
|
||||
gtype_id = getattr(pcls, 'gtype_id', make_gtype_id(pcls.name))
|
||||
docs = pcls.docs
|
||||
annotations = {}
|
||||
for a in pcls.annotations:
|
||||
pieces = a.split()
|
||||
prefix = pieces[0]
|
||||
if prefix.find('.') >= 0:
|
||||
annotations[prefix] = ' '.join(pieces[1:])
|
||||
else:
|
||||
raise RuntimeError("unknown annotation '%s' in class %s" % (a, name))
|
||||
cls = What(name, short_name, gtype_id, docs)
|
||||
cls.summary = pcls.summary
|
||||
cls.annotations = annotations
|
||||
self.boxed.append(cls)
|
||||
self.__class_dict[name] = cls
|
||||
|
||||
def __add_boxed(self, pcls):
|
||||
self.__add_boxed_or_pointer(pcls, Boxed)
|
||||
|
||||
def __add_pointer(self, pcls):
|
||||
self.__add_boxed_or_pointer(pcls, Pointer)
|
||||
|
||||
def __add_enum(self, ptyp):
|
||||
if DEBUG:
|
||||
print 'enum', ptyp.name
|
||||
name = ptyp.name
|
||||
short_name = getattr(ptyp, 'short_name', strip_module_prefix_from_class(ptyp.name, self.name))
|
||||
gtype_id = getattr(ptyp, 'gtype_id', make_gtype_id(ptyp.name))
|
||||
docs = ptyp.docs
|
||||
annotations = {}
|
||||
for a in ptyp.annotations:
|
||||
pieces = a.split()
|
||||
prefix = pieces[0]
|
||||
if prefix.find('.') >= 0:
|
||||
annotations[prefix] = ' '.join(pieces[1:])
|
||||
else:
|
||||
raise RuntimeError("unknown annotation '%s' in class %s" % (a, name))
|
||||
if isinstance(ptyp, dparser.Enum):
|
||||
enum = Enum(name, short_name, gtype_id, docs)
|
||||
else:
|
||||
enum = Flags(name, short_name, gtype_id, docs)
|
||||
for value in ptyp.values:
|
||||
attributes = self.__parse_enum_value_annotations(value.annotations)
|
||||
enum.values.append(EnumValue(value.name, attributes, value.docs))
|
||||
enum.summary = ptyp.summary
|
||||
enum.annotations = annotations
|
||||
self.enums.append(enum)
|
||||
|
||||
def __parse_enum_value_annotations(self, annotations):
|
||||
attributes = {}
|
||||
for a in annotations:
|
||||
pieces = a.split()
|
||||
prefix = pieces[0]
|
||||
if '.' in prefix[1:-1] and len(pieces) == 2:
|
||||
attributes[prefix] = pieces[1]
|
||||
if attributes:
|
||||
return attributes
|
||||
else:
|
||||
return None
|
||||
|
||||
def __parse_param_or_retval_annotation(self, annotation, param):
|
||||
pieces = annotation.split()
|
||||
prefix = pieces[0]
|
||||
if prefix == 'transfer':
|
||||
if len(pieces) > 2:
|
||||
raise RuntimeError("invalid annotation '%s'" % (a,))
|
||||
if not pieces[1] in ('none', 'container', 'full'):
|
||||
raise RuntimeError("invalid annotation '%s'" % (a,))
|
||||
param.transfer_mode = pieces[1]
|
||||
return True
|
||||
if prefix == 'element-type':
|
||||
if len(pieces) > 3:
|
||||
raise RuntimeError("invalid annotation '%s'" % (a,))
|
||||
if len(pieces) == 2:
|
||||
param.element_type = pieces[1]
|
||||
else:
|
||||
param.element_type = pieces[1:]
|
||||
return True
|
||||
if prefix == 'array':
|
||||
if len(pieces) == 1:
|
||||
param.array = True
|
||||
return True
|
||||
if len(pieces) > 2:
|
||||
raise RuntimeError("invalid annotation '%s'" % (a,))
|
||||
m = re.match(r'fixed-size\s*=\s*(\d+)$', pieces[1])
|
||||
if m:
|
||||
param.array_fixed_size = int(m.group(1))
|
||||
return True
|
||||
m = re.match(r'length\s*=\s*(\S+)$', pieces[1])
|
||||
if m:
|
||||
param.array_len_param = m.group(1)
|
||||
return True
|
||||
m = re.match(r'zero-terminated\s*=\s*(\d+)$', pieces[1])
|
||||
if m:
|
||||
param.array_zero_terminated = bool(int(m.group(1)))
|
||||
return True
|
||||
raise RuntimeError("invalid annotation '%s'" % (a,))
|
||||
if prefix == 'type':
|
||||
if len(pieces) > 2:
|
||||
raise RuntimeError("invalid annotation '%s'" % (a,))
|
||||
param.type = pieces[1]
|
||||
return True
|
||||
if '.' in prefix[1:-1] and len(pieces) == 2:
|
||||
param.attributes[prefix] = pieces[1]
|
||||
return False
|
||||
|
||||
def __parse_param_annotation(self, annotation, param):
|
||||
pieces = annotation.split()
|
||||
prefix = pieces[0]
|
||||
if prefix == 'out':
|
||||
if len(pieces) > 2:
|
||||
raise RuntimeError("invalid annotation '%s'" % (a,))
|
||||
if len(pieces) == 1:
|
||||
param.out = True
|
||||
return True
|
||||
if pieces[1] == 'caller-allocates':
|
||||
param.out = True
|
||||
param.caller_allocates = True
|
||||
return True
|
||||
if pieces[1] == 'callee-allocates':
|
||||
param.out = True
|
||||
param.callee_allocates = True
|
||||
return True
|
||||
raise RuntimeError("invalid annotation '%s'" % (a,))
|
||||
if prefix == 'in':
|
||||
if len(pieces) > 1:
|
||||
raise RuntimeError("invalid annotation '%s'" % (a,))
|
||||
param.in_ = True
|
||||
return True
|
||||
if prefix == 'inout':
|
||||
if len(pieces) > 1:
|
||||
raise RuntimeError("invalid annotation '%s'" % (a,))
|
||||
param.inout = True
|
||||
return True
|
||||
if prefix == 'allow-none':
|
||||
if len(pieces) > 1:
|
||||
raise RuntimeError("invalid annotation '%s'" % (a,))
|
||||
param.allow_none = True
|
||||
return True
|
||||
if prefix == 'default':
|
||||
if len(pieces) != 2:
|
||||
raise RuntimeError("invalid annotation '%s'" % (a,))
|
||||
param.default_value = pieces[1]
|
||||
return True
|
||||
if prefix == 'scope':
|
||||
if len(pieces) != 2:
|
||||
raise RuntimeError("invalid annotation '%s'" % (a,))
|
||||
if not pieces[1] in ('call', 'async', 'notified'):
|
||||
raise RuntimeError("invalid annotation '%s'" % (a,))
|
||||
param.scope = pieces[1]
|
||||
return True
|
||||
if '.' in prefix[1:-1] and len(pieces) == 2:
|
||||
param.attributes[prefix] = pieces[1]
|
||||
return False
|
||||
|
||||
def __parse_retval(self, pretval):
|
||||
retval = Retval(pretval.type, pretval.docs)
|
||||
if pretval.annotations:
|
||||
for a in pretval.annotations:
|
||||
if not self.__parse_param_or_retval_annotation(a, retval):
|
||||
raise RuntimeError("invalid annotation '%s'" % (a,))
|
||||
if not retval.type:
|
||||
raise RuntimeError('return type missing')
|
||||
return retval
|
||||
|
||||
def __parse_param(self, pp, pfunc):
|
||||
if DEBUG:
|
||||
print pp.name, pp.type, pp.docs
|
||||
param = Param(pp.name, pp.type, pp.docs)
|
||||
if pp.annotations:
|
||||
for a in pp.annotations:
|
||||
if self.__parse_param_or_retval_annotation(a, param):
|
||||
pass
|
||||
elif self.__parse_param_annotation(a, param):
|
||||
pass
|
||||
else:
|
||||
raise RuntimeError("in %s: invalid annotation '%s'" % (pfunc.name, a,))
|
||||
if param.type is None:
|
||||
raise RuntimeError('in %s: type of param "%s" is missing' % (pfunc.name, param.name))
|
||||
return param
|
||||
|
||||
def __add_vmethod(self, pfunc):
|
||||
_, cls, name = pfunc.name.split(':')
|
||||
assert _ == 'vfunc'
|
||||
params = []
|
||||
retval = None
|
||||
docs = pfunc.docs
|
||||
if pfunc.annotations:
|
||||
for a in pfunc.annotations:
|
||||
raise RuntimeError("unknown annotation '%s' in function %s" % (a, name))
|
||||
|
||||
if pfunc.params:
|
||||
for p in pfunc.params:
|
||||
params.append(self.__parse_param(p, pfunc))
|
||||
|
||||
if pfunc.retval:
|
||||
retval = self.__parse_retval(pfunc.retval)
|
||||
|
||||
meth = VMethod(name, cls, params[1:], retval, docs)
|
||||
this_class_methods = self.__vmethods.get(cls)
|
||||
if not this_class_methods:
|
||||
this_class_methods = []
|
||||
self.__vmethods[cls] = this_class_methods
|
||||
this_class_methods.append(meth)
|
||||
|
||||
def __add_signal(self, pfunc):
|
||||
_, cls, name = pfunc.name.split(':')
|
||||
assert _ == 'signal'
|
||||
params = []
|
||||
retval = None
|
||||
docs = pfunc.docs
|
||||
if pfunc.annotations:
|
||||
for a in pfunc.annotations:
|
||||
raise RuntimeError("unknown annotation '%s' in function %s" % (a, name))
|
||||
|
||||
if pfunc.params:
|
||||
for p in pfunc.params:
|
||||
params.append(self.__parse_param(p, pfunc))
|
||||
|
||||
if pfunc.retval:
|
||||
retval = self.__parse_retval(pfunc.retval)
|
||||
|
||||
meth = Signal(name, cls, params[1:], retval, docs)
|
||||
this_class_signals = self.__signals.get(cls)
|
||||
if not this_class_signals:
|
||||
this_class_signals = []
|
||||
self.__signals[cls] = this_class_signals
|
||||
this_class_signals.append(meth)
|
||||
|
||||
def __add_function(self, pfunc):
|
||||
name = pfunc.name
|
||||
c_name = pfunc.name
|
||||
params = []
|
||||
retval = None
|
||||
docs = pfunc.docs
|
||||
cls = None
|
||||
constructor_of = None
|
||||
static_method_of = None
|
||||
kwargs = False
|
||||
annotations = {}
|
||||
|
||||
if pfunc.annotations:
|
||||
for a in pfunc.annotations:
|
||||
pieces = a.split()
|
||||
prefix = pieces[0]
|
||||
if prefix == 'constructor-of':
|
||||
assert len(pieces) == 2
|
||||
constructor_of = pieces[1]
|
||||
elif prefix == 'static-method-of':
|
||||
assert len(pieces) == 2
|
||||
static_method_of = pieces[1]
|
||||
elif prefix == 'moo-kwargs':
|
||||
assert len(pieces) == 1
|
||||
kwargs = True
|
||||
elif prefix.find('.') >= 0:
|
||||
annotations[prefix] = ' '.join(pieces[1:])
|
||||
else:
|
||||
raise RuntimeError("unknown annotation '%s' in function %s" % (a, name))
|
||||
|
||||
if pfunc.params:
|
||||
for p in pfunc.params:
|
||||
params.append(self.__parse_param(p, pfunc))
|
||||
|
||||
if pfunc.retval:
|
||||
retval = self.__parse_retval(pfunc.retval)
|
||||
|
||||
if hasattr(pfunc, 'method_of'):
|
||||
cls = pfunc.method_of
|
||||
elif static_method_of:
|
||||
cls = static_method_of
|
||||
elif constructor_of:
|
||||
cls = constructor_of
|
||||
elif params:
|
||||
m = re.match(r'(const-)?([\w\d_]+)\*', params[0].type)
|
||||
if m:
|
||||
cls = m.group(2)
|
||||
if not self.__class_dict.has_key(cls):
|
||||
cls = None
|
||||
|
||||
if cls:
|
||||
name = strip_class_prefix(name, cls)
|
||||
else:
|
||||
name = strip_module_prefix(name, self.name)
|
||||
|
||||
if constructor_of:
|
||||
func = Constructor(name, c_name, cls, params, retval, docs)
|
||||
if constructor_of in self.__constructors:
|
||||
raise RuntimeError('duplicated constructor of class %s' % constructor_of)
|
||||
self.__constructors[constructor_of] = func
|
||||
elif cls:
|
||||
if static_method_of:
|
||||
func = StaticMethod(name, c_name, cls, params, retval, docs)
|
||||
else:
|
||||
func = Method(name, c_name, cls, params[1:], retval, docs)
|
||||
this_class_methods = self.__methods.get(cls)
|
||||
if not this_class_methods:
|
||||
this_class_methods = []
|
||||
self.__methods[cls] = this_class_methods
|
||||
this_class_methods.append(func)
|
||||
else:
|
||||
func = Function(name, c_name, params, retval, docs)
|
||||
self.functions.append(func)
|
||||
|
||||
func.summary = pfunc.summary
|
||||
func.annotations = annotations
|
||||
func.kwargs = kwargs
|
||||
|
||||
def init_from_dox(self, blocks):
|
||||
for b in blocks:
|
||||
if isinstance(b, dparser.Class):
|
||||
self.__add_class(b)
|
||||
elif isinstance(b, dparser.Boxed):
|
||||
self.__add_boxed(b)
|
||||
elif isinstance(b, dparser.Pointer):
|
||||
self.__add_pointer(b)
|
||||
elif isinstance(b, dparser.Enum) or isinstance(b, dparser.Flags):
|
||||
self.__add_enum(b)
|
||||
elif isinstance(b, dparser.Flags):
|
||||
self.__add_flags(b)
|
||||
elif isinstance(b, dparser.VMethod):
|
||||
self.__add_vmethod(b)
|
||||
elif isinstance(b, dparser.Signal):
|
||||
self.__add_signal(b)
|
||||
elif isinstance(b, dparser.Function):
|
||||
self.__add_function(b)
|
||||
else:
|
||||
raise RuntimeError('oops')
|
||||
|
||||
instance_types = {}
|
||||
for cls in self.classes + self.boxed:
|
||||
if cls.name in instance_types:
|
||||
raise RuntimeError('duplicated class %s' % (cls.name,))
|
||||
instance_types[cls.name] = cls
|
||||
|
||||
for cls in self.__constructors:
|
||||
func = self.__constructors[cls]
|
||||
if not cls in instance_types:
|
||||
raise RuntimeError('Constructor of unknown class %s' % cls)
|
||||
else:
|
||||
cls = instance_types[cls]
|
||||
if cls.constructor is not None:
|
||||
raise RuntimeError('duplicated constructor in class %s' % cls)
|
||||
cls.constructor = func
|
||||
|
||||
for cls in self.__methods:
|
||||
methods = self.__methods[cls]
|
||||
if not cls in instance_types:
|
||||
raise RuntimeError('Methods of unknown class %s' % cls)
|
||||
else:
|
||||
cls = instance_types[cls]
|
||||
for m in methods:
|
||||
m.cls = cls
|
||||
if isinstance(m, Method):
|
||||
cls.methods.append(m)
|
||||
elif isinstance(m, StaticMethod):
|
||||
cls.static_methods.append(m)
|
||||
else:
|
||||
oops()
|
||||
|
||||
for cls in self.__vmethods:
|
||||
methods = self.__vmethods[cls]
|
||||
if not cls in instance_types:
|
||||
raise RuntimeError('Virtual methods of unknown class %s' % cls)
|
||||
else:
|
||||
cls = instance_types[cls]
|
||||
for m in methods:
|
||||
m.cls = cls
|
||||
cls.vmethods += methods
|
||||
|
||||
for cls in self.__signals:
|
||||
signals = self.__signals[cls]
|
||||
if not cls in instance_types:
|
||||
raise RuntimeError('Signals of unknown class %s' % cls)
|
||||
else:
|
||||
cls = instance_types[cls]
|
||||
for s in signals:
|
||||
s.cls = cls
|
||||
cls.signals += signals
|
||||
|
||||
def format_func(func):
|
||||
if func.retval and func.retval.type:
|
||||
s = func.retval.type + ' '
|
||||
else:
|
||||
s = 'void '
|
||||
s += func.name
|
||||
s += ' ('
|
||||
for i in range(len(func.params)):
|
||||
if i != 0:
|
||||
s += ', '
|
||||
p = func.params[i]
|
||||
s += '%s %s' % (p.type, p.name)
|
||||
s += ')'
|
||||
return s
|
||||
|
||||
if DEBUG:
|
||||
for cls in self.classes:
|
||||
print 'class %s' % (cls.name,)
|
||||
for meth in cls.methods:
|
||||
print ' %s' % (format_func(meth),)
|
||||
for func in self.functions:
|
||||
print format_func(func)
|
|
@ -0,0 +1,201 @@
|
|||
import sys
|
||||
import xml.etree.ElementTree as etree
|
||||
|
||||
import mdp.module as module
|
||||
|
||||
class Writer(object):
|
||||
def __init__(self, out):
|
||||
object.__init__(self)
|
||||
self.out = out
|
||||
self.xml = etree.TreeBuilder()
|
||||
self.__tag_opened = False
|
||||
self.__depth = 0
|
||||
|
||||
def __start_tag(self, tag, attrs={}):
|
||||
if self.__tag_opened:
|
||||
self.xml.data('\n')
|
||||
if self.__depth > 0:
|
||||
self.xml.data(' ' * self.__depth)
|
||||
elm = self.xml.start(tag, attrs)
|
||||
self.__tag_opened = True
|
||||
self.__depth += 1
|
||||
return elm
|
||||
|
||||
def __end_tag(self, tag):
|
||||
if not self.__tag_opened and self.__depth > 1:
|
||||
self.xml.data(' ' * (self.__depth - 1))
|
||||
elm = self.xml.end(tag)
|
||||
self.xml.data('\n')
|
||||
self.__tag_opened = False
|
||||
self.__depth -= 1
|
||||
return elm
|
||||
|
||||
def __write_docs(self, docs):
|
||||
if not docs:
|
||||
return
|
||||
self.__start_tag('doc')
|
||||
docs = ' '.join(docs)
|
||||
self.xml.data(docs)
|
||||
self.__end_tag('doc')
|
||||
|
||||
def __write_summary(self, summary):
|
||||
if not summary:
|
||||
return
|
||||
self.__start_tag('summary')
|
||||
if isinstance(summary, list):
|
||||
assert len(summary) == 1
|
||||
summary = summary[0]
|
||||
self.xml.data(summary)
|
||||
self.__end_tag('summary')
|
||||
|
||||
def __write_param_or_retval_annotations(self, param, elm):
|
||||
for k in param.attributes:
|
||||
elm.set(k, self.attributes[v])
|
||||
if param.transfer_mode is not None:
|
||||
elm.set('transfer_mode', param.transfer_mode)
|
||||
if param.element_type is not None:
|
||||
elm.set('element_type', param.element_type)
|
||||
if param.array:
|
||||
elm.set('array', '1')
|
||||
if param.array_fixed_len is not None:
|
||||
elm.set('array_fixed_len', str(param.array_fixed_len))
|
||||
if param.array_len_param is not None:
|
||||
elm.set('array_len_param', param.array_len_param)
|
||||
if param.array_zero_terminated:
|
||||
elm.set('array_zero_terminated', '1')
|
||||
|
||||
def __write_param_annotations(self, param, elm):
|
||||
self.__write_param_or_retval_annotations(param, elm)
|
||||
if param.inout:
|
||||
elm.set('inout', '1')
|
||||
elif param.out:
|
||||
elm.set('out', '1')
|
||||
if param.caller_allocates:
|
||||
elm.set('caller_allocates', '1')
|
||||
elif param.callee_allocates:
|
||||
elm.set('callee_allocates', '1')
|
||||
if param.allow_none:
|
||||
elm.set('allow_none', '1')
|
||||
if param.default_value is not None:
|
||||
elm.set('default_value', param.default_value)
|
||||
if param.scope != 'call':
|
||||
elm.set('scope', param.scope)
|
||||
|
||||
def __write_retval_annotations(self, retval, elm):
|
||||
self.__write_param_or_retval_annotations(retval, elm)
|
||||
|
||||
def __check_type(self, param, func):
|
||||
if param.type in ('char*', 'const-char*'):
|
||||
print >>sys.stderr, '*** WARNING: raw type %s used in function %s' % (param.type, func)
|
||||
|
||||
def __write_param(self, param, func):
|
||||
self.__check_type(param, func)
|
||||
dic = dict(name=param.name, type=param.type)
|
||||
elm = self.__start_tag('param', dic)
|
||||
self.__write_param_annotations(param, elm)
|
||||
self.__write_docs(param.docs)
|
||||
self.__end_tag('param')
|
||||
|
||||
def __write_retval(self, retval, func):
|
||||
self.__check_type(retval, func)
|
||||
dic = dict(type=retval.type)
|
||||
elm = self.__start_tag('retval', dic)
|
||||
self.__write_retval_annotations(retval, elm)
|
||||
self.__write_docs(retval.docs)
|
||||
self.__end_tag('retval')
|
||||
|
||||
def __write_class(self, cls):
|
||||
if not cls.parent and cls.name != 'GObject':
|
||||
raise RuntimeError('parent missing in class %s' % (cls.name,))
|
||||
dic = dict(name=cls.name, short_name=cls.short_name, parent=cls.parent or 'none', gtype_id=cls.gtype_id)
|
||||
for k in cls.annotations:
|
||||
dic[k] = cls.annotations[k]
|
||||
if cls.constructable:
|
||||
dic['constructable'] = '1'
|
||||
self.__start_tag('class', dic)
|
||||
self.__write_summary(cls.summary)
|
||||
self.__write_docs(cls.docs)
|
||||
if cls.constructor is not None:
|
||||
self.__write_function(cls.constructor, 'constructor')
|
||||
for meth in sorted(cls.static_methods, lambda x, y: cmp(x.name, y.name)):
|
||||
self.__write_function(meth, 'static-method')
|
||||
for meth in sorted(cls.signals, lambda x, y: cmp(x.name, y.name)):
|
||||
self.__write_function(meth, 'signal')
|
||||
for meth in sorted(cls.vmethods, lambda x, y: cmp(x.name, y.name)):
|
||||
self.__write_function(meth, 'virtual')
|
||||
for meth in sorted(cls.methods, lambda x, y: cmp(x.name, y.name)):
|
||||
self.__write_function(meth, 'method')
|
||||
self.__end_tag('class')
|
||||
|
||||
def __write_boxed(self, cls):
|
||||
dic = dict(name=cls.name, short_name=cls.short_name, gtype_id=cls.gtype_id)
|
||||
for k in cls.annotations:
|
||||
dic[k] = cls.annotations[k]
|
||||
tag = 'boxed' if isinstance(cls, module.Boxed) else 'pointer'
|
||||
self.__start_tag(tag, dic)
|
||||
self.__write_summary(cls.summary)
|
||||
self.__write_docs(cls.docs)
|
||||
if cls.constructor is not None:
|
||||
self.__write_function(cls.constructor, 'constructor')
|
||||
for meth in cls.methods:
|
||||
self.__write_function(meth, 'method')
|
||||
self.__end_tag(tag)
|
||||
|
||||
def __write_enum(self, enum):
|
||||
if isinstance(enum, module.Enum):
|
||||
tag = 'enum'
|
||||
else:
|
||||
tag = 'flags'
|
||||
dic = dict(name=enum.name, short_name=enum.short_name, gtype_id=enum.gtype_id)
|
||||
for k in enum.annotations:
|
||||
dic[k] = enum.annotations[k]
|
||||
self.__start_tag(tag, dic)
|
||||
|
||||
for v in enum.values:
|
||||
dic = dict(name=v.name)
|
||||
if v.attributes:
|
||||
dic.update(v.attributes)
|
||||
elm = self.__start_tag('value', dic)
|
||||
self.__write_docs(v.docs)
|
||||
self.__end_tag('value')
|
||||
|
||||
self.__write_summary(enum.summary)
|
||||
self.__write_docs(enum.docs)
|
||||
self.__end_tag(tag)
|
||||
|
||||
def __write_function(self, func, tag):
|
||||
name=func.name
|
||||
if tag == 'signal':
|
||||
name = name.replace('_', '-')
|
||||
dic = dict(name=name)
|
||||
if tag != 'virtual' and tag != 'signal':
|
||||
dic['c_name'] = func.c_name
|
||||
if getattr(func, 'kwargs', False):
|
||||
dic['kwargs'] = '1'
|
||||
for k in func.annotations:
|
||||
dic[k] = func.annotations[k]
|
||||
self.__start_tag(tag, dic)
|
||||
for p in func.params:
|
||||
self.__write_param(p, func.c_name)
|
||||
if func.retval:
|
||||
self.__write_retval(func.retval, func.c_name)
|
||||
self.__write_summary(func.summary)
|
||||
self.__write_docs(func.docs)
|
||||
self.__end_tag(tag)
|
||||
|
||||
def write(self, module):
|
||||
self.__start_tag('module', dict(name=module.name))
|
||||
for cls in sorted(module.classes, lambda x, y: cmp(x.name, y.name)):
|
||||
self.__write_class(cls)
|
||||
for cls in sorted(module.boxed, lambda x, y: cmp(x.name, y.name)):
|
||||
self.__write_boxed(cls)
|
||||
for enum in sorted(module.enums, lambda x, y: cmp(x.name, y.name)):
|
||||
self.__write_enum(enum)
|
||||
for func in sorted(module.functions, lambda x, y: cmp(x.name, y.name)):
|
||||
self.__write_function(func, 'function')
|
||||
self.__end_tag('module')
|
||||
elm = self.xml.close()
|
||||
etree.ElementTree(elm).write(self.out)
|
||||
|
||||
def write_xml(module, out):
|
||||
Writer(out).write(module)
|
|
@ -0,0 +1 @@
|
|||
# empty
|
|
@ -0,0 +1,193 @@
|
|||
from mpi.module import *
|
||||
|
||||
def split_camel_case_name(name):
|
||||
comps = []
|
||||
cur = ''
|
||||
for c in name:
|
||||
if c.islower() or not cur:
|
||||
cur += c
|
||||
else:
|
||||
comps.append(cur)
|
||||
cur = c
|
||||
if cur:
|
||||
comps.append(cur)
|
||||
return comps
|
||||
|
||||
class_template = """\
|
||||
(define-object %(short_name)s
|
||||
(in-module "%(module)s")
|
||||
(parent "%(parent)s")
|
||||
(c-name "%(name)s")
|
||||
(gtype-id "%(gtype_id)s")
|
||||
)
|
||||
"""
|
||||
|
||||
method_start_template = """\
|
||||
(define-method %(name)s
|
||||
(of-object "%(class)s")
|
||||
(c-name "%(c_name)s")
|
||||
(return-type "%(return_type)s")
|
||||
"""
|
||||
|
||||
vmethod_start_template = """\
|
||||
(define-virtual %(name)s
|
||||
(of-object "%(class)s")
|
||||
(return-type "%(return_type)s")
|
||||
"""
|
||||
|
||||
function_start_template = """\
|
||||
(define-function %(name)s
|
||||
(c-name "%(c_name)s")
|
||||
(return-type "%(return_type)s")
|
||||
"""
|
||||
|
||||
type_template = """\
|
||||
(define-%(what)s %(short_name)s
|
||||
(in-module "%(module)s")
|
||||
(c-name "%(name)s")
|
||||
(gtype-id "%(gtype_id)s")
|
||||
)
|
||||
"""
|
||||
|
||||
class Writer(object):
|
||||
def __init__(self, out):
|
||||
object.__init__(self)
|
||||
self.out = out
|
||||
self.module = None
|
||||
|
||||
def __write_class_decl(self, cls):
|
||||
dic = dict(name=cls.name,
|
||||
short_name=cls.short_name,
|
||||
module=self.module.name,
|
||||
parent=cls.parent,
|
||||
gtype_id=cls.gtype_id)
|
||||
self.out.write(class_template % dic)
|
||||
self.out.write('\n')
|
||||
|
||||
def __write_boxed_decl(self, cls):
|
||||
dic = dict(name=cls.name,
|
||||
short_name=cls.short_name,
|
||||
module=self.module.name,
|
||||
gtype_id=cls.gtype_id,
|
||||
what='boxed')
|
||||
self.out.write(type_template % dic)
|
||||
self.out.write('\n')
|
||||
|
||||
def __write_pointer_decl(self, cls):
|
||||
dic = dict(name=cls.name,
|
||||
short_name=cls.short_name,
|
||||
module=self.module.name,
|
||||
gtype_id=cls.gtype_id,
|
||||
what='pointer')
|
||||
self.out.write(type_template % dic)
|
||||
self.out.write('\n')
|
||||
|
||||
def __write_enum_decl(self, cls):
|
||||
dic = dict(name=cls.name,
|
||||
short_name=cls.short_name,
|
||||
module=self.module.name,
|
||||
gtype_id=cls.gtype_id,
|
||||
what='enum' if isinstance(cls, Enum) else 'flags')
|
||||
self.out.write(type_template % dic)
|
||||
self.out.write('\n')
|
||||
|
||||
def __get_pygtk_type_name(self, typ):
|
||||
if isinstance(typ, InstanceType):
|
||||
return typ.name + '*'
|
||||
elif typ.name in ('utf8', 'filename', 'cstring'):
|
||||
return 'char*'
|
||||
elif typ.name in ('const-utf8', 'const-filename', 'const-cstring'):
|
||||
return 'const-char*'
|
||||
else:
|
||||
return typ.name
|
||||
|
||||
def __write_function_or_method(self, meth, cls):
|
||||
if meth.retval is None:
|
||||
return_type = 'none'
|
||||
else:
|
||||
return_type = self.__get_pygtk_type_name(meth.retval.type)
|
||||
dic = dict(name=meth.name, c_name=meth.c_name, return_type=return_type)
|
||||
if not cls:
|
||||
self.out.write(function_start_template % dic)
|
||||
elif isinstance(meth, Constructor):
|
||||
dic['class'] = cls.name
|
||||
self.out.write(function_start_template % dic)
|
||||
self.out.write(' (is-constructor-of %s)\n' % cls.name)
|
||||
elif isinstance(meth, StaticMethod):
|
||||
dic['class'] = cls.name
|
||||
self.out.write(method_start_template % dic)
|
||||
self.out.write(' (is-static-method #t)\n')
|
||||
elif isinstance(meth, VMethod):
|
||||
dic['class'] = cls.name
|
||||
self.out.write(vmethod_start_template % dic)
|
||||
else:
|
||||
dic['class'] = cls.name
|
||||
self.out.write(method_start_template % dic)
|
||||
if meth.retval:
|
||||
if meth.retval.transfer_mode == 'full':
|
||||
self.out.write(' (caller-owns-return #t)\n')
|
||||
elif meth.retval.transfer_mode is not None:
|
||||
raise RuntimeError('do not know how to handle transfer mode %s' % (meth.retval.transfer_mode,))
|
||||
if meth.params:
|
||||
self.out.write(' (parameters\n')
|
||||
for p in meth.params:
|
||||
self.out.write(' \'("%s" "%s"' % (self.__get_pygtk_type_name(p.type), p.name))
|
||||
if p.allow_none:
|
||||
self.out.write(' (null-ok)')
|
||||
if p.default_value is not None:
|
||||
self.out.write(' (default "%s")' % (p.default_value,))
|
||||
self.out.write(')\n')
|
||||
self.out.write(' )\n')
|
||||
self.out.write(')\n\n')
|
||||
|
||||
def __write_class_method(self, meth, cls):
|
||||
self.__write_function_or_method(meth, cls)
|
||||
|
||||
def __write_static_class_method(self, meth, cls):
|
||||
self.__write_function_or_method(meth, cls)
|
||||
|
||||
def __write_class_methods(self, cls):
|
||||
self.out.write('; methods of %s\n\n' % cls.name)
|
||||
if cls.constructor is not None:
|
||||
self.__write_function_or_method(cls.constructor, cls)
|
||||
if hasattr(cls, 'constructable') and cls.constructable:
|
||||
cons = Constructor()
|
||||
cons.name = '%s__new__' % cls.name
|
||||
cons.c_name = cons.name
|
||||
self.__write_function_or_method(cons, cls)
|
||||
if isinstance(cls, Class):
|
||||
for meth in cls.vmethods:
|
||||
self.__write_class_method(meth, cls)
|
||||
for meth in cls.methods:
|
||||
self.__write_class_method(meth, cls)
|
||||
for meth in cls.static_methods:
|
||||
self.__write_static_class_method(meth, cls)
|
||||
|
||||
def __write_function(self, func):
|
||||
self.__write_function_or_method(func, None)
|
||||
|
||||
def write(self, module):
|
||||
self.module = module
|
||||
self.out.write('; -*- scheme -*-\n\n')
|
||||
self.out.write('; classes\n\n')
|
||||
for cls in module.get_classes():
|
||||
self.__write_class_decl(cls)
|
||||
self.out.write('; boxed types\n\n')
|
||||
for cls in module.get_boxed():
|
||||
self.__write_boxed_decl(cls)
|
||||
self.out.write('; pointer types\n\n')
|
||||
for cls in module.get_pointers():
|
||||
self.__write_pointer_decl(cls)
|
||||
self.out.write('; enums and flags\n\n')
|
||||
for enum in module.get_enums():
|
||||
self.__write_enum_decl(enum)
|
||||
for cls in module.get_classes():
|
||||
self.__write_class_methods(cls)
|
||||
for cls in module.get_boxed():
|
||||
self.__write_class_methods(cls)
|
||||
for cls in module.get_pointers():
|
||||
self.__write_class_methods(cls)
|
||||
self.out.write('; functions\n\n')
|
||||
for func in module.get_functions():
|
||||
self.__write_function(func)
|
||||
self.module = None
|
|
@ -0,0 +1,502 @@
|
|||
import StringIO
|
||||
|
||||
from mpi.util import *
|
||||
from mpi.module import *
|
||||
|
||||
lua_constants = {
|
||||
'NULL': '<constant>nil</constant>',
|
||||
'TRUE': '<constant>true</constant>',
|
||||
'FALSE': '<constant>false</constant>',
|
||||
'INDEXBASE': '<constant>1</constant>',
|
||||
}
|
||||
|
||||
python_constants = {
|
||||
'NULL': '<constant>None</constant>',
|
||||
'TRUE': '<constant>True</constant>',
|
||||
'FALSE': '<constant>False</constant>',
|
||||
'GTK_RESPONSE_OK': '<constant><ulink url="http://library.gnome.org/devel/pygtk/stable/' +
|
||||
'gtk-constants.html#gtk-response-type-constants">gtk.RESPONSE_OK</ulink></constant>',
|
||||
'INDEXBASE': '<constant>0</constant>',
|
||||
}
|
||||
|
||||
common_types = {
|
||||
'gboolean': '<constant>bool</constant>',
|
||||
'strv': 'list of strings',
|
||||
}
|
||||
|
||||
lua_types = dict(common_types)
|
||||
lua_types.update({
|
||||
'index': '<constant>integer index (1-based)</constant>',
|
||||
'value': '<constant>value</constant>',
|
||||
'gunichar': '<constant>string</constant>',
|
||||
'double': '<constant>number</constant>',
|
||||
'int': '<constant>integer</constant>',
|
||||
'gint': '<constant>integer</constant>',
|
||||
'guint': '<constant>integer</constant>',
|
||||
'gulong': '<constant>integer</constant>',
|
||||
'const-utf8': '<constant>string</constant>',
|
||||
'utf8': '<constant>string</constant>',
|
||||
'const-filename': '<constant>string</constant>',
|
||||
'filename': '<constant>string</constant>',
|
||||
'const-cstring': '<constant>string</constant>',
|
||||
'cstring': '<constant>string</constant>',
|
||||
})
|
||||
|
||||
python_types = dict(common_types)
|
||||
python_types.update({
|
||||
'index': '<constant>integer index (0-based)</constant>',
|
||||
'gunichar': '<constant>str</constant>',
|
||||
'double': '<constant>float</constant>',
|
||||
'int': '<constant>int</constant>',
|
||||
'gint': '<constant>int</constant>',
|
||||
'guint': '<constant>int</constant>',
|
||||
'gulong': '<constant>int</constant>',
|
||||
'const-utf8': '<constant>str</constant>',
|
||||
'utf8': '<constant>str</constant>',
|
||||
'const-filename': '<constant>str</constant>',
|
||||
'filename': '<constant>str</constant>',
|
||||
'const-cstring': '<constant>str</constant>',
|
||||
'cstring': '<constant>str</constant>',
|
||||
})
|
||||
|
||||
def format_python_symbol_ref(symbol):
|
||||
constants = {
|
||||
}
|
||||
classes = {
|
||||
'GFile': '<ulink url="http://library.gnome.org/devel/pygobject/stable/class-giofile.html">gio.File</ulink>',
|
||||
'GObject': '<ulink url="http://library.gnome.org/devel/pygobject/stable/class-gobject.html">gobject.Object</ulink>',
|
||||
'GType': 'type',
|
||||
}
|
||||
if symbol in constants:
|
||||
return '<constant>%s</constant>' % constants[symbol]
|
||||
if symbol in classes:
|
||||
return '<constant>%s</constant>' % classes[symbol]
|
||||
if symbol.startswith('Gtk'):
|
||||
return ('<constant><ulink url="http://library.gnome.org/devel/pygtk/stable/class-' + \
|
||||
'gtk%s.html">gtk.%s</ulink></constant>') % (symbol[3:].lower(), symbol[3:])
|
||||
if symbol.startswith('Gdk'):
|
||||
return '<constant><ulink url="http://library.gnome.org/devel/pygtk/stable/class-' + \
|
||||
'gdk%s.html">gtk.gdk.%s</ulink></constant>' % (symbol[3:].lower(), symbol[3:])
|
||||
raise NotImplementedError(symbol)
|
||||
|
||||
def split_camel_case_name(name):
|
||||
comps = []
|
||||
cur = ''
|
||||
for c in name:
|
||||
if c.islower() or not cur:
|
||||
cur += c
|
||||
else:
|
||||
comps.append(cur)
|
||||
cur = c
|
||||
if cur:
|
||||
comps.append(cur)
|
||||
return comps
|
||||
|
||||
def name_all_caps(cls):
|
||||
return '_'.join([s.upper() for s in split_camel_case_name(cls.name)])
|
||||
|
||||
class Writer(object):
|
||||
def __init__(self, mode, template, out):
|
||||
super(Writer, self).__init__()
|
||||
self.file = out
|
||||
self.out = StringIO.StringIO()
|
||||
self.mode = mode
|
||||
self.template = template
|
||||
if mode == 'python':
|
||||
self.constants = python_constants
|
||||
self.builtin_types = python_types
|
||||
elif mode == 'lua':
|
||||
self.constants = lua_constants
|
||||
self.builtin_types = lua_types
|
||||
else:
|
||||
oops('unknown mode %s' % mode)
|
||||
|
||||
self.section_suffix = ' (%s)' % self.mode.capitalize()
|
||||
|
||||
def __format_symbol_ref(self, name):
|
||||
sym = self.symbols.get(name)
|
||||
if sym:
|
||||
if isinstance(sym, EnumValue):
|
||||
return '<constant><link linkend="%(mode)s.%(parent)s" endterm="%(mode)s.%(symbol)s.title"></link></constant>' % \
|
||||
dict(symbol=name, mode=self.mode, parent=sym.enum.symbol_id())
|
||||
elif isinstance(sym, Type):
|
||||
return '<constant><link linkend="%(mode)s.%(symbol)s">%(name)s</link></constant>' % \
|
||||
dict(symbol=name, mode=self.mode, name=self.__make_class_name(sym))
|
||||
elif isinstance(sym, Method):
|
||||
return '<constant><link linkend="%(mode)s.%(symbol)s">%(Class)s.%(method)s()</link></constant>' % \
|
||||
dict(symbol=name, mode=self.mode, Class=self.__make_class_name(sym.cls), method=sym.name)
|
||||
else:
|
||||
oops(name)
|
||||
if self.mode == 'python':
|
||||
return format_python_symbol_ref(name)
|
||||
else:
|
||||
raise NotImplementedError(name)
|
||||
|
||||
def __string_to_bool(self, s):
|
||||
if s == '0':
|
||||
return False
|
||||
elif s == '1':
|
||||
return True
|
||||
else:
|
||||
oops()
|
||||
|
||||
def __check_bind_ann(self, obj):
|
||||
bind = self.__string_to_bool(obj.annotations.get('moo.' + self.mode, '1'))
|
||||
if bind:
|
||||
bind = not self.__string_to_bool(obj.annotations.get('moo.private', '0'))
|
||||
return bind
|
||||
|
||||
def __format_constant(self, value):
|
||||
if value in self.constants:
|
||||
return self.constants[value]
|
||||
try:
|
||||
i = int(value)
|
||||
return value
|
||||
except ValueError:
|
||||
pass
|
||||
formatted = self.__format_symbol_ref(value)
|
||||
if formatted:
|
||||
return formatted
|
||||
error("unknown constant '%s'" % value)
|
||||
return value
|
||||
|
||||
def __format_default_value(self, p):
|
||||
if p.type.name == 'index' and self.mode == 'lua':
|
||||
return str(int(p.default_value) + 1)
|
||||
else:
|
||||
return self.__format_constant(p.default_value)
|
||||
|
||||
def __format_doc(self, doc):
|
||||
text = doc.text
|
||||
text = re.sub(r'@([\w\d_]+)(?!\{)', r'<parameter>\1</parameter>', text)
|
||||
text = re.sub(r'%NULL\b', '<constant>%s</constant>' % self.constants['NULL'], text)
|
||||
text = re.sub(r'%TRUE\b', '<constant>%s</constant>' % self.constants['TRUE'], text)
|
||||
text = re.sub(r'%FALSE\b', '<constant>%s</constant>' % self.constants['FALSE'], text)
|
||||
text = re.sub(r'%INDEXBASE\b', '<constant>%s</constant>' % self.constants['INDEXBASE'], text)
|
||||
text = text.replace(r'<n/>', '')
|
||||
text = text.replace(r'<nl/>', '\n')
|
||||
|
||||
def repl_func(m):
|
||||
func_id = m.group(1)
|
||||
symbol = self.symbols.get(func_id)
|
||||
if not isinstance(symbol, MethodBase) or symbol.cls == self.current_class:
|
||||
return '<function><link linkend="%(mode)s.%(func_id)s" endterm="%(mode)s.%(func_id)s.title"/></function>' % \
|
||||
dict(func_id=func_id, mode=self.mode)
|
||||
else:
|
||||
return '<function><link linkend="%(mode)s.%(func_id)s">%(Class)s.%(method)s()</link></function>' % \
|
||||
dict(func_id=func_id, mode=self.mode, Class=self.__make_class_name(symbol.cls), method=symbol.name)
|
||||
text = re.sub(r'([\w\d_.]+)\(\)', repl_func, text)
|
||||
|
||||
def repl_signal(m):
|
||||
cls = m.group(1)
|
||||
signal = m.group(2).replace('_', '-')
|
||||
symbol = 'signal:%s:%s' % (cls, signal)
|
||||
if self.symbols[cls] != self.current_class:
|
||||
return '<function><link linkend="%(mode)s.%(symbol)s">%(Class)s.%(signal)s</link></function>' % \
|
||||
dict(Class=cls, symbol=symbol, mode=self.mode, signal=signal)
|
||||
else:
|
||||
return '<function><link linkend="%(mode)s.%(symbol)s">%(signal)s</link></function>' % \
|
||||
dict(symbol=symbol, mode=self.mode, signal=signal)
|
||||
text = re.sub(r'([\w\d_-]+)::([\w\d_-]+)', repl_signal, text)
|
||||
|
||||
def repl_symbol(m):
|
||||
symbol = m.group(1)
|
||||
formatted = self.__format_symbol_ref(symbol)
|
||||
if not formatted:
|
||||
raise RuntimeError('unknown symbol %s' % symbol)
|
||||
return formatted
|
||||
text = re.sub(r'#([\w\d_]+)', repl_symbol, text)
|
||||
|
||||
assert not re.search(r'NULL|TRUE|FALSE', text)
|
||||
return text
|
||||
|
||||
def __make_class_name(self, cls):
|
||||
return '%s.%s' % (cls.module.name.lower(), cls.short_name)
|
||||
|
||||
def __get_obj_name(self, cls):
|
||||
name = cls.annotations.get('moo.doc-object-name')
|
||||
if not name:
|
||||
name = '_'.join([c.lower() for c in split_camel_case_name(cls.name)[1:]])
|
||||
return name
|
||||
|
||||
def __write_function(self, func, cls):
|
||||
if not self.__check_bind_ann(func):
|
||||
return
|
||||
|
||||
func_params = list(func.params)
|
||||
if func.has_gerror_return:
|
||||
func_params = func_params[:-1]
|
||||
params = []
|
||||
for p in func_params:
|
||||
if not self.__check_bind_ann(p.type):
|
||||
return
|
||||
if p.default_value is not None:
|
||||
params.append('%s=%s' % (p.name, self.__format_default_value(p)))
|
||||
else:
|
||||
params.append(p.name)
|
||||
|
||||
if isinstance(func, Constructor):
|
||||
if self.mode == 'python':
|
||||
func_title = cls.short_name + '()'
|
||||
func_name = cls.short_name
|
||||
elif self.mode == 'lua':
|
||||
func_title = 'new' + '()'
|
||||
func_name = '%s.new' % cls.short_name
|
||||
else:
|
||||
oops()
|
||||
elif isinstance(func, Signal):
|
||||
if self.mode == 'python':
|
||||
func_title = 'signal ' + func.name
|
||||
func_name = func.name
|
||||
elif self.mode == 'lua':
|
||||
func_title = 'signal ' + func.name
|
||||
func_name = func.name
|
||||
else:
|
||||
oops()
|
||||
elif cls is not None:
|
||||
if self.mode in ('python', 'lua'):
|
||||
func_title = func.name + '()'
|
||||
func_name = '%s.%s' % (self.__get_obj_name(cls), func.name) \
|
||||
if not isinstance(func, StaticMethod) \
|
||||
else '%s.%s' % (cls.short_name, func.name)
|
||||
else:
|
||||
oops()
|
||||
else:
|
||||
func_title = func.name + '()'
|
||||
func_name = '%s.%s' % (self.module.name.lower(), func.name)
|
||||
|
||||
params_string = ', '.join(params)
|
||||
|
||||
if func.summary:
|
||||
oops(func_id)
|
||||
|
||||
func_id = func.symbol_id()
|
||||
mode = self.mode
|
||||
|
||||
if mode == 'lua' and func.kwargs:
|
||||
left_paren, right_paren = '{}'
|
||||
else:
|
||||
left_paren, right_paren = '()'
|
||||
|
||||
self.out.write("""\
|
||||
<!-- %(func_id)s -->
|
||||
<sect2 id="%(mode)s.%(func_id)s">
|
||||
<title id="%(mode)s.%(func_id)s.title">%(func_title)s</title>
|
||||
<programlisting>%(func_name)s%(left_paren)s%(params_string)s%(right_paren)s</programlisting>
|
||||
""" % locals())
|
||||
|
||||
if func.doc:
|
||||
self.out.write('<para>%s</para>\n' % self.__format_doc(func.doc))
|
||||
|
||||
if func_params:
|
||||
self.out.write("""\
|
||||
<variablelist>
|
||||
<?dbhtml list-presentation="table"?>
|
||||
<?dbhtml term-separator=" : "?>
|
||||
""")
|
||||
|
||||
for p in func_params:
|
||||
if p.doc:
|
||||
docs = doc=self.__format_doc(p.doc)
|
||||
else:
|
||||
ptype = p.type.symbol_id()
|
||||
if ptype.endswith('*'):
|
||||
ptype = ptype[:-1]
|
||||
if ptype.startswith('const-'):
|
||||
ptype = ptype[len('const-'):]
|
||||
if ptype in self.builtin_types:
|
||||
docs = self.builtin_types[ptype]
|
||||
if p.allow_none:
|
||||
docs = docs + ' or ' + self.__format_constant('NULL')
|
||||
elif ptype.endswith('Array'):
|
||||
elmtype = ptype[:-len('Array')]
|
||||
if elmtype in self.symbols and isinstance(self.symbols[elmtype], InstanceType):
|
||||
docs = 'list of %s objects' % self.__format_symbol_ref(self.symbols[elmtype].symbol_id())
|
||||
else:
|
||||
docs = self.__format_symbol_ref(ptype)
|
||||
else:
|
||||
docs = self.__format_symbol_ref(ptype)
|
||||
if p.allow_none:
|
||||
docs = docs + ' or ' + self.__format_constant('NULL')
|
||||
|
||||
param_dic = dict(param=p.name, doc=docs)
|
||||
self.out.write("""\
|
||||
<varlistentry>
|
||||
<term><parameter>%(param)s</parameter></term>
|
||||
<listitem><para>%(doc)s</para></listitem>
|
||||
</varlistentry>
|
||||
""" % param_dic)
|
||||
|
||||
self.out.write('</variablelist>\n')
|
||||
|
||||
if func.retval:
|
||||
retdoc = None
|
||||
if func.retval.doc:
|
||||
retdoc = self.__format_doc(func.retval.doc)
|
||||
else:
|
||||
rettype = func.retval.type.symbol_id()
|
||||
if rettype.endswith('*'):
|
||||
rettype = rettype[:-1]
|
||||
if rettype in self.builtin_types:
|
||||
retdoc = self.builtin_types[rettype]
|
||||
elif rettype.endswith('Array'):
|
||||
elmtype = rettype[:-len('Array')]
|
||||
if elmtype in self.symbols and isinstance(self.symbols[elmtype], InstanceType):
|
||||
retdoc = 'list of %s objects' % self.__format_symbol_ref(self.symbols[elmtype].symbol_id())
|
||||
else:
|
||||
retdoc = self.__format_symbol_ref(rettype)
|
||||
else:
|
||||
retdoc = self.__format_symbol_ref(rettype)
|
||||
if retdoc:
|
||||
self.out.write('<para><parameter>Returns:</parameter> %s</para>\n' % retdoc)
|
||||
|
||||
self.out.write('</sect2>\n')
|
||||
|
||||
def __write_gobject_constructor(self, cls):
|
||||
func = Constructor()
|
||||
self.__write_function(func, cls)
|
||||
|
||||
def __write_class(self, cls):
|
||||
if not self.__check_bind_ann(cls):
|
||||
return
|
||||
|
||||
self.current_class = cls
|
||||
|
||||
title = self.__make_class_name(cls)
|
||||
if cls.summary:
|
||||
title += ' - ' + cls.summary.text
|
||||
dic = dict(class_id=cls.symbol_id(), title=title, mode=self.mode)
|
||||
self.out.write("""\
|
||||
<!-- %(class_id)s -->
|
||||
<sect1 id="%(mode)s.%(class_id)s">
|
||||
<title id="%(mode)s.%(class_id)s.title">%(title)s</title>
|
||||
""" % dic)
|
||||
|
||||
if cls.doc:
|
||||
self.out.write('<para>%s</para>\n' % self.__format_doc(cls.doc))
|
||||
|
||||
if getattr(cls, 'parent', 'none') != 'none':
|
||||
self.out.write("""\
|
||||
<programlisting>
|
||||
%(ParentClass)s
|
||||
|
|
||||
+-- %(Class)s
|
||||
</programlisting>
|
||||
""" % dict(ParentClass=self.__format_symbol_ref(cls.parent), Class=self.__make_class_name(cls)))
|
||||
|
||||
if hasattr(cls, 'signals') and cls.signals:
|
||||
for signal in cls.signals:
|
||||
self.__write_function(signal, cls)
|
||||
if cls.constructor is not None:
|
||||
self.__write_function(cls.constructor, cls)
|
||||
if hasattr(cls, 'constructable') and cls.constructable:
|
||||
self.__write_gobject_constructor(cls)
|
||||
for meth in cls.static_methods:
|
||||
self.__write_function(meth, cls)
|
||||
if isinstance(cls, Class):
|
||||
if cls.vmethods:
|
||||
implement_me('virtual methods of %s' % cls.name)
|
||||
for meth in cls.methods:
|
||||
self.__write_function(meth, cls)
|
||||
|
||||
self.out.write("""\
|
||||
</sect1>
|
||||
""" % dic)
|
||||
|
||||
self.current_class = None
|
||||
|
||||
def __write_enum(self, enum):
|
||||
if not self.__check_bind_ann(enum):
|
||||
return
|
||||
|
||||
do_write = False
|
||||
for v in enum.values:
|
||||
if self.__check_bind_ann(v):
|
||||
do_write = True
|
||||
break
|
||||
|
||||
if not do_write:
|
||||
return
|
||||
|
||||
title = self.__make_class_name(enum)
|
||||
if enum.summary:
|
||||
title += ' - ' + enum.summary.text
|
||||
dic = dict(title=title,
|
||||
mode=self.mode,
|
||||
enum_id=enum.symbol_id())
|
||||
|
||||
self.out.write("""\
|
||||
<!-- %(enum_id)s -->
|
||||
<sect2 id="%(mode)s.%(enum_id)s">
|
||||
<title id="%(mode)s.%(enum_id)s.title">%(title)s</title>
|
||||
""" % dic)
|
||||
|
||||
if enum.doc:
|
||||
self.out.write('<para>%s</para>\n' % self.__format_doc(enum.doc))
|
||||
|
||||
self.out.write("""\
|
||||
<variablelist>
|
||||
<?dbhtml list-presentation="table"?>
|
||||
""")
|
||||
|
||||
for v in enum.values:
|
||||
if not self.__check_bind_ann(v):
|
||||
continue
|
||||
value_dic = dict(mode=self.mode, enum_id=v.name, value=v.short_name,
|
||||
doc=self.__format_doc(v.doc) if v.doc else '')
|
||||
self.out.write("""\
|
||||
<varlistentry>
|
||||
<term><constant id="%(mode)s.%(enum_id)s.title">%(value)s</constant></term>
|
||||
<listitem><para>%(doc)s</para></listitem>
|
||||
</varlistentry>
|
||||
""" % value_dic)
|
||||
|
||||
self.out.write('</variablelist>\n')
|
||||
|
||||
self.out.write('</sect2>\n')
|
||||
|
||||
def write(self, module):
|
||||
self.module = module
|
||||
self.symbols = module.get_symbols()
|
||||
self.current_class = None
|
||||
|
||||
classes = module.get_classes() + module.get_boxed() + module.get_pointers()
|
||||
for cls in sorted(classes, lambda cls1, cls2: cmp(cls1.short_name, cls2.short_name)):
|
||||
self.__write_class(cls)
|
||||
|
||||
funcs = []
|
||||
for f in module.get_functions():
|
||||
if self.__check_bind_ann(f):
|
||||
funcs.append(f)
|
||||
|
||||
dic = dict(mode=self.mode)
|
||||
|
||||
if funcs:
|
||||
self.out.write("""\
|
||||
<!-- functions -->
|
||||
<sect1 id="%(mode)s.functions">
|
||||
<title>Functions</title>
|
||||
""" % dic)
|
||||
|
||||
for func in funcs:
|
||||
self.__write_function(func, None)
|
||||
|
||||
self.out.write('</sect1>\n')
|
||||
|
||||
self.out.write("""\
|
||||
<!-- enums -->
|
||||
<sect1 id="%(mode)s.enums">
|
||||
<title>Enumerations</title>
|
||||
""" % dic)
|
||||
|
||||
for func in module.get_enums():
|
||||
self.__write_enum(func)
|
||||
|
||||
self.out.write('</sect1>\n')
|
||||
|
||||
content = self.out.getvalue()
|
||||
template = open(self.template).read()
|
||||
self.file.write(template.replace('###GENERATED###', content))
|
||||
|
||||
del self.out
|
||||
del self.module
|
|
@ -0,0 +1,547 @@
|
|||
import sys
|
||||
|
||||
from mpi.module import *
|
||||
|
||||
tmpl_file_start = """\
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
%(headers)s
|
||||
#include "moolua/moo-lua-api-util.h"
|
||||
|
||||
void moo_test_coverage_record (const char *lang, const char *function);
|
||||
|
||||
"""
|
||||
|
||||
tmpl_cfunc_method_start = """\
|
||||
static int
|
||||
%(cfunc)s (gpointer pself, G_GNUC_UNUSED lua_State *L, G_GNUC_UNUSED int first_arg)
|
||||
{
|
||||
#ifdef MOO_ENABLE_COVERAGE
|
||||
moo_test_coverage_record ("lua", "%(c_name)s");
|
||||
#endif
|
||||
MooLuaCurrentFunc cur_func ("%(current_function)s");
|
||||
%(check_kwargs)s %(Class)s *self = (%(Class)s*) pself;
|
||||
"""
|
||||
|
||||
tmpl_cfunc_func_start = """\
|
||||
static int
|
||||
%(cfunc)s (G_GNUC_UNUSED lua_State *L)
|
||||
{
|
||||
#ifdef MOO_ENABLE_COVERAGE
|
||||
moo_test_coverage_record ("lua", "%(c_name)s");
|
||||
#endif
|
||||
MooLuaCurrentFunc cur_func ("%(current_function)s");
|
||||
%(check_kwargs)s"""
|
||||
|
||||
tmpl_register_module_start = """\
|
||||
static void
|
||||
%(module)s_lua_api_register (void)
|
||||
{
|
||||
static gboolean been_here = FALSE;
|
||||
|
||||
if (been_here)
|
||||
return;
|
||||
|
||||
been_here = TRUE;
|
||||
|
||||
"""
|
||||
|
||||
tmpl_register_one_type_start = """\
|
||||
MooLuaMethodEntry methods_%(Class)s[] = {
|
||||
"""
|
||||
tmpl_register_one_type_end = """\
|
||||
{ NULL, NULL }
|
||||
};
|
||||
moo_lua_register_methods (%(gtype_id)s, methods_%(Class)s);
|
||||
|
||||
"""
|
||||
|
||||
class ArgHelper(object):
|
||||
def format_arg(self, allow_none, default_value, arg_name, arg_idx, param_name):
|
||||
return ''
|
||||
|
||||
def c_allow_none(attr):
|
||||
if attr is True:
|
||||
return 'TRUE'
|
||||
elif attr in (False, None):
|
||||
return 'FALSE'
|
||||
else:
|
||||
oops()
|
||||
|
||||
class SimpleArgHelper(ArgHelper):
|
||||
def __init__(self, name, suffix, can_be_null=False):
|
||||
super(SimpleArgHelper, self).__init__()
|
||||
self.name = name
|
||||
self.suffix = suffix
|
||||
self.can_be_null = can_be_null
|
||||
|
||||
def format_arg(self, allow_none, default_value, arg_name, arg_idx, param_name):
|
||||
dic = dict(type=self.name, arg_name=arg_name, default_value=default_value,
|
||||
arg_idx=arg_idx, param_name=param_name, suffix=self.suffix,
|
||||
allow_none=c_allow_none(allow_none))
|
||||
if self.can_be_null:
|
||||
if default_value is not None:
|
||||
return '%(type)s %(arg_name)s = moo_lua_get_arg_%(suffix)s_opt (L, %(arg_idx)s, "%(param_name)s", %(default_value)s, %(allow_none)s);' % dic
|
||||
else:
|
||||
return '%(type)s %(arg_name)s = moo_lua_get_arg_%(suffix)s (L, %(arg_idx)s, "%(param_name)s", %(allow_none)s);' % dic
|
||||
else:
|
||||
if default_value is not None:
|
||||
return '%(type)s %(arg_name)s = moo_lua_get_arg_%(suffix)s_opt (L, %(arg_idx)s, "%(param_name)s", %(default_value)s);' % dic
|
||||
else:
|
||||
return '%(type)s %(arg_name)s = moo_lua_get_arg_%(suffix)s (L, %(arg_idx)s, "%(param_name)s");' % dic
|
||||
|
||||
_arg_helpers = {}
|
||||
_arg_helpers['int'] = SimpleArgHelper('int', 'int')
|
||||
_arg_helpers['gint'] = SimpleArgHelper('int', 'int')
|
||||
_arg_helpers['guint'] = SimpleArgHelper('guint', 'uint')
|
||||
_arg_helpers['glong'] = SimpleArgHelper('long', 'long')
|
||||
_arg_helpers['gulong'] = SimpleArgHelper('gulong', 'ulong')
|
||||
_arg_helpers['gboolean'] = SimpleArgHelper('gboolean', 'bool')
|
||||
_arg_helpers['index'] = SimpleArgHelper('int', 'index')
|
||||
_arg_helpers['double'] = SimpleArgHelper('double', 'double')
|
||||
_arg_helpers['const-char*'] = SimpleArgHelper('const char*', 'string', True)
|
||||
_arg_helpers['char*'] = SimpleArgHelper('char*', 'string', True)
|
||||
_arg_helpers['const-utf8'] = SimpleArgHelper('const char*', 'utf8', True)
|
||||
_arg_helpers['utf8'] = SimpleArgHelper('char*', 'utf8', True)
|
||||
_arg_helpers['const-filename'] = SimpleArgHelper('const char*', 'filename', True)
|
||||
_arg_helpers['filename'] = SimpleArgHelper('char*', 'filename', True)
|
||||
_arg_helpers['const-cstring'] = SimpleArgHelper('const char*', 'string', True)
|
||||
_arg_helpers['cstring'] = SimpleArgHelper('char*', 'string', True)
|
||||
def find_arg_helper(param):
|
||||
return _arg_helpers[param.type.name]
|
||||
|
||||
_pod_ret_helpers = {}
|
||||
_pod_ret_helpers['int'] = ('int', 'int64')
|
||||
_pod_ret_helpers['uint'] = ('guint', 'uint64')
|
||||
_pod_ret_helpers['gint'] = ('int', 'int64')
|
||||
_pod_ret_helpers['guint'] = ('guint', 'uint64')
|
||||
_pod_ret_helpers['glong'] = ('long', 'int64')
|
||||
_pod_ret_helpers['gulong'] = ('gulong', 'uint64')
|
||||
_pod_ret_helpers['gboolean'] = ('gboolean', 'bool')
|
||||
_pod_ret_helpers['index'] = ('int', 'index')
|
||||
def find_pod_ret_helper(name):
|
||||
return _pod_ret_helpers[name]
|
||||
|
||||
class Writer(object):
|
||||
def __init__(self, out):
|
||||
super(Writer, self).__init__()
|
||||
self.out = out
|
||||
|
||||
def __write_function_param(self, func_body, param, i, meth, cls):
|
||||
dic = dict(narg=i, gtype_id=param.type.gtype_id, param_name=param.name,
|
||||
allow_none=c_allow_none(param.allow_none),
|
||||
default_value=param.default_value,
|
||||
first_arg='first_arg' if cls else '1',
|
||||
arg_idx=('first_arg + %d' % (i,)) if cls else ('1 + %d' % (i,)),
|
||||
TypeName=param.type.name,
|
||||
)
|
||||
|
||||
if meth.kwargs:
|
||||
func_body.start.append('int arg_idx%(narg)d = %(arg_idx)s;' % dic)
|
||||
func_body.start.append('if (kwargs)')
|
||||
func_body.start.append(' arg_idx%(narg)d = moo_lua_get_kwarg (L, %(first_arg)s, %(narg)d + 1, "%(param_name)s");' % dic)
|
||||
|
||||
if param.default_value is None:
|
||||
func_body.start.append('if (arg_idx%(narg)d == MOO_NONEXISTING_INDEX)' % dic)
|
||||
func_body.start.append(' moo_lua_arg_error (L, 0, "%(param_name)s", "parameter \'%(param_name)s\' missing");' % dic)
|
||||
|
||||
dic['arg_idx'] = 'arg_idx%(narg)d' % dic
|
||||
|
||||
if param.type.name == 'GtkTextIter':
|
||||
assert param.default_value is None or param.default_value == 'NULL'
|
||||
if param.default_value is not None:
|
||||
dic['get_arg'] = 'moo_lua_get_arg_iter_opt'
|
||||
else:
|
||||
dic['get_arg'] = 'moo_lua_get_arg_iter'
|
||||
if cls.name == 'MooEdit':
|
||||
dic['buffer'] = 'moo_edit_get_buffer (self)'
|
||||
else:
|
||||
dic['buffer'] = 'NULL'
|
||||
if param.default_value is not None:
|
||||
func_body.start.append('GtkTextIter arg%(narg)d_iter;' % dic)
|
||||
func_body.start.append(('GtkTextIter *arg%(narg)d = %(get_arg)s (L, %(arg_idx)s, ' + \
|
||||
'"%(param_name)s", %(buffer)s, &arg%(narg)d_iter) ? &arg%(narg)d_iter : NULL;') % dic)
|
||||
else:
|
||||
func_body.start.append('GtkTextIter arg%(narg)d_iter;' % dic)
|
||||
func_body.start.append('GtkTextIter *arg%(narg)d = &arg%(narg)d_iter;' % dic)
|
||||
func_body.start.append('%(get_arg)s (L, %(arg_idx)s, "%(param_name)s", %(buffer)s, &arg%(narg)d_iter);' % dic)
|
||||
elif param.type.name == 'GdkRectangle':
|
||||
assert param.default_value is None or param.default_value == 'NULL'
|
||||
if param.default_value is not None:
|
||||
dic['get_arg'] = 'moo_lua_get_arg_rect_opt'
|
||||
else:
|
||||
dic['get_arg'] = 'moo_lua_get_arg_rect'
|
||||
if param.default_value is not None:
|
||||
func_body.start.append('GdkRectangle arg%(narg)d_rect;' % dic)
|
||||
func_body.start.append(('GdkRectangle *arg%(narg)d = %(get_arg)s (L, %(arg_idx)s, ' + \
|
||||
'"%(param_name)s", &arg%(narg)d_rect) ? &arg%(narg)d_rect : NULL;') % dic)
|
||||
else:
|
||||
func_body.start.append('GdkRectangle arg%(narg)d_rect;' % dic)
|
||||
func_body.start.append('GdkRectangle *arg%(narg)d = &arg%(narg)d_rect;' % dic)
|
||||
func_body.start.append('%(get_arg)s (L, %(arg_idx)s, "%(param_name)s", &arg%(narg)d_rect);' % dic)
|
||||
elif param.type.name == 'SignalClosure*':
|
||||
assert param.default_value is None
|
||||
func_body.start.append(('MooLuaSignalClosure *arg%(narg)d = moo_lua_get_arg_signal_closure ' + \
|
||||
'(L, %(arg_idx)s, "%(param_name)s");') % dic)
|
||||
func_body.end.append('g_closure_unref ((GClosure*) arg%(narg)d);' % dic)
|
||||
elif isinstance(param.type, Class) or isinstance(param.type, Boxed) or isinstance(param.type, Pointer):
|
||||
if param.default_value is not None:
|
||||
func_body.start.append(('%(TypeName)s *arg%(narg)d = (%(TypeName)s*) ' + \
|
||||
'moo_lua_get_arg_instance_opt (L, %(arg_idx)s, "%(param_name)s", ' + \
|
||||
'%(gtype_id)s, %(allow_none)s);') % dic)
|
||||
else:
|
||||
func_body.start.append(('%(TypeName)s *arg%(narg)d = (%(TypeName)s*) ' + \
|
||||
'moo_lua_get_arg_instance (L, %(arg_idx)s, "%(param_name)s", ' + \
|
||||
'%(gtype_id)s, %(allow_none)s);') % dic)
|
||||
elif isinstance(param.type, Enum) or isinstance(param.type, Flags):
|
||||
if param.default_value is not None:
|
||||
func_body.start.append(('%(TypeName)s arg%(narg)d = (%(TypeName)s) ' + \
|
||||
'moo_lua_get_arg_enum_opt (L, %(arg_idx)s, "%(param_name)s", ' + \
|
||||
'%(gtype_id)s, %(default_value)s);') % dic)
|
||||
else:
|
||||
func_body.start.append(('%(TypeName)s arg%(narg)d = (%(TypeName)s) ' + \
|
||||
'moo_lua_get_arg_enum (L, %(arg_idx)s, "%(param_name)s", ' + \
|
||||
'%(gtype_id)s);') % dic)
|
||||
elif isinstance(param.type, ArrayType):
|
||||
assert isinstance(param.type.elm_type, Class)
|
||||
dic['gtype_id'] = param.type.elm_type.gtype_id
|
||||
if param.default_value is not None:
|
||||
func_body.start.append(('%(TypeName)s arg%(narg)d = (%(TypeName)s) ' + \
|
||||
'moo_lua_get_arg_object_array_opt (L, %(arg_idx)s, "%(param_name)s", ' + \
|
||||
'%(gtype_id)s);') % dic)
|
||||
else:
|
||||
func_body.start.append(('%(TypeName)s arg%(narg)d = (%(TypeName)s) ' + \
|
||||
'moo_lua_get_arg_object_array (L, %(arg_idx)s, "%(param_name)s", ' + \
|
||||
'%(gtype_id)s);') % dic)
|
||||
func_body.end.append('moo_object_array_free ((MooObjectArray*) arg%(narg)d);' % dic)
|
||||
elif param.type.name == 'strv':
|
||||
assert param.default_value is None or param.default_value == 'NULL'
|
||||
if param.default_value is not None:
|
||||
func_body.start.append(('char **arg%(narg)d = moo_lua_get_arg_strv_opt (L, %(arg_idx)s, "%(param_name)s", %(allow_none)s);') % dic)
|
||||
else:
|
||||
func_body.start.append(('char **arg%(narg)d = moo_lua_get_arg_strv (L, %(arg_idx)s, "%(param_name)s", %(allow_none)s);') % dic)
|
||||
func_body.end.append('g_strfreev (arg%(narg)d);' % dic)
|
||||
else:
|
||||
assert param.transfer_mode is None
|
||||
arg_helper = find_arg_helper(param)
|
||||
func_body.start.append(arg_helper.format_arg(param.allow_none, param.default_value,
|
||||
'arg%(narg)d' % dic, '%(arg_idx)s' % dic, param.name))
|
||||
|
||||
def __write_function(self, meth, cls, method_cfuncs):
|
||||
assert not isinstance(meth, VMethod)
|
||||
|
||||
bind = meth.annotations.get('moo.lua', '1')
|
||||
if bind == '0':
|
||||
return
|
||||
elif bind != '1':
|
||||
raise RuntimeError('invalid value %s for moo.lua annotation' % (bind,))
|
||||
|
||||
cfunc = meth.annotations.get('moo.lua.cfunc')
|
||||
if cfunc:
|
||||
method_cfuncs.append([meth.name, cfunc])
|
||||
return
|
||||
|
||||
is_constructor = isinstance(meth, Constructor)
|
||||
static_method = isinstance(meth, StaticMethod)
|
||||
own_return = is_constructor or (meth.retval and meth.retval.transfer_mode == 'full')
|
||||
|
||||
params = []
|
||||
for i in range(len(meth.params)):
|
||||
p = meth.params[i]
|
||||
|
||||
if not p.type.name in _arg_helpers and not isinstance(p.type, ArrayType) and \
|
||||
not isinstance(p.type, GTypedType) and not isinstance(p.type, GErrorReturnType) and \
|
||||
not p.type.name in ('SignalClosure*', 'strv'):
|
||||
raise RuntimeError("cannot write function %s because of '%s' parameter" % (meth.c_name, p.type.name))
|
||||
|
||||
if isinstance(p.type, GErrorReturnType):
|
||||
assert i == len(meth.params) - 1
|
||||
assert meth.has_gerror_return
|
||||
else:
|
||||
params.append(p)
|
||||
|
||||
check_kwargs = ''
|
||||
has_self = cls and not is_constructor and not static_method
|
||||
if has_self:
|
||||
first_arg = 'first_arg'
|
||||
else:
|
||||
first_arg = '1'
|
||||
|
||||
if meth.kwargs:
|
||||
check_kwargs = ' bool kwargs = moo_lua_check_kwargs (L, %s);\n' % first_arg
|
||||
|
||||
dic = dict(name=meth.name, c_name=meth.c_name, check_kwargs=check_kwargs, first_arg=first_arg)
|
||||
if has_self:
|
||||
dic['cfunc'] = 'cfunc_%s_%s' % (cls.name, meth.name)
|
||||
dic['Class'] = cls.name
|
||||
dic['current_function'] = '%s.%s' % (cls.name, meth.name)
|
||||
self.out.write(tmpl_cfunc_method_start % dic)
|
||||
elif static_method:
|
||||
dic['cfunc'] = 'cfunc_%s_%s' % (cls.name, meth.name)
|
||||
dic['Class'] = cls.name
|
||||
dic['current_function'] = '%s.%s' % (cls.name, meth.name)
|
||||
self.out.write(tmpl_cfunc_func_start % dic)
|
||||
elif is_constructor:
|
||||
dic['cfunc'] = 'cfunc_%s_new' % cls.name
|
||||
dic['Class'] = cls.name
|
||||
dic['current_function'] = '%s.new' % cls.name
|
||||
self.out.write(tmpl_cfunc_func_start % dic)
|
||||
else:
|
||||
dic['cfunc'] = 'cfunc_%s' % meth.name
|
||||
dic['current_function'] = meth.name
|
||||
self.out.write(tmpl_cfunc_func_start % dic)
|
||||
|
||||
method_cfuncs.append([meth.name, dic['cfunc']])
|
||||
|
||||
class FuncBody:
|
||||
def __init__(self):
|
||||
self.start = []
|
||||
self.end = []
|
||||
|
||||
func_body = FuncBody()
|
||||
func_call = ''
|
||||
|
||||
i = 0
|
||||
for p in params:
|
||||
self.__write_function_param(func_body, p, i, meth, None if (is_constructor or static_method) else cls)
|
||||
i += 1
|
||||
|
||||
if meth.has_gerror_return:
|
||||
func_body.start.append('GError *error = NULL;')
|
||||
|
||||
if meth.retval:
|
||||
dic = {'gtype_id': meth.retval.type.gtype_id,
|
||||
'make_copy': 'FALSE' if own_return else 'TRUE',
|
||||
}
|
||||
if isinstance(meth.retval.type, Class):
|
||||
func_call = 'gpointer ret = '
|
||||
push_ret = 'moo_lua_push_object (L, (GObject*) ret, %(make_copy)s);' % dic
|
||||
elif isinstance(meth.retval.type, Boxed):
|
||||
func_call = 'gpointer ret = '
|
||||
push_ret = 'moo_lua_push_boxed (L, ret, %(gtype_id)s, %(make_copy)s);' % dic
|
||||
elif isinstance(meth.retval.type, Pointer):
|
||||
func_call = 'gpointer ret = '
|
||||
push_ret = 'moo_lua_push_pointer (L, ret, %(gtype_id)s, %(make_copy)s);' % dic
|
||||
elif isinstance(meth.retval.type, Enum) or isinstance(meth.retval.type, Flags):
|
||||
func_call = '%s ret = ' % meth.retval.type.name
|
||||
push_ret = 'moo_lua_push_int (L, ret);' % dic
|
||||
elif isinstance(meth.retval.type, ArrayType):
|
||||
assert isinstance(meth.retval.type.elm_type, Class)
|
||||
dic['gtype_id'] = meth.retval.type.elm_type.gtype_id
|
||||
func_call = 'MooObjectArray *ret = (MooObjectArray*) '
|
||||
push_ret = 'moo_lua_push_object_array (L, ret, %(make_copy)s);' % dic
|
||||
elif meth.retval.type.name == 'strv':
|
||||
assert meth.retval.transfer_mode == 'full'
|
||||
func_call = 'char **ret = '
|
||||
push_ret = 'moo_lua_push_strv (L, ret);'
|
||||
elif meth.retval.type.name in ('char*', 'cstring'):
|
||||
assert meth.retval.transfer_mode == 'full'
|
||||
func_call = 'char *ret = '
|
||||
push_ret = 'moo_lua_push_string (L, ret);'
|
||||
elif meth.retval.type.name == 'utf8':
|
||||
assert meth.retval.transfer_mode == 'full'
|
||||
func_call = 'char *ret = '
|
||||
push_ret = 'moo_lua_push_utf8 (L, ret);'
|
||||
elif meth.retval.type.name == 'filename':
|
||||
assert meth.retval.transfer_mode == 'full'
|
||||
func_call = 'char *ret = '
|
||||
push_ret = 'moo_lua_push_filename (L, ret);'
|
||||
elif meth.retval.type.name in ('const-char*', 'const-cstring'):
|
||||
assert meth.retval.transfer_mode != 'full'
|
||||
func_call = 'const char *ret = '
|
||||
push_ret = 'moo_lua_push_string_copy (L, ret);'
|
||||
elif meth.retval.type.name == 'const-utf8':
|
||||
assert meth.retval.transfer_mode != 'full'
|
||||
func_call = 'const char *ret = '
|
||||
push_ret = 'moo_lua_push_utf8_copy (L, ret);'
|
||||
elif meth.retval.type.name == 'const-filename':
|
||||
assert meth.retval.transfer_mode != 'full'
|
||||
func_call = 'const char *ret = '
|
||||
push_ret = 'moo_lua_push_filename_copy (L, ret);'
|
||||
elif meth.retval.type.name == 'gunichar':
|
||||
func_call = 'gunichar ret = '
|
||||
push_ret = 'moo_lua_push_gunichar (L, ret);'
|
||||
else:
|
||||
typ, suffix = find_pod_ret_helper(meth.retval.type.name)
|
||||
dic['suffix'] = suffix
|
||||
func_call = '%s ret = ' % typ
|
||||
push_ret = 'moo_lua_push_%(suffix)s (L, ret);' % dic
|
||||
else:
|
||||
push_ret = '0;'
|
||||
|
||||
if not meth.has_gerror_return:
|
||||
func_body.end.append('return %s' % push_ret)
|
||||
else:
|
||||
func_body.end.append('int ret_lua = %s' % push_ret)
|
||||
func_body.end.append('ret_lua += moo_lua_push_error (L, error);')
|
||||
func_body.end.append('return ret_lua;')
|
||||
|
||||
func_call += '%s (' % meth.c_name
|
||||
first_arg = True
|
||||
if cls and not is_constructor and not static_method:
|
||||
first_arg = False
|
||||
func_call += 'self'
|
||||
for i in range(len(params)):
|
||||
if not first_arg:
|
||||
func_call += ', '
|
||||
first_arg = False
|
||||
func_call += 'arg%d' % i
|
||||
if meth.has_gerror_return:
|
||||
func_call += ', &error'
|
||||
func_call += ');'
|
||||
|
||||
for line in func_body.start:
|
||||
print >>self.out, ' ' + line
|
||||
print >>self.out, ' ' + func_call
|
||||
for line in func_body.end:
|
||||
print >>self.out, ' ' + line
|
||||
|
||||
self.out.write('}\n\n')
|
||||
|
||||
# if not cls:
|
||||
# self.out.write(function_start_template % dic)
|
||||
# elif isinstance(meth, Constructor):
|
||||
# dic['class'] = cls.name
|
||||
# self.out.write(function_start_template % dic)
|
||||
# self.out.write(' (is-constructor-of %s)\n' % cls.name)
|
||||
# elif isinstance(meth, VMethod):
|
||||
# dic['class'] = cls.name
|
||||
# self.out.write(vmethod_start_template % dic)
|
||||
# else:
|
||||
# dic['class'] = cls.name
|
||||
# self.out.write(method_start_template % dic)
|
||||
# if meth.retval:
|
||||
# if meth.retval.transfer_mode == 'full':
|
||||
# self.out.write(' (caller-owns-return #t)\n')
|
||||
# elif meth.retval.transfer_mode is not None:
|
||||
# raise RuntimeError('do not know how to handle transfer mode %s' % (meth.retval.transfer_mode,))
|
||||
# if meth.params:
|
||||
# self.out.write(' (parameters\n')
|
||||
# for p in meth.params:
|
||||
# self.out.write(' \'("%s" "%s"' % (p.type, p.name))
|
||||
# if p.allow_none:
|
||||
# self.out.write(' (null-ok)')
|
||||
# if p.default_value is not None:
|
||||
# self.out.write(' (default "%s")' % (p.default_value,))
|
||||
# self.out.write(')\n')
|
||||
# self.out.write(' )\n')
|
||||
# self.out.write(')\n\n')
|
||||
|
||||
def __write_gobject_constructor(self, name, cls):
|
||||
dic = dict(func=name, gtype_id=cls.gtype_id)
|
||||
self.out.write("""\
|
||||
static void *%(func)s (void)
|
||||
{
|
||||
return g_object_new (%(gtype_id)s, (char*) NULL);
|
||||
}
|
||||
|
||||
""" % dic)
|
||||
|
||||
def __write_class(self, cls):
|
||||
bind = cls.annotations.get('moo.lua', '1')
|
||||
if bind == '0':
|
||||
return ([], [])
|
||||
self.out.write('// methods of %s\n\n' % cls.name)
|
||||
method_cfuncs = []
|
||||
static_method_cfuncs = []
|
||||
for meth in cls.methods:
|
||||
if not isinstance(meth, VMethod):
|
||||
self.__write_function(meth, cls, method_cfuncs)
|
||||
for meth in cls.static_methods:
|
||||
self.__write_function(meth, cls, static_method_cfuncs)
|
||||
if cls.constructor:
|
||||
self.__write_function(cls.constructor, cls, static_method_cfuncs)
|
||||
# if hasattr(cls, 'constructable') and cls.constructable:
|
||||
# cons = Constructor()
|
||||
# cons.retval = Retval()
|
||||
# cons.retval.type = cls
|
||||
# cons.retval.transfer_mode = 'full'
|
||||
# cons.name = 'new'
|
||||
# cons.c_name = '%s__new__' % cls.name
|
||||
# self.__write_gobject_constructor(cons.c_name, cls)
|
||||
# self.__write_function(cons, cls, static_method_cfuncs)
|
||||
return (method_cfuncs, static_method_cfuncs)
|
||||
|
||||
def __write_register_module(self, module, all_method_cfuncs):
|
||||
self.out.write(tmpl_register_module_start % dict(module=module.name.lower()))
|
||||
for cls in module.get_classes() + module.get_boxed() + module.get_pointers():
|
||||
method_cfuncs = all_method_cfuncs[cls.name]
|
||||
if method_cfuncs:
|
||||
dic = dict(Class=cls.name, gtype_id=cls.gtype_id)
|
||||
self.out.write(tmpl_register_one_type_start % dic)
|
||||
for name, cfunc in method_cfuncs:
|
||||
self.out.write(' { "%s", %s },\n' % (name, cfunc))
|
||||
self.out.write(tmpl_register_one_type_end % dic)
|
||||
self.out.write('}\n\n')
|
||||
|
||||
def write(self, module, include_headers):
|
||||
self.module = module
|
||||
|
||||
start_dic = dict(headers='')
|
||||
|
||||
if include_headers:
|
||||
start_dic['headers'] = '\n' + '\n'.join(['#include "%s"' % h for h in include_headers]) + '\n'
|
||||
|
||||
self.out.write(tmpl_file_start % start_dic)
|
||||
|
||||
all_method_cfuncs = {}
|
||||
all_static_method_cfuncs = {}
|
||||
|
||||
for cls in module.get_classes() + module.get_boxed() + module.get_pointers():
|
||||
method_cfuncs, static_method_cfuncs = self.__write_class(cls)
|
||||
all_method_cfuncs[cls.name] = method_cfuncs
|
||||
all_static_method_cfuncs[cls.short_name] = static_method_cfuncs
|
||||
|
||||
package_name=module.name.lower()
|
||||
dic = dict(module=module.name.lower(), package_name=package_name)
|
||||
|
||||
all_func_cfuncs = []
|
||||
|
||||
# for cls in module.get_classes() + module.get_boxed() + module.get_pointers():
|
||||
# if cls.constructor:
|
||||
# self.__write_function(cls.constructor, cls, all_func_cfuncs)
|
||||
|
||||
for func in module.get_functions():
|
||||
self.__write_function(func, None, all_func_cfuncs)
|
||||
|
||||
self.out.write('static const luaL_Reg %(module)s_lua_functions[] = {\n' % dic)
|
||||
for name, cfunc in all_func_cfuncs:
|
||||
self.out.write(' { "%s", %s },\n' % (name, cfunc))
|
||||
self.out.write(' { NULL, NULL }\n')
|
||||
self.out.write('};\n\n')
|
||||
|
||||
for cls_name in all_static_method_cfuncs:
|
||||
cfuncs = all_static_method_cfuncs[cls_name]
|
||||
if not cfuncs:
|
||||
continue
|
||||
self.out.write('static const luaL_Reg %s_lua_functions[] = {\n' % cls_name)
|
||||
for name, cfunc in cfuncs:
|
||||
self.out.write(' { "%s", %s },\n' % (name, cfunc))
|
||||
self.out.write(' { NULL, NULL }\n')
|
||||
self.out.write('};\n\n')
|
||||
|
||||
self.__write_register_module(module, all_method_cfuncs)
|
||||
|
||||
self.out.write("""\
|
||||
void %(module)s_lua_api_add_to_lua (lua_State *L)
|
||||
{
|
||||
%(module)s_lua_api_register ();
|
||||
|
||||
luaL_register (L, "%(package_name)s", %(module)s_lua_functions);
|
||||
|
||||
""" % dic)
|
||||
|
||||
for cls_name in all_static_method_cfuncs:
|
||||
cfuncs = all_static_method_cfuncs[cls_name]
|
||||
if not cfuncs:
|
||||
continue
|
||||
self.out.write(' moo_lua_register_static_methods (L, "%s", "%s", %s_lua_functions);\n' % (package_name, cls_name, cls_name))
|
||||
|
||||
self.out.write('\n')
|
||||
for enum in module.get_enums():
|
||||
self.out.write(' moo_lua_register_enum (L, "%s", %s, "%s");\n' % (package_name, enum.gtype_id, module.name.upper() + '_'))
|
||||
|
||||
self.out.write("}\n")
|
||||
|
||||
del self.module
|
|
@ -0,0 +1,553 @@
|
|||
import re
|
||||
import sys
|
||||
import xml.etree.ElementTree as _etree
|
||||
|
||||
class Doc(object):
|
||||
def __init__(self, text):
|
||||
object.__init__(self)
|
||||
self.text = text
|
||||
|
||||
@staticmethod
|
||||
def from_xml(elm):
|
||||
return Doc(elm.text)
|
||||
|
||||
def _set_unique_attribute(obj, attr, value):
|
||||
if getattr(obj, attr) is not None:
|
||||
raise RuntimeError("duplicated attribute '%s'" % (attr,))
|
||||
setattr(obj, attr, value)
|
||||
|
||||
def _set_unique_attribute_bool(obj, attr, value):
|
||||
if value.lower() in ('0', 'false', 'no'):
|
||||
value = False
|
||||
elif value.lower() in ('1', 'true', 'yes'):
|
||||
value = True
|
||||
else:
|
||||
raise RuntimeError("bad value '%s' for boolean attribute '%s'" % (value, attr))
|
||||
_set_unique_attribute(obj, attr, value)
|
||||
|
||||
class _XmlObject(object):
|
||||
def __init__(self):
|
||||
object.__init__(self)
|
||||
self.doc = None
|
||||
self.summary = None
|
||||
self.annotations = {}
|
||||
self.module = None
|
||||
|
||||
@classmethod
|
||||
def from_xml(cls, module, elm, *args):
|
||||
obj = cls()
|
||||
obj.module = module
|
||||
obj._parse_xml(module, elm, *args)
|
||||
return obj
|
||||
|
||||
def _parse_xml_element(self, module, elm):
|
||||
if elm.tag in ('doc', 'summary'):
|
||||
_set_unique_attribute(self, elm.tag, Doc.from_xml(elm))
|
||||
else:
|
||||
raise RuntimeError('unknown element %s' % (elm.tag,))
|
||||
|
||||
def _parse_attribute(self, attr, value):
|
||||
if attr.find('.') >= 0:
|
||||
self.annotations[attr] = value
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def _parse_xml(self, module, elm, *args):
|
||||
for attr, value in elm.items():
|
||||
if not self._parse_attribute(attr, value):
|
||||
raise RuntimeError('unknown attribute %s' % (attr,))
|
||||
for child in elm.getchildren():
|
||||
self._parse_xml_element(module, child)
|
||||
|
||||
class _ParamBase(_XmlObject):
|
||||
def __init__(self):
|
||||
_XmlObject.__init__(self)
|
||||
self.type = None
|
||||
self.transfer_mode = None
|
||||
|
||||
def _parse_attribute(self, attr, value):
|
||||
if attr in ('type', 'transfer_mode'):
|
||||
_set_unique_attribute(self, attr, value)
|
||||
else:
|
||||
return _XmlObject._parse_attribute(self, attr, value)
|
||||
return True
|
||||
|
||||
class Param(_ParamBase):
|
||||
def __init__(self):
|
||||
_ParamBase.__init__(self)
|
||||
self.name = None
|
||||
self.default_value = None
|
||||
self.allow_none = None
|
||||
|
||||
def _parse_attribute(self, attr, value):
|
||||
if attr in ('default_value', 'name'):
|
||||
_set_unique_attribute(self, attr, value)
|
||||
elif attr in ('allow_none',):
|
||||
_set_unique_attribute_bool(self, attr, value)
|
||||
else:
|
||||
return _ParamBase._parse_attribute(self, attr, value)
|
||||
return True
|
||||
|
||||
class Retval(_ParamBase):
|
||||
def __init__(self):
|
||||
_ParamBase.__init__(self)
|
||||
|
||||
class FunctionBase(_XmlObject):
|
||||
def __init__(self):
|
||||
_XmlObject.__init__(self)
|
||||
self.name = None
|
||||
self.c_name = None
|
||||
self.retval = None
|
||||
self.params = []
|
||||
self.has_gerror_return = False
|
||||
self.kwargs = None
|
||||
|
||||
def _parse_attribute(self, attr, value):
|
||||
if attr in ('c_name', 'name'):
|
||||
_set_unique_attribute(self, attr, value)
|
||||
elif attr in ('kwargs',):
|
||||
_set_unique_attribute_bool(self, attr, value)
|
||||
else:
|
||||
return _XmlObject._parse_attribute(self, attr, value)
|
||||
return True
|
||||
|
||||
def _parse_xml_element(self, module, elm):
|
||||
if elm.tag == 'retval':
|
||||
_set_unique_attribute(self, 'retval', Retval.from_xml(module, elm))
|
||||
elif elm.tag == 'param':
|
||||
self.params.append(Param.from_xml(module, elm))
|
||||
else:
|
||||
_XmlObject._parse_xml_element(self, module, elm)
|
||||
|
||||
def _parse_xml(self, module, elm, *args):
|
||||
_XmlObject._parse_xml(self, module, elm, *args)
|
||||
if not self.name:
|
||||
raise RuntimeError('function name missing')
|
||||
if not self.c_name:
|
||||
raise RuntimeError('function c_name missing')
|
||||
|
||||
class Function(FunctionBase):
|
||||
def __init__(self):
|
||||
FunctionBase.__init__(self)
|
||||
|
||||
def symbol_id(self):
|
||||
return self.c_name
|
||||
|
||||
class MethodBase(FunctionBase):
|
||||
def __init__(self):
|
||||
super(MethodBase, self).__init__()
|
||||
|
||||
def _parse_xml(self, module, elm, cls):
|
||||
super(MethodBase, self)._parse_xml(module, elm, cls)
|
||||
self.cls = cls
|
||||
|
||||
class Constructor(MethodBase):
|
||||
def __init__(self):
|
||||
super(Constructor, self).__init__()
|
||||
|
||||
def symbol_id(self):
|
||||
return self.c_name
|
||||
|
||||
class StaticMethod(MethodBase):
|
||||
def __init__(self):
|
||||
super(StaticMethod, self).__init__()
|
||||
|
||||
def symbol_id(self):
|
||||
return self.c_name
|
||||
|
||||
class Method(MethodBase):
|
||||
def __init__(self):
|
||||
super(Method, self).__init__()
|
||||
|
||||
def symbol_id(self):
|
||||
return self.c_name
|
||||
|
||||
class VMethod(MethodBase):
|
||||
def __init__(self):
|
||||
super(VMethod, self).__init__()
|
||||
self.c_name = "fake"
|
||||
|
||||
def symbol_id(self):
|
||||
return '%s::%s' % (self.cls.name, self.name)
|
||||
|
||||
class Signal(MethodBase):
|
||||
def __init__(self):
|
||||
super(Signal, self).__init__()
|
||||
self.c_name = "fake"
|
||||
|
||||
def symbol_id(self):
|
||||
return 'signal:%s:%s' % (self.cls.name, self.name)
|
||||
|
||||
class Type(_XmlObject):
|
||||
def __init__(self):
|
||||
_XmlObject.__init__(self)
|
||||
self.name = None
|
||||
self.c_name = None
|
||||
self.gtype_id = None
|
||||
|
||||
def symbol_id(self):
|
||||
return self.name
|
||||
|
||||
class BasicType(Type):
|
||||
def __init__(self, name):
|
||||
Type.__init__(self)
|
||||
self.name = name
|
||||
|
||||
class ArrayType(Type):
|
||||
def __init__(self, elm_type):
|
||||
Type.__init__(self)
|
||||
self.elm_type = elm_type
|
||||
self.name = '%sArray*' % elm_type.name
|
||||
self.c_name = '%sArray*' % elm_type.name
|
||||
|
||||
class GErrorReturnType(Type):
|
||||
def __init__(self):
|
||||
Type.__init__(self)
|
||||
self.name = 'GError**'
|
||||
|
||||
class GTypedType(Type):
|
||||
def __init__(self):
|
||||
Type.__init__(self)
|
||||
self.short_name = None
|
||||
|
||||
def _parse_attribute(self, attr, value):
|
||||
if attr in ('short_name', 'name', 'gtype_id'):
|
||||
_set_unique_attribute(self, attr, value)
|
||||
else:
|
||||
return Type._parse_attribute(self, attr, value)
|
||||
return True
|
||||
|
||||
def _parse_xml(self, module, elm, *args):
|
||||
Type._parse_xml(self, module, elm, *args)
|
||||
if self.name is None:
|
||||
raise RuntimeError('class name missing')
|
||||
if self.short_name is None:
|
||||
raise RuntimeError('class short name missing')
|
||||
if self.gtype_id is None:
|
||||
raise RuntimeError('class gtype missing')
|
||||
|
||||
class EnumValue(_XmlObject):
|
||||
def __init__(self):
|
||||
super(EnumValue, self).__init__()
|
||||
self.name = None
|
||||
self.short_name = None
|
||||
self.enum = None
|
||||
|
||||
def symbol_id(self):
|
||||
return self.name
|
||||
|
||||
def _parse_attribute(self, attr, value):
|
||||
if attr in ('name'):
|
||||
_set_unique_attribute(self, attr, value)
|
||||
else:
|
||||
return super(EnumValue, self)._parse_attribute(attr, value)
|
||||
return True
|
||||
|
||||
def _parse_xml(self, module, elm, *args):
|
||||
super(EnumValue, self)._parse_xml(module, elm, *args)
|
||||
if self.name is None:
|
||||
raise RuntimeError('enum value name missing')
|
||||
if not self.short_name:
|
||||
self.short_name = self.name
|
||||
prefix = module.name.upper() + '_'
|
||||
if self.short_name.startswith(prefix):
|
||||
self.short_name = self.short_name[len(prefix):]
|
||||
|
||||
class EnumBase(GTypedType):
|
||||
def __init__(self):
|
||||
super(EnumBase, self).__init__()
|
||||
self.values = []
|
||||
self.__value_hash = {}
|
||||
|
||||
def _parse_xml_element(self, module, elm):
|
||||
if elm.tag == 'value':
|
||||
value = EnumValue.from_xml(module, elm)
|
||||
assert not value.name in self.__value_hash
|
||||
self.__value_hash[value.name] = value
|
||||
value.enum = self
|
||||
self.values.append(value)
|
||||
else:
|
||||
super(EnumBase, self)._parse_xml_element(module, elm)
|
||||
|
||||
class Enum(EnumBase):
|
||||
def __init__(self):
|
||||
super(Enum, self).__init__()
|
||||
|
||||
class Flags(EnumBase):
|
||||
def __init__(self):
|
||||
super(Flags, self).__init__()
|
||||
|
||||
class InstanceType(GTypedType):
|
||||
def __init__(self):
|
||||
GTypedType.__init__(self)
|
||||
self.constructor = None
|
||||
self.methods = []
|
||||
self.static_methods = []
|
||||
self.__method_hash = {}
|
||||
|
||||
def _parse_xml_element(self, module, elm):
|
||||
if elm.tag == 'method':
|
||||
meth = Method.from_xml(module, elm, self)
|
||||
assert not meth.name in self.__method_hash
|
||||
self.__method_hash[meth.name] = meth
|
||||
self.methods.append(meth)
|
||||
elif elm.tag == 'static-method':
|
||||
meth = StaticMethod.from_xml(module, elm, self)
|
||||
assert not meth.name in self.__method_hash
|
||||
self.__method_hash[meth.name] = meth
|
||||
self.static_methods.append(meth)
|
||||
elif elm.tag == 'constructor':
|
||||
assert not self.constructor
|
||||
self.constructor = Constructor.from_xml(module, elm, self)
|
||||
else:
|
||||
GTypedType._parse_xml_element(self, module, elm)
|
||||
|
||||
class Pointer(InstanceType):
|
||||
def __init__(self):
|
||||
InstanceType.__init__(self)
|
||||
|
||||
class Boxed(InstanceType):
|
||||
def __init__(self):
|
||||
InstanceType.__init__(self)
|
||||
|
||||
class Class(InstanceType):
|
||||
def __init__(self):
|
||||
InstanceType.__init__(self)
|
||||
self.parent = None
|
||||
self.vmethods = []
|
||||
self.signals = []
|
||||
self.constructable = None
|
||||
self.__vmethod_hash = {}
|
||||
self.__signal_hash = {}
|
||||
|
||||
def _parse_attribute(self, attr, value):
|
||||
if attr in ('parent'):
|
||||
_set_unique_attribute(self, attr, value)
|
||||
elif attr in ('constructable'):
|
||||
_set_unique_attribute_bool(self, attr, value)
|
||||
else:
|
||||
return InstanceType._parse_attribute(self, attr, value)
|
||||
return True
|
||||
|
||||
def _parse_xml_element(self, module, elm):
|
||||
if elm.tag == 'virtual':
|
||||
meth = VMethod.from_xml(module, elm, self)
|
||||
assert not meth.name in self.__vmethod_hash
|
||||
self.__vmethod_hash[meth.name] = meth
|
||||
self.vmethods.append(meth)
|
||||
elif elm.tag == 'signal':
|
||||
meth = Signal.from_xml(module, elm, self)
|
||||
assert not meth.name in self.__signal_hash
|
||||
self.__signal_hash[meth.name] = meth
|
||||
self.signals.append(meth)
|
||||
else:
|
||||
InstanceType._parse_xml_element(self, module, elm)
|
||||
|
||||
def _parse_xml(self, module, elm, *args):
|
||||
InstanceType._parse_xml(self, module, elm, *args)
|
||||
if self.parent is None:
|
||||
raise RuntimeError('class parent name missing')
|
||||
if self.constructable and self.constructor:
|
||||
raise RuntimeError('both constructor and constructable attributes present')
|
||||
|
||||
class Module(object):
|
||||
def __init__(self):
|
||||
object.__init__(self)
|
||||
self.name = None
|
||||
self.__classes = []
|
||||
self.__boxed = []
|
||||
self.__pointers = []
|
||||
self.__enums = []
|
||||
self.__class_hash = {}
|
||||
self.__functions = []
|
||||
self.__function_hash = {}
|
||||
self.__import_modules = []
|
||||
self.__parsing_done = False
|
||||
self.__types = {}
|
||||
self.__symbols = {}
|
||||
|
||||
def __add_type(self, typ):
|
||||
if typ.name in self.__class_hash:
|
||||
raise RuntimeError('duplicated type %s' % typ.name)
|
||||
self.__class_hash[typ.name] = typ
|
||||
|
||||
def __finish_type(self, typ):
|
||||
if isinstance(typ, Type):
|
||||
return typ
|
||||
if typ in self.__types:
|
||||
return self.__types[typ]
|
||||
if typ == 'GError**':
|
||||
return GErrorReturnType()
|
||||
m = re.match(r'(const-)?([\w\d_]+)\*', typ)
|
||||
if m:
|
||||
name = m.group(2)
|
||||
if name in self.__types:
|
||||
obj_type = self.__types[name]
|
||||
if isinstance(obj_type, InstanceType):
|
||||
return obj_type
|
||||
m = re.match(r'Array<([\w\d_]+)>\*', typ)
|
||||
if m:
|
||||
elm_type = self.__finish_type(m.group(1))
|
||||
return ArrayType(elm_type)
|
||||
m = re.match(r'([\w\d_]+)Array\*', typ)
|
||||
if m:
|
||||
elm_type = self.__finish_type(m.group(1))
|
||||
return ArrayType(elm_type)
|
||||
return BasicType(typ)
|
||||
|
||||
def __finish_parsing_method(self, meth, typ):
|
||||
sym_id = meth.symbol_id()
|
||||
if self.__symbols.get(sym_id):
|
||||
raise RuntimeError('duplicate symbol %s' % sym_id)
|
||||
self.__symbols[sym_id] = meth
|
||||
|
||||
for p in meth.params:
|
||||
p.type = self.__finish_type(p.type)
|
||||
if meth.retval:
|
||||
meth.retval.type = self.__finish_type(meth.retval.type)
|
||||
|
||||
meth.has_gerror_return = False
|
||||
if meth.params and isinstance(meth.params[-1].type, GErrorReturnType):
|
||||
meth.has_gerror_return = True
|
||||
|
||||
if meth.kwargs:
|
||||
params = list(meth.params)
|
||||
pos_args = []
|
||||
kw_args = []
|
||||
if meth.has_gerror_return:
|
||||
params = params[:-1]
|
||||
seen_kwarg = False
|
||||
for p in params:
|
||||
if p.default_value is not None:
|
||||
seen_kwarg = True
|
||||
elif seen_kwarg:
|
||||
raise RuntimeError('in %s: parameter without a default value follows a kwarg one' % sym_id)
|
||||
if p.default_value is not None:
|
||||
kw_args.append(p)
|
||||
else:
|
||||
pos_args.append(p)
|
||||
|
||||
def __finish_parsing_type(self, typ):
|
||||
if hasattr(typ, 'constructor') and typ.constructor is not None:
|
||||
self.__finish_parsing_method(typ.constructor, typ)
|
||||
for meth in typ.static_methods:
|
||||
self.__finish_parsing_method(meth, typ)
|
||||
for meth in typ.methods:
|
||||
self.__finish_parsing_method(meth, typ)
|
||||
if hasattr(typ, 'vmethods'):
|
||||
for meth in typ.vmethods:
|
||||
self.__finish_parsing_method(meth, typ)
|
||||
if hasattr(typ, 'signals'):
|
||||
for meth in typ.signals:
|
||||
self.__finish_parsing_method(meth, typ)
|
||||
|
||||
def __finish_parsing_enum(self, typ):
|
||||
for v in typ.values:
|
||||
sym_id = v.symbol_id()
|
||||
if self.__symbols.get(sym_id):
|
||||
raise RuntimeError('duplicate symbol %s' % sym_id)
|
||||
self.__symbols[sym_id] = v
|
||||
|
||||
def __add_type_symbol(self, typ):
|
||||
sym_id = typ.symbol_id()
|
||||
if self.__symbols.get(sym_id):
|
||||
raise RuntimeError('duplicate symbol %s' % sym_id)
|
||||
self.__symbols[sym_id] = typ
|
||||
|
||||
def __finish_parsing(self):
|
||||
if self.__parsing_done:
|
||||
return
|
||||
|
||||
for typ in self.__classes + self.__boxed + self.__pointers + self.__enums:
|
||||
self.__add_type_symbol(typ)
|
||||
self.__types[typ.name] = typ
|
||||
|
||||
for module in self.__import_modules:
|
||||
for typ in module.get_classes() + module.get_boxed() + \
|
||||
module.get_pointers() + module.get_enums():
|
||||
self.__types[typ.name] = typ
|
||||
for sym in module.__symbols:
|
||||
if self.__symbols.get(sym):
|
||||
raise RuntimeError('duplicate symbol %s' % sym)
|
||||
self.__symbols[sym] = module.__symbols[sym]
|
||||
|
||||
for typ in self.__classes + self.__boxed + self.__pointers:
|
||||
self.__finish_parsing_type(typ)
|
||||
|
||||
for typ in self.__enums:
|
||||
self.__finish_parsing_enum(typ)
|
||||
|
||||
for func in self.__functions:
|
||||
self.__finish_parsing_method(func, None)
|
||||
|
||||
self.__parsing_done = True
|
||||
|
||||
def get_classes(self):
|
||||
self.__finish_parsing()
|
||||
return list(self.__classes)
|
||||
|
||||
def get_boxed(self):
|
||||
self.__finish_parsing()
|
||||
return list(self.__boxed)
|
||||
|
||||
def get_pointers(self):
|
||||
self.__finish_parsing()
|
||||
return list(self.__pointers)
|
||||
|
||||
def get_enums(self):
|
||||
self.__finish_parsing()
|
||||
return list(self.__enums)
|
||||
|
||||
def get_functions(self):
|
||||
self.__finish_parsing()
|
||||
return list(self.__functions)
|
||||
|
||||
def get_symbols(self):
|
||||
self.__finish_parsing()
|
||||
return dict(self.__symbols)
|
||||
|
||||
def __parse_module_entry(self, elm):
|
||||
if elm.tag == 'class':
|
||||
cls = Class.from_xml(self, elm)
|
||||
self.__add_type(cls)
|
||||
self.__classes.append(cls)
|
||||
elif elm.tag == 'boxed':
|
||||
cls = Boxed.from_xml(self, elm)
|
||||
self.__add_type(cls)
|
||||
self.__boxed.append(cls)
|
||||
elif elm.tag == 'pointer':
|
||||
cls = Pointer.from_xml(self, elm)
|
||||
self.__add_type(cls)
|
||||
self.__pointers.append(cls)
|
||||
elif elm.tag == 'enum':
|
||||
enum = Enum.from_xml(self, elm)
|
||||
self.__add_type(enum)
|
||||
self.__enums.append(enum)
|
||||
elif elm.tag == 'flags':
|
||||
enum = Flags.from_xml(self, elm)
|
||||
self.__add_type(enum)
|
||||
self.__enums.append(enum)
|
||||
elif elm.tag == 'function':
|
||||
func = Function.from_xml(self, elm)
|
||||
assert not func.name in self.__function_hash
|
||||
self.__function_hash[func.name] = func
|
||||
self.__functions.append(func)
|
||||
else:
|
||||
raise RuntimeError('unknown element %s' % (elm.tag,))
|
||||
|
||||
def import_module(self, mod):
|
||||
self.__import_modules.append(mod)
|
||||
|
||||
@staticmethod
|
||||
def from_xml(filename):
|
||||
mod = Module()
|
||||
xml = _etree.ElementTree()
|
||||
xml.parse(filename)
|
||||
root = xml.getroot()
|
||||
assert root.tag == 'module'
|
||||
mod.name = root.get('name')
|
||||
assert mod.name is not None
|
||||
for elm in root.getchildren():
|
||||
mod.__parse_module_entry(elm)
|
||||
return mod
|
|
@ -0,0 +1,12 @@
|
|||
import sys
|
||||
|
||||
__all__ = [ 'implement_me', 'oops', 'warning' ]
|
||||
|
||||
def implement_me(what):
|
||||
print >> sys.stderr, 'implement me: %s' % what
|
||||
|
||||
def oops(message=None):
|
||||
raise RuntimeError(message)
|
||||
|
||||
def warning(message):
|
||||
print >>sys.stderr, "WARNING:", message
|
|
@ -0,0 +1,65 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import optparse
|
||||
import fnmatch
|
||||
import filecmp
|
||||
|
||||
from mdp.docparser import Parser
|
||||
from mdp.module import Module
|
||||
import mdp.xmlwriter
|
||||
|
||||
def read_files(files, opts):
|
||||
p = Parser()
|
||||
p.read_files(files)
|
||||
mod = Module('Moo' if not opts.module else opts.module)
|
||||
mod.init_from_dox(p.classes + p.enums + p.functions + p.vmethods + p.signals)
|
||||
return mod
|
||||
|
||||
def parse_args():
|
||||
op = optparse.OptionParser()
|
||||
op.add_option("--source-dir", dest="source_dirs", action="append",
|
||||
help="parse source files from DIR", metavar="DIR")
|
||||
op.add_option("--source-file", dest="source_files", action="append",
|
||||
help="parse source file FILE", metavar="FILE")
|
||||
op.add_option("--skip", dest="skip_globs", action="append",
|
||||
help="skip files which match pattern PAT", metavar="PAT")
|
||||
op.add_option("--output", dest="output", action="store",
|
||||
help="write result to FILE", metavar="FILE")
|
||||
op.add_option("--module", dest="module", action="store",
|
||||
help="generate module MOD", metavar="MOD")
|
||||
(opts, args) = op.parse_args()
|
||||
if args:
|
||||
op.error("too many arguments")
|
||||
source_files = []
|
||||
if opts.source_files:
|
||||
source_files += [os.path.abspath(f) for f in opts.source_files]
|
||||
skip_pat = None
|
||||
if opts.skip_globs:
|
||||
skip_pat = re.compile('|'.join([fnmatch.translate(g) for g in opts.skip_globs]))
|
||||
if opts.source_dirs:
|
||||
for source_dir in opts.source_dirs:
|
||||
for root, dirs, files in os.walk(source_dir):
|
||||
for f in files:
|
||||
if f.endswith('.c') or f.endswith('.cpp') or f.endswith('.h'):
|
||||
if skip_pat is None or not skip_pat.match(f):
|
||||
source_files.append(os.path.join(root, f))
|
||||
if not source_files:
|
||||
op.error("no input files")
|
||||
return opts, source_files
|
||||
|
||||
opts, files = parse_args()
|
||||
mod = read_files(files, opts)
|
||||
tmp_file = opts.output + '.tmp'
|
||||
with open(tmp_file, 'w') as out:
|
||||
mdp.xmlwriter.write_xml(mod, out)
|
||||
|
||||
if not os.path.exists(opts.output):
|
||||
os.rename(tmp_file, opts.output)
|
||||
elif filecmp.cmp(tmp_file, opts.output):
|
||||
os.remove(tmp_file)
|
||||
else:
|
||||
os.remove(opts.output)
|
||||
os.rename(tmp_file, opts.output)
|
|
@ -0,0 +1,286 @@
|
|||
source_files = \
|
||||
../moo/moolua/medit-lua.h\
|
||||
../moo/moolua/medit-lua.cpp\
|
||||
../moo/mooapp/mooappabout.cpp\
|
||||
../moo/mooapp/mooappabout.h\
|
||||
../moo/mooapp/mooapp-accels.h\
|
||||
../moo/mooapp/mooapp.cpp\
|
||||
../moo/mooapp/mooapp.h\
|
||||
../moo/mooapp/mooapp-info.h\
|
||||
../moo/mooapp/mooapp-private.h\
|
||||
../moo/mooapp/moohtml.cpp\
|
||||
../moo/mooapp/moohtml.h\
|
||||
../moo/mooapp/moolinklabel.cpp\
|
||||
../moo/mooapp/moolinklabel.h\
|
||||
../moo/mooedit/mooedit-accels.h\
|
||||
../moo/mooedit/mooeditaction.cpp\
|
||||
../moo/mooedit/mooeditaction-factory.cpp\
|
||||
../moo/mooedit/mooeditaction-factory.h\
|
||||
../moo/mooedit/mooeditaction.h\
|
||||
../moo/mooedit/mooeditbookmark.cpp\
|
||||
../moo/mooedit/mooeditbookmark.h\
|
||||
../moo/mooedit/mooedit.cpp\
|
||||
../moo/mooedit/mooeditconfig.cpp\
|
||||
../moo/mooedit/mooeditconfig.h\
|
||||
../moo/mooedit/mooeditdialogs.cpp\
|
||||
../moo/mooedit/mooeditdialogs.h\
|
||||
../moo/mooedit/mooedit-enum-types.c\
|
||||
../moo/mooedit/mooedit-enum-types.h\
|
||||
../moo/mooedit/mooedit-enums.h\
|
||||
../moo/mooedit/mooeditfileinfo.cpp\
|
||||
../moo/mooedit/mooeditfileinfo.h\
|
||||
../moo/mooedit/mooedit-fileops.cpp\
|
||||
../moo/mooedit/mooedit-fileops.h\
|
||||
../moo/mooedit/mooeditfiltersettings.cpp\
|
||||
../moo/mooedit/mooeditfiltersettings.h\
|
||||
../moo/mooedit/mooedit.h\
|
||||
../moo/mooedit/mooedithistoryitem.cpp\
|
||||
../moo/mooedit/mooedithistoryitem.h\
|
||||
../moo/mooedit/mooedit-impl.h\
|
||||
../moo/mooedit/mooeditor.cpp\
|
||||
../moo/mooedit/mooeditor.h\
|
||||
../moo/mooedit/mooeditor-impl.h\
|
||||
../moo/mooedit/mooeditor-private.h\
|
||||
../moo/mooedit/mooeditor-tests.cpp\
|
||||
../moo/mooedit/mooeditor-tests.h\
|
||||
../moo/mooedit/mooeditprefs.cpp\
|
||||
../moo/mooedit/mooeditprefs.h\
|
||||
../moo/mooedit/mooeditprefspage.cpp\
|
||||
../moo/mooedit/mooedit-private.h\
|
||||
../moo/mooedit/mooedit-script.cpp\
|
||||
../moo/mooedit/mooedit-script.h\
|
||||
../moo/mooedit/mooedittab.cpp\
|
||||
../moo/mooedit/mooedittab.h\
|
||||
../moo/mooedit/mooedittypes.h\
|
||||
../moo/mooedit/mooeditview.cpp\
|
||||
../moo/mooedit/mooeditview.h\
|
||||
../moo/mooedit/mooeditview-script.cpp\
|
||||
../moo/mooedit/mooeditview-script.h\
|
||||
../moo/mooedit/mooeditwindow.cpp\
|
||||
../moo/mooedit/mooeditwindow.h\
|
||||
../moo/mooedit/mooeditwindow-impl.h\
|
||||
../moo/mooedit/moofold.cpp\
|
||||
../moo/mooedit/moofold.h\
|
||||
../moo/mooedit/mooindenter.cpp\
|
||||
../moo/mooedit/mooindenter.h\
|
||||
../moo/mooedit/moolang.cpp\
|
||||
../moo/mooedit/moolang.h\
|
||||
../moo/mooedit/moolangmgr.cpp\
|
||||
../moo/mooedit/moolangmgr.h\
|
||||
../moo/mooedit/moolangmgr-private.h\
|
||||
../moo/mooedit/moolang-private.h\
|
||||
../moo/mooedit/moolinebuffer.c\
|
||||
../moo/mooedit/moolinebuffer.h\
|
||||
../moo/mooedit/moolinemark.c\
|
||||
../moo/mooedit/moolinemark.h\
|
||||
../moo/mooedit/mooplugin.c\
|
||||
../moo/mooedit/mooplugin.h\
|
||||
../moo/mooedit/mooplugin-loader.c\
|
||||
../moo/mooedit/mooplugin-loader.h\
|
||||
../moo/mooedit/mooplugin-macro.h\
|
||||
../moo/mooedit/mootextbtree.c\
|
||||
../moo/mooedit/mootextbtree.h\
|
||||
../moo/mooedit/mootextbuffer.c\
|
||||
../moo/mooedit/mootextfind.c\
|
||||
../moo/mooedit/mootextfind.h\
|
||||
../moo/mooedit/mootextiter.h\
|
||||
../moo/mooedit/mootextprint.c\
|
||||
../moo/mooedit/mootextprint.h\
|
||||
../moo/mooedit/mootextprint-private.h\
|
||||
../moo/mooedit/mootext-private.h\
|
||||
../moo/mooedit/mootextsearch.c\
|
||||
../moo/mooedit/mootextsearch.h\
|
||||
../moo/mooedit/mootextsearch-private.h\
|
||||
../moo/mooedit/mootextstylescheme.c\
|
||||
../moo/mooedit/mootextstylescheme.h\
|
||||
../moo/mooedit/mootextview.c\
|
||||
../moo/mooedit/mootextview.h\
|
||||
../moo/mooedit/mootextview-input.c\
|
||||
../moo/mooedit/mootextview-private.h\
|
||||
../moo/moofileview/moobookmarkmgr.c\
|
||||
../moo/moofileview/moobookmarkmgr.h\
|
||||
../moo/moofileview/moobookmarkview.c\
|
||||
../moo/moofileview/moobookmarkview.h\
|
||||
../moo/moofileview/moofile.c\
|
||||
../moo/moofileview/moofileentry.c\
|
||||
../moo/moofileview/moofileentry.h\
|
||||
../moo/moofileview/moofile.h\
|
||||
../moo/moofileview/moofile-private.h\
|
||||
../moo/moofileview/moofilesystem.c\
|
||||
../moo/moofileview/moofilesystem.h\
|
||||
../moo/moofileview/moofileview-accels.h\
|
||||
../moo/moofileview/moofileview-aux.h\
|
||||
../moo/moofileview/moofileview.c\
|
||||
../moo/moofileview/moofileview-dialogs.c\
|
||||
../moo/moofileview/moofileview-dialogs.h\
|
||||
../moo/moofileview/moofileview.h\
|
||||
../moo/moofileview/moofileview-impl.h\
|
||||
../moo/moofileview/moofileview-private.h\
|
||||
../moo/moofileview/moofileview-tools.c\
|
||||
../moo/moofileview/moofileview-tools.h\
|
||||
../moo/moofileview/moofolder.c\
|
||||
../moo/moofileview/moofolder.h\
|
||||
../moo/moofileview/moofoldermodel.c\
|
||||
../moo/moofileview/moofoldermodel.h\
|
||||
../moo/moofileview/moofoldermodel-private.h\
|
||||
../moo/moofileview/moofolder-private.h\
|
||||
../moo/moofileview/mooiconview.c\
|
||||
../moo/moofileview/mooiconview.h\
|
||||
../moo/moofileview/mootreeview.c\
|
||||
../moo/moofileview/mootreeview.h\
|
||||
../moo/mooutils/mooaccelbutton.c\
|
||||
../moo/mooutils/mooaccelbutton.h\
|
||||
../moo/mooutils/mooaccel.cpp\
|
||||
../moo/mooutils/mooaccel.h\
|
||||
../moo/mooutils/mooaccelprefs.c\
|
||||
../moo/mooutils/mooaccelprefs.h\
|
||||
../moo/mooutils/mooactionbase.c\
|
||||
../moo/mooutils/mooactionbase.h\
|
||||
../moo/mooutils/mooactionbase-private.h\
|
||||
../moo/mooutils/mooaction.c\
|
||||
../moo/mooutils/mooactioncollection.c\
|
||||
../moo/mooutils/mooactioncollection.h\
|
||||
../moo/mooutils/mooactionfactory.c\
|
||||
../moo/mooutils/mooactionfactory.h\
|
||||
../moo/mooutils/mooactiongroup.c\
|
||||
../moo/mooutils/mooactiongroup.h\
|
||||
../moo/mooutils/mooaction.h\
|
||||
../moo/mooutils/mooaction-private.h\
|
||||
../moo/mooutils/mooappinput-common.c\
|
||||
../moo/mooutils/mooappinput.h\
|
||||
../moo/mooutils/mooapp-ipc.c\
|
||||
../moo/mooutils/mooapp-ipc.h\
|
||||
../moo/mooutils/mooarray.h\
|
||||
../moo/mooutils/mooatom.h\
|
||||
../moo/mooutils/moobigpaned.c\
|
||||
../moo/mooutils/moobigpaned.h\
|
||||
../moo/mooutils/mooclosure.c\
|
||||
../moo/mooutils/mooclosure.h\
|
||||
../moo/mooutils/moocombo.c\
|
||||
../moo/mooutils/moocombo.h\
|
||||
../moo/mooutils/moocompat.h\
|
||||
../moo/mooutils/moodialogs.c\
|
||||
../moo/mooutils/moodialogs.h\
|
||||
../moo/mooutils/mooeditops.c\
|
||||
../moo/mooutils/mooeditops.h\
|
||||
../moo/mooutils/mooencodings.c\
|
||||
../moo/mooutils/mooencodings-data.h\
|
||||
../moo/mooutils/mooencodings.h\
|
||||
../moo/mooutils/mooentry.cpp\
|
||||
../moo/mooutils/mooentry.h\
|
||||
../moo/mooutils/moo-environ.h\
|
||||
../moo/mooutils/moofiledialog.c\
|
||||
../moo/mooutils/moofiledialog.h\
|
||||
../moo/mooutils/moofileicon.c\
|
||||
../moo/mooutils/moofileicon.h\
|
||||
../moo/mooutils/moofilewatch.c\
|
||||
../moo/mooutils/moofilewatch.h\
|
||||
../moo/mooutils/moofilewriter.cpp\
|
||||
../moo/mooutils/moofilewriter.h\
|
||||
../moo/mooutils/moofilewriter-private.h\
|
||||
../moo/mooutils/moofiltermgr.c\
|
||||
../moo/mooutils/moofiltermgr.h\
|
||||
../moo/mooutils/moofontsel.c\
|
||||
../moo/mooutils/moofontsel.h\
|
||||
../moo/mooutils/mooglade.c\
|
||||
../moo/mooutils/mooglade.h\
|
||||
../moo/mooutils/moohelp.c\
|
||||
../moo/mooutils/moohelp.h\
|
||||
../moo/mooutils/moohistorycombo.c\
|
||||
../moo/mooutils/moohistorycombo.h\
|
||||
../moo/mooutils/moohistorylist.c\
|
||||
../moo/mooutils/moohistorylist.h\
|
||||
../moo/mooutils/moohistorymgr.c\
|
||||
../moo/mooutils/moohistorymgr.h\
|
||||
../moo/mooutils/mooi18n.cpp\
|
||||
../moo/mooutils/mooi18n.h\
|
||||
../moo/mooutils/moolist.h\
|
||||
../moo/mooutils/moomarkup.c\
|
||||
../moo/mooutils/moomarkup.h\
|
||||
../moo/mooutils/moomenuaction.c\
|
||||
../moo/mooutils/moomenuaction.h\
|
||||
../moo/mooutils/moomenu.c\
|
||||
../moo/mooutils/moomenu.h\
|
||||
../moo/mooutils/moomenumgr.c\
|
||||
../moo/mooutils/moomenumgr.h\
|
||||
../moo/mooutils/moomenutoolbutton.c\
|
||||
../moo/mooutils/moomenutoolbutton.h\
|
||||
../moo/mooutils/moo-mime.c\
|
||||
../moo/mooutils/moo-mime.h\
|
||||
../moo/mooutils/moonotebook.c\
|
||||
../moo/mooutils/moonotebook.h\
|
||||
../moo/mooutils/mooonce.h\
|
||||
../moo/mooutils/moopane.c\
|
||||
../moo/mooutils/moopaned.c\
|
||||
../moo/mooutils/moopaned.h\
|
||||
../moo/mooutils/moopane.h\
|
||||
../moo/mooutils/mooprefs.c\
|
||||
../moo/mooutils/mooprefsdialog.c\
|
||||
../moo/mooutils/mooprefsdialog.h\
|
||||
../moo/mooutils/mooprefs.h\
|
||||
../moo/mooutils/mooprefspage.c\
|
||||
../moo/mooutils/mooprefspage.h\
|
||||
../moo/mooutils/moospawn.c\
|
||||
../moo/mooutils/moospawn.h\
|
||||
../moo/mooutils/moostock.c\
|
||||
../moo/mooutils/moostock.h\
|
||||
../moo/mooutils/moo-test-macros.h\
|
||||
../moo/mooutils/moo-test-utils.cpp\
|
||||
../moo/mooutils/moo-test-utils.h\
|
||||
../moo/mooutils/mootypedecl-macros.h\
|
||||
../moo/mooutils/mootype-macros.h\
|
||||
../moo/mooutils/moouixml.c\
|
||||
../moo/mooutils/moouixml.h\
|
||||
../moo/mooutils/mooundo.c\
|
||||
../moo/mooutils/mooundo.h\
|
||||
../moo/mooutils/mooutils-debug.h\
|
||||
../moo/mooutils/mooutils-enums.c\
|
||||
../moo/mooutils/mooutils-enums.h\
|
||||
../moo/mooutils/mooutils-file.c\
|
||||
../moo/mooutils/mooutils-file.h\
|
||||
../moo/mooutils/mooutils-fs.cpp\
|
||||
../moo/mooutils/mooutils-fs.h\
|
||||
../moo/mooutils/mooutils-gobject.cpp\
|
||||
../moo/mooutils/mooutils-gobject.h\
|
||||
../moo/mooutils/mooutils-gobject-private.h\
|
||||
../moo/mooutils/mooutils.h\
|
||||
../moo/mooutils/mooutils-macros.h\
|
||||
../moo/mooutils/mooutils-mem.h\
|
||||
../moo/mooutils/mooutils-messages.h\
|
||||
../moo/mooutils/mooutils-misc.cpp\
|
||||
../moo/mooutils/mooutils-misc.h\
|
||||
../moo/mooutils/mooutils-script.c\
|
||||
../moo/mooutils/mooutils-script.h\
|
||||
../moo/mooutils/mooutils-tests.h\
|
||||
../moo/mooutils/mooutils-thread.cpp\
|
||||
../moo/mooutils/mooutils-thread.h\
|
||||
../moo/mooutils/mooutils-treeview.c\
|
||||
../moo/mooutils/mooutils-treeview.h\
|
||||
../moo/mooutils/mooutils-win32.cpp\
|
||||
../moo/mooutils/moowin32/mingw/fnmatch.h\
|
||||
../moo/mooutils/moowin32/mingw/netinet/in.h\
|
||||
../moo/mooutils/moowin32/ms/sys/time.h\
|
||||
../moo/mooutils/moowin32/ms/unistd.h\
|
||||
../moo/mooutils/moowindow.c\
|
||||
../moo/mooutils/moowindow.h\
|
||||
../moo/plugins/support/moocmdview.cpp\
|
||||
../moo/plugins/support/moocmdview.h\
|
||||
../moo/plugins/support/mooeditwindowoutput.cpp\
|
||||
../moo/plugins/support/mooeditwindowoutput.h\
|
||||
../moo/plugins/support/moolineview.cpp\
|
||||
../moo/plugins/support/moolineview.h\
|
||||
../moo/plugins/support/moooutputfilter.cpp\
|
||||
../moo/plugins/support/moooutputfilter.h\
|
||||
../moo/plugins/usertools/moocommand.cpp\
|
||||
../moo/plugins/usertools/moocommanddisplay.cpp\
|
||||
../moo/plugins/usertools/moocommanddisplay.h\
|
||||
../moo/plugins/usertools/moocommand.h\
|
||||
../moo/plugins/usertools/moocommand-private.h\
|
||||
../moo/plugins/usertools/moooutputfilterregex.cpp\
|
||||
../moo/plugins/usertools/moooutputfilterregex.h\
|
||||
../moo/plugins/usertools/moousertools.cpp\
|
||||
../moo/plugins/usertools/moousertools-enums.cpp\
|
||||
../moo/plugins/usertools/moousertools-enums.h\
|
||||
../moo/plugins/usertools/moousertools.h\
|
||||
../moo/plugins/usertools/moousertools-prefs.cpp\
|
||||
../moo/plugins/usertools/moousertools-prefs.h
|
|
@ -0,0 +1,39 @@
|
|||
#!/bin/sh
|
||||
[ -z "$ACLOCAL" ] && ACLOCAL=aclocal
|
||||
[ -z "$AUTOCONF" ] && AUTOCONF=autoconf
|
||||
[ -z "$AUTOHEADER" ] && AUTOHEADER=autoheader
|
||||
[ -z "$AUTOMAKE" ] && AUTOMAKE=automake
|
||||
[ -z "$LIBTOOLIZE" ] && LIBTOOLIZE=libtoolize
|
||||
|
||||
workingdir=`pwd`
|
||||
rel_srcdir=`dirname "$0"`
|
||||
srcdir=`cd "$rel_srcdir" && pwd`
|
||||
|
||||
cd "$srcdir"
|
||||
|
||||
run_cmd() {
|
||||
echo "$@"
|
||||
"$@" || exit $!
|
||||
}
|
||||
|
||||
run_cmd $LIBTOOLIZE --copy --force
|
||||
|
||||
run_cmd $ACLOCAL --force -I m4 $ACLOCAL_FLAGS
|
||||
run_cmd $AUTOCONF --force
|
||||
run_cmd $AUTOHEADER --force
|
||||
run_cmd $AUTOMAKE --add-missing --copy --force-missing
|
||||
|
||||
cd $workingdir
|
||||
|
||||
run_configure=true
|
||||
configure_args="--enable-dev-mode"
|
||||
if [ "$1" ]; then
|
||||
:
|
||||
else
|
||||
echo "Done. Run '$rel_srcdir/configure --enable-dev-mode' to configure and then 'make' to build"
|
||||
run_configure=false
|
||||
fi
|
||||
|
||||
if $run_configure; then
|
||||
run_cmd $rel_srcdir/configure $configure_args "$@"
|
||||
fi
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
files = subprocess.Popen(['hg', 'log', '-r', 'tip', '--template', '{files}'],
|
||||
stdout=subprocess.PIPE).communicate()[0].split()
|
||||
|
||||
status = 0
|
||||
|
||||
for name in files:
|
||||
if not os.path.exists(name) or name.startswith('medit/data') or \
|
||||
name.endswith('.icns') or name.endswith('.png'):
|
||||
continue
|
||||
f = open(name, 'rb')
|
||||
if '\r' in f.read():
|
||||
print >> sys.stderr, "%s contains \\r character" % (name,)
|
||||
status = 1
|
||||
f.close()
|
||||
|
||||
sys.exit(status)
|
|
@ -0,0 +1,222 @@
|
|||
# Function for setting up precompiled headers. Usage:
|
||||
#
|
||||
# add_library/executable(target
|
||||
# pchheader.c pchheader.cpp pchheader.h)
|
||||
#
|
||||
# add_precompiled_header(target pchheader.h
|
||||
# [FORCEINCLUDE]
|
||||
# [SOURCE_C pchheader.c]
|
||||
# [SOURCE_CXX pchheader.cpp])
|
||||
#
|
||||
# Options:
|
||||
#
|
||||
# FORCEINCLUDE: Add compiler flags to automatically include the
|
||||
# pchheader.h from every source file. Works with both GCC and
|
||||
# MSVC. This is recommended.
|
||||
#
|
||||
# SOURCE_C/CXX: Specifies the .c/.cpp source file that includes
|
||||
# pchheader.h for generating the pre-compiled header
|
||||
# output. Defaults to pchheader.c. Only required for MSVC.
|
||||
#
|
||||
# Caveats:
|
||||
#
|
||||
# * Its not currently possible to use the same precompiled-header in
|
||||
# more than a single target in the same directory (No way to set
|
||||
# the source file properties differently for each target).
|
||||
#
|
||||
# * MSVC: A source file with the same name as the header must exist
|
||||
# and be included in the target (E.g. header.cpp). Name of file
|
||||
# can be changed using the SOURCE_CXX/SOURCE_C options.
|
||||
#
|
||||
# License:
|
||||
#
|
||||
# Copyright (C) 2009-2013 Lars Christensen <larsch@belunktum.dk>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the 'Software') deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
include(CMakeParseArguments)
|
||||
|
||||
macro(combine_arguments _variable)
|
||||
set(_result "")
|
||||
foreach(_element ${${_variable}})
|
||||
set(_result "${_result} \"${_element}\"")
|
||||
endforeach()
|
||||
string(STRIP "${_result}" _result)
|
||||
set(${_variable} "${_result}")
|
||||
endmacro()
|
||||
|
||||
function(export_all_flags _filename)
|
||||
set(_include_directories "$<TARGET_PROPERTY:${_target},INCLUDE_DIRECTORIES>")
|
||||
set(_compile_definitions "$<TARGET_PROPERTY:${_target},COMPILE_DEFINITIONS>")
|
||||
set(_compile_flags "$<TARGET_PROPERTY:${_target},COMPILE_FLAGS>")
|
||||
set(_compile_options "$<TARGET_PROPERTY:${_target},COMPILE_OPTIONS>")
|
||||
set(_include_directories "$<$<BOOL:${_include_directories}>:-I$<JOIN:${_include_directories},\n-I>\n>")
|
||||
set(_compile_definitions "$<$<BOOL:${_compile_definitions}>:-D$<JOIN:${_compile_definitions},\n-D>\n>")
|
||||
set(_compile_flags "$<$<BOOL:${_compile_flags}>:$<JOIN:${_compile_flags},\n>\n>")
|
||||
set(_compile_options "$<$<BOOL:${_compile_options}>:$<JOIN:${_compile_options},\n>\n>")
|
||||
file(GENERATE OUTPUT "${_filename}" CONTENT "${_compile_definitions}${_include_directories}${_compile_flags}${_compile_options}\n")
|
||||
endfunction()
|
||||
|
||||
function(add_precompiled_header _target _input)
|
||||
cmake_parse_arguments(_PCH "FORCEINCLUDE" "SOURCE_CXX:SOURCE_C" "" ${ARGN})
|
||||
|
||||
get_filename_component(_input_we ${_input} NAME_WE)
|
||||
if(NOT _PCH_SOURCE_CXX)
|
||||
set(_PCH_SOURCE_CXX "${_input_we}.cpp")
|
||||
endif()
|
||||
if(NOT _PCH_SOURCE_C)
|
||||
set(_PCH_SOURCE_C "${_input_we}.c")
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
|
||||
set(_cxx_path "${CMAKE_CFG_INTDIR}/${_target}_cxx_pch")
|
||||
set(_c_path "${CMAKE_CFG_INTDIR}/${_target}_c_pch")
|
||||
make_directory("${_cxx_path}")
|
||||
make_directory("${_c_path}")
|
||||
set(_pch_cxx_header "${_cxx_path}/${_input}")
|
||||
set(_pch_cxx_pch "${_cxx_path}/${_input_we}.pch")
|
||||
set(_pch_c_header "${_c_path}/${_input}")
|
||||
set(_pch_c_pch "${_c_path}/${_input_we}.pch")
|
||||
|
||||
get_target_property(sources ${_target} SOURCES)
|
||||
foreach(_source ${sources})
|
||||
set(_pch_compile_flags "")
|
||||
if(_source MATCHES \\.\(cc|cxx|cpp|c\)$)
|
||||
if(_source MATCHES \\.\(cpp|cxx|cc\)$)
|
||||
set(_pch_header "${_input}")
|
||||
set(_pch "${_pch_cxx_pch}")
|
||||
else()
|
||||
set(_pch_header "${_input}")
|
||||
set(_pch "${_pch_c_pch}")
|
||||
endif()
|
||||
|
||||
if(_source STREQUAL "${_PCH_SOURCE_CXX}")
|
||||
set(_pch_compile_flags "${_pch_compile_flags} \"/Fp${_pch_cxx_pch}\" /Yc${_input}")
|
||||
set(_pch_source_cxx_found TRUE)
|
||||
elseif(_source STREQUAL "${_PCH_SOURCE_C}")
|
||||
set(_pch_compile_flags "${_pch_compile_flags} \"/Fp${_pch_c_pch}\" /Yc${_input}")
|
||||
set(_pch_source_c_found TRUE)
|
||||
else()
|
||||
if(_source MATCHES \\.\(cpp|cxx|cc\)$)
|
||||
set(_pch_compile_flags "${_pch_compile_flags} \"/Fp${_pch_cxx_pch}\" /Yu${_input}")
|
||||
set(_pch_source_cxx_needed TRUE)
|
||||
else()
|
||||
set(_pch_compile_flags "${_pch_compile_flags} \"/Fp${_pch_c_pch}\" /Yu${_input}")
|
||||
set(_pch_source_c_needed TRUE)
|
||||
endif()
|
||||
if(_PCH_FORCEINCLUDE)
|
||||
set(_pch_compile_flags "${_pch_compile_flags} /FI${_input}")
|
||||
endif(_PCH_FORCEINCLUDE)
|
||||
endif()
|
||||
|
||||
get_source_file_property(_object_depends "${_source}" OBJECT_DEPENDS)
|
||||
if(NOT _object_depends)
|
||||
set(_object_depends)
|
||||
endif()
|
||||
if(_PCH_FORCEINCLUDE)
|
||||
if(_source MATCHES \\.\(cc|cxx|cpp\)$)
|
||||
list(APPEND _object_depends "${_pch_header}")
|
||||
else()
|
||||
list(APPEND _object_depends "${_pch_header}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_source_files_properties(${_source} PROPERTIES
|
||||
COMPILE_FLAGS "${_pch_compile_flags}"
|
||||
OBJECT_DEPENDS "${_object_depends}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(_pch_source_cxx_needed AND NOT _pch_source_cxx_found)
|
||||
message(FATAL_ERROR "A source file ${_PCH_SOURCE_CXX} for ${_input} is required for MSVC builds. Can be set with the SOURCE_CXX option.")
|
||||
endif()
|
||||
if(_pch_source_c_needed AND NOT _pch_source_c_found)
|
||||
message(FATAL_ERROR "A source file ${_PCH_SOURCE_C} for ${_input} is required for MSVC builds. Can be set with the SOURCE_C option.")
|
||||
endif()
|
||||
endif(MSVC)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
get_filename_component(_name ${_input} NAME)
|
||||
set(_pch_header "${CMAKE_CURRENT_SOURCE_DIR}/${_input}")
|
||||
set(_pch_binary_dir "${CMAKE_CURRENT_BINARY_DIR}/${_target}_pch")
|
||||
set(_pchfile "${_pch_binary_dir}/${_input}")
|
||||
set(_outdir "${CMAKE_CURRENT_BINARY_DIR}/${_target}_pch/${_name}.gch")
|
||||
make_directory(${_outdir})
|
||||
set(_output_cxx "${_outdir}/.c++")
|
||||
set(_output_c "${_outdir}/.c")
|
||||
|
||||
set(_pch_flags_file "${_pch_binary_dir}/compile_flags.rsp")
|
||||
export_all_flags("${_pch_flags_file}")
|
||||
set(_compiler_FLAGS "@${_pch_flags_file}")
|
||||
add_custom_command(
|
||||
OUTPUT "${_pchfile}"
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy "${_pch_header}" "${_pchfile}"
|
||||
DEPENDS "${_pch_header}"
|
||||
COMMENT "Updating ${_name}")
|
||||
add_custom_command(
|
||||
OUTPUT "${_output_cxx}"
|
||||
COMMAND "${CMAKE_CXX_COMPILER}" ${_compiler_FLAGS} -x c++-header -o "${_output_cxx}" "${_pchfile}"
|
||||
DEPENDS "${_pchfile}" "${_pch_flags_file}"
|
||||
COMMENT "Precompiling ${_name} for ${_target} (C++)")
|
||||
add_custom_command(
|
||||
OUTPUT "${_output_c}"
|
||||
COMMAND "${CMAKE_C_COMPILER}" ${_compiler_FLAGS} -x c-header -o "${_output_c}" "${_pchfile}"
|
||||
DEPENDS "${_pchfile}" "${_pch_flags_file}"
|
||||
COMMENT "Precompiling ${_name} for ${_target} (C)")
|
||||
|
||||
get_property(_sources TARGET ${_target} PROPERTY SOURCES)
|
||||
foreach(_source ${_sources})
|
||||
set(_pch_compile_flags "")
|
||||
|
||||
if(_source MATCHES \\.\(cc|cxx|cpp|c\)$)
|
||||
get_source_file_property(_pch_compile_flags "${_source}" COMPILE_FLAGS)
|
||||
if(NOT _pch_compile_flags)
|
||||
set(_pch_compile_flags)
|
||||
endif()
|
||||
separate_arguments(_pch_compile_flags)
|
||||
list(APPEND _pch_compile_flags -Winvalid-pch)
|
||||
if(_PCH_FORCEINCLUDE)
|
||||
list(APPEND _pch_compile_flags -include "${_pchfile}")
|
||||
else(_PCH_FORCEINCLUDE)
|
||||
list(APPEND _pch_compile_flags "-I${_pch_binary_dir}")
|
||||
endif(_PCH_FORCEINCLUDE)
|
||||
|
||||
get_source_file_property(_object_depends "${_source}" OBJECT_DEPENDS)
|
||||
if(NOT _object_depends)
|
||||
set(_object_depends)
|
||||
endif()
|
||||
list(APPEND _object_depends "${_pchfile}")
|
||||
if(_source MATCHES \\.\(cc|cxx|cpp\)$)
|
||||
list(APPEND _object_depends "${_output_cxx}")
|
||||
else()
|
||||
list(APPEND _object_depends "${_output_c}")
|
||||
endif()
|
||||
|
||||
combine_arguments(_pch_compile_flags)
|
||||
message("${_source}" ${_pch_compile_flags})
|
||||
set_source_files_properties(${_source} PROPERTIES
|
||||
COMPILE_FLAGS "${_pch_compile_flags}"
|
||||
OBJECT_DEPENDS "${_object_depends}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
endfunction()
|
|
@ -0,0 +1,50 @@
|
|||
#pragma once
|
||||
|
||||
#define MOO_PACKAGE_NAME "@MOO_PACKAGE_NAME@"
|
||||
|
||||
#define MOO_WEBSITE "@MOO_WEBSITE@"
|
||||
#define MOO_WEB_CONTACT "@MOO_WEB_CONTACT@"
|
||||
#define MOO_EMAIL "@MOO_EMAIL@"
|
||||
#define MOO_COPYRIGHT "@MOO_COPYRIGHT@"
|
||||
#define PACKAGE_BUGREPORT "@MOO_EMAIL@"
|
||||
|
||||
#define GETTEXT_PACKAGE "@GETTEXT_PACKAGE@"
|
||||
|
||||
#define MOO_PREFS_XML_FILE_NAME "@MOO_PREFS_XML_FILE_NAME@"
|
||||
#define MOO_STATE_XML_FILE_NAME "@MOO_STATE_XML_FILE_NAME@"
|
||||
#define MOO_NAMED_SESSION_XML_FILE_NAME "@MOO_NAMED_SESSION_XML_FILE_NAME@"
|
||||
#define MOO_SESSION_XML_FILE_NAME "@MOO_SESSION_XML_FILE_NAME@"
|
||||
|
||||
#define MEDIT_PORTABLE_DATA_DIR "@MEDIT_PORTABLE_DATA_DIR@"
|
||||
#define MEDIT_PORTABLE_CACHE_DIR "@MEDIT_PORTABLE_CACHE_DIR@"
|
||||
#define MEDIT_PORTABLE_MAGIC_FILE_NAME "@MEDIT_PORTABLE_MAGIC_FILE_NAME@"
|
||||
|
||||
#define MOO_VERSION "@MOO_VERSION@"
|
||||
#define MOO_DISPLAY_VERSION "@MOO_DISPLAY_VERSION@"
|
||||
#define MOO_MAJOR_VERSION @MOO_MAJOR_VERSION@
|
||||
#define MOO_MICRO_VERSION @MOO_MICRO_VERSION@
|
||||
#define MOO_MINOR_VERSION @MOO_MINOR_VERSION@
|
||||
#define MOO_MODULE_MAJOR_VERSION @MOO_MODULE_MAJOR_VERSION@
|
||||
#define MOO_MODULE_MINOR_VERSION @MOO_MODULE_MINOR_VERSION@
|
||||
|
||||
#cmakedefine MOO_BUILD_FROM_MINGW 1
|
||||
#cmakedefine MOO_BUILD_FROM_MSVC 1
|
||||
|
||||
#cmakedefine MOO_BUILD_CTAGS 1
|
||||
#cmakedefine MOO_ENABLE_COVERAGE 1
|
||||
#cmakedefine MOO_ENABLE_PYTHON 1
|
||||
#cmakedefine MOO_BROKEN_GTK_THEME 1
|
||||
#cmakedefine MOO_NEED_GETTIMEOFDAY 1
|
||||
|
||||
#cmakedefine ENABLE_NLS 1
|
||||
#cmakedefine HAVE_BIND_TEXTDOMAIN_CODESET 1
|
||||
#cmakedefine HAVE_GETC_UNLOCKED 1
|
||||
#cmakedefine HAVE_MMAP 1
|
||||
#cmakedefine HAVE_UNISTD_H 1
|
||||
#cmakedefine HAVE_SYS_UTSNAME_H 1
|
||||
#cmakedefine HAVE_SIGNAL_H 1
|
||||
#cmakedefine HAVE_SYS_WAIT_H 1
|
||||
|
||||
#define MOO_CONFIG_H_INCLUDED 1
|
||||
|
||||
#include <moo-config.h>
|
|
@ -0,0 +1,235 @@
|
|||
m4_define([_moo_major_version_],[1])
|
||||
m4_define([_moo_minor_version_],[2])
|
||||
m4_define([_moo_micro_version_],[90])
|
||||
m4_define([_moo_version_suffix_],[devel])
|
||||
m4_define([_moo_module_major_version_],[2])
|
||||
m4_define([_moo_module_minor_version_],[0])
|
||||
m4_define([_moo_version_],[_moo_major_version_._moo_minor_version_._moo_micro_version_])
|
||||
|
||||
m4_if(_moo_version_suffix_,[],
|
||||
[m4_define([_moo_display_version_],[_moo_version_])],
|
||||
[m4_define([_moo_display_version_],[_moo_version_-_moo_version_suffix_])])
|
||||
|
||||
m4_define([_moo_website_],[http://mooedit.sourceforge.net/])
|
||||
m4_define([_moo_web_contact_],[http://mooedit.sourceforge.net/contact.html])
|
||||
m4_define([_moo_email_],[emuntyan@users.sourceforge.net])
|
||||
m4_define([_moo_copyright_],[2004-2014 Yevgen Muntyan <_moo_email_>])
|
||||
|
||||
AC_PREREQ([2.68])
|
||||
AC_INIT([medit],[_moo_display_version_],[_moo_email_])
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_SUBST(ACLOCAL_FLAGS)
|
||||
|
||||
AM_INIT_AUTOMAKE([1.11 foreign dist-bzip2 no-dist-gzip subdir-objects])
|
||||
AM_SILENT_RULES([yes])
|
||||
LT_INIT([disable-shared])
|
||||
# AC_PROG_RANLIB
|
||||
|
||||
AC_SUBST(MOO_MAJOR_VERSION,_moo_major_version_)
|
||||
AC_SUBST(MOO_MINOR_VERSION,_moo_minor_version_)
|
||||
AC_SUBST(MOO_MICRO_VERSION,_moo_micro_version_)
|
||||
AC_SUBST(MOO_MODULE_MAJOR_VERSION,_moo_module_major_version_)
|
||||
AC_SUBST(MOO_MODULE_MINOR_VERSION,_moo_module_minor_version_)
|
||||
AC_SUBST(MOO_VERSION,_moo_version_)
|
||||
AC_SUBST(MOO_DISPLAY_VERSION,"_moo_display_version_")
|
||||
AC_SUBST(MOO_EMAIL,"_moo_email_")
|
||||
AC_SUBST(MOO_WEBSITE,"_moo_website_")
|
||||
AC_SUBST(MOO_WEB_CONTACT,"_moo_web_contact_")
|
||||
AC_SUBST(MOO_COPYRIGHT,"_moo_copyright_")
|
||||
|
||||
# keep in sync with po/maintain
|
||||
AC_SUBST(MOO_PACKAGE_NAME,"medit-1")
|
||||
|
||||
MOO_PREFS_XML_FILE_NAME="prefs.xml"
|
||||
MOO_STATE_XML_FILE_NAME="state.xml"
|
||||
MOO_NAMED_SESSION_XML_FILE_NAME="session-%s.xml"
|
||||
MOO_SESSION_XML_FILE_NAME="session.xml"
|
||||
MEDIT_PORTABLE_MAGIC_FILE_NAME="medit-portable"
|
||||
MEDIT_PORTABLE_DATA_DIR="medit-portable-data"
|
||||
MEDIT_PORTABLE_CACHE_DIR="medit-portable-cache"
|
||||
AC_SUBST(MEDIT_PORTABLE_MAGIC_FILE_NAME,$MEDIT_PORTABLE_MAGIC_FILE_NAME)
|
||||
|
||||
AC_SUBST(GETTEXT_PACKAGE,$MOO_PACKAGE_NAME)
|
||||
AC_SUBST(GETTEXT_PACKAGE_GSV,"$MOO_PACKAGE_NAME-gsv")
|
||||
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[GETTEXT_PACKAGE])
|
||||
MOO_INTL
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_MKDIR_P
|
||||
AM_PROG_CC_C_O
|
||||
|
||||
AC_ARG_VAR([WINDRES], [windres])
|
||||
AC_CHECK_TOOL(WINDRES, windres, :)
|
||||
|
||||
AC_ARG_VAR([MOO_PYTHON], [Python executable, required to run build scripts])
|
||||
AC_CHECK_PROGS(MOO_PYTHON, [python2 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 python], [none])
|
||||
if test "x$MOO_PYTHON" = "x"; then
|
||||
AC_MSG_ERROR([Python not found, it is required for the build])
|
||||
fi
|
||||
|
||||
MOO_AC_FLAGS
|
||||
|
||||
AM_MAINTAINER_MODE([enable])
|
||||
|
||||
AC_CHECK_PROG([TXT2TAGS], txt2tags, txt2tags)
|
||||
if test x$MOO_DEV_MODE = "xyes" -a "x$TXT2TAGS" = "x"; then
|
||||
AC_MSG_ERROR([txt2tags not found])
|
||||
fi
|
||||
|
||||
AC_CHECK_PROG([XSLTPROC], xsltproc, xsltproc)
|
||||
if test x$MOO_DEV_MODE = "xyes" -a "x$XSLTPROC" = "x"; then
|
||||
AC_MSG_ERROR([xsltproc not found])
|
||||
fi
|
||||
|
||||
AC_DEFINE_UNQUOTED(MOO_CONFIG_H_INCLUDED, 1, MOO_CONFIG_H_INCLUDED)
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AH_TOP([#ifndef __CONFIG_H__
|
||||
#define __CONFIG_H__])
|
||||
AH_BOTTOM([#include <moo-config.h>
|
||||
#endif // __CONFIG_H__])
|
||||
|
||||
MOO_LT_LIB_M
|
||||
|
||||
AC_DEFINE_UNQUOTED(MOO_VERSION,["$MOO_VERSION"],[MOO_VERSION])
|
||||
AC_DEFINE_UNQUOTED(MOO_DISPLAY_VERSION,["$MOO_DISPLAY_VERSION"],[MOO_DISPLAY_VERSION])
|
||||
AC_DEFINE_UNQUOTED(MOO_MAJOR_VERSION,[$MOO_MAJOR_VERSION],[MOO_MAJOR_VERSION])
|
||||
AC_DEFINE_UNQUOTED(MOO_MICRO_VERSION,[$MOO_MICRO_VERSION],[MOO_MICRO_VERSION])
|
||||
AC_DEFINE_UNQUOTED(MOO_MINOR_VERSION,[$MOO_MINOR_VERSION],[MOO_MINOR_VERSION])
|
||||
AC_DEFINE_UNQUOTED(MOO_MODULE_MAJOR_VERSION,[$MOO_MODULE_MAJOR_VERSION],[MOO_MODULE_MAJOR_VERSION])
|
||||
AC_DEFINE_UNQUOTED(MOO_MODULE_MINOR_VERSION,[$MOO_MODULE_MINOR_VERSION],[MOO_MODULE_MINOR_VERSION])
|
||||
|
||||
AC_DEFINE_UNQUOTED(MOO_EMAIL,["$MOO_EMAIL"],MOO_EMAIL)
|
||||
AC_DEFINE_UNQUOTED(PACKAGE_BUGREPORT,["$PACKAGE_BUGREPORT"],PACKAGE_BUGREPORT)
|
||||
AC_DEFINE_UNQUOTED(MOO_COPYRIGHT,["$MOO_COPYRIGHT"],MOO_COPYRIGHT)
|
||||
AC_DEFINE_UNQUOTED(MOO_WEBSITE,["$MOO_WEBSITE"],MOO_WEBSITE)
|
||||
AC_DEFINE_UNQUOTED(MOO_WEB_CONTACT,["$MOO_WEB_CONTACT"],MOO_WEB_CONTACT)
|
||||
|
||||
MOO_AC_CHECK_OS
|
||||
MOO_AC_PYTHON
|
||||
|
||||
MOO_BUILD_APP=true
|
||||
MOO_BUILD_MODULE=false
|
||||
AC_ARG_ENABLE(moo-module,
|
||||
AS_HELP_STRING([--enable-moo-module],[build standalone python module instead of medit, default NO (you must also use --enable-shared with this option)]),[
|
||||
if test "$enable_moo_module" = "yes"; then
|
||||
MOO_BUILD_APP=false
|
||||
MOO_BUILD_MODULE=true
|
||||
fi
|
||||
])
|
||||
if $MOO_BUILD_MODULE; then
|
||||
if ! $MOO_ENABLE_PYTHON; then
|
||||
AC_MSG_ERROR([Python bindings are not enabled, can't build python module])
|
||||
elif test "$enable_shared" != "yes"; then
|
||||
AC_MSG_ERROR([Python module can't be built without --enable-shared option])
|
||||
fi
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(MOO_BUILD_APP, [$MOO_BUILD_APP])
|
||||
AM_CONDITIONAL(MOO_BUILD_MODULE, [$MOO_BUILD_MODULE])
|
||||
|
||||
AC_SUBST(MOO_TOP_SRCDIR,`cd $srcdir && pwd`)
|
||||
if test x"$MOO_TOP_SRCDIR" = x"`pwd`"; then
|
||||
AC_SUBST(MOO_CP_TO_SRCDIR,true)
|
||||
AC_SUBST(MOO_MV_TO_SRCDIR,true)
|
||||
else
|
||||
AC_SUBST(MOO_CP_TO_SRCDIR,cp)
|
||||
AC_SUBST(MOO_MV_TO_SRCDIR,mv)
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(MOO_BUILD_CTAGS, [$MOO_OS_UNIX])
|
||||
if $MOO_OS_UNIX; then
|
||||
AC_DEFINE(MOO_BUILD_CTAGS, 1, [build ctags plugin])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(coverage,
|
||||
AS_HELP_STRING([--enable-coverage],[check test coverage]),[
|
||||
MOO_ENABLE_COVERAGE="$enable_coverage"
|
||||
],[
|
||||
MOO_ENABLE_COVERAGE="no"
|
||||
])
|
||||
AM_CONDITIONAL(MOO_ENABLE_COVERAGE, test "x$MOO_ENABLE_COVERAGE" = "xyes")
|
||||
if test "x$MOO_ENABLE_COVERAGE" = "xyes"; then
|
||||
AC_DEFINE(MOO_ENABLE_COVERAGE, 1, [enable code coverage testing])
|
||||
fi
|
||||
|
||||
if $MOO_OS_WIN32; then
|
||||
_moo_cygwin=false
|
||||
if test "$OSTYPE" = "cygwin"; then
|
||||
_moo_cygwin=true
|
||||
fi
|
||||
|
||||
if $_moo_cygwin; then
|
||||
MEDIT_INNO_COMPILER='"/cygdrive/c/Program Files (x86)/Inno Setup 5/ISCC.exe"'
|
||||
elif test -d $HOME/.wine/drive_c/windows/syswow64 -o -d "/cygdrive/c/Program Files (x86)"; then
|
||||
MEDIT_INNO_COMPILER='wine "c:\\program files (x86)\\inno setup 5\\ISCC.exe"'
|
||||
else
|
||||
MEDIT_INNO_COMPILER='wine "c:\\program files\\inno setup 5\\ISCC.exe"'
|
||||
fi
|
||||
AC_MSG_CHECKING([Inno compiler])
|
||||
AC_MSG_RESULT([$MEDIT_INNO_COMPILER])
|
||||
|
||||
_moo_win32_config=release
|
||||
if test "$MOO_DEBUG_ENABLED" = "yes"; then
|
||||
_moo_win32_config="debug"
|
||||
fi
|
||||
if test -n "$mgwconfig"; then
|
||||
_moo_win32_config="$mgwconfig"
|
||||
fi
|
||||
AC_ARG_VAR([MOO_WIN32_CONFIG], [$_moo_win32_config])
|
||||
AC_MSG_CHECKING([Win32 build configuration])
|
||||
AC_MSG_RESULT([$MOO_WIN32_CONFIG])
|
||||
|
||||
AC_SUBST(MEDIT_WIN32_APP_UID,"7F9F899F-EE8A-47F0-9981-8C525AF78E4D")
|
||||
|
||||
if $_moo_cygwin; then
|
||||
AC_SUBST(MEDIT_INNO_TOP_SRCDIR,"`cygpath -m $MOO_TOP_SRCDIR`")
|
||||
_moo_this_dir=`pwd`
|
||||
AC_SUBST(MEDIT_INNO_TOP_BUILDDIR,"`cygpath -m $_moo_this_dir`")
|
||||
AC_SUBST(MEDIT_INNO_INSTDIR,"`cygpath -m $prefix`")
|
||||
else
|
||||
AC_SUBST(MEDIT_INNO_TOP_SRCDIR,"Z:$MOO_TOP_SRCDIR")
|
||||
AC_SUBST(MEDIT_INNO_TOP_BUILDDIR,"Z:`pwd`")
|
||||
AC_SUBST(MEDIT_INNO_INSTDIR,"Z:`cd $prefix && pwd`")
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([MEDIT_INNO_TOP_SRCDIR])
|
||||
AC_MSG_RESULT([$MEDIT_INNO_TOP_SRCDIR])
|
||||
AC_MSG_CHECKING([MEDIT_INNO_TOP_BUILDDIR])
|
||||
AC_MSG_RESULT([$MEDIT_INNO_TOP_BUILDDIR])
|
||||
AC_MSG_CHECKING([MEDIT_INNO_INSTDIR])
|
||||
AC_MSG_RESULT([$MEDIT_INNO_INSTDIR])
|
||||
|
||||
AC_SUBST(MEDIT_INNO_COMPILER)
|
||||
MEDIT_INNO_INSTALLER_SUFFIX=""
|
||||
if test -n "$MOO_WIN32_CONFIG" -a "$MOO_WIN32_CONFIG" != "release"; then
|
||||
MEDIT_INNO_INSTALLER_SUFFIX="-$MOO_WIN32_CONFIG"
|
||||
fi
|
||||
AC_SUBST(MEDIT_SETUP_NAME, "medit-$MOO_DISPLAY_VERSION$MEDIT_INNO_INSTALLER_SUFFIX")
|
||||
AC_MSG_CHECKING([Win32 setup name])
|
||||
AC_MSG_RESULT([$MEDIT_SETUP_NAME])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(install-hooks,
|
||||
AS_HELP_STRING([--enable-install-hooks],[run gtk-update-icon-cache during 'make install']),[
|
||||
MOO_ENABLE_INSTALL_HOOKS="$enable_install_hooks"
|
||||
],[
|
||||
if $MOO_BUILD_APP; then
|
||||
MOO_ENABLE_INSTALL_HOOKS="yes"
|
||||
else
|
||||
MOO_ENABLE_INSTALL_HOOKS="no"
|
||||
fi
|
||||
])
|
||||
AM_CONDITIONAL(MOO_ENABLE_INSTALL_HOOKS, test "x$MOO_ENABLE_INSTALL_HOOKS" = "xyes")
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
api/Makefile
|
||||
doc/Makefile
|
||||
moo/Makefile
|
||||
po/Makefile
|
||||
po-gsv/Makefile
|
||||
])
|
||||
AC_OUTPUT
|
|
@ -0,0 +1,153 @@
|
|||
BUILT_SOURCES =
|
||||
|
||||
if MOO_DEV_MODE
|
||||
|
||||
$(srcdir)/built/medit-defines.ent: medit-defines.ent.in $(top_builddir)/config.status
|
||||
$(AM_V_GEN)cd $(top_builddir) && ./config.status --silent --file=doc/medit-defines.ent
|
||||
$(AM_V_at)$(MKDIR_P) $(srcdir)/built
|
||||
$(AM_V_at)mv medit-defines.ent $(srcdir)/built/
|
||||
|
||||
gendocbook_files = \
|
||||
$(top_srcdir)/api/gendocbook.py \
|
||||
$(top_srcdir)/api/mpi/__init__.py \
|
||||
$(top_srcdir)/api/mpi/module.py \
|
||||
$(top_srcdir)/api/mpi/docbookwriter.py
|
||||
|
||||
script_docbook_sources = \
|
||||
built/medit-defines.ent \
|
||||
built/script-python.docbook \
|
||||
built/script-lua.docbook \
|
||||
built/script-lua-gtk.docbook
|
||||
|
||||
$(srcdir)/built/script-python.docbook: $(gendocbook_files) script-python.tmpl.docbook $(top_srcdir)/api/moo.xml
|
||||
$(AM_V_at)$(MKDIR_P) $(srcdir)/built
|
||||
$(AM_V_GEN)$(MOO_PYTHON) $(top_srcdir)/api/gendocbook.py \
|
||||
--python --template $(srcdir)/script-python.tmpl.docbook \
|
||||
$(top_srcdir)/api/moo.xml > script-python.docbook.tmp && \
|
||||
mv script-python.docbook.tmp $(srcdir)/built/script-python.docbook
|
||||
|
||||
$(srcdir)/built/script-lua.docbook: $(gendocbook_files) script-lua.tmpl.docbook $(top_srcdir)/api/moo.xml $(top_srcdir)/api/gtk.xml
|
||||
$(AM_V_at)$(MKDIR_P) $(srcdir)/built
|
||||
$(AM_V_GEN)$(MOO_PYTHON) $(top_srcdir)/api/gendocbook.py \
|
||||
--lua --template $(srcdir)/script-lua.tmpl.docbook \
|
||||
--import $(top_srcdir)/api/gtk.xml \
|
||||
$(top_srcdir)/api/moo.xml > script-lua.docbook.tmp && \
|
||||
mv script-lua.docbook.tmp $(srcdir)/built/script-lua.docbook
|
||||
|
||||
$(srcdir)/built/script-lua-gtk.docbook: $(gendocbook_files) script-lua-gtk.tmpl.docbook $(top_srcdir)/api/gtk.xml
|
||||
$(AM_V_at)$(MKDIR_P) $(srcdir)/built
|
||||
$(AM_V_GEN)$(MOO_PYTHON) $(top_srcdir)/api/gendocbook.py \
|
||||
--lua --template $(srcdir)/script-lua-gtk.tmpl.docbook \
|
||||
$(top_srcdir)/api/gtk.xml > script-lua-gtk.docbook.tmp && \
|
||||
mv script-lua-gtk.docbook.tmp $(srcdir)/built/script-lua-gtk.docbook
|
||||
|
||||
# $(srcdir)/help/script-python.html: built/script-python.docbook built/medit-defines.ent script.xsl
|
||||
# $(AM_V_at)$(MKDIR_P) $(srcdir)/help/
|
||||
# $(AM_V_GEN)$(XSLTPROC) --output script-python.html.tmp \
|
||||
# $(srcdir)/script.xsl $(srcdir)/built/script-python.docbook \
|
||||
# && mv script-python.html.tmp $(srcdir)/help/script-python.html
|
||||
#
|
||||
# $(srcdir)/help/script-lua.html: built/script-lua.docbook built/medit-defines.ent script.xsl
|
||||
# $(AM_V_at)$(MKDIR_P) $(srcdir)/help/
|
||||
# $(AM_V_GEN)$(XSLTPROC) --output script-lua.html.tmp \
|
||||
# $(srcdir)/script.xsl $(srcdir)/built/script-lua.docbook \
|
||||
# && mv script-lua.html.tmp $(srcdir)/help/script-lua.html
|
||||
#
|
||||
# $(srcdir)/help/script-lua-gtk.html: built/script-lua-gtk.docbook built/medit-defines.ent script.xsl
|
||||
# $(AM_V_at)$(MKDIR_P) $(srcdir)/help/
|
||||
# $(AM_V_GEN)$(XSLTPROC) --output script-lua-gtk.html.tmp \
|
||||
# $(srcdir)/script.xsl $(srcdir)/built/script-lua-gtk.docbook \
|
||||
# && mv script-lua-gtk.html.tmp $(srcdir)/help/script-lua-gtk.html
|
||||
|
||||
$(srcdir)/help/script/index.html: $(script_docbook_sources) script-book.xsl
|
||||
$(AM_V_GEN)cd $(srcdir) && $(XSLTPROC) --xinclude script-book.xsl script.docbook
|
||||
|
||||
$(srcdir)/help/medit.css: medit.css
|
||||
$(AM_V_at)$(MKDIR_P) $(srcdir)/help/
|
||||
$(AM_V_GEN)cp $(srcdir)/medit.css $(srcdir)/help/
|
||||
|
||||
$(srcdir)/built/lgpl.no-fancy-chars: $(top_srcdir)/COPYING
|
||||
$(AM_V_at)$(MKDIR_P) $(srcdir)/built
|
||||
tr -d '\014' < $(top_srcdir)/COPYING > lgpl.no-fancy-chars.tmp && \
|
||||
mv lgpl.no-fancy-chars.tmp $(srcdir)/built/lgpl.no-fancy-chars
|
||||
|
||||
docbook_files = \
|
||||
medit.docbook \
|
||||
prefs.docbook \
|
||||
regex.docbook \
|
||||
user-tools.docbook \
|
||||
license.docbook
|
||||
|
||||
docbook_sources = \
|
||||
$(docbook_files) \
|
||||
built/lgpl.no-fancy-chars \
|
||||
built/medit-defines.ent
|
||||
|
||||
$(srcdir)/help/index.html: $(docbook_sources) medit.xsl medit-common.xsl
|
||||
$(AM_V_GEN)cd $(srcdir) && $(XSLTPROC) --xinclude medit.xsl medit.docbook
|
||||
|
||||
$(srcdir)/help/help.html: $(docbook_sources) medit-single.xsl medit-common.xsl
|
||||
$(AM_V_at)$(MKDIR_P) $(srcdir)/help/
|
||||
$(AM_V_GEN)$(XSLTPROC) --xinclude --output help.html.tmp $(srcdir)/medit-single.xsl $(srcdir)/medit.docbook && \
|
||||
mv help.html.tmp $(srcdir)/help/help.html
|
||||
|
||||
toc.xml: $(docbook_sources)
|
||||
$(AM_V_GEN)$(XSLTPROC) --output toc.xml --xinclude \
|
||||
--stringparam chunk.first.sections 1 \
|
||||
http://docbook.sourceforge.net/release/xsl/current/html/maketoc.xsl $(srcdir)/medit.docbook
|
||||
|
||||
moo-help-sections.h.stamp: $(docbook_files) toc.xml genhelpsectionsh.py
|
||||
$(AM_V_at)$(MKDIR_P) $(srcdir)/built
|
||||
$(AM_V_GEN)$(MOO_PYTHON) $(srcdir)/genhelpsectionsh.py --toc=toc.xml --srcdir=$(srcdir) $(docbook_files) > moo-help-sections.h.tmp
|
||||
$(AM_V_at)cmp -s moo-help-sections.h.tmp $(srcdir)/built/moo-help-sections.h || \
|
||||
mv moo-help-sections.h.tmp $(srcdir)/built/moo-help-sections.h
|
||||
$(AM_V_at)rm -f moo-help-sections.h.tmp
|
||||
$(AM_V_at)echo stamp > moo-help-sections.h.stamp
|
||||
|
||||
png_files = prefs-file-filters.png prefs-file-selector.png
|
||||
dest_png_files = $(addprefix $(srcdir)/help/img/,$(png_files))
|
||||
|
||||
$(srcdir)/help/img/%.png: img/%.png
|
||||
$(AM_V_at)$(MKDIR_P) $(srcdir)/help/img/
|
||||
$(AM_V_GEN)cp $(srcdir)/img/$*.png $(srcdir)/help/img/
|
||||
|
||||
all-am: doc
|
||||
doc: \
|
||||
$(srcdir)/help/index.html \
|
||||
$(srcdir)/help/help.html \
|
||||
$(srcdir)/help/script/index.html \
|
||||
$(srcdir)/help/medit.css \
|
||||
$(srcdir)/built/medit.1 \
|
||||
$(dest_png_files) \
|
||||
moo-help-sections.h.stamp
|
||||
|
||||
$(srcdir)/built/man-medit.t2t: man-medit.t2t.in $(top_builddir)/config.status
|
||||
$(AM_V_at)$(MKDIR_P) $(srcdir)/built
|
||||
$(AM_V_GEN)cd $(top_builddir) && ./config.status --silent --file=doc/man-medit.t2t
|
||||
$(AM_V_at)mv man-medit.t2t $(srcdir)/built/man-medit.t2t
|
||||
|
||||
$(srcdir)/built/medit.1: built/man-medit.t2t
|
||||
$(AM_V_GEN)$(TXT2TAGS) --target=man --outfile=- $(srcdir)/built/man-medit.t2t | grep -v "cmdline: txt2tags" \
|
||||
> medit.1.tmp && mv medit.1.tmp $(srcdir)/built/medit.1
|
||||
|
||||
endif
|
||||
|
||||
EXTRA_DIST = help built/moo-help-sections.h built/medit.1
|
||||
|
||||
install-data-local:
|
||||
$(MKDIR_P) $(DESTDIR)$(MOO_HELP_DIR)/img $(DESTDIR)$(MOO_HELP_DIR)/script
|
||||
cd $(srcdir) && $(INSTALL_DATA) help/*.html help/*.css $(DESTDIR)$(MOO_HELP_DIR)
|
||||
cd $(srcdir) && $(INSTALL_DATA) help/script/*.html $(DESTDIR)$(MOO_HELP_DIR)/script
|
||||
cd $(srcdir) && $(INSTALL_DATA) help/img/*.png $(DESTDIR)$(MOO_HELP_DIR)/img
|
||||
|
||||
uninstall-local:
|
||||
rm -f $(DESTDIR)$(MOO_HELP_DIR)/*.html \
|
||||
$(DESTDIR)$(MOO_HELP_DIR)/*.css \
|
||||
$(DESTDIR)$(MOO_HELP_DIR)/script/*.html \
|
||||
$(DESTDIR)$(MOO_HELP_DIR)/img/*.png
|
||||
|
||||
if MOO_OS_UNIX
|
||||
if MOO_BUILD_APP
|
||||
dist_man_MANS = built/medit.1
|
||||
endif MOO_BUILD_APP
|
||||
endif MOO_OS_UNIX
|
|
@ -0,0 +1,71 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import optparse
|
||||
|
||||
op = optparse.OptionParser()
|
||||
op.add_option("--toc", action="store")
|
||||
op.add_option("--srcdir", action="store")
|
||||
(opts, args) = op.parse_args()
|
||||
|
||||
srcdir = opts.srcdir or '.'
|
||||
|
||||
def resolve_filename(filename):
|
||||
if os.path.exists(filename):
|
||||
return filename
|
||||
fullname = os.path.join(srcdir, filename)
|
||||
if os.path.exists(fullname):
|
||||
return fullname
|
||||
raise RuntimeError('could not find file %s' % filename)
|
||||
|
||||
def parse_toc(filename):
|
||||
filename = resolve_filename(filename)
|
||||
dic = {}
|
||||
for line in open(filename):
|
||||
m = re.search(r'<tocentry linkend="([\w\d_.-]+)"><\?dbhtml filename="([\w\d_.-]+)"\?>', line)
|
||||
if m:
|
||||
dic[m.group(1)] = m.group(2)
|
||||
return dic
|
||||
|
||||
def parse_docbook(filename):
|
||||
filename = resolve_filename(filename)
|
||||
dic = {}
|
||||
for line in open(filename):
|
||||
m = re.search(r'id\s*=\s*"([\w\d_.-]+)"\s+moo.helpsection\s*=\s*"([\w\d_.-]+)"', line)
|
||||
if m:
|
||||
dic[m.group(2)] = m.group(1)
|
||||
else:
|
||||
m = re.search(r'moo.helpsection\s*=\s*"([\w\d_.-]+)"\s+id\s*=\s*"([\w\d_.-]+)"', line)
|
||||
if m:
|
||||
dic[m.group(1)] = m.group(2)
|
||||
return dic
|
||||
|
||||
map_id_to_html = parse_toc(opts.toc)
|
||||
map_hsection_to_id = {}
|
||||
for f in args:
|
||||
map_hsection_to_id.update(parse_docbook(f))
|
||||
|
||||
map_hsection_to_html = {
|
||||
'PREFS_ACCELS': 'index.html',
|
||||
'DIALOG_REPLACE': 'index.html',
|
||||
'DIALOG_FIND': 'index.html',
|
||||
'FILE_SELECTOR': 'index.html',
|
||||
'DIALOG_FIND_FILE': 'index.html',
|
||||
'DIALOG_FIND_IN_FILES': 'index.html',
|
||||
}
|
||||
|
||||
for section in map_hsection_to_id:
|
||||
map_hsection_to_html[section] = os.path.basename(map_id_to_html[map_hsection_to_id[section]])
|
||||
|
||||
map_hsection_to_html['PREFS_PLUGINS'] = map_hsection_to_html['PREFS_DIALOG']
|
||||
map_hsection_to_html['PREFS_VIEW'] = map_hsection_to_html['PREFS_DIALOG']
|
||||
|
||||
print '#ifndef MOO_HELP_SECTIONS_H'
|
||||
print '#define MOO_HELP_SECTIONS_H'
|
||||
print ''
|
||||
for section in sorted(map_hsection_to_html.keys()):
|
||||
print '#define HELP_SECTION_%s "%s"' % (section, map_hsection_to_html[section])
|
||||
print ''
|
||||
print '#endif /* MOO_HELP_SECTIONS_H */'
|
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
|
@ -0,0 +1,87 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE chapter [
|
||||
<!ENTITY % medit-defines SYSTEM "built/medit-defines.ent">
|
||||
%medit-defines;
|
||||
]>
|
||||
<chapter id="chapter-license" moo.helpsection="APP_LICENSE">
|
||||
<title>License</title>
|
||||
|
||||
<para>
|
||||
&medit; as a whole is distributed under the terms of the GNU General
|
||||
Public License, version 2, but most of its code is released under the
|
||||
GNU Lesser General Public License. Full text of these licenses, as well
|
||||
as licenses and acknowledgements for third-party software incorporated
|
||||
in &medit;, can be found in this section.
|
||||
</para>
|
||||
|
||||
|
||||
<sect1 id="section-license-gpl">
|
||||
<title>GNU General Public License</title>
|
||||
<literallayout>
|
||||
<xi:include href="../COPYING.GPL" parse="text" xmlns:xi="http://www.w3.org/2001/XInclude"/>
|
||||
</literallayout>
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="section-license-lgpl">
|
||||
<title>GNU Lesser General Public License</title>
|
||||
<literallayout>
|
||||
<xi:include href="built/lgpl.no-fancy-chars" parse="text" xmlns:xi="http://www.w3.org/2001/XInclude"/>
|
||||
</literallayout>
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="section-license-lua">
|
||||
<title>Lua License</title>
|
||||
<literallayout>
|
||||
<xi:include href="../moo/moolua/lua/COPYRIGHT" parse="text" xmlns:xi="http://www.w3.org/2001/XInclude"/>
|
||||
</literallayout>
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="section-license-lfs">
|
||||
<title>LuaFileSystem License</title>
|
||||
<literallayout>
|
||||
LuaFileSystem - File System Library for Lua
|
||||
Copyright 2003-2007 PUC-Rio
|
||||
http://www.keplerproject.org/luafilesystem
|
||||
|
||||
LuaFileSystem is a Lua library developed to complement the set of functions
|
||||
related to file systems offered by the standard Lua distribution. LuaFileSystem
|
||||
offers a portable way to access the underlying directory structure and file
|
||||
attributes. LuaFileSystem is free software and uses the same license as Lua 5.1
|
||||
Current version is 1.2.1.
|
||||
</literallayout>
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="section-license-xdg-utils">
|
||||
<title>xdg-utils License</title>
|
||||
<literallayout>
|
||||
Copyright 2006, Kevin Krammer <kevin.krammer@gmx.at>
|
||||
Copyright 2006, Jeremy White <jwhite@codeweavers.com>
|
||||
|
||||
LICENSE:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
</literallayout>
|
||||
</sect1>
|
||||
|
||||
|
||||
</chapter>
|
|
@ -0,0 +1,99 @@
|
|||
MEDIT
|
||||
|
||||
September 2010
|
||||
|
||||
%!encoding: UTF-8
|
||||
|
||||
= NAME =
|
||||
|
||||
medit - text editor
|
||||
|
||||
|
||||
= SYNOPSIS =
|
||||
|
||||
**medit** [//OPTION//]... [//FILES//]
|
||||
|
||||
|
||||
= DESCRIPTION =
|
||||
|
||||
**medit** is a text editor.
|
||||
|
||||
|
||||
= OPTIONS =
|
||||
|
||||
: **-n**, **--new-app**
|
||||
run new instance of **medit**. By default **medit** opens //FILES//
|
||||
(or creates a new document if none are given) in an existing instance
|
||||
of application
|
||||
|
||||
: **-s**, **--use-session**[=//yes|no//]
|
||||
load and save session. By default **medit** does it when **-n** is not used.
|
||||
If this option is not given on command line then medit uses the corresponding
|
||||
preferences setting.
|
||||
|
||||
: **--pid** //PID//
|
||||
use existing instance with process id //PID//.
|
||||
|
||||
: **--app-name** //NAME//
|
||||
use instance name //NAME//. If an instance with this name is already running,
|
||||
then it will send files given on the command line to that instance and exit.
|
||||
|
||||
: **-e**, **--encoding** //ENCODING//
|
||||
use provided character encoding to open the file
|
||||
|
||||
: **-l**, **--line** //LINE//
|
||||
open file and position cursor on line //LINE//. Alternatively
|
||||
line number may be specified with filename, e.g.
|
||||
medit foo.txt:12
|
||||
|
||||
: **-r**, **--reload**
|
||||
automatically reload opened file if it was modified on disk by another program.
|
||||
|
||||
: **-w**, **--new-window**
|
||||
open file in a new window.
|
||||
|
||||
: **-t**, **--new-tab**
|
||||
open file in a new tab.
|
||||
|
||||
: **--log-file** //FILE//
|
||||
write debug output into //FILE//. This option is only useful on Windows.
|
||||
|
||||
: **--log-window**
|
||||
show debug output in a log window. This option is only useful on Windows.
|
||||
|
||||
: **--debug** //DOMAINS//
|
||||
enable debug output for //DOMAINS// (if **medit** was compiled with
|
||||
--enable-debug option).
|
||||
|
||||
: **--geometry** //WIDTHxHEIGHT//
|
||||
: **--geometry** //WIDTHxHEIGHT+X+Y//
|
||||
default window size and position.
|
||||
|
||||
: **-h**, **--help**
|
||||
show summary of options.
|
||||
|
||||
: **-v**, **--version**
|
||||
show program version.
|
||||
|
||||
: //FILES//
|
||||
list of files to open. Filenames may include line numbers after colon,
|
||||
e.g. /tmp/file.txt:200. Trailing colon is ignored.
|
||||
|
||||
|
||||
= ENVIRONMENT VARIABLES =
|
||||
|
||||
: MEDIT_PID
|
||||
if set, it is used as --pid argument. When medit spawns a process (e.g. a DVI viewer) it sets
|
||||
MEDIT_PID to its own process id, so the child process may in turn simply use 'medit filename'
|
||||
to open a file (e.g. for inverse DVI search).
|
||||
|
||||
|
||||
= CONTACT =
|
||||
|
||||
@MOO_WEB_CONTACT@
|
||||
|
||||
|
||||
= AUTHOR =
|
||||
|
||||
Written and maintained by Yevgen Muntyan <@MOO_EMAIL@>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version='1.0'?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
|
||||
<xsl:param name="html.stylesheet" select="'medit.css'"/>
|
||||
<xsl:output method="html" indent="yes"/>
|
||||
<xsl:param name="chunker.output.indent" select="'yes'"/>
|
||||
|
||||
</xsl:stylesheet>
|
|
@ -0,0 +1,6 @@
|
|||
<!-- -%- lang:none -%- -->
|
||||
<!ENTITY medit "<application>medit</application>">
|
||||
<!ENTITY medit-version "@MOO_DISPLAY_VERSION@">
|
||||
<!ENTITY medit-user-data-dir-unix "<filename>$HOME/.local/share/medit-1/</filename>">
|
||||
<!ENTITY medit-prefs-xml-unix "<filename>$HOME/.local/share/medit-1/prefs.xml</filename>">
|
||||
<!ENTITY medit-user-tools-dir-unix "<filename>$HOME/.local/share/medit-1/tools/</filename>">
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version='1.0'?>
|
||||
<xsl:stylesheet
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
|
||||
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl"/>
|
||||
|
||||
<xsl:import href="medit-common.xsl"/>
|
||||
|
||||
</xsl:stylesheet>
|
|
@ -0,0 +1,141 @@
|
|||
.variablelist
|
||||
{
|
||||
padding: 4px;
|
||||
margin-left: 3em;
|
||||
}
|
||||
.variablelist td:first-child
|
||||
{
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.programlisting
|
||||
{
|
||||
/* tango:sky blue 0/1 */
|
||||
background: #e6f3ff;
|
||||
/* border: solid 1px #729fcf;*/
|
||||
/* padding: 0.5em;*/
|
||||
font-family: monospace;
|
||||
white-space: pre;
|
||||
/* background: #F4F4F4;*/
|
||||
border: solid 1px #C5C5C5;
|
||||
padding: 0.25em;
|
||||
margin: 0.5em;
|
||||
}
|
||||
|
||||
.code
|
||||
{
|
||||
font-family: monospace;
|
||||
white-space: pre;
|
||||
background: #e6f3ff;
|
||||
/* background: #F4F4F4;*/
|
||||
/* border: solid 1px #C5C5C5;*/
|
||||
padding: 0.1em;
|
||||
/* margin: 0.5em;*/
|
||||
}
|
||||
|
||||
div.table table
|
||||
{
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0px;
|
||||
/* tango:aluminium 3 */
|
||||
border: solid 1px #babdb6;
|
||||
}
|
||||
|
||||
div.table table td, div.table table th
|
||||
{
|
||||
/* tango:aluminium 3 */
|
||||
border: solid 1px #babdb6;
|
||||
padding: 3px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
div.table table th
|
||||
{
|
||||
/* tango:aluminium 2 */
|
||||
background-color: #d3d7cf;
|
||||
}
|
||||
|
||||
hr
|
||||
{
|
||||
/* tango:aluminium 3 */
|
||||
color: #babdb6;
|
||||
background: #babdb6;
|
||||
border: none 0px;
|
||||
height: 1px;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.warning
|
||||
{
|
||||
/* tango:orange 0/1 */
|
||||
background: #ffeed9;
|
||||
border-color: #ffb04f;
|
||||
}
|
||||
.note
|
||||
{
|
||||
/* tango:chameleon 0/0.5 */
|
||||
background: #d8ffb2;
|
||||
border-color: #abf562;
|
||||
}
|
||||
.note, .warning
|
||||
{
|
||||
padding: 0.5em;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
}
|
||||
.note h3, .warning h3
|
||||
{
|
||||
margin-top: 0.0em
|
||||
}
|
||||
/*.note p, .warning p
|
||||
{
|
||||
margin-bottom: 0.0em
|
||||
}*/
|
||||
|
||||
/* blob links */
|
||||
h2 .extralinks, h3 .extralinks
|
||||
{
|
||||
float: right;
|
||||
/* tango:aluminium 3 */
|
||||
color: #babdb6;
|
||||
font-size: 80%;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.annotation
|
||||
{
|
||||
/* tango:aluminium 5 */
|
||||
color: #555753;
|
||||
font-size: 80%;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.listing_frame {
|
||||
/* tango:sky blue 1 */
|
||||
border: solid 1px #729fcf;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.listing_lines, .listing_code {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
padding: 0.5em;
|
||||
}
|
||||
.listing_lines {
|
||||
/* tango:sky blue 0.5 */
|
||||
background: #a6c5e3;
|
||||
/* tango:aluminium 6 */
|
||||
color: #2e3436;
|
||||
}
|
||||
.listing_code {
|
||||
/* tango:sky blue 0 */
|
||||
background: #e6f3ff;
|
||||
}
|
||||
.listing_code .programlisting {
|
||||
/* override from previous */
|
||||
border: none 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
.listing_lines pre, .listing_code pre {
|
||||
margin: 0px;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?><!-- -%- indent-width:1 -%- -->
|
||||
<!DOCTYPE book [
|
||||
<!ENTITY % medit-defines SYSTEM "built/medit-defines.ent">
|
||||
%medit-defines;
|
||||
]>
|
||||
<book id="medit-manual">
|
||||
|
||||
<bookinfo>
|
||||
<title>&medit; manual</title>
|
||||
<date>12/26/2010</date>
|
||||
<releaseinfo>&medit-version;</releaseinfo>
|
||||
</bookinfo>
|
||||
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="prefs.docbook"/>
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="regex.docbook"/>
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="user-tools.docbook"/>
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="license.docbook"/>
|
||||
|
||||
</book>
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version='1.0'?>
|
||||
<xsl:stylesheet
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
|
||||
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/chunk.xsl"/>
|
||||
|
||||
<xsl:import href="medit-common.xsl"/>
|
||||
|
||||
<xsl:param name="base.dir" select="'help/'"/>
|
||||
<xsl:param name="chunk.first.sections" select="'1'"/>
|
||||
|
||||
</xsl:stylesheet>
|
|
@ -0,0 +1,441 @@
|
|||
<?xml version="1.0"?><!-- -%- indent-width:2 -%- -->
|
||||
<!DOCTYPE chapter [
|
||||
<!ENTITY % medit-defines SYSTEM "built/medit-defines.ent">
|
||||
%medit-defines;
|
||||
]>
|
||||
<chapter id="chapter-prefs">
|
||||
<title>Preferences</title>
|
||||
|
||||
<sect1 id="section-prefs-dialog" moo.helpsection="PREFS_DIALOG">
|
||||
<title>Preferences dialog</title>
|
||||
<para>
|
||||
<guilabel>Preferences</guilabel> provides access to almost all &medit; settings.
|
||||
Some settings are not available here, see <xref linkend="section-prefs-xml"/>.
|
||||
</para>
|
||||
<para>
|
||||
<guilabel>Preferences</guilabel> dialog has several tabs:
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><guilabel>General</guilabel></term>
|
||||
<listitem>Contains settings which didn't find place in other sections, see
|
||||
<xref linkend="section-prefs-general"/>.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><guilabel>View</guilabel></term>
|
||||
<listitem>Contains settings which control how &medit; displays text.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><guilabel>File</guilabel></term>
|
||||
<listitem>Contains settings which control how &medit; saves and loads files, see
|
||||
<xref linkend="section-prefs-file"/>.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><guilabel>Languages</guilabel></term>
|
||||
<listitem>See <xref linkend="section-prefs-langs"/>.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><guilabel>File Filters</guilabel></term>
|
||||
<listitem>See <xref linkend="section-prefs-file-filters"/>.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><guilabel>Plugins</guilabel></term>
|
||||
<listitem>Displays information about available plugings and allows to disable/enable them.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><guilabel>File Selector</guilabel></term>
|
||||
<listitem>Contains File Selector settings, see <xref linkend="section-prefs-file-selector"/>.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><guilabel>Tools</guilabel></term>
|
||||
<listitem>User-defined tools, see <xref linkend="section-prefs-user-tools"/>.</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="section-prefs-general" moo.helpsection="PREFS_GENERAL">
|
||||
<title><guilabel>General</guilabel> tab</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><parameter>Smart Home and End</parameter></term>
|
||||
<listitem>If checked, <keycap>Home</keycap> key moves cursor to first non-whitespace character
|
||||
on the line on first <keycap>Home</keycap> key press, and moves cursor to the first character on the line
|
||||
on second key press. Analogously <keycap>End</keycap> key moves cursor past last non-whitespace character
|
||||
on the line, and then past last character on next key press.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Enable auto indentation</parameter></term>
|
||||
<listitem>If checked, pressing <keycap>Enter</keycap> key inserts line end character and
|
||||
whitespace to indent next line according to indentation settings.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Do not use tabs for indentation</parameter></term>
|
||||
<listitem>If checked, spaces are used for indentation instead of tab character.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Tab key indents</parameter></term>
|
||||
<listitem>If checked, <keycap>Tab</keycap> key inserts whitespace characters according
|
||||
to indentation settings to indent text at cursor. Otherwise <keycap>Tab</keycap> key
|
||||
only inserts single tab character.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Tab width</parameter></term>
|
||||
<listitem>Displayed width of tab character in spaces. By default it is
|
||||
<constant>8</constant>.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Indent width</parameter></term>
|
||||
<listitem>Number of spaces inserted by single <keycap>Tab</keycap> key press. If tabs are
|
||||
used for indentation then <keycap>Tab</keycap> key inserts spaces until line indent is
|
||||
multiple of tab width, then it replaces spaces with tabs (if indent width is a multiple
|
||||
of tab width then only tab characters are used.)</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="section-prefs-file" moo.helpsection="PREFS_FILE">
|
||||
<title><guilabel>File</guilabel> tab</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><parameter>Encodings to autodetect</parameter></term>
|
||||
<listitem><para>This entry contains comma-separated list of encodings used when
|
||||
loading files if encoding is not specified in the <guilabel>Open</guilabel>.
|
||||
&medit; tries every encoding from the list one by one and stops when file
|
||||
content is valid text in this encoding. <code>LOCALE</code> denotes encoding
|
||||
from current locale.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Encoding for new files</parameter></term>
|
||||
<listitem><para>This is default encoding to save new files. For every document
|
||||
its encoding on disk can be changed using Encoding submenu of Document menu.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Remove trailing spaces</parameter></term>
|
||||
<listitem><para>If checked, trailing whitespace characters are removed from each
|
||||
line of the document on save.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Ensure trailing newline</parameter></term>
|
||||
<listitem><para>If checked, new line character will be added to document on save
|
||||
if it doesn't end with one.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Make backups</parameter></term>
|
||||
<listitem><para>If checked, old file contents will be moved to backup file on
|
||||
save.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Enable session support</parameter></term>
|
||||
<listitem><para>If checked, &medit; will remember open documents on exit and restore
|
||||
them next time it's launched.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Open and Save As dialogs show current document folder</parameter></term>
|
||||
<listitem><para>If checked, Open and Save As dialogs will show folder of the current document.
|
||||
Otherwise they will show last used folder.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="section-prefs-langs" moo.helpsection="PREFS_LANGS">
|
||||
<title><guilabel>Languages</guilabel> tab</title>
|
||||
<para>
|
||||
<guilabel>Languages and files</guilabel> tab allows customizing
|
||||
how syntax highlighting language and editing options are chosen
|
||||
depending on the document filename, as well as setting editing options for
|
||||
all documents which use given language and choosing file patterns and mime types
|
||||
for which the given language should be used.
|
||||
</para>
|
||||
<para>
|
||||
Here you can set editing options on per-language basis, as well as define
|
||||
for which file patterns and mime types given language should be used.
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><guilabel>Language</guilabel> combo box</term>
|
||||
<listitem><para>
|
||||
Choose the language you want to customize. Settings for <code>None</code> will apply to
|
||||
documents for which no syntax highlighting language was chosen.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><guilabel>Mime types</guilabel></term>
|
||||
<listitem><para>
|
||||
Selected language will be used for files with these mime types, unless the language
|
||||
is chosen based on the filename or overridden in the <guilabel>File filters tab</guilabel> section.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><guilabel>Extensions</guilabel></term>
|
||||
<listitem><para>
|
||||
Selected language will be used for files whose filenames match these patterns,
|
||||
unless overridden in the <guilabel>File filters tab</guilabel> section.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><guilabel>Options</guilabel></term>
|
||||
<listitem><para>
|
||||
Default editing options to use in documents which use the given language. These
|
||||
options can be overridden using <guilabel>File filters tab</guilabel> section, and options set
|
||||
in the file text have a higher priority as well. See <xref linkend="section-editing-options"/>
|
||||
for format of this entry content.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="section-prefs-file-filters" moo.helpsection="PREFS_FILTERS">
|
||||
<title>File filters tab</title>
|
||||
<para>
|
||||
<guilabel>File filters tab</guilabel> section allows to customize editing options,
|
||||
as well as syntax highlighting language, on per-document basis using regular
|
||||
expressions which are matched against the document filename (globs can also be
|
||||
used, see below). Full file paths are used, so one can have per-directory settings.
|
||||
</para>
|
||||
<para>
|
||||
The filters are applied in the order they appear in the list, one by one. All filters
|
||||
are applied to every file, so several filters may affect options in the same file. In
|
||||
this way one can set some options for a set of files or a directory, then set or modify
|
||||
some additional options for certain files in that set, etc.
|
||||
</para>
|
||||
<para>
|
||||
To add a filter, use <guilabel>New</guilabel> button. Click the filter in the list to
|
||||
select it, then click the <guilabel>Filter</guilabel> or <guilabel>Options</guilabel>
|
||||
part of it to edit. Use <guilabel>Delete</guilabel> button to delete a filter,
|
||||
and <guilabel>Up</guilabel> and <guilabel>Down</guilabel> buttons to change the order in
|
||||
which they are applied.
|
||||
</para>
|
||||
<para>
|
||||
<guilabel>Filter</guilabel> field contains a regular expression matched agains the
|
||||
document filename. If it is found in the filename,
|
||||
then the options from the <guilabel>Options</guilabel> field are applied to the
|
||||
document. Example:
|
||||
<programlisting>projects/moo/</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Use dollar if you need to match ends of filenames, e.g. "<code>\.doc$</code>" will work as
|
||||
"<code>*.doc</code>" pattern.
|
||||
</para>
|
||||
<para>
|
||||
Alternatively it can be
|
||||
a comma-separated list of globs prefixed with "<code>globs:</code>" or a list
|
||||
of language ids prefixed with "<code>langs:</code>", e.g.
|
||||
<programlisting>globs:*.c,*.h</programlisting>
|
||||
or
|
||||
<programlisting>langs:c,c++</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
<guilabel>Options</guilabel> field contains the options, in format described in
|
||||
<xref linkend="section-editing-options"/>.
|
||||
</para>
|
||||
<informalexample>
|
||||
<graphic fileref="img/prefs-file-filters.png" align="center"/>
|
||||
</informalexample>
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="section-prefs-file-selector" moo.helpsection="PREFS_FILE_SELECTOR">
|
||||
<title><guilabel>File Selector</guilabel> tab</title>
|
||||
<para>
|
||||
<guilabel>File Selector</guilabel> tab in the <guilabel>Preferences</guilabel>
|
||||
dialog allows to define custom commands which are available in
|
||||
<guimenu>Open With</guimenu> submenu of context menu in File Selector. By default
|
||||
this submenu contains single item <guimenuitem>Default Application</guimenuitem>
|
||||
which opens selected file with default application as configured in the system.
|
||||
Here you can add additional commands and set whether they should be available
|
||||
only for given file patterns or syntax highlighting languages.
|
||||
</para>
|
||||
<para>
|
||||
Use <guilabel>New</guilabel> button to create new command, <guilabel>Delete</guilabel>
|
||||
button to delete selected command, and <guilabel>Up</guilabel> and <guilabel>Down</guilabel>
|
||||
to change relative order of the commands, they will appear in the menu in the same order
|
||||
as in this list.
|
||||
</para>
|
||||
<para>
|
||||
The following entries set the command properties:
|
||||
<variablelist>
|
||||
<?dbhtml list-presentation="table"?>
|
||||
<!-- <?dbhtml term-separator=" : "?>-->
|
||||
<varlistentry>
|
||||
<term><parameter>Name</parameter></term>
|
||||
<listitem>Menu item label for this command.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Command</parameter></term>
|
||||
<listitem>Shell command to execute when the menu item is activated. <code>%f</code> will
|
||||
be replaced with full path of the selected file; if more than one file is selected then
|
||||
the command will be executed for each file one by one. If <parameter>command</parameter>
|
||||
contains <code>%F</code> and several files are selected then <code>%F</code> will be
|
||||
replaced with the space-separated list of paths of all selected files. If a single file
|
||||
is selected then <code>%f</code> and <code>%F</code> behave in the same way.
|
||||
Example: <code>firefox %f</code>, <code>glade %F</code></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Extensions</parameter></term>
|
||||
<listitem>Semicolon-separated list of file patterns to define for which files this command
|
||||
is available, e.g. <code>*.c;*.h</code>. Use <code>*</code> if the command should
|
||||
be available for all files.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Mime types</parameter></term>
|
||||
<listitem>Semicolon-separated list of mime types to define for which files this command
|
||||
is available, e.g. <code>application/docbook+xml;application/x-glade</code>. Leave it empty
|
||||
if <parameter>Extensions</parameter> entry defines whether the command should be enabled.</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
<informalexample>
|
||||
<graphic fileref="img/prefs-file-selector.png" align="center"/>
|
||||
</informalexample>
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="section-editing-options">
|
||||
<title>Options for editing text</title>
|
||||
<para>
|
||||
&medit; has some editing options which can be set in the document text,
|
||||
or in the <guilabel>Preferences</guilabel> dialog for sets of files or for given syntax
|
||||
highlighting language.
|
||||
</para>
|
||||
<para>
|
||||
To set the options in the document text, place the following on the first,
|
||||
second or the last line of the document:
|
||||
<programlisting>
|
||||
-%- <parameter>options</parameter> -%-
|
||||
</programlisting>
|
||||
where <parameter>options</parameter> is the option string
|
||||
<programlisting>
|
||||
<parameter>key</parameter>: <parameter>value</parameter>; <parameter>key</parameter>: <parameter>value</parameter>; ...
|
||||
</programlisting>
|
||||
(the latter is the format used also in the <guilabel>Preferences</guilabel> dialog).
|
||||
</para>
|
||||
<para>
|
||||
For example, the following might be the first line in a C file:
|
||||
<programlisting>
|
||||
/* -%- indent-width: 2; use-tabs: yes; strip: yes -%- */
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Values can be strings, integers, or booleans.
|
||||
</para>
|
||||
<para>
|
||||
Booleans are <code>yes</code>, <code>no</code>, <code>true</code>, <code>false</code>, <code>1</code>, <code>0</code>.
|
||||
</para>
|
||||
<para>
|
||||
If a string value contains <code>:</code> character, then the following syntax may be used:
|
||||
<code><parameter>key</parameter>=/<parameter>value</parameter>/</code>. Any character may be used instead of slash (and it
|
||||
must not occur in the <parameter>value</parameter>). Example: <code>word-chars=@-/:@</code>
|
||||
</para>
|
||||
<para>
|
||||
The following options are available:
|
||||
<variablelist>
|
||||
<?dbhtml list-presentation="table"?>
|
||||
<?dbhtml term-separator=" : "?>
|
||||
<varlistentry>
|
||||
<term><code>lang</code></term>
|
||||
<listitem><para>syntax highlighting language to use in this document. Special value <code>none</code> will
|
||||
turn off syntax highlighting in this document.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>strip</code></term>
|
||||
<listitem><para>a boolean value, whether trailing whitespace should be removed from the document on save.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>add-newline</code></term>
|
||||
<listitem><para>a boolean value, whether the editor should ensure that saved files have a trailing new line character.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>indent-width</code></term>
|
||||
<listitem><para>an integer specifying indentation offset used when the Tab key is pressed to indent text.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>tab-width</code></term>
|
||||
<listitem><para>displayed width of the tab character. Note that this is <emphasis>not</emphasis> the same as
|
||||
<code>indent-width</code>.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>use-tabs</code></term>
|
||||
<listitem><para>whether tab character should be used for indentation.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
<para>
|
||||
&medit; tries to understand modelines of Vim, Emacs, and Kate text editors, so chances are it will correctly
|
||||
pick up the conventional settings from source files.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="section-prefs-xml">
|
||||
<title>Preferences files</title>
|
||||
<para>
|
||||
&medit; preferences are stored in &medit-prefs-xml-unix; file.
|
||||
It is an XML file which may be edited to set preferences which have not found
|
||||
their place in the <guilabel>Preferences</guilabel> dialog.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
&medit; reads the preferences file on startup and writes it whenever <guilabel>OK</guilabel>
|
||||
or <guilabel>Apply</guilabel> button is clicked in the <guilabel>Preferences</guilabel> dialog. Therefore, if you
|
||||
modify the preferences file, your changes may be overwritten, and they not take
|
||||
effect until you restart &medit;.
|
||||
</para>
|
||||
</note>
|
||||
<para>
|
||||
The following "hidden" settings are available:
|
||||
<variablelist>
|
||||
<?dbhtml term-separator=" : "?>
|
||||
<varlistentry>
|
||||
<term><parameter>Editor/window_title</parameter></term>
|
||||
<listitem><para>Format of the window title. It is a string which may
|
||||
contain format sequences, which are percent sign followed by a character:
|
||||
<variablelist>
|
||||
<?dbhtml list-presentation="table"?>
|
||||
<?dbhtml term-separator=" : "?>
|
||||
<varlistentry>
|
||||
<term><code>%a</code></term>
|
||||
<listitem>application name</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>%b</code></term>
|
||||
<listitem>current document basename</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>%f</code></term>
|
||||
<listitem>full path of the current document</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>%u</code></term>
|
||||
<listitem>URI of the current document</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>%s</code></term>
|
||||
<listitem>the status of the current document, e.g. "<code> [modified]</code>". It is prefixed
|
||||
with a space, so that "<code>%b%s</code>" produces a nice string</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>%%</code></term>
|
||||
<listitem>the percent character</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
Default value is "<code>%a - %f%s</code>" which produces something like "<code>medit - /home/user/file [modified]</code>".
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Editor/window_title_no_doc</parameter></term>
|
||||
<listitem><para>same as <parameter>Editor/window_title</parameter>, used when no document is open.
|
||||
Default value is "<code>%a</code>".</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
</chapter>
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE chapter [
|
||||
<!ENTITY % medit-defines SYSTEM "built/medit-defines.ent">
|
||||
%medit-defines;
|
||||
]>
|
||||
<chapter id="chapter-regex">
|
||||
<title>Regular expressions</title>
|
||||
|
||||
<para>
|
||||
&medit; uses regular expressions functionality provided by Glib, which in turn uses
|
||||
<ulink url="http://pcre.org/">PCRE</ulink> library. See
|
||||
<ulink url="http://library.gnome.org/devel/glib/stable/glib-regex-syntax.html">Glib manual</ulink>
|
||||
for complete description of regular expression syntax.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Regular expression searches in a document text are limited to single lines, unless the
|
||||
search pattern includes newline character. For example, pattern "<code>.*</code>" will match every
|
||||
line in the document, pattern "<code>.*\n.*</code>" will match pairs of consecutive lines. This means
|
||||
that it is mostly impossible to perform searches for text which spawns multiple lines.
|
||||
</para>
|
||||
|
||||
</chapter>
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version='1.0'?>
|
||||
<xsl:stylesheet
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
|
||||
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/chunk.xsl"/>
|
||||
|
||||
<xsl:param name="html.stylesheet" select="'../medit.css'"/>
|
||||
<xsl:output method="html" indent="yes"/>
|
||||
|
||||
<xsl:param name="chunker.output.indent" select="'yes'"/>
|
||||
|
||||
<xsl:param name="base.dir" select="'help/script/'"/>
|
||||
<xsl:param name="chunk.first.sections" select="'1'"/>
|
||||
|
||||
<xsl:param name="toc.section.depth" select="1"/>
|
||||
<xsl:param name="generate.section.toc.level" select="1"/>
|
||||
|
||||
<!--<xsl:param name="variablelist.as.table" select="1"/>-->
|
||||
|
||||
<!-- <xsl:template match="sect1">
|
||||
<xsl:if test="preceding-sibling::sect1">
|
||||
<hr/>
|
||||
</xsl:if>
|
||||
<xsl:apply-imports/>
|
||||
</xsl:template>-->
|
||||
|
||||
<xsl:template match="sect2">
|
||||
<xsl:if test="preceding-sibling::sect2">
|
||||
<hr/>
|
||||
</xsl:if>
|
||||
<xsl:apply-imports/>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE chapter [
|
||||
<!ENTITY % medit-defines SYSTEM "medit-defines.ent">
|
||||
%medit-defines;
|
||||
]>
|
||||
<chapter id="chapter-script-lua-gtk">
|
||||
<?dbhtml filename="lua-gtk.html"?>
|
||||
<title>Gtk API for Lua scripts</title>
|
||||
<sect1>
|
||||
<title>Introduction</title>
|
||||
<para>Lua scripts running in &medit; have a limited access to
|
||||
<ulink url="http://www.gtk.org/">Gtk</ulink> functionality
|
||||
exposed through <code>gtk</code> package in addition to functions in
|
||||
<link linkend="chapter-script-lua"><code>moo</code> package</link>.
|
||||
It is not a goal to provide complete Lua bindings for Gtk,
|
||||
and it is not a goal to enable creating UI in Lua scripts.
|
||||
If there is a demand, &medit; might bind more Gtk functionality,
|
||||
but so far Lua in &medit; is supposed to be lean and mean
|
||||
scripting language which is always available. Use Python if
|
||||
you need more functionality.</para>
|
||||
<para>
|
||||
Notations used in this manual are described
|
||||
<link linkend="section-script-lua-notations">here</link>.
|
||||
</para>
|
||||
</sect1>
|
||||
###GENERATED###
|
||||
</chapter>
|
|
@ -0,0 +1,79 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE article [
|
||||
<!ENTITY % medit-defines SYSTEM "medit-defines.ent">
|
||||
%medit-defines;
|
||||
]>
|
||||
<chapter id="chapter-script-lua">
|
||||
<?dbhtml filename="lua-moo.html"?>
|
||||
<title>&medit; Lua API</title>
|
||||
|
||||
<sect1 id="section-script-lua-introduction">
|
||||
<title>Introduction</title>
|
||||
<para>Lua scripts running in &medit; have access to its
|
||||
functionality through the <code>moo</code> package.</para>
|
||||
<warning>
|
||||
Functions which are not documented here may or may not work differently in
|
||||
the future and they may disappear without notice. Contact the author if you
|
||||
need functions which are not present here.
|
||||
</warning>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="section-script-lua-object-model">
|
||||
<title>&medit; object model</title>
|
||||
<para>&medit; uses a very simple object model where its objects are
|
||||
represented as user data in Lua and methods are provided via metatable
|
||||
shared by all objects of all "classes". Method dispatch is dynamic,
|
||||
i.e. metatable does not contain functions which correspond to methods,
|
||||
and <code>obj:method</code> returns a function object which knows which
|
||||
method on which object it is going to call.</para>
|
||||
<para>This manual lists and talks about "classes", but it is merely
|
||||
to avoid complicated terminology. When we say that an object belongs
|
||||
to or is an instance of a class <code>Foo</code>, it just means that
|
||||
it has methods listed in manual section for class <code>Foo</code>
|
||||
and methods of parent classes, if any.</para>
|
||||
<note>
|
||||
To call a method, you can use both <code>obj:method(args)</code>
|
||||
and <code>obj.method(args)</code>.
|
||||
</note>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="section-script-lua-notations">
|
||||
<title>Notations</title>
|
||||
<para>This manual uses the following conventions:</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>Optional parameters</term>
|
||||
<listitem>
|
||||
<programlisting>func(arg1=val1, arg2=val, arg3=val3)</programlisting>
|
||||
<code><parameter>arg</parameter>=val</code> means that
|
||||
parameter <parameter>arg</parameter> is optional, and function receives
|
||||
value <code>val</code> if it's missing. Not all parameters are necessarily
|
||||
optional. For example, <programlisting>insert_text(text, where=nil)</programlisting>
|
||||
means that <parameter>text</parameter> may not be missing or <constant>nil</constant>
|
||||
(unless documentation says otherwise), and <parameter>where</parameter> is optional.
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Keyword parameters</term>
|
||||
<listitem>
|
||||
<programlisting>func{arg1, arg2, kwarg1=kwval1, kwarg2=kwval2}</programlisting>
|
||||
This means that function can be called in an alternative way: actual parameters are
|
||||
taken from the single table parameter, which must be a dictionary with keys
|
||||
<parameter>kwarg1</parameter>, <parameter>kwarg2</parameter>, etc., and whose array part
|
||||
must contain exactly as many values as there are non-optional arguments. Similarly
|
||||
to regular parameters, <code><parameter>kwarg</parameter>=kwval</code> means that
|
||||
<parameter>kwarg</parameter> is optional. For example, above function can be called
|
||||
as follows.
|
||||
<programlisting>
|
||||
<!-- -->func{1, 2, kwarg1='foo'} -- equivalent to func(1, 2, 'foo')
|
||||
<!-- -->func{3, 4, kwarg2='bar'} -- equivalent to func(3, 4, kwval1, 'bar')
|
||||
<!-- -->func{5, 6, kwarg2='baz', kwarg1='bud', } -- equivalent to func(5, 6, 'bud', 'baz')</programlisting>
|
||||
This is similar to Python keyword arguments (with the difference that keyword arguments
|
||||
may be used only if function is documented to support them).
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
</sect1>
|
||||
###GENERATED###
|
||||
</chapter>
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE chapter [
|
||||
<!ENTITY % medit-defines SYSTEM "medit-defines.ent">
|
||||
%medit-defines;
|
||||
]>
|
||||
<chapter id="chapter-script-python">
|
||||
<?dbhtml filename="python-moo.html"?>
|
||||
<title>&medit; Python API</title>
|
||||
<sect1>
|
||||
<title>Introduction</title>
|
||||
<para>When compiled with Python support, &medit; uses
|
||||
<ulink url="http://www.pygtk.org/">PyGtk</ulink>. Its functionality is
|
||||
exposed through <code>moo</code> module. You can use built-in Python console
|
||||
available from <guimenu>Tools</guimenu> menu to experiment with &medit; API.</para>
|
||||
<note>
|
||||
Classes and functions documented here are guaranteed to work as long as you
|
||||
follow the rules from their documentation (most often there are no special
|
||||
rules, but for some functions you may or may not use named arguments, etc.)
|
||||
</note>
|
||||
<warning>
|
||||
<code>moo</code> module has more classes and functions than documented here,
|
||||
but undocumented classes and functions may or may not work differently in
|
||||
the future and they may disappear without notice. Contact the author if you
|
||||
need functions which are not present here.
|
||||
</warning>
|
||||
</sect1>
|
||||
###GENERATED###
|
||||
</chapter>
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?><!-- -%- indent-width:1 -%- -->
|
||||
<!DOCTYPE book [
|
||||
<!ENTITY % medit-defines SYSTEM "built/medit-defines.ent">
|
||||
%medit-defines;
|
||||
]>
|
||||
<book id="medit-scripting-manual">
|
||||
|
||||
<bookinfo>
|
||||
<title>&medit; scripting manual</title>
|
||||
<date>1/22/2011</date>
|
||||
<releaseinfo>&medit-version;</releaseinfo>
|
||||
</bookinfo>
|
||||
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="built/script-lua.docbook"/>
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="built/script-lua-gtk.docbook"/>
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="built/script-python.docbook"/>
|
||||
|
||||
</book>
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version='1.0'?>
|
||||
<xsl:stylesheet
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
|
||||
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl"/>
|
||||
|
||||
<xsl:param name="html.stylesheet" select="'medit.css'"/>
|
||||
<xsl:output method="html" indent="yes"/>
|
||||
|
||||
<!--<xsl:param name="variablelist.as.table" select="1"/>-->
|
||||
|
||||
<xsl:template match="sect1">
|
||||
<xsl:if test="preceding-sibling::sect1">
|
||||
<hr/>
|
||||
</xsl:if>
|
||||
<xsl:apply-imports/>
|
||||
</xsl:template>
|
||||
|
||||
<!-- <xsl:template match="sect2">
|
||||
<xsl:if test="preceding-sibling::sect2">
|
||||
<hr/>
|
||||
</xsl:if>
|
||||
<xsl:apply-imports/>
|
||||
</xsl:template>-->
|
||||
|
||||
</xsl:stylesheet>
|
|
@ -0,0 +1,406 @@
|
|||
<?xml version="1.0"?><!-- -%- indent-width:2 -%- -->
|
||||
<!DOCTYPE chapter [
|
||||
<!ENTITY % medit-defines SYSTEM "built/medit-defines.ent">
|
||||
%medit-defines;
|
||||
]>
|
||||
<chapter id="chapter-user-tools" moo.helpsection="USER_TOOLS">
|
||||
<title>User-defined tools</title>
|
||||
|
||||
<para>
|
||||
&medit; allows extending its functionality with user-defined
|
||||
<parameter>tools</parameter>. It can be a Lua script or a Python script (if &medit; has been
|
||||
built with Python support) which are executed inside &medit;,
|
||||
or a shell script which can use the text of the open document as
|
||||
its input and/or output.
|
||||
</para>
|
||||
<para>
|
||||
There are some predefined tools which you can use as
|
||||
an example or to modify to suit your needs.
|
||||
</para>
|
||||
|
||||
|
||||
<sect1 id="section-prefs-user-tools" moo.helpsection="PREFS_USER_TOOLS">
|
||||
<title>Managing tools in <guilabel>Preferences</guilabel> dialog</title>
|
||||
|
||||
<para>
|
||||
To create a new tool or to modify existing ones, open
|
||||
<guilabel>Preferences</guilabel> dialog and select <guilabel>Tools</guilabel> in the list on the left.
|
||||
</para>
|
||||
<para>
|
||||
Select the tool in the list or click the <guibutton>New</guibutton>
|
||||
button to create a new one. To modify the order in which tools
|
||||
appear in the <guimenu>Tools</guimenu> menu (or in the document
|
||||
context menu), use <guibutton>Up</guibutton> and <guibutton>Down</guibutton> buttons. To rename a tool,
|
||||
click its name in the list to select it and then click again to
|
||||
edit the name. Use the <guibutton>Delete</guibutton> button to delete a tool.
|
||||
</para>
|
||||
<para>
|
||||
The following controls are available to modify tools:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<parameter><guilabel>Files</guilabel></parameter> entry specifies for which files the tool is going to be available. It can
|
||||
contain the following:
|
||||
<itemizedlist>
|
||||
<listitem>a comma-separated list of file patterns, e.g. <programlisting><code>*.c,*.h</code></programlisting></listitem>
|
||||
<listitem>a comma-separated list of languages prefixed with "<code>langs:</code>", e.g.
|
||||
<programlisting><code>langs: c, c++, objc</code></programlisting></listitem>
|
||||
<listitem>a regular expression matching document filename prefixed with "<code>regex:</code>", e.g. the above
|
||||
pattern list may be written as <programlisting><code>regex:\.[ch]$</code></programlisting></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>Empty entry means that the tool will be available for all documents.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<parameter><guilabel>Requires</guilabel></parameter> combo box specifies whether the tool should be
|
||||
enabled depending on current document.
|
||||
<variablelist>
|
||||
<?dbhtml list-presentation="table"?>
|
||||
<!-- <?dbhtml term-separator=" : "?>-->
|
||||
<varlistentry>
|
||||
<term><parameter>Nothing</parameter></term>
|
||||
<listitem>the tool is enabled regardless whether there is an open document.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Document</parameter></term>
|
||||
<listitem>the tool is enabled only if there is an open document. For example, if the tool manipulates
|
||||
current document text, then it needs a document to be there.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>File on disk</parameter></term>
|
||||
<listitem>the tool is enabled only if current document is saved on disk (i.e. it is not "Untitled").
|
||||
For example, to compile a TeX file, it needs to be saved first.</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<parameter><guilabel>Save</guilabel></parameter> combo box specifies what should be saved every time
|
||||
before the command is executed.
|
||||
<variablelist>
|
||||
<?dbhtml list-presentation="table"?>
|
||||
<!-- <?dbhtml term-separator=" : "?>-->
|
||||
<varlistentry>
|
||||
<term><parameter>Nothing</parameter></term>
|
||||
<listitem>nothing will be saved.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Current document</parameter></term>
|
||||
<listitem>current document will be automatically saved. For example, you probably want to save currrent
|
||||
document before compiling it with latex.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>All documents</parameter></term>
|
||||
<listitem>all open documents will be automatically saved. For example, if the tool builds a C project, then
|
||||
you probably want to save all open files before running make.</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<parameter><guilabel>Type</guilabel></parameter> combo specifies the type of the tool: a Python script, a
|
||||
Lua script, or a shell script.
|
||||
</listitem>
|
||||
<listitem>
|
||||
<guilabel>Code</guilabel> text field contains script or shell command text. See
|
||||
<xref linkend="section-user-tools-shell"/>, <xref linkend="section-user-tools-lua"/>,
|
||||
<xref linkend="section-user-tools-python"/> for details on what can be here.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="section-storing-tools-in-files">
|
||||
<title>Storing tools in files</title>
|
||||
|
||||
<para>
|
||||
It is possible to create tools without using the <guilabel>Preferences</guilabel> dialog,
|
||||
they can be stored in files in <filename>tools</filename> subfolder of the &medit; data
|
||||
folders (or <filename>tools-context</filename> for tools which appear in the document context
|
||||
menu). In particular, on Unix systems you can place files into &medit-user-tools-dir-unix; folder.
|
||||
</para>
|
||||
<para>
|
||||
Names of the files in the <filename>tools</filename> folder are used as their menu item
|
||||
labels, after stripping first three characters, so you can use trhee-character
|
||||
prefix to affect the order of the menu items, e.g. you can have <filename>00-Do Something</filename>,
|
||||
<filename>01-Another tool</filename> files to have them in that order in the menu. The files
|
||||
may be of three types:
|
||||
<itemizedlist>
|
||||
<listitem>files with extension "<filename>.py</filename>", they will be used
|
||||
as Python scripts;</listitem>
|
||||
<listitem>files with extension "<filename>.lua</filename>", they will be used
|
||||
as Lua scripts;</listitem>
|
||||
<listitem>executable files, they will be executed in the same way
|
||||
as shell commands.</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>
|
||||
Note that files with <filename>.py</filename> and <filename>.lua</filename> extensions will be
|
||||
executed inside &medit; process; if you want to use them as regular scripts, then just remove the
|
||||
extension.
|
||||
</para>
|
||||
<para>
|
||||
To set parameters for a tool, place them on the first or the second line of the file in
|
||||
the following format:
|
||||
<programlisting>
|
||||
!! <parameter>key</parameter>=<parameter>value</parameter>; <parameter>key</parameter>=<parameter>value</parameter>; ... !!
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
<parameter>key</parameter> may be one of the following:
|
||||
<variablelist>
|
||||
<?dbhtml list-presentation="table"?>
|
||||
<varlistentry>
|
||||
<term><code>position</code></term>
|
||||
<listitem>it can be <code>start</code> or <code>end</code>, and it defines whether the menu item
|
||||
will be located at the start or at the end of the menu.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>id</code></term>
|
||||
<listitem>the tool identificator.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>name</code></term>
|
||||
<listitem>the tool name, i.e. the label used in the menu item. Overrides the file name.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>accel</code></term>
|
||||
<listitem>default keyboard accelerator used to invoke this tool.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>menu</code></term>
|
||||
<listitem>the menu to place this tool into. By default tools are located in the <guimenu>Tools</guimenu> menu,
|
||||
but they can be as well put into any other menu.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>langs</code></term>
|
||||
<listitem>comma-separated list of languages for which this tool will be enabled.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>file-filter</code></term>
|
||||
<listitem>defines for which files this tool will be enabled. The value has the same format as
|
||||
in the <guilabel>Preferences</guilabel> dialog.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>options</code></term>
|
||||
<listitem>this corresponds to Requires and Save controls in the <guilabel>Preferences</guilabel> dialog. It is a
|
||||
comma-separated list of the following:
|
||||
<variablelist>
|
||||
<?dbhtml list-presentation="table"?>
|
||||
<varlistentry>
|
||||
<term><code>need-doc</code></term>
|
||||
<listitem>tool will be enabled only if there is an open document.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>need-file</code></term>
|
||||
<listitem>tool will be enabled only if current document is saved on disk (i.e. it is not "Untitled").</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>need-save</code></term>
|
||||
<listitem>current document will be automatically saved before the command is executed.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>need-save-all</code></term>
|
||||
<listitem>all open documents will be automatically saved before the command is executed.</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
<para>
|
||||
In addition to these, you can set input and output options for executable files (see <xref linkend="section-user-tools-shell"/>
|
||||
for the meaning of these options):
|
||||
<variablelist>
|
||||
<?dbhtml list-presentation="table"?>
|
||||
<varlistentry>
|
||||
<term><code>input</code></term>
|
||||
<listitem><code>none</code>, <code>lines</code>, <code>selection</code>, or <code>doc</code>.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>output</code></term>
|
||||
<listitem><code>none</code>, <code>async</code>, <code>pane</code>, <code>insert</code>, or <code>new-doc</code>.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>filter</code></term>
|
||||
<listitem>output filter name.</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="section-user-tools-shell">
|
||||
<title>Shell scripts</title>
|
||||
|
||||
<para>
|
||||
Shell script user tools execute command entered in the <guilabel>Command</guilabel>
|
||||
text field using default user shell on Unix systems or <command>cmd.exe</command> on Windows.
|
||||
</para>
|
||||
<para>
|
||||
Its input and output are specified by the following controls:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<parameter><guilabel>Input</guilabel></parameter> entry specifies what text from the document should be passed to the command.
|
||||
The text is passed via command's standard input, except for <parameter>Document copy</parameter> case.
|
||||
<variablelist>
|
||||
<?dbhtml list-presentation="table"?>
|
||||
<varlistentry>
|
||||
<term><parameter>None</parameter></term>
|
||||
<listitem>no input text.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Selected lines</parameter></term>
|
||||
<listitem>the lines containing selection or the line containing the cursor in
|
||||
case when no text is selected.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Selection</parameter></term>
|
||||
<listitem>exact selected text. This will be different from <parameter>Selected lines</parameter>
|
||||
if selection does not span whole lines of the document, for instance if it is a single word.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Whole document</parameter></term>
|
||||
<listitem>whole document contents.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Document copy</parameter></term>
|
||||
<listitem>document contents will be saved to a temporary file and the file path will be stored
|
||||
in <envar>INPUT_FILE</envar> environment variable. No text will be passed to the command via standard
|
||||
input.</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<parameter><guilabel>Output</guilabel></parameter> entry specifies how the standard output of the command should be redirected.
|
||||
<variablelist>
|
||||
<?dbhtml list-presentation="table"?>
|
||||
<varlistentry>
|
||||
<term><parameter>None</parameter></term>
|
||||
<listitem>the command output will be discarded.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>None, asynchronous</parameter></term>
|
||||
<listitem>the command output will be discarded, and the command will be executed in background.
|
||||
Use this if you need to launch some external program like a web browser.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Output pane</parameter></term>
|
||||
<listitem>the command output will be displayed in an output pane. This is useful for running programs
|
||||
like compilers, where you want to see the output.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>Insert into the document</parameter></term>
|
||||
<listitem>output will be inserted into the current document at the cursor position. It will replace the
|
||||
text used as an input, if any.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>New document</parameter></term>
|
||||
<listitem>new document will be created and the command output will be inserted into it.</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<parameter><guilabel>Filter</guilabel></parameter> combo. If the output pane is used, then it can be passed through a
|
||||
<parameter>filter</parameter>: the filter can match filenames and line numbers, so when you click
|
||||
the text in the output pane it will open the corresponding file. This is used for compilers and
|
||||
similar commands, which output locations of errors in processed files.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>
|
||||
Shell script user tools have a number of environment variables set.
|
||||
<envar>APP_PID</envar> variable is set so that opening a file in the same instance
|
||||
of &medit; is as simple as <code>medit filename</code> (on the other hand, you will
|
||||
have to use command line options if you need to run a new &medit; instance). The
|
||||
following environment variables are set when scripts are executed:
|
||||
<variablelist>
|
||||
<?dbhtml list-presentation="table"?>
|
||||
<!-- <?dbhtml term-separator=" : "?>-->
|
||||
<varlistentry>
|
||||
<term><envar>APP_PID</envar></term>
|
||||
<listitem>current process id.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><envar>DOC</envar></term>
|
||||
<listitem>document basename ("<filename>file.c</filename>" for file <filename>/home/user/file.c</filename>).</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><envar>DOC_DIR</envar></term>
|
||||
<listitem>document directory ("<filename>/home/user</filename>" for file <filename>/home/user/file.c</filename>). Full file path is
|
||||
<filename><envar>$DOC_DIR</envar>/<envar>$DOC</envar></filename>.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><envar>DOC_BASE</envar></term>
|
||||
<listitem>basename without extension ("<filename>file</filename>" for file <filename>/home/user/file.c</filename>).</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><envar>DOC_EXT</envar></term>
|
||||
<listitem>document filename extension including the period ("<filename>.c</filename>" for file
|
||||
<filename>/home/user/file.c</filename>). Basename is always
|
||||
<filename><envar>$DOC_BASE</envar><envar>$DOC_EXT</envar></filename>.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><envar>DOC_PATH</envar></term>
|
||||
<listitem>full document path.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><envar>LINE</envar></term>
|
||||
<listitem><constant>1</constant>-based number of the line containing cursor.
|
||||
For example, if cursor is at the first line then <envar>LINE</envar> will be
|
||||
set to <constant>1</constant>.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><envar>LINE0</envar></term>
|
||||
<listitem><constant>0</constant>-based number of the line containing cursor.
|
||||
For example, if cursor is at the first line then <envar>LINE0</envar> will be
|
||||
set to <constant>0</constant>.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><envar>DATA_DIR</envar></term>
|
||||
<listitem>user data directory (&medit-user-data-dir-unix; on Unix systems).</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><envar>INPUT_FILE</envar></term>
|
||||
<listitem>if <parameter>input</parameter> was set to "Document copy" then this is set to
|
||||
full path of the temporary file containing document text.</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
<para>
|
||||
Additionally, all shell commands which run inside &medit; will have
|
||||
<filename><envar>DATA_DIR</envar>/scripts</filename>
|
||||
directories in <envar>$PATH</envar>, so you may place some &medit;-specific programs
|
||||
or scripts into <filename><envar>DATA_DIR</envar>/scripts/</filename> to be used from shell script tools.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="section-user-tools-lua">
|
||||
<title>Lua scripts</title>
|
||||
|
||||
<para>
|
||||
<ulink url="script/lua-moo.html">Medit API for Lua scripts</ulink>.
|
||||
</para>
|
||||
<para>
|
||||
<ulink url="script/lua-gtk.html">Gtk API for Lua scripts</ulink>.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="section-user-tools-python">
|
||||
<title>Python scripts</title>
|
||||
|
||||
<para>
|
||||
<ulink url="script/python-moo.html">Medit API for Python scripts</ulink>.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
|
||||
</chapter>
|
|
@ -0,0 +1,19 @@
|
|||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
|
||||
#print "Output file:", sys.argv[1]
|
||||
#print "Working dir:", os.getcwd()
|
||||
#print "Executing command:", sys.argv[2:]
|
||||
output = subprocess.check_output(sys.argv[2:], stdin=None, shell=False, universal_newlines=False)
|
||||
output = output.replace('\r\n', '\n').replace('\r', '\n')
|
||||
|
||||
filename = sys.argv[1]
|
||||
tmp = filename + '.tmp'
|
||||
if not os.path.exists(os.path.dirname(tmp)):
|
||||
os.makedirs(os.path.dirname(tmp))
|
||||
with open(tmp, 'w') as f:
|
||||
f.write(output)
|
||||
if os.path.exists(filename):
|
||||
os.remove(filename)
|
||||
os.rename(tmp, filename)
|
|
@ -0,0 +1,7 @@
|
|||
[paths]
|
||||
default = ssh://hg@bitbucket.org/medit/medit
|
||||
|
||||
[hooks]
|
||||
# Reject commits which would introduce windows-style text" files
|
||||
pretxncommit.crlf = python:hgext.win32text.forbidcrlf
|
||||
pretxncommit.glade = tools/checkglade
|
|
@ -0,0 +1,269 @@
|
|||
AC_DEFUN([_MOO_AC_CHECK_C_COMPILER_OPTIONS],[
|
||||
AC_LANG_PUSH([C])
|
||||
for opt in $1; do
|
||||
save_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $opt"
|
||||
if test "x$MOO_STRICT_MODE" = "xyes"; then
|
||||
CFLAGS="-Werror $CFLAGS"
|
||||
fi
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[MOO_CFLAGS="$MOO_CFLAGS $opt"],[:])
|
||||
CFLAGS="$save_CFLAGS"
|
||||
done
|
||||
AC_LANG_POP([C])
|
||||
])
|
||||
|
||||
AC_DEFUN([_MOO_AC_CHECK_CXX_COMPILER_OPTIONS],[
|
||||
AC_LANG_PUSH([C++])
|
||||
for opt in $1; do
|
||||
save_CXXFLAGS="$CXXFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $opt"
|
||||
if test "x$MOO_STRICT_MODE" = "xyes"; then
|
||||
CXXFLAGS="-Werror $CXXFLAGS"
|
||||
fi
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[MOO_CXXFLAGS="$MOO_CXXFLAGS $opt"],[:])
|
||||
CXXFLAGS="$save_CXXFLAGS"
|
||||
done
|
||||
AC_LANG_POP([C++])
|
||||
])
|
||||
|
||||
# _MOO_AC_CHECK_COMPILER_OPTIONS(options)
|
||||
AC_DEFUN([_MOO_AC_CHECK_COMPILER_OPTIONS],[
|
||||
_MOO_AC_CHECK_C_COMPILER_OPTIONS([$1])
|
||||
_MOO_AC_CHECK_CXX_COMPILER_OPTIONS([$1])
|
||||
])
|
||||
|
||||
AC_DEFUN([MOO_COMPILER],[
|
||||
# icc pretends to be gcc or configure thinks it's gcc, but icc doesn't
|
||||
# error on unknown options, so just don't try gcc options with icc
|
||||
MOO_ICC=false
|
||||
MOO_GCC=false
|
||||
if test "$CC" = "icc"; then
|
||||
MOO_ICC=true
|
||||
elif test "x$GCC" = "xyes"; then
|
||||
MOO_GCC=true
|
||||
fi
|
||||
])
|
||||
|
||||
##############################################################################
|
||||
# MOO_AC_DEBUG()
|
||||
#
|
||||
AC_DEFUN_ONCE([MOO_AC_DEBUG],[
|
||||
|
||||
MOO_DEBUG_ENABLED="no"
|
||||
|
||||
AC_ARG_ENABLE(debug,
|
||||
AS_HELP_STRING([--enable-debug],[enable debug options (default = NO)]),[
|
||||
if test "$enableval" = "xno"; then
|
||||
MOO_DEBUG_ENABLED="no"
|
||||
else
|
||||
MOO_DEBUG_ENABLED="yes"
|
||||
fi
|
||||
],[
|
||||
MOO_DEBUG_ENABLED="no"
|
||||
])
|
||||
AM_CONDITIONAL(MOO_DEBUG_ENABLED, test x$MOO_DEBUG_ENABLED = "xyes")
|
||||
|
||||
AC_ARG_ENABLE(dev-mode,
|
||||
AS_HELP_STRING([--enable-dev-mode],[dev-mode (default = NO, unless --enable-debug is used)]),[
|
||||
if test "$enableval" = "xno"; then
|
||||
MOO_DEV_MODE="no"
|
||||
else
|
||||
MOO_DEV_MODE="yes"
|
||||
fi
|
||||
],[
|
||||
MOO_DEV_MODE="$MOO_DEBUG_ENABLED"
|
||||
])
|
||||
AM_CONDITIONAL(MOO_DEV_MODE, test x$MOO_DEV_MODE = "xyes")
|
||||
|
||||
AC_ARG_ENABLE(strict,
|
||||
AS_HELP_STRING([--enable-strict],[enable all warnings and -Werror (default = NO)]),[
|
||||
if test "$enableval" = "xno"; then
|
||||
MOO_STRICT_MODE="no"
|
||||
else
|
||||
MOO_STRICT_MODE="yes"
|
||||
fi
|
||||
],[
|
||||
MOO_STRICT_MODE="no"
|
||||
])
|
||||
AM_CONDITIONAL(MOO_STRICT_MODE, test x$MOO_STRICT_MODE = "xyes")
|
||||
|
||||
MOO_COMPILER
|
||||
|
||||
_MOO_AC_CHECK_COMPILER_OPTIONS([dnl
|
||||
-Wall -Wextra -fexceptions -fno-strict-aliasing dnl
|
||||
-Wno-missing-field-initializers dnl
|
||||
-Wno-format-y2k -Wno-overlength-strings dnl
|
||||
-Wno-deprecated-declarations dnl
|
||||
])
|
||||
_MOO_AC_CHECK_CXX_COMPILER_OPTIONS([dnl
|
||||
-std=c++11 -fno-rtti dnl
|
||||
])
|
||||
|
||||
if test "x$MOO_DEBUG_ENABLED" = "xyes"; then
|
||||
_MOO_AC_CHECK_COMPILER_OPTIONS([-ftrapv])
|
||||
else
|
||||
_MOO_AC_CHECK_CXX_COMPILER_OPTIONS([-fno-enforce-eh-specs])
|
||||
fi
|
||||
|
||||
if test "x$MOO_STRICT_MODE" = "xyes"; then
|
||||
if $MOO_GCC; then
|
||||
MOO_CFLAGS="$MOO_CFLAGS -Werror"
|
||||
MOO_CXXFLAGS="$MOO_CXXFLAGS -Werror"
|
||||
fi
|
||||
_MOO_AC_CHECK_COMPILER_OPTIONS([dnl
|
||||
-Wpointer-arith -Wsign-compare -Wreturn-type dnl
|
||||
-Wwrite-strings -Wmissing-format-attribute dnl
|
||||
-Wdisabled-optimization -Wendif-labels dnl
|
||||
-Wvla -Winit-self dnl
|
||||
])
|
||||
# -Wlogical-op triggers warning in strchr() when compiled with optimizations
|
||||
if test "x$MOO_DEBUG_ENABLED" = "xyes"; then
|
||||
_MOO_AC_CHECK_COMPILER_OPTIONS([-Wlogical-op])
|
||||
else
|
||||
_MOO_AC_CHECK_COMPILER_OPTIONS([-Wuninitialized])
|
||||
fi
|
||||
_MOO_AC_CHECK_C_COMPILER_OPTIONS([dnl
|
||||
-Wmissing-prototypes -Wnested-externs -Wnolong-long dnl
|
||||
])
|
||||
_MOO_AC_CHECK_CXX_COMPILER_OPTIONS([dnl
|
||||
-fno-nonansi-builtins -fno-gnu-keywords dnl
|
||||
-Wctor-dtor-privacy -Wabi -Wstrict-null-sentinel dnl
|
||||
-Woverloaded-virtual -Wsign-promo -Wnon-virtual-dtor dnl
|
||||
-Wno-long-long dnl
|
||||
])
|
||||
fi
|
||||
|
||||
# m4_foreach([wname],[unused, sign-compare, write-strings],[dnl
|
||||
# m4_define([_moo_WNAME],[MOO_W_NO_[]m4_bpatsubst(m4_toupper(wname),-,_)])
|
||||
# _moo_WNAME=
|
||||
# _MOO_AC_CHECK_COMPILER_OPTIONS(_moo_WNAME,[-Wno-wname])
|
||||
# AC_SUBST(_moo_WNAME)
|
||||
# m4_undefine([_moo_WNAME])
|
||||
# ])
|
||||
|
||||
if test "x$MOO_DEBUG_ENABLED" = "xyes"; then
|
||||
MOO_CPPFLAGS="$MOO_CPPFLAGS -DENABLE_DEBUG -DENABLE_PROFILE -DG_ENABLE_DEBUG dnl
|
||||
-DG_ENABLE_PROFILE -DMOO_DEBUG -DDEBUG"
|
||||
else
|
||||
MOO_CPPFLAGS="$MOO_CPPFLAGS -DNDEBUG=1 -DG_DISABLE_CAST_CHECKS -DG_DISABLE_ASSERT"
|
||||
fi
|
||||
])
|
||||
|
||||
##############################################################################
|
||||
# MOO_AC_SET_DIRS
|
||||
#
|
||||
AC_DEFUN_ONCE([MOO_AC_SET_DIRS],[
|
||||
if test "x$MOO_PACKAGE_NAME" = x; then
|
||||
AC_MSG_ERROR([MOO_PACKAGE_NAME not set])
|
||||
fi
|
||||
|
||||
AC_SUBST(MOO_PACKAGE_NAME)
|
||||
AC_DEFINE_UNQUOTED([MOO_PACKAGE_NAME], "$MOO_PACKAGE_NAME", [data goes into /usr/share/$MOO_PACKAGE_NAME, etc.])
|
||||
|
||||
AC_SUBST(MOO_DATA_DIR, "${datadir}/$MOO_PACKAGE_NAME")
|
||||
AC_SUBST(MOO_LIB_DIR, "${libdir}/$MOO_PACKAGE_NAME")
|
||||
|
||||
AC_SUBST(MOO_DOC_DIR, "${datadir}/doc/$MOO_PACKAGE_NAME")
|
||||
AC_SUBST(MOO_HELP_DIR, "${MOO_DOC_DIR}/help")
|
||||
|
||||
AC_SUBST(MOO_TEXT_LANG_FILES_DIR, "${MOO_DATA_DIR}/language-specs")
|
||||
|
||||
AC_DEFINE_UNQUOTED([MOO_PREFS_XML_FILE_NAME], "$MOO_PREFS_XML_FILE_NAME", [prefs.xml])
|
||||
AC_DEFINE_UNQUOTED([MOO_STATE_XML_FILE_NAME], "$MOO_STATE_XML_FILE_NAME", [state.xml])
|
||||
AC_DEFINE_UNQUOTED([MOO_SESSION_XML_FILE_NAME], "$MOO_SESSION_XML_FILE_NAME", [session.xml])
|
||||
AC_DEFINE_UNQUOTED([MOO_NAMED_SESSION_XML_FILE_NAME], "$MOO_NAMED_SESSION_XML_FILE_NAME", [session-%s.xml])
|
||||
AC_DEFINE_UNQUOTED([MEDIT_PORTABLE_MAGIC_FILE_NAME], "$MEDIT_PORTABLE_MAGIC_FILE_NAME", [file which enables portable mode])
|
||||
AC_DEFINE_UNQUOTED([MEDIT_PORTABLE_DATA_DIR], "$MEDIT_PORTABLE_DATA_DIR", [prefs files are saved in this directory])
|
||||
AC_DEFINE_UNQUOTED([MEDIT_PORTABLE_CACHE_DIR], "$MEDIT_PORTABLE_CACHE_DIR", [cache files are saved in this directory])
|
||||
|
||||
AC_SUBST(MOO_PYTHON_PLUGIN_DIR, "${MOO_DATA_DIR}/plugins")
|
||||
AC_SUBST(MOO_PYTHON_LIB_DIR, "${MOO_DATA_DIR}/python")
|
||||
])
|
||||
|
||||
##############################################################################
|
||||
# MOO_AC_FLAGS(moo_top_dir)
|
||||
#
|
||||
AC_DEFUN_ONCE([MOO_AC_FLAGS],[
|
||||
AC_REQUIRE([MOO_AC_CHECK_OS])
|
||||
AC_REQUIRE([MOO_AC_SET_DIRS])
|
||||
|
||||
MOO_PKG_CHECK_GTK_VERSIONS
|
||||
MOO_AC_DEBUG
|
||||
|
||||
AC_CHECK_FUNCS_ONCE(getc_unlocked)
|
||||
AC_CHECK_HEADERS(unistd.h sys/utsname.h signal.h sys/wait.h)
|
||||
|
||||
AC_CHECK_FUNCS(mmap)
|
||||
|
||||
moo_top_src_dir=`cd $srcdir && pwd`
|
||||
MOO_CFLAGS="$MOO_CFLAGS $GTK_CFLAGS"
|
||||
MOO_CXXFLAGS="$MOO_CXXFLAGS $GTK_CFLAGS"
|
||||
MOO_CPPFLAGS="$MOO_CPPFLAGS -I$moo_top_src_dir/moo -DXDG_PREFIX=_moo_edit_xdg -DG_LOG_DOMAIN=\\\"Moo\\\""
|
||||
MOO_LIBS="$MOO_LIBS $GTK_LIBS $GTHREAD_LIBS $GMODULE_LIBS $LIBM"
|
||||
|
||||
if test "x$MOO_STRICT_MODE" != "xyes"; then
|
||||
# G_DISABLE_DEPRECATED (or rather lack of it) is not respected anymore. Glib wants you
|
||||
# to define it; if you don't, then you got to jump through additional hoops in order to
|
||||
# really not disable deprecated stuff.
|
||||
MOO_CPPFLAGS="$MOO_CPPFLAGS -DGLIB_DISABLE_DEPRECATION_WARNINGS=1"
|
||||
else
|
||||
#MOO_CPPFLAGS="$MOO_CPPFLAGS -DG_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED"
|
||||
#MOO_CPPFLAGS="$MOO_CPPFLAGS -DGSEAL_ENABLE"
|
||||
#MOO_CPPFLAGS="$MOO_CPPFLAGS -DGTK_DISABLE_SINGLE_INCLUDES"
|
||||
true
|
||||
fi
|
||||
|
||||
if $GDK_X11; then
|
||||
_moo_x_pkgs=
|
||||
m4_foreach([_pkg_],[x11, xext, xrender, ice, sm],[
|
||||
PKG_CHECK_EXISTS(_pkg_,[_moo_x_pkgs="$_moo_x_pkgs _pkg_"],[:])
|
||||
])
|
||||
if test -n "$_moo_x_pkgs"; then
|
||||
PKG_CHECK_MODULES(X,[$_moo_x_pkgs])
|
||||
MOO_CFLAGS="$MOO_CFLAGS $X_CFLAGS"
|
||||
MOO_CXXFLAGS="$MOO_CXXFLAGS $X_CFLAGS"
|
||||
MOO_LIBS="$MOO_LIBS $X_LIBS"
|
||||
fi
|
||||
fi
|
||||
|
||||
if $MOO_OS_WIN32; then
|
||||
MOO_CPPFLAGS="$MOO_CPPFLAGS -DUNICODE -D_UNICODE -DSTRICT -DWIN32_LEAN_AND_MEAN -I$moo_top_src_dir/moo/mooutils/moowin32/mingw"
|
||||
|
||||
# work around bug in i586-mingw32msvc-gcc-4.2.1-sjlj
|
||||
# it defines __STRICT_ANSI__ for some reason and that
|
||||
# breaks compilation:
|
||||
# /usr/lib/gcc/i586-mingw32msvc/4.2.1-sjlj/include/c++/cwchar:164: error: ‘::swprintf’ has not been declared
|
||||
# /usr/lib/gcc/i586-mingw32msvc/4.2.1-sjlj/include/c++/cwchar:171: error: ‘::vswprintf’ has not been declared
|
||||
MOO_CPPFLAGS="$MOO_CPPFLAGS -U__STRICT_ANSI__"
|
||||
|
||||
MOO_LIBS="$MOO_LIBS -lmooglib"
|
||||
fi
|
||||
|
||||
if $MOO_OS_UNIX; then
|
||||
MOO_CPPFLAGS="$MOO_CPPFLAGS -DMOO_DATA_DIR=\\\"${MOO_DATA_DIR}\\\" -DMOO_LIB_DIR=\\\"${MOO_LIB_DIR}\\\""
|
||||
MOO_CPPFLAGS="$MOO_CPPFLAGS -DMOO_LOCALE_DIR=\\\"${localedir}\\\" -DMOO_HELP_DIR=\\\"${MOO_HELP_DIR}\\\""
|
||||
fi
|
||||
|
||||
MOO_CFLAGS="$MOO_CFLAGS $XML_CFLAGS"
|
||||
MOO_CXXFLAGS="$MOO_CXXFLAGS $XML_CFLAGS"
|
||||
MOO_LIBS="$MOO_LIBS $XML_LIBS"
|
||||
|
||||
AC_SUBST(MOO_CPPFLAGS)
|
||||
AC_SUBST(MOO_CFLAGS)
|
||||
AC_SUBST(MOO_CXXFLAGS)
|
||||
AC_SUBST(MOO_LIBS)
|
||||
|
||||
# MOO_INI_IN_IN_RULE='%.ini.desktop.in: %.ini.desktop.in.in $(top_builddir)/config.status ; cd $(top_builddir) && $(SHELL) ./config.status --file=$(subdir)/[$]@'
|
||||
# MOO_INI_IN_RULE='%.ini: %.ini.in $(top_builddir)/config.status ; cd $(top_builddir) && $(SHELL) ./config.status --file=$(subdir)/[$]@'
|
||||
# MOO_WIN32_RC_RULE='%.res: %.rc.in $(top_builddir)/config.status ; cd $(top_builddir) && $(SHELL) ./config.status --file=$(subdir)/[$]*.rc && cd $(subdir) && $(WINDRES) -i [$]*.rc --input-format=rc -o [$]@ -O coff && rm [$]*.rc'
|
||||
# AC_SUBST(MOO_INI_IN_IN_RULE)
|
||||
# AC_SUBST(MOO_INI_IN_RULE)
|
||||
# AC_SUBST(MOO_WIN32_RC_RULE)
|
||||
|
||||
# MOO_XML2H='$(top_srcdir)/moo/mooutils/xml2h.sh'
|
||||
# MOO_GLADE_SUBDIR_RULE='%-glade.h: glade/%.glade $(MOO_XML2H) ; $(SHELL) $(top_srcdir)/moo/mooutils/xml2h.sh `basename "[$]*" | sed -e "s/-/_/"`_glade_xml [$]< > [$]@.tmp && mv [$]@.tmp [$]@'
|
||||
# MOO_GLADE_RULE='%-glade.h: %.glade $(MOO_XML2H) ; $(SHELL) $(top_srcdir)/moo/mooutils/xml2h.sh `basename "[$]*" | sed -e "s/-/_/"`_glade_xml [$]< > [$]@.tmp && mv [$]@.tmp [$]@'
|
||||
# AC_SUBST(MOO_XML2H)
|
||||
# AC_SUBST(MOO_GLADE_SUBDIR_RULE)
|
||||
# AC_SUBST(MOO_GLADE_RULE)
|
||||
])
|
|
@ -0,0 +1,100 @@
|
|||
##############################################################################
|
||||
# _MOO_SPLIT_VERSION(NAME,version)
|
||||
#
|
||||
AC_DEFUN([_MOO_SPLIT_VERSION],[AC_REQUIRE([LT_AC_PROG_SED])
|
||||
$1[]_VERSION="$2"
|
||||
$1[]_MAJOR_VERSION=`echo "$2" | $SED 's/\([[^.]][[^.]]*\).*/\1/'`
|
||||
$1[]_MINOR_VERSION=`echo "$2" | $SED 's/[[^.]][[^.]]*.\([[^.]][[^.]]*\).*/\1/'`
|
||||
$1[]_MICRO_VERSION=`echo "$2" | $SED 's/[[^.]][[^.]]*.[[^.]][[^.]]*.\(.*\)/\1/'`
|
||||
])
|
||||
|
||||
##############################################################################
|
||||
# _MOO_SPLIT_VERSION_PKG(PKG_NAME,pkg-name)
|
||||
#
|
||||
AC_DEFUN([_MOO_SPLIT_VERSION_PKG],[
|
||||
AC_MSG_CHECKING($1 version)
|
||||
_moo_ac_version=`$PKG_CONFIG --modversion $2`
|
||||
_MOO_SPLIT_VERSION([$1],[$_moo_ac_version])
|
||||
AC_MSG_RESULT($[]$1[]_MAJOR_VERSION.$[]$1[]_MINOR_VERSION.$[]$1[]_MICRO_VERSION)
|
||||
])
|
||||
|
||||
|
||||
##############################################################################
|
||||
# MOO_CHECK_MINOR_VERSION(PKG_NAME,pkg-name,versions)
|
||||
#
|
||||
AC_DEFUN([MOO_CHECK_MINOR_VERSION],[
|
||||
_MOO_SPLIT_VERSION_PKG($1,$2)
|
||||
m4_foreach([num],[$3],
|
||||
[AM_CONDITIONAL($1[]_2_[]num, test $[]$1[]_MINOR_VERSION -ge num)
|
||||
if test $[]$1[]_MINOR_VERSION -ge num; then
|
||||
$1[]_2_[]num=yes
|
||||
fi
|
||||
])
|
||||
])
|
||||
|
||||
|
||||
##############################################################################
|
||||
# _MOO_CHECK_BROKEN_GTK_THEME
|
||||
#
|
||||
AC_DEFUN([_MOO_CHECK_BROKEN_GTK_THEME],[
|
||||
AC_ARG_WITH([broken-gtk-theme], AS_HELP_STRING([--with-broken-gtk-theme],[Work around bug in gtk theme (Suse 9 has one)]), [
|
||||
if test x$with_broken_gtk_theme = "xyes"; then
|
||||
MOO_BROKEN_GTK_THEME="yes"
|
||||
fi
|
||||
])
|
||||
|
||||
if test x$MOO_BROKEN_GTK_THEME = xyes; then
|
||||
AC_MSG_NOTICE([Broken gtk theme])
|
||||
AC_DEFINE(MOO_BROKEN_GTK_THEME, 1, [broken gtk theme])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
##############################################################################
|
||||
# MOO_PKG_CHECK_GTK_VERSIONS
|
||||
#
|
||||
AC_DEFUN_ONCE([MOO_PKG_CHECK_GTK_VERSIONS],[
|
||||
AC_REQUIRE([MOO_AC_CHECK_OS])
|
||||
PKG_CHECK_MODULES(GTK, gtk+-2.0)
|
||||
PKG_CHECK_MODULES(GLIB, glib-2.0)
|
||||
PKG_CHECK_MODULES(GTHREAD, gthread-2.0)
|
||||
PKG_CHECK_MODULES(GMODULE, gmodule-2.0)
|
||||
# PKG_CHECK_MODULES(GDK, gdk-2.0)
|
||||
MOO_CHECK_MINOR_VERSION(GLIB, glib-2.0, [32])
|
||||
|
||||
PKG_CHECK_MODULES(XML, libxml-2.0)
|
||||
|
||||
_MOO_CHECK_BROKEN_GTK_THEME
|
||||
|
||||
gdk_target=`$PKG_CONFIG --variable=target gdk-2.0`
|
||||
|
||||
GDK_X11=false
|
||||
GDK_WIN32=false
|
||||
GDK_QUARTZ=false
|
||||
|
||||
case $gdk_target in
|
||||
x11)
|
||||
GDK_X11=true
|
||||
;;
|
||||
quartz)
|
||||
GDK_QUARTZ=true
|
||||
;;
|
||||
win32)
|
||||
GDK_WIN32=true
|
||||
;;
|
||||
esac
|
||||
|
||||
AM_CONDITIONAL(GDK_X11, $GDK_X11)
|
||||
AM_CONDITIONAL(GDK_WIN32, $GDK_WIN32)
|
||||
AM_CONDITIONAL(GDK_QUARTZ, $GDK_QUARTZ)
|
||||
|
||||
AC_SUBST(GLIB_GENMARSHAL, `$PKG_CONFIG --variable=glib_genmarshal glib-2.0`)
|
||||
AC_SUBST(GLIB_MKENUMS, `$PKG_CONFIG --variable=glib_mkenums glib-2.0`)
|
||||
|
||||
AC_ARG_VAR([GDK_PIXBUF_CSOURCE], [gdk-pixbuf-csource])
|
||||
AC_CHECK_TOOL(GDK_PIXBUF_CSOURCE, gdk-pixbuf-csource, [:])
|
||||
if test "$GDK_PIXBUF_CSOURCE" = ":"; then
|
||||
AC_MSG_ERROR([gdk-pixbuf-csource not found])
|
||||
fi
|
||||
|
||||
])
|
|
@ -0,0 +1,32 @@
|
|||
AC_DEFUN([_MOO_INTLTOOL],[
|
||||
AC_PATH_PROG(INTLTOOL_UPDATE, [intltool-update])
|
||||
AC_PATH_PROG(INTLTOOL_MERGE, [intltool-merge])
|
||||
AC_PATH_PROG(INTLTOOL_EXTRACT, [intltool-extract])
|
||||
if test -z "$INTLTOOL_UPDATE" -o -z "$INTLTOOL_MERGE" -o -z "$INTLTOOL_EXTRACT"; then
|
||||
AC_MSG_ERROR([The intltool scripts were not found. Please install intltool or use --disable-nls to ignore.])
|
||||
fi
|
||||
AC_SUBST(MOO_INTLTOOL_INI_DEPS,'$(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po)')
|
||||
AC_SUBST(MOO_INTLTOOL_INI_CMD,'$(AM''_V_GEN)LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@')
|
||||
])
|
||||
|
||||
AC_DEFUN([_MOO_INTLTOOL_NO_NLS],[
|
||||
AC_SUBST(MOO_INTLTOOL_INI_DEPS,'')
|
||||
AC_SUBST(MOO_INTLTOOL_INI_CMD,'$(AM''_V_GEN)sed -e "s/^_//g" $< > [$]@.tmp && mv [$]@.tmp [$]@')
|
||||
])
|
||||
|
||||
AC_DEFUN([MOO_INTL],[
|
||||
AM_GLIB_GNU_GETTEXT
|
||||
AC_ARG_ENABLE([nls],AS_HELP_STRING([--disable-nls],[do not use Native Language Support]),[
|
||||
ENABLE_NLS=$enableval
|
||||
],[
|
||||
ENABLE_NLS=yes
|
||||
])
|
||||
AC_SUBST([ENABLE_NLS])
|
||||
if test "$ENABLE_NLS" = "yes"; then
|
||||
_MOO_INTLTOOL
|
||||
AC_DEFINE(ENABLE_NLS, 1)
|
||||
else
|
||||
_MOO_INTLTOOL_NO_NLS
|
||||
fi
|
||||
AC_SUBST(MOO_PO_SUBDIRS_RULE,'$(top_srcdir)/po-gsv/Makefile.am: $(top_srcdir)/po/Makefile.am ; sed -e "s/GETTEXT_PACKAGE/GETTEXT_PACKAGE_GSV/g" $(top_srcdir)/po/Makefile.am > $(top_srcdir)/po-gsv/Makefile.am.tmp && mv $(top_srcdir)/po-gsv/Makefile.am.tmp $(top_srcdir)/po-gsv/Makefile.am')
|
||||
])
|
|
@ -0,0 +1,64 @@
|
|||
AC_DEFUN([MOO_AC_CHECK_OS],[
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
|
||||
m4_define([_moo_oses_],[CYGWIN WIN32 MINGW DARWIN UNIX FREEBSD BSD LINUX FDO])
|
||||
|
||||
m4_foreach_w([_moo_os_],_moo_oses_,[dnl
|
||||
MOO_OS_[]_moo_os_=false
|
||||
])
|
||||
|
||||
case $host in
|
||||
*-*-mingw32*)
|
||||
MOO_OS_WIN32=true
|
||||
MOO_OS_NAME="Win32"
|
||||
;;
|
||||
*-*-cygwin*)
|
||||
MOO_OS_CYGWIN=true
|
||||
MOO_OS_NAME="CygWin"
|
||||
;;
|
||||
*-*-darwin*)
|
||||
MOO_OS_DARWIN=true
|
||||
MOO_OS_NAME="Darwin"
|
||||
;;
|
||||
*-*-freebsd*)
|
||||
MOO_OS_FREEBSD=true
|
||||
MOO_OS_NAME="FreeBSD"
|
||||
;;
|
||||
*-*-linux*)
|
||||
MOO_OS_LINUX=true
|
||||
MOO_OS_NAME="Linux"
|
||||
;;
|
||||
*)
|
||||
MOO_OS_UNIX=true
|
||||
MOO_OS_NAME="Unix"
|
||||
;;
|
||||
esac
|
||||
|
||||
if $MOO_OS_WIN32; then : ; else MOO_OS_UNIX=true; fi
|
||||
if $MOO_OS_DARWIN; then MOO_OS_BSD=true; fi
|
||||
if $MOO_OS_FREEBSD; then MOO_OS_BSD=true; fi
|
||||
|
||||
m4_foreach_w([_moo_os_],_moo_oses_,[dnl
|
||||
AM_CONDITIONAL(MOO_OS_[]_moo_os_,[$MOO_OS_[]_moo_os_])
|
||||
])
|
||||
|
||||
])
|
||||
|
||||
# LT_LIB_M macro from libtool.m4
|
||||
AC_DEFUN([MOO_LT_LIB_M],
|
||||
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
|
||||
LIBM=
|
||||
case $host in
|
||||
*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
|
||||
# These system don't have libm, or don't need it
|
||||
;;
|
||||
*-ncr-sysv4.3*)
|
||||
AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
|
||||
AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
|
||||
;;
|
||||
*)
|
||||
AC_CHECK_LIB(m, cos, LIBM="-lm")
|
||||
;;
|
||||
esac
|
||||
AC_SUBST([LIBM])
|
||||
])# LT_LIB_M
|
|
@ -0,0 +1,57 @@
|
|||
##############################################################################
|
||||
# MOO_AC_PYTHON()
|
||||
#
|
||||
AC_DEFUN_ONCE([MOO_AC_PYTHON],[
|
||||
AC_REQUIRE([MOO_AC_CHECK_OS])
|
||||
|
||||
MOO_ENABLE_PYTHON=true
|
||||
_moo_want_python="auto"
|
||||
_moo_python_version=2.2
|
||||
|
||||
AC_ARG_WITH([python],AS_HELP_STRING([--with-python],[whether to compile python support (default = YES)]),[
|
||||
if test "x$with_python" = "xno"; then
|
||||
MOO_ENABLE_PYTHON=false
|
||||
elif test "x$with_python" = "xyes"; then
|
||||
_moo_want_python="yes"
|
||||
_moo_python_version="2.2"
|
||||
else
|
||||
_moo_want_python="yes"
|
||||
_moo_python_version="$with_python"
|
||||
fi
|
||||
])
|
||||
|
||||
if $MOO_ENABLE_PYTHON; then
|
||||
MOO_ENABLE_PYTHON=false
|
||||
MOO_AC_CHECK_PYTHON($_moo_python_version,[
|
||||
PKG_CHECK_MODULES(PYGTK,pygtk-2.0 >= 2.6.0,[
|
||||
MOO_ENABLE_PYTHON=true
|
||||
],[:])
|
||||
])
|
||||
|
||||
if $MOO_ENABLE_PYTHON; then
|
||||
AC_SUBST([PYGTK_DEFS_DIR],[`$PKG_CONFIG --variable=defsdir pygtk-2.0`])
|
||||
AC_SUBST([PYGOBJECT_DEFS_DIR],[`$PKG_CONFIG --variable=defsdir pygobject-2.0`])
|
||||
fi
|
||||
|
||||
if $MOO_ENABLE_PYTHON; then
|
||||
AC_MSG_NOTICE([compiling python support])
|
||||
elif test "x$_moo_want_python" = "xyes"; then
|
||||
AC_MSG_ERROR([python support requested but python cannot be used])
|
||||
elif test "x$_moo_want_python" = "xauto"; then
|
||||
AC_MSG_WARN([disabled python support])
|
||||
else
|
||||
AC_MSG_NOTICE([disabled python support])
|
||||
fi
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(MOO_ENABLE_PYTHON, $MOO_ENABLE_PYTHON)
|
||||
if $MOO_ENABLE_PYTHON; then
|
||||
AC_DEFINE(MOO_ENABLE_PYTHON, 1, [build python bindings and plugin])
|
||||
fi
|
||||
|
||||
if $MOO_ENABLE_PYTHON; then
|
||||
MOO_CFLAGS="$MOO_CFLAGS $PYGTK_CFLAGS $PYTHON_INCLUDES"
|
||||
MOO_CXXFLAGS="$MOO_CXXFLAGS $PYGTK_CFLAGS $PYTHON_INCLUDES"
|
||||
MOO_LIBS="$MOO_LIBS $PYGTK_LIBS $PYTHON_LIBS"
|
||||
fi
|
||||
])
|
|
@ -0,0 +1,147 @@
|
|||
##############################################################################
|
||||
# _MOO_AC_PYTHON_DEVEL(action-if-found,action-if-not-found)
|
||||
# checks python headers and libs. it's
|
||||
# http://www.gnu.org/software/ac-archive/htmldoc/ac_python_devel.html,
|
||||
# modified to allow actions if-found/if-not-found
|
||||
#
|
||||
AC_DEFUN([_MOO_AC_PYTHON_DEVEL],[
|
||||
python_found=no
|
||||
|
||||
if test "$cross_compiling" = yes; then
|
||||
test -z "$PYTHON_INCLUDES" || python_found=yes
|
||||
else
|
||||
# Check for distutils first
|
||||
AC_MSG_CHECKING([for the distutils Python package])
|
||||
$PYTHON -c "import distutils" 2>/dev/null
|
||||
if test $? -eq 0; then
|
||||
python_found=yes
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
python_found=no
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_WARN([cannot import Python module "distutils".
|
||||
Please check your Python installation.])
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for Python include path
|
||||
# if PYTHON_INCLUDES is set, do not do anything
|
||||
if test $python_found = yes; then
|
||||
AC_MSG_CHECKING([for Python include path])
|
||||
|
||||
if test -z "$PYTHON_INCLUDES"; then
|
||||
python_path=`$PYTHON -c "import distutils.sysconfig; \
|
||||
print distutils.sysconfig.get_python_inc();"`
|
||||
if test -n "${python_path}"; then
|
||||
python_path="-I$python_path"
|
||||
fi
|
||||
PYTHON_INCLUDES=$python_path
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT([$PYTHON_INCLUDES])
|
||||
AC_SUBST([PYTHON_INCLUDES])
|
||||
fi
|
||||
|
||||
# Check for Python linker flags
|
||||
# if PYTHON_LIBS is set, do not do anything
|
||||
if test $python_found = yes; then
|
||||
AC_MSG_CHECKING([Python linker flags])
|
||||
|
||||
if test "x$PYTHON_LIBS" = "x"; then
|
||||
# (makes two attempts to ensure we've got a version number
|
||||
# from the interpreter)
|
||||
py_version=`$PYTHON -c "from distutils.sysconfig import *; \
|
||||
from string import join; \
|
||||
print join(get_config_vars('VERSION'))"`
|
||||
if test "x$py_version" = "x[None]"; then
|
||||
if test "x$PYTHON_VERSION" != "x"; then
|
||||
py_version=$PYTHON_VERSION
|
||||
else
|
||||
py_version=`$PYTHON -c "import sys; \
|
||||
print sys.version[[:3]]"`
|
||||
fi
|
||||
fi
|
||||
|
||||
PYTHON_LIBS=`$PYTHON -c "from distutils.sysconfig import *; \
|
||||
from string import join; \
|
||||
print '-L' + PREFIX + '/lib', \
|
||||
'-lpython';"`$py_version
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT([$PYTHON_LIBS])
|
||||
AC_SUBST([PYTHON_LIBS])
|
||||
fi
|
||||
|
||||
if test $python_found = yes; then
|
||||
m4_if([$1],[],[:],[$1])
|
||||
else
|
||||
m4_if([$2],[],[:],[$2])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
##############################################################################
|
||||
# MOO_AC_CHECK_PYTHON_NATIVE(min-version,action-if-found,action-if-not-found)
|
||||
# checks python stuff when building for unix
|
||||
#
|
||||
AC_DEFUN([MOO_AC_CHECK_PYTHON_NATIVE],[
|
||||
m4_define_default([_AM_PYTHON_INTERPRETER_LIST],[python2 python2.7 python2.6 python])
|
||||
AM_PATH_PYTHON([$1],[
|
||||
_MOO_AC_PYTHON_DEVEL([
|
||||
python_found=yes
|
||||
],[
|
||||
AC_MSG_WARN([Found python interpreter but no development headers or libraries])
|
||||
python_found=no
|
||||
])
|
||||
],[
|
||||
python_found=no
|
||||
])
|
||||
|
||||
if test x$python_found = xyes; then
|
||||
m4_if([$2],[],[:],[$2])
|
||||
else
|
||||
PYTHON_INCLUDES=""
|
||||
PYTHON_LIBS=""
|
||||
m4_if([$3],[],[:],[$3])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN([MOO_AM_PYTHON_DEVEL_CROSS_MINGW],[
|
||||
if test x"$PYTHON_INCLUDES" = x -o x"$PYTHON_LIBS" = x -o x"$PYTHON_VERSION" = x; then
|
||||
AC_MSG_ERROR([The following variables must be set: PYTHON_INCLUDES, PYTHON_LIBS, PYTHON_VERSION])
|
||||
fi
|
||||
AC_ARG_VAR([PYTHON_INCLUDES], [python preprocessor flags])
|
||||
AC_ARG_VAR([PYTHON_LIBS], [python linker flags])
|
||||
AC_ARG_VAR([PYTHON_VERSION], [python version])
|
||||
|
||||
AC_SUBST(PYTHON_INCLUDES)
|
||||
AC_SUBST(PYTHON_LIBS)
|
||||
AC_MSG_CHECKING([for Python include path])
|
||||
AC_MSG_RESULT([$PYTHON_INCLUDES])
|
||||
AC_MSG_CHECKING([for Python linker flags])
|
||||
AC_MSG_RESULT([$PYTHON_LIBS])
|
||||
|
||||
AC_SUBST([PYTHON_VERSION],[$PYTHON_VERSION])
|
||||
AC_SUBST([PYTHON_PREFIX], ['${prefix}'])
|
||||
AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}'])
|
||||
AC_SUBST([PYTHON_PLATFORM], [nt])
|
||||
AC_SUBST([pythondir], [$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages])
|
||||
AC_SUBST([pyexecdir], [$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages])
|
||||
|
||||
$1
|
||||
])
|
||||
|
||||
|
||||
##############################################################################
|
||||
# MOO_AC_CHECK_PYTHON(min-version,action-if-found,action-if-not-found)
|
||||
# checks for python, python includes and libs
|
||||
#
|
||||
AC_DEFUN([MOO_AC_CHECK_PYTHON],[
|
||||
AC_REQUIRE([MOO_AC_CHECK_OS])
|
||||
if test "$cross_compiling" = yes -a "$MOO_OS_WIN32" = true; then
|
||||
MOO_AM_PYTHON_DEVEL_CROSS_MINGW([$2],[$3])
|
||||
else
|
||||
MOO_AC_CHECK_PYTHON_NATIVE([$1],[$2],[$3])
|
||||
fi
|
||||
])
|
|
@ -0,0 +1,199 @@
|
|||
FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/genmarshals_h.cmake
|
||||
"EXECUTE_PROCESS(COMMAND ${GLIB_GENMARSHAL} --prefix=_moo_marshal --header ${CMAKE_CURRENT_SOURCE_DIR}/marshals.list
|
||||
RESULT_VARIABLE result
|
||||
OUTPUT_VARIABLE output
|
||||
ERROR_VARIABLE error
|
||||
OUTPUT_FILE marshals.h.tmp)
|
||||
if(NOT result EQUAL 0)
|
||||
MESSAGE(FATAL_ERROR \"Error generating marshals.h: \${output} \${error}\")
|
||||
endif()
|
||||
file(RENAME marshals.h.tmp marshals.h)
|
||||
")
|
||||
add_custom_command(OUTPUT marshals.h
|
||||
COMMAND ${CMAKE_COMMAND} -P genmarshals_h.cmake
|
||||
MAIN_DEPENDENCY marshals.list)
|
||||
LIST(APPEND built_moo_sources marshals.h)
|
||||
|
||||
macro(ADD_GXML input)
|
||||
string(REPLACE ".glade" "-gxml.h" _gxml_output "${input}")
|
||||
string(REPLACE "/glade/" "/" _gxml_output "${_gxml_output}")
|
||||
#message(STATUS "_gxml_output: ${_gxml_output}")
|
||||
add_custom_command(OUTPUT ${_gxml_output}
|
||||
COMMAND ${MOO_PYTHON} ${CMAKE_SOURCE_DIR}/tools/glade2c.py --output=${_gxml_output} ${CMAKE_CURRENT_SOURCE_DIR}/${input}
|
||||
MAIN_DEPENDENCY ${input}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/tools/glade2c.py
|
||||
COMMENT "Generating ${_gxml_output} from ${input}")
|
||||
list(APPEND built_moo_sources ${_gxml_output})
|
||||
endmacro(ADD_GXML)
|
||||
|
||||
macro(XML2H _xml2h_input _xml2h_output _xml2h_variable)
|
||||
add_custom_command(OUTPUT ${_xml2h_output}
|
||||
COMMAND ${MOO_PYTHON} ${CMAKE_SOURCE_DIR}/tools/xml2h.py ${CMAKE_CURRENT_SOURCE_DIR}/${_xml2h_input} ${_xml2h_output} ${_xml2h_variable}
|
||||
MAIN_DEPENDENCY ${_xml2h_input}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/tools/xml2h.py
|
||||
COMMENT "Generating ${_xml2h_output} from ${_xml2h_input}")
|
||||
list(APPEND built_moo_sources ${_xml2h_output})
|
||||
endmacro(XML2H)
|
||||
|
||||
macro(ADD_UI input)
|
||||
string(REPLACE ".xml" "-ui.h" _ui_output "${input}")
|
||||
# message(STATUS "_ui_output: ${_ui_output}")
|
||||
string(REGEX REPLACE ".*/([^/]*)\\.xml" "\\1" _ui_variable "${input}")
|
||||
XML2H(${input} ${_ui_output} ${_ui_variable}_ui_xml)
|
||||
endmacro(ADD_UI)
|
||||
|
||||
file(MAKE_DIRECTORY
|
||||
${CMAKE_CURRENT_BINARY_DIR}/mooapp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/mooedit
|
||||
${CMAKE_CURRENT_BINARY_DIR}/moofileview
|
||||
${CMAKE_CURRENT_BINARY_DIR}/mooutils
|
||||
${CMAKE_CURRENT_BINARY_DIR}/moolua
|
||||
${CMAKE_CURRENT_BINARY_DIR}/plugins/usertools
|
||||
${CMAKE_CURRENT_BINARY_DIR}/medit-app
|
||||
)
|
||||
|
||||
include(xdgmime/xdgmime.cmake)
|
||||
include(moocpp/moocpp.cmake)
|
||||
include(mooutils/mooutils.cmake)
|
||||
include(mooedit/mooedit.cmake)
|
||||
include(moofileview/moofileview.cmake)
|
||||
include(gtksourceview/gtksourceview.cmake)
|
||||
if(NOT MOO_OS_WIN32)
|
||||
include(eggsmclient/eggsmclient.cmake)
|
||||
endif()
|
||||
include(mooapp/mooapp.cmake)
|
||||
include(moolua/moolua.cmake)
|
||||
if(MOO_ENABLE_PYTHON)
|
||||
include(moopython/moopython.cmake)
|
||||
endif()
|
||||
include(plugins/plugins.cmake)
|
||||
include(medit-app/medit-app.cmake)
|
||||
|
||||
SET(MEDIT_SOURCES
|
||||
CMakeLists.txt
|
||||
${moo_sources}
|
||||
${built_moo_sources}
|
||||
)
|
||||
|
||||
macro(ADD_MODULE name)
|
||||
string(REPLACE "-" "_" _escaped_name "${name}")
|
||||
source_group(${name} FILES ${${_escaped_name}_sources} ${${_escaped_name}_extra_files})
|
||||
source_group(${name}\\generated FILES ${built_${_escaped_name}_sources})
|
||||
#source_group(${name} FILES ${${_escaped_name}_sources} ${${_escaped_name}_extra_files})
|
||||
#source_group(${name}\\generated FILES ${built_${_escaped_name}_sources})
|
||||
LIST(APPEND MEDIT_SOURCES ${${_escaped_name}_sources} ${built_${_escaped_name}_sources})
|
||||
LIST(APPEND MEDIT_EXTRA_DIST ${${_escaped_name}_extra_dist} ${${_escaped_name}_extra_files})
|
||||
endmacro(ADD_MODULE)
|
||||
|
||||
ADD_MODULE(xdgmime)
|
||||
ADD_MODULE(eggsmclient)
|
||||
ADD_MODULE(gtksourceview)
|
||||
ADD_MODULE(moocpp)
|
||||
ADD_MODULE(mooutils)
|
||||
ADD_MODULE(moofileview)
|
||||
ADD_MODULE(mooedit)
|
||||
ADD_MODULE(mooapp)
|
||||
ADD_MODULE(plugins)
|
||||
ADD_MODULE(moolua)
|
||||
if(MOO_ENABLE_PYTHON)
|
||||
ADD_MODULE(moopython)
|
||||
endif()
|
||||
ADD_MODULE(medit-app)
|
||||
|
||||
if(WIN32)
|
||||
include_directories(${PROJECT_SOURCE_DIR}/moo/mooutils/moowin32/ms)
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
${PROJECT_BINARY_DIR}
|
||||
${GTK_INCLUDE_DIRS}
|
||||
${LIBXML2_INCLUDE_DIRS}
|
||||
)
|
||||
link_directories(${GTK_LIBRARY_DIRS} ${GMODULE_LIBRARY_DIRS})
|
||||
|
||||
source_group(misc REGULAR_EXPRESSION .*)
|
||||
source_group("generated\\sources" REGULAR_EXPRESSION ".*\\.c(pp)?$")
|
||||
source_group("generated\\headers" REGULAR_EXPRESSION ".*\\.h$")
|
||||
source_group("misc\\glade" REGULAR_EXPRESSION ".*\\.glade$")
|
||||
|
||||
set(MOO_USE_PCH ${WIN32})
|
||||
if(MOO_USE_PCH)
|
||||
set(MEDIT_PCH_SOURCES
|
||||
moo-pch.c
|
||||
moo-pch.cpp
|
||||
moo-pch.h
|
||||
)
|
||||
endif()
|
||||
|
||||
add_executable(medit WIN32
|
||||
${MEDIT_SOURCES}
|
||||
${MEDIT_PCH_SOURCES}
|
||||
)
|
||||
|
||||
if(MOO_USE_PCH)
|
||||
add_precompiled_header(medit
|
||||
moo-pch.h
|
||||
FORCEINCLUDE
|
||||
SOURCE_C moo-pch.c
|
||||
SOURCE_CXX moo-pch.cpp)
|
||||
endif()
|
||||
|
||||
if(MOO_BUILD_FROM_MINGW)
|
||||
LIST(APPEND MEDIT_LIBS libmooglib-0)
|
||||
endif()
|
||||
|
||||
target_link_libraries(medit
|
||||
${GTK_LIBRARIES}
|
||||
${GMODULE_LIBRARIES}
|
||||
${LIBXML2_LIBRARIES}
|
||||
${XLIB_LIBRARIES}
|
||||
#${LIBM}
|
||||
${PYTHON_LIBRARY}
|
||||
${moo_libadd}
|
||||
${MEDIT_LIBS}
|
||||
)
|
||||
|
||||
install(TARGETS medit RUNTIME DESTINATION bin)
|
||||
|
||||
if(MOO_BUILD_FROM_MINGW)
|
||||
# xxx this is wrong, doing it temporarily so it doesn't install python lib every time
|
||||
if(NOT EXISTS "${MOO_GTK_DIST_DIR}/bin/libglib-2.0-0.dll")
|
||||
install(DIRECTORY ${MOO_GTK_DIST_DIR}/bin DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
install(DIRECTORY ${MOO_GTK_DIST_DIR}/etc DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
install(DIRECTORY ${MOO_GTK_DIST_DIR}/lib DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
install(DIRECTORY ${MOO_GTK_DIST_DIR}/share DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
endif()
|
||||
|
||||
#install(DIRECTORY ${CMAKE_SOURCE_DIR}/plat/win32/gtk-win/extra/medit-data/bin DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
#install(DIRECTORY ${CMAKE_SOURCE_DIR}/plat/win32/gtk-win/extra/medit-data/etc DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
endif()
|
||||
|
||||
# zzz
|
||||
# if MOO_OS_UNIX
|
||||
# desktopdir = $(datadir)/applications
|
||||
# desktop_DATA = medit-app/medit.desktop
|
||||
# medit-app/medit.desktop: medit-app/medit.desktop.in @MOO_INTLTOOL_INI_DEPS@
|
||||
# $(AM_V_at)$(MKDIR_P) medit-app
|
||||
# @MOO_INTLTOOL_INI_CMD@
|
||||
# CLEANFILES += medit-app/medit.desktop
|
||||
# endif MOO_OS_UNIX
|
||||
|
||||
# zzz
|
||||
# iconthemedir = $(datadir)/icons/hicolor/48x48/apps
|
||||
# icontheme_DATA = mooutils/pixmaps/medit.png
|
||||
# if MOO_ENABLE_INSTALL_HOOKS
|
||||
# update_icon_cache = gtk-update-icon-cache -f -t $(DESTDIR)$(datadir)/icons/hicolor
|
||||
# install-data-hook: install-data-hook-gtk-icon-cache
|
||||
# install-data-hook-gtk-icon-cache:
|
||||
# @if echo "Updating icon cache" && $(update_icon_cache); then
|
||||
# echo "Done.";
|
||||
# else
|
||||
# echo "*** GTK icon cache not updated. After install, run this:";\
|
||||
# echo $(update_icon_cache);
|
||||
# fi
|
||||
# uninstall-hook: uninstall-data-hook-gtk-icon-cache
|
||||
# uninstall-data-hook-gtk-icon-cache:
|
||||
# @if echo "Updating icon cache" && $(update_icon_cache); then echo "Done."; else echo "Failed."; fi
|
||||
# endif
|
||||
|
||||
# zzz include medit-module/Makefile.incl
|
|
@ -0,0 +1,97 @@
|
|||
EXTRA_DIST =
|
||||
BUILT_SOURCES =
|
||||
CLEANFILES =
|
||||
bin_PROGRAMS =
|
||||
noinst_LIBRARIES =
|
||||
|
||||
AM_CPPFLAGS = $(MOO_CPPFLAGS) -I$(top_srcdir)/doc/built -Imooutils/glade
|
||||
AM_CFLAGS = $(MOO_CFLAGS)
|
||||
AM_CXXFLAGS = $(MOO_CXXFLAGS)
|
||||
|
||||
moo_sources =
|
||||
built_moo_sources =
|
||||
moo_libadd =
|
||||
|
||||
plugins_sources =
|
||||
built_plugins_sources =
|
||||
|
||||
moo_srcdir = $(srcdir)
|
||||
moo_builddir = .
|
||||
|
||||
moo_sources += moo-config.h
|
||||
|
||||
moo_sources += \
|
||||
mooglib/moo-glib.h \
|
||||
mooglib/moo-stat.h \
|
||||
mooglib/moo-time.h
|
||||
EXTRA_DIST += \
|
||||
mooglib/moo-glib.cpp
|
||||
|
||||
if !MOO_OS_WIN32
|
||||
moo_sources += mooglib/moo-glib.cpp
|
||||
endif
|
||||
|
||||
EXTRA_DIST += marshals.list
|
||||
built_moo_sources += marshals.h
|
||||
marshals.h: marshals.list
|
||||
$(AM_V_GEN)$(GLIB_GENMARSHAL) --prefix=_moo_marshal --header $(srcdir)/marshals.list > marshals.h.tmp \
|
||||
&& mv marshals.h.tmp marshals.h
|
||||
|
||||
include mooedit/Makefile.incl
|
||||
include xdgmime/Makefile.incl
|
||||
include mooutils/Makefile.incl
|
||||
include moofileview/Makefile.incl
|
||||
include gtksourceview/Makefile.incl
|
||||
include eggsmclient/Makefile.incl
|
||||
include mooapp/Makefile.incl
|
||||
include moolua/Makefile.incl
|
||||
include moopython/Makefile.incl
|
||||
include plugins/Makefile.incl
|
||||
include medit-app/Makefile.incl
|
||||
include medit-module/Makefile.incl
|
||||
include moocpp/Makefile.incl
|
||||
|
||||
BUILT_SOURCES += $(built_moo_sources) $(built_plugins_sources)
|
||||
CLEANFILES += $(built_moo_sources) $(built_plugins_sources)
|
||||
|
||||
test:
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) test
|
||||
|
||||
# glade/%-gxml.h: glade/%.glade $(top_srcdir)/tools/glade2c.py
|
||||
# $(MKDIR_P) glade
|
||||
# $(MOO_PYTHON) $(top_srcdir)/tools/glade2c.py $< > $@.tmp && mv $@.tmp $@
|
||||
|
||||
mooutils/%-gxml.h: mooutils/glade/%.glade $(top_srcdir)/tools/glade2c.py
|
||||
$(AM_V_at) $(MKDIR_P) `dirname $@`
|
||||
$(AM_V_GEN)$(MOO_PYTHON) $(top_srcdir)/tools/glade2c.py $< > $@.tmp && mv $@.tmp $@
|
||||
|
||||
moofileview/%-gxml.h: moofileview/glade/%.glade $(top_srcdir)/tools/glade2c.py
|
||||
$(AM_V_at) $(MKDIR_P) `dirname $@`
|
||||
$(AM_V_GEN)$(MOO_PYTHON) $(top_srcdir)/tools/glade2c.py $< > $@.tmp && mv $@.tmp $@
|
||||
|
||||
mooedit/%-gxml.h: mooedit/glade/%.glade $(top_srcdir)/tools/glade2c.py
|
||||
$(AM_V_at) $(MKDIR_P) `dirname $@`
|
||||
$(AM_V_GEN)$(MOO_PYTHON) $(top_srcdir)/tools/glade2c.py $< > $@.tmp && mv $@.tmp $@
|
||||
|
||||
mooapp/%-gxml.h: mooapp/glade/%.glade $(top_srcdir)/tools/glade2c.py
|
||||
$(AM_V_at) $(MKDIR_P) `dirname $@`
|
||||
$(AM_V_GEN)$(MOO_PYTHON) $(top_srcdir)/tools/glade2c.py $< > $@.tmp && mv $@.tmp $@
|
||||
|
||||
plugins/%-gxml.h: plugins/glade/%.glade $(top_srcdir)/tools/glade2c.py
|
||||
$(AM_V_at) $(MKDIR_P) `dirname $@`
|
||||
$(AM_V_GEN)$(MOO_PYTHON) $(top_srcdir)/tools/glade2c.py $< > $@.tmp && mv $@.tmp $@
|
||||
|
||||
plugins/usertools/%-gxml.h: plugins/usertools/glade/%.glade $(top_srcdir)/tools/glade2c.py
|
||||
$(AM_V_at) $(MKDIR_P) `dirname $@`
|
||||
$(AM_V_GEN)$(MOO_PYTHON) $(top_srcdir)/tools/glade2c.py $< > $@.tmp && mv $@.tmp $@
|
||||
|
||||
# %-ui.h: %.xml $(top_srcdir)/tools/xml2h.py
|
||||
# $(AM_V_GEN)$(MOO_PYTHON) $(top_srcdir)/tools/xml2h.py $< $@.tmp $*_ui_xml && mv $@.tmp $@
|
||||
|
||||
moofileview/%-ui.h: moofileview/%.xml $(top_srcdir)/tools/xml2h.py
|
||||
$(AM_V_at) $(MKDIR_P) `dirname $@`
|
||||
$(AM_V_GEN)$(MOO_PYTHON) $(top_srcdir)/tools/xml2h.py $< $@.tmp $*_ui_xml && mv $@.tmp $@
|
||||
|
||||
mooedit/%-ui.h: mooedit/%.xml $(top_srcdir)/tools/xml2h.py
|
||||
$(AM_V_at) $(MKDIR_P) `dirname $@`
|
||||
$(AM_V_GEN)$(MOO_PYTHON) $(top_srcdir)/tools/xml2h.py $< $@.tmp $*_ui_xml && mv $@.tmp $@
|
|
@ -0,0 +1,18 @@
|
|||
moo_sources += \
|
||||
eggsmclient/eggsmclient.c \
|
||||
eggsmclient/eggsmclient.h \
|
||||
eggsmclient/eggsmclient-mangle.h \
|
||||
eggsmclient/eggsmclient-private.h
|
||||
|
||||
if MOO_OS_WIN32
|
||||
moo_sources += eggsmclient/eggsmclient-win32.c
|
||||
else !MOO_OS_WIN32
|
||||
if MOO_OS_DARWIN
|
||||
moo_sources += eggsmclient/eggsmclient-dummy.c
|
||||
else !MOO_OS_DARWIN
|
||||
AM_CFLAGS += -DEGG_SM_CLIENT_BACKEND_XSMP
|
||||
moo_sources += eggsmclient/eggsmclient-xsmp.c eggsmclient/eggdesktopfile.h eggsmclient/eggdesktopfile.c
|
||||
endif !MOO_OS_DARWIN
|
||||
endif !MOO_OS_WIN32
|
||||
|
||||
# -%- strip:true -%-
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,163 @@
|
|||
/* eggdesktopfile.h - Freedesktop.Org Desktop Files
|
||||
* Copyright (C) 2007 Novell, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; see the file COPYING.LIB. If not,
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place -
|
||||
* Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __EGG_DESKTOP_FILE_H__
|
||||
#define __EGG_DESKTOP_FILE_H__
|
||||
|
||||
#include <mooglib/moo-glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct EggDesktopFile EggDesktopFile;
|
||||
|
||||
typedef enum {
|
||||
EGG_DESKTOP_FILE_TYPE_UNRECOGNIZED,
|
||||
|
||||
EGG_DESKTOP_FILE_TYPE_APPLICATION,
|
||||
EGG_DESKTOP_FILE_TYPE_LINK,
|
||||
EGG_DESKTOP_FILE_TYPE_DIRECTORY
|
||||
} EggDesktopFileType;
|
||||
|
||||
EggDesktopFile *egg_desktop_file_new (const char *desktop_file_path,
|
||||
GError **error);
|
||||
|
||||
EggDesktopFile *egg_desktop_file_new_from_data_dirs (const char *desktop_file_path,
|
||||
GError **error);
|
||||
EggDesktopFile *egg_desktop_file_new_from_dirs (const char *desktop_file_path,
|
||||
const char **search_dirs,
|
||||
GError **error);
|
||||
EggDesktopFile *egg_desktop_file_new_from_key_file (GKeyFile *key_file,
|
||||
const char *source,
|
||||
GError **error);
|
||||
|
||||
void egg_desktop_file_free (EggDesktopFile *desktop_file);
|
||||
|
||||
const char *egg_desktop_file_get_source (EggDesktopFile *desktop_file);
|
||||
|
||||
EggDesktopFileType egg_desktop_file_get_desktop_file_type (EggDesktopFile *desktop_file);
|
||||
|
||||
const char *egg_desktop_file_get_name (EggDesktopFile *desktop_file);
|
||||
const char *egg_desktop_file_get_icon (EggDesktopFile *desktop_file);
|
||||
|
||||
gboolean egg_desktop_file_can_launch (EggDesktopFile *desktop_file,
|
||||
const char *desktop_environment);
|
||||
|
||||
gboolean egg_desktop_file_accepts_documents (EggDesktopFile *desktop_file);
|
||||
gboolean egg_desktop_file_accepts_multiple (EggDesktopFile *desktop_file);
|
||||
gboolean egg_desktop_file_accepts_uris (EggDesktopFile *desktop_file);
|
||||
|
||||
char *egg_desktop_file_parse_exec (EggDesktopFile *desktop_file,
|
||||
GSList *documents,
|
||||
GError **error);
|
||||
|
||||
gboolean egg_desktop_file_launch (EggDesktopFile *desktop_file,
|
||||
GSList *documents,
|
||||
GError **error,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
|
||||
typedef enum {
|
||||
EGG_DESKTOP_FILE_LAUNCH_CLEARENV = 1,
|
||||
EGG_DESKTOP_FILE_LAUNCH_PUTENV,
|
||||
EGG_DESKTOP_FILE_LAUNCH_SCREEN,
|
||||
EGG_DESKTOP_FILE_LAUNCH_WORKSPACE,
|
||||
EGG_DESKTOP_FILE_LAUNCH_DIRECTORY,
|
||||
EGG_DESKTOP_FILE_LAUNCH_TIME,
|
||||
EGG_DESKTOP_FILE_LAUNCH_FLAGS,
|
||||
EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC,
|
||||
EGG_DESKTOP_FILE_LAUNCH_RETURN_PID,
|
||||
EGG_DESKTOP_FILE_LAUNCH_RETURN_STDIN_PIPE,
|
||||
EGG_DESKTOP_FILE_LAUNCH_RETURN_STDOUT_PIPE,
|
||||
EGG_DESKTOP_FILE_LAUNCH_RETURN_STDERR_PIPE,
|
||||
EGG_DESKTOP_FILE_LAUNCH_RETURN_STARTUP_ID
|
||||
} EggDesktopFileLaunchOption;
|
||||
|
||||
/* Standard Keys */
|
||||
#define EGG_DESKTOP_FILE_GROUP "Desktop Entry"
|
||||
|
||||
#define EGG_DESKTOP_FILE_KEY_TYPE "Type"
|
||||
#define EGG_DESKTOP_FILE_KEY_VERSION "Version"
|
||||
#define EGG_DESKTOP_FILE_KEY_NAME "Name"
|
||||
#define EGG_DESKTOP_FILE_KEY_GENERIC_NAME "GenericName"
|
||||
#define EGG_DESKTOP_FILE_KEY_NO_DISPLAY "NoDisplay"
|
||||
#define EGG_DESKTOP_FILE_KEY_COMMENT "Comment"
|
||||
#define EGG_DESKTOP_FILE_KEY_ICON "Icon"
|
||||
#define EGG_DESKTOP_FILE_KEY_HIDDEN "Hidden"
|
||||
#define EGG_DESKTOP_FILE_KEY_ONLY_SHOW_IN "OnlyShowIn"
|
||||
#define EGG_DESKTOP_FILE_KEY_NOT_SHOW_IN "NotShowIn"
|
||||
#define EGG_DESKTOP_FILE_KEY_TRY_EXEC "TryExec"
|
||||
#define EGG_DESKTOP_FILE_KEY_EXEC "Exec"
|
||||
#define EGG_DESKTOP_FILE_KEY_PATH "Path"
|
||||
#define EGG_DESKTOP_FILE_KEY_TERMINAL "Terminal"
|
||||
#define EGG_DESKTOP_FILE_KEY_MIME_TYPE "MimeType"
|
||||
#define EGG_DESKTOP_FILE_KEY_CATEGORIES "Categories"
|
||||
#define EGG_DESKTOP_FILE_KEY_STARTUP_NOTIFY "StartupNotify"
|
||||
#define EGG_DESKTOP_FILE_KEY_STARTUP_WM_CLASS "StartupWMClass"
|
||||
#define EGG_DESKTOP_FILE_KEY_URL "URL"
|
||||
|
||||
/* Accessors */
|
||||
gboolean egg_desktop_file_has_key (EggDesktopFile *desktop_file,
|
||||
const char *key,
|
||||
GError **error);
|
||||
char *egg_desktop_file_get_string (EggDesktopFile *desktop_file,
|
||||
const char *key,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
char *egg_desktop_file_get_locale_string (EggDesktopFile *desktop_file,
|
||||
const char *key,
|
||||
const char *locale,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
gboolean egg_desktop_file_get_boolean (EggDesktopFile *desktop_file,
|
||||
const char *key,
|
||||
GError **error);
|
||||
double egg_desktop_file_get_numeric (EggDesktopFile *desktop_file,
|
||||
const char *key,
|
||||
GError **error);
|
||||
int egg_desktop_file_get_integer (EggDesktopFile *desktop_file,
|
||||
const char *key,
|
||||
GError **error);
|
||||
char **egg_desktop_file_get_string_list (EggDesktopFile *desktop_file,
|
||||
const char *key,
|
||||
gsize *length,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
char **egg_desktop_file_get_locale_string_list (EggDesktopFile *desktop_file,
|
||||
const char *key,
|
||||
const char *locale,
|
||||
gsize *length,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
|
||||
|
||||
/* Errors */
|
||||
#define EGG_DESKTOP_FILE_ERROR egg_desktop_file_error_quark()
|
||||
|
||||
GQuark egg_desktop_file_error_quark (void);
|
||||
|
||||
typedef enum {
|
||||
EGG_DESKTOP_FILE_ERROR_INVALID,
|
||||
EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE,
|
||||
EGG_DESKTOP_FILE_ERROR_UNRECOGNIZED_OPTION
|
||||
} EggDesktopFileError;
|
||||
|
||||
/* Global application desktop file */
|
||||
void egg_set_desktop_file (const char *desktop_file_path);
|
||||
void egg_set_desktop_file_without_defaults (const char *desktop_file_path);
|
||||
EggDesktopFile *egg_get_desktop_file (void);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __EGG_DESKTOP_FILE_H__ */
|
|
@ -0,0 +1,297 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "eggsmclient.h"
|
||||
#include "eggsmclient-private.h"
|
||||
|
||||
#include "eggdesktopfile.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <dbus/dbus-glib.h>
|
||||
|
||||
#define GSM_DBUS_NAME "org.gnome.SessionManager"
|
||||
#define GSM_DBUS_PATH "/org/gnome/SessionManager"
|
||||
#define GSM_DBUS_INTERFACE "org.gnome.SessionManager"
|
||||
|
||||
#define GSM_CLIENT_PRIVATE_DBUS_INTERFACE "org.gnome.SessionManager.ClientPrivate"
|
||||
#define GSM_CLIENT_DBUS_INTERFACE "org.gnome.SessionManager.Client"
|
||||
|
||||
#define EGG_TYPE_SM_CLIENT_DBUS (egg_sm_client_dbus_get_type ())
|
||||
#define EGG_SM_CLIENT_DBUS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SM_CLIENT_DBUS, EggSMClientDBus))
|
||||
#define EGG_SM_CLIENT_DBUS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SM_CLIENT_DBUS, EggSMClientDBusClass))
|
||||
#define EGG_IS_SM_CLIENT_DBUS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SM_CLIENT_DBUS))
|
||||
#define EGG_IS_SM_CLIENT_DBUS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SM_CLIENT_DBUS))
|
||||
#define EGG_SM_CLIENT_DBUS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SM_CLIENT_DBUS, EggSMClientDBusClass))
|
||||
|
||||
typedef struct _EggSMClientDBus EggSMClientDBus;
|
||||
typedef struct _EggSMClientDBusClass EggSMClientDBusClass;
|
||||
|
||||
struct _EggSMClientDBus
|
||||
{
|
||||
EggSMClient parent;
|
||||
|
||||
DBusGConnection *conn;
|
||||
DBusGProxy *sm_proxy, *client_proxy;
|
||||
char *client_path;
|
||||
};
|
||||
|
||||
struct _EggSMClientDBusClass
|
||||
{
|
||||
EggSMClientClass parent_class;
|
||||
|
||||
};
|
||||
|
||||
static void sm_client_dbus_startup (EggSMClient *client,
|
||||
const char *client_id);
|
||||
static void sm_client_dbus_will_quit (EggSMClient *client,
|
||||
gboolean will_quit);
|
||||
static gboolean sm_client_dbus_end_session (EggSMClient *client,
|
||||
EggSMClientEndStyle style,
|
||||
gboolean request_confirmation);
|
||||
|
||||
static void dbus_client_query_end_session (DBusGProxy *proxy,
|
||||
guint flags,
|
||||
gpointer smclient);
|
||||
static void dbus_client_end_session (DBusGProxy *proxy,
|
||||
guint flags,
|
||||
gpointer smclient);
|
||||
static void dbus_client_cancel_end_session (DBusGProxy *proxy,
|
||||
gpointer smclient);
|
||||
static void dbus_client_stop (DBusGProxy *proxy,
|
||||
gpointer smclient);
|
||||
|
||||
G_DEFINE_TYPE (EggSMClientDBus, egg_sm_client_dbus, EGG_TYPE_SM_CLIENT)
|
||||
|
||||
static void
|
||||
egg_sm_client_dbus_init (EggSMClientDBus *dbus)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static void
|
||||
egg_sm_client_dbus_class_init (EggSMClientDBusClass *klass)
|
||||
{
|
||||
EggSMClientClass *sm_client_class = EGG_SM_CLIENT_CLASS (klass);
|
||||
|
||||
sm_client_class->startup = sm_client_dbus_startup;
|
||||
sm_client_class->will_quit = sm_client_dbus_will_quit;
|
||||
sm_client_class->end_session = sm_client_dbus_end_session;
|
||||
}
|
||||
|
||||
EggSMClient *
|
||||
egg_sm_client_dbus_new (void)
|
||||
{
|
||||
DBusGConnection *conn;
|
||||
DBusGProxy *proxy;
|
||||
EggSMClientDBus *dbus;
|
||||
|
||||
conn = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
|
||||
if (!conn)
|
||||
return NULL;
|
||||
|
||||
proxy = dbus_g_proxy_new_for_name (conn, GSM_DBUS_NAME, GSM_DBUS_PATH,
|
||||
GSM_DBUS_INTERFACE);
|
||||
if (!proxy)
|
||||
{
|
||||
g_object_unref (conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dbus = g_object_new (EGG_TYPE_SM_CLIENT_DBUS, NULL);
|
||||
dbus->conn = conn;
|
||||
dbus->sm_proxy = proxy;
|
||||
return (EggSMClient *)dbus;
|
||||
}
|
||||
|
||||
static void
|
||||
sm_client_dbus_startup (EggSMClient *client,
|
||||
const char *client_id)
|
||||
{
|
||||
EggSMClientDBus *dbus = (EggSMClientDBus *)client;
|
||||
GError *error = NULL;
|
||||
char *client_path, *ret_client_id;
|
||||
DBusGProxy *client_public;
|
||||
|
||||
if (!dbus_g_proxy_call (dbus->sm_proxy, "RegisterClient", &error,
|
||||
G_TYPE_STRING, g_get_prgname (),
|
||||
G_TYPE_STRING, client_id,
|
||||
G_TYPE_INVALID,
|
||||
DBUS_TYPE_G_OBJECT_PATH, &client_path,
|
||||
G_TYPE_INVALID))
|
||||
{
|
||||
g_warning ("Failed to register client: %s", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_debug ("Client registered with session manager: %s", client_path);
|
||||
dbus->client_proxy = dbus_g_proxy_new_for_name (dbus->conn, GSM_DBUS_NAME,
|
||||
client_path,
|
||||
GSM_CLIENT_PRIVATE_DBUS_INTERFACE);
|
||||
dbus_g_proxy_add_signal (dbus->client_proxy, "QueryEndSession",
|
||||
G_TYPE_UINT,
|
||||
G_TYPE_INVALID);
|
||||
dbus_g_proxy_connect_signal (dbus->client_proxy, "QueryEndSession",
|
||||
G_CALLBACK (dbus_client_query_end_session),
|
||||
dbus, NULL);
|
||||
dbus_g_proxy_add_signal (dbus->client_proxy, "EndSession",
|
||||
G_TYPE_UINT,
|
||||
G_TYPE_INVALID);
|
||||
dbus_g_proxy_connect_signal (dbus->client_proxy, "EndSession",
|
||||
G_CALLBACK (dbus_client_end_session),
|
||||
dbus, NULL);
|
||||
dbus_g_proxy_add_signal (dbus->client_proxy, "CancelEndSession",
|
||||
G_TYPE_INVALID);
|
||||
dbus_g_proxy_connect_signal (dbus->client_proxy, "CancelEndSession",
|
||||
G_CALLBACK (dbus_client_cancel_end_session),
|
||||
dbus, NULL);
|
||||
dbus_g_proxy_add_signal (dbus->client_proxy, "Stop",
|
||||
G_TYPE_INVALID);
|
||||
dbus_g_proxy_connect_signal (dbus->client_proxy, "Stop",
|
||||
G_CALLBACK (dbus_client_stop),
|
||||
dbus, NULL);
|
||||
|
||||
client_public = dbus_g_proxy_new_for_name (dbus->conn, GSM_DBUS_NAME,
|
||||
client_path,
|
||||
GSM_CLIENT_DBUS_INTERFACE);
|
||||
if (dbus_g_proxy_call (client_public, "GetStartupId", &error,
|
||||
G_TYPE_INVALID,
|
||||
G_TYPE_STRING, &ret_client_id,
|
||||
G_TYPE_INVALID))
|
||||
{
|
||||
gdk_threads_enter ();
|
||||
#if !GTK_CHECK_VERSION(2,23,3) && !GTK_CHECK_VERSION(3,0,0)
|
||||
gdk_set_sm_client_id (ret_client_id);
|
||||
#else
|
||||
gdk_x11_set_sm_client_id (ret_client_id);
|
||||
#endif
|
||||
gdk_threads_leave ();
|
||||
|
||||
g_debug ("Got client ID \"%s\"", ret_client_id);
|
||||
g_free (ret_client_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Could not get client id: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
g_object_unref (client_public);
|
||||
}
|
||||
|
||||
static void
|
||||
sm_client_dbus_shutdown (EggSMClient *client)
|
||||
{
|
||||
EggSMClientDBus *dbus = EGG_SM_CLIENT_DBUS (client);
|
||||
GError *error = NULL;
|
||||
|
||||
if (!dbus_g_proxy_call (dbus->sm_proxy, "UnregisterClient", &error,
|
||||
DBUS_TYPE_G_OBJECT_PATH, dbus->client_path,
|
||||
G_TYPE_INVALID,
|
||||
G_TYPE_INVALID))
|
||||
{
|
||||
g_warning ("Failed to unregister client: %s", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_free (dbus->client_path);
|
||||
dbus->client_path = NULL;
|
||||
|
||||
g_object_unref (dbus->client_proxy);
|
||||
dbus->client_proxy = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_client_query_end_session (DBusGProxy *proxy,
|
||||
guint flags,
|
||||
gpointer smclient)
|
||||
{
|
||||
egg_sm_client_quit_requested (smclient);
|
||||
}
|
||||
|
||||
static void
|
||||
sm_client_dbus_will_quit (EggSMClient *client,
|
||||
gboolean will_quit)
|
||||
{
|
||||
EggSMClientDBus *dbus = (EggSMClientDBus *)client;
|
||||
|
||||
g_return_if_fail (dbus->client_proxy != NULL);
|
||||
|
||||
dbus_g_proxy_call (dbus->client_proxy, "EndSessionResponse", NULL,
|
||||
G_TYPE_BOOLEAN, will_quit,
|
||||
G_TYPE_STRING, NULL,
|
||||
G_TYPE_INVALID,
|
||||
G_TYPE_INVALID);
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_client_end_session (DBusGProxy *proxy,
|
||||
guint flags,
|
||||
gpointer smclient)
|
||||
{
|
||||
sm_client_dbus_will_quit (smclient, TRUE);
|
||||
sm_client_dbus_shutdown (smclient);
|
||||
egg_sm_client_quit (smclient);
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_client_cancel_end_session (DBusGProxy *proxy,
|
||||
gpointer smclient)
|
||||
{
|
||||
egg_sm_client_quit_cancelled (smclient);
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_client_stop (DBusGProxy *proxy,
|
||||
gpointer smclient)
|
||||
{
|
||||
sm_client_dbus_shutdown (smclient);
|
||||
egg_sm_client_quit (smclient);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sm_client_dbus_end_session (EggSMClient *client,
|
||||
EggSMClientEndStyle style,
|
||||
gboolean request_confirmation)
|
||||
{
|
||||
EggSMClientDBus *dbus = (EggSMClientDBus *)client;
|
||||
|
||||
if (style == EGG_SM_CLIENT_END_SESSION_DEFAULT ||
|
||||
style == EGG_SM_CLIENT_LOGOUT)
|
||||
{
|
||||
return dbus_g_proxy_call (dbus->sm_proxy, "Logout", NULL,
|
||||
G_TYPE_UINT, request_confirmation ? 0 : 1,
|
||||
G_TYPE_INVALID,
|
||||
G_TYPE_INVALID);
|
||||
}
|
||||
else
|
||||
{
|
||||
return dbus_g_proxy_call (dbus->sm_proxy, "Shutdown", NULL,
|
||||
G_TYPE_INVALID,
|
||||
G_TYPE_INVALID);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
#include "config.h"
|
||||
#include "eggsmclient-private.h"
|
||||
|
||||
#define EGG_TYPE_SM_CLIENT_DUMMY (egg_sm_client_dummy_get_type ())
|
||||
#define EGG_SM_CLIENT_DUMMY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SM_CLIENT_DUMMY, EggSMClientDummy))
|
||||
#define EGG_SM_CLIENT_DUMMY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SM_CLIENT_DUMMY, EggSMClientDummyClass))
|
||||
#define EGG_IS_SM_CLIENT_DUMMY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SM_CLIENT_DUMMY))
|
||||
#define EGG_IS_SM_CLIENT_DUMMY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SM_CLIENT_DUMMY))
|
||||
#define EGG_SM_CLIENT_DUMMY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SM_CLIENT_DUMMY, EggSMClientDummyClass))
|
||||
|
||||
typedef EggSMClient EggSMClientDummy;
|
||||
typedef EggSMClientClass EggSMClientDummyClass;
|
||||
|
||||
G_DEFINE_TYPE (EggSMClientDummy, egg_sm_client_dummy, EGG_TYPE_SM_CLIENT)
|
||||
|
||||
static void
|
||||
egg_sm_client_dummy_init (G_GNUC_UNUSED EggSMClientDummy *client)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
sm_client_dummy_startup (G_GNUC_UNUSED EggSMClient *client,
|
||||
G_GNUC_UNUSED const char *client_id)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
egg_sm_client_dummy_class_init (EggSMClientDummyClass *klass)
|
||||
{
|
||||
klass->startup = sm_client_dummy_startup;
|
||||
}
|
||||
|
||||
EggSMClient *
|
||||
egg_sm_client_dummy_new (void)
|
||||
{
|
||||
return g_object_new (EGG_TYPE_SM_CLIENT_DUMMY, NULL);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef EGG_SM_CLIENT_MANGLE_H
|
||||
#define EGG_SM_CLIENT_MANGLE_H
|
||||
|
||||
#define egg_sm_client_xsmp_get_type _moo_egg_sm_client_xsmp_get_type
|
||||
#define egg_sm_client_win32_get_type _moo_egg_sm_client_win32_get_type
|
||||
#define egg_sm_client_osx_get_type _moo_egg_sm_client_osx_get_type
|
||||
|
||||
#define egg_sm_client_get_type _moo_egg_sm_client_get_type
|
||||
#define egg_sm_client_get_option_group _moo_egg_sm_client_get_option_group
|
||||
#define egg_sm_client_register _moo_egg_sm_client_register
|
||||
#define egg_sm_client_get _moo_egg_sm_client_get
|
||||
#define egg_sm_client_is_resumed _moo_egg_sm_client_is_resumed
|
||||
#define egg_sm_client_get_state_dir _moo_egg_sm_client_get_state_dir
|
||||
#define egg_sm_client_get_config_prefix _moo_egg_sm_client_get_config_prefix
|
||||
#define egg_sm_client_set_restart_command _moo_egg_sm_client_set_restart_command
|
||||
#define egg_sm_client_will_quit _moo_egg_sm_client_will_quit
|
||||
#define egg_sm_client_end_session _moo_egg_sm_client_end_session
|
||||
#define egg_sm_client_save_state _moo_egg_sm_client_save_state
|
||||
#define egg_sm_client_quit_requested _moo_egg_sm_client_quit_requested
|
||||
#define egg_sm_client_quit_cancelled _moo_egg_sm_client_quit_cancelled
|
||||
#define egg_sm_client_quit _moo_egg_sm_client_quit
|
||||
#define egg_sm_client_xsmp_new _moo_egg_sm_client_xsmp_new
|
||||
#define egg_sm_client_dbus_new _moo_egg_sm_client_dbus_new
|
||||
#define egg_sm_client_win32_new _moo_egg_sm_client_win32_new
|
||||
#define egg_sm_client_osx_new _moo_egg_sm_client_osx_new
|
||||
#define egg_sm_client_dummy_new _moo_egg_sm_client_dummy_new
|
||||
#define egg_sm_client_get_mode _moo_egg_sm_client_get_mode
|
||||
#define egg_sm_client_get_state_file _moo_egg_sm_client_get_state_file
|
||||
#define egg_sm_client_set_mode _moo_egg_sm_client_set_mode
|
||||
|
||||
#endif /* EGG_SM_CLIENT_MANGLE_H */
|
|
@ -0,0 +1,235 @@
|
|||
/*
|
||||
* Copyright (C) 2007 Novell, Inc.
|
||||
* Copyright (C) 2008 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* EggSMClientOSX
|
||||
*
|
||||
* For details on the OS X logout process, see:
|
||||
* http://developer.apple.com/documentation/MacOSX/Conceptual/BPSystemStartup/Articles/BootProcess.html#//apple_ref/doc/uid/20002130-114618
|
||||
*
|
||||
* EggSMClientOSX registers for the kAEQuitApplication AppleEvent; the
|
||||
* handler we register (quit_requested()) will be invoked from inside
|
||||
* the quartz event-handling code (specifically, from inside
|
||||
* [NSApplication nextEventMatchingMask]) when an AppleEvent arrives.
|
||||
* We use AESuspendTheCurrentEvent() and AEResumeTheCurrentEvent() to
|
||||
* allow asynchronous / non-main-loop-reentering processing of the
|
||||
* quit request. (These are part of the Carbon framework; it doesn't
|
||||
* seem to be possible to handle AppleEvents asynchronously from
|
||||
* Cocoa.)
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "eggsmclient-private.h"
|
||||
#include <mooglib/moo-glib.h>
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
|
||||
#define EGG_TYPE_SM_CLIENT_OSX (egg_sm_client_osx_get_type ())
|
||||
#define EGG_SM_CLIENT_OSX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SM_CLIENT_OSX, EggSMClientOSX))
|
||||
#define EGG_SM_CLIENT_OSX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SM_CLIENT_OSX, EggSMClientOSXClass))
|
||||
#define EGG_IS_SM_CLIENT_OSX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SM_CLIENT_OSX))
|
||||
#define EGG_IS_SM_CLIENT_OSX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SM_CLIENT_OSX))
|
||||
#define EGG_SM_CLIENT_OSX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SM_CLIENT_OSX, EggSMClientOSXClass))
|
||||
|
||||
typedef struct _EggSMClientOSX EggSMClientOSX;
|
||||
typedef struct _EggSMClientOSXClass EggSMClientOSXClass;
|
||||
|
||||
struct _EggSMClientOSX {
|
||||
EggSMClient parent;
|
||||
|
||||
AppleEvent quit_event, quit_reply;
|
||||
gboolean quit_requested, quitting;
|
||||
};
|
||||
|
||||
struct _EggSMClientOSXClass
|
||||
{
|
||||
EggSMClientClass parent_class;
|
||||
|
||||
};
|
||||
|
||||
static void sm_client_osx_startup (EggSMClient *client,
|
||||
const char *client_id);
|
||||
static void sm_client_osx_will_quit (EggSMClient *client,
|
||||
gboolean will_quit);
|
||||
static gboolean sm_client_osx_end_session (EggSMClient *client,
|
||||
EggSMClientEndStyle style,
|
||||
gboolean request_confirmation);
|
||||
|
||||
static pascal OSErr quit_requested (const AppleEvent *, AppleEvent *, long);
|
||||
|
||||
G_DEFINE_TYPE (EggSMClientOSX, egg_sm_client_osx, EGG_TYPE_SM_CLIENT)
|
||||
|
||||
static void
|
||||
egg_sm_client_osx_init (EggSMClientOSX *osx)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static void
|
||||
egg_sm_client_osx_class_init (EggSMClientOSXClass *klass)
|
||||
{
|
||||
EggSMClientClass *sm_client_class = EGG_SM_CLIENT_CLASS (klass);
|
||||
|
||||
sm_client_class->startup = sm_client_osx_startup;
|
||||
sm_client_class->will_quit = sm_client_osx_will_quit;
|
||||
sm_client_class->end_session = sm_client_osx_end_session;
|
||||
}
|
||||
|
||||
EggSMClient *
|
||||
egg_sm_client_osx_new (void)
|
||||
{
|
||||
return g_object_new (EGG_TYPE_SM_CLIENT_OSX, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
sm_client_osx_startup (EggSMClient *client,
|
||||
const char *client_id)
|
||||
{
|
||||
AEInstallEventHandler (kCoreEventClass, kAEQuitApplication,
|
||||
NewAEEventHandlerUPP (quit_requested),
|
||||
(long)GPOINTER_TO_SIZE (client), false);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
idle_quit_requested (gpointer client)
|
||||
{
|
||||
egg_sm_client_quit_requested (client);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static pascal OSErr
|
||||
quit_requested (const AppleEvent *aevt, AppleEvent *reply, long refcon)
|
||||
{
|
||||
EggSMClient *client = GSIZE_TO_POINTER ((gsize)refcon);
|
||||
EggSMClientOSX *osx = GSIZE_TO_POINTER ((gsize)refcon);
|
||||
|
||||
g_return_val_if_fail (!osx->quit_requested, userCanceledErr);
|
||||
|
||||
/* FIXME AEInteractWithUser? */
|
||||
|
||||
osx->quit_requested = TRUE;
|
||||
AEDuplicateDesc (aevt, &osx->quit_event);
|
||||
AEDuplicateDesc (reply, &osx->quit_reply);
|
||||
AESuspendTheCurrentEvent (aevt);
|
||||
|
||||
/* Don't emit the "quit_requested" signal immediately, since we're
|
||||
* called from a weird point in the guts of gdkeventloop-quartz.c
|
||||
*/
|
||||
g_idle_add (idle_quit_requested, client);
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static pascal OSErr
|
||||
quit_requested_resumed (const AppleEvent *aevt, AppleEvent *reply, long refcon)
|
||||
{
|
||||
EggSMClientOSX *osx = GSIZE_TO_POINTER ((gsize)refcon);
|
||||
|
||||
osx->quit_requested = FALSE;
|
||||
return osx->quitting ? noErr : userCanceledErr;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
idle_will_quit (gpointer client)
|
||||
{
|
||||
EggSMClientOSX *osx = (EggSMClientOSX *)client;
|
||||
|
||||
/* Resume the event with a new handler that will return a value to
|
||||
* the system.
|
||||
*/
|
||||
AEResumeTheCurrentEvent (&osx->quit_event, &osx->quit_reply,
|
||||
NewAEEventHandlerUPP (quit_requested_resumed),
|
||||
(long)GPOINTER_TO_SIZE (client));
|
||||
AEDisposeDesc (&osx->quit_event);
|
||||
AEDisposeDesc (&osx->quit_reply);
|
||||
|
||||
if (osx->quitting)
|
||||
egg_sm_client_quit (client);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
sm_client_osx_will_quit (EggSMClient *client,
|
||||
gboolean will_quit)
|
||||
{
|
||||
EggSMClientOSX *osx = (EggSMClientOSX *)client;
|
||||
|
||||
g_return_if_fail (osx->quit_requested);
|
||||
|
||||
osx->quitting = will_quit;
|
||||
|
||||
/* Finish in an idle handler since the caller might have called
|
||||
* egg_sm_client_will_quit() from inside the "quit_requested" signal
|
||||
* handler, but may not expect the "quit" signal to arrive during
|
||||
* the _will_quit() call.
|
||||
*/
|
||||
g_idle_add (idle_will_quit, client);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sm_client_osx_end_session (EggSMClient *client,
|
||||
EggSMClientEndStyle style,
|
||||
gboolean request_confirmation)
|
||||
{
|
||||
static const ProcessSerialNumber loginwindow_psn = { 0, kSystemProcess };
|
||||
AppleEvent event = { typeNull, NULL }, reply = { typeNull, NULL };
|
||||
AEAddressDesc target;
|
||||
AEEventID id;
|
||||
OSErr err;
|
||||
|
||||
switch (style)
|
||||
{
|
||||
case EGG_SM_CLIENT_END_SESSION_DEFAULT:
|
||||
case EGG_SM_CLIENT_LOGOUT:
|
||||
id = request_confirmation ? kAELogOut : kAEReallyLogOut;
|
||||
break;
|
||||
case EGG_SM_CLIENT_REBOOT:
|
||||
id = request_confirmation ? kAEShowRestartDialog : kAERestart;
|
||||
break;
|
||||
case EGG_SM_CLIENT_SHUTDOWN:
|
||||
id = request_confirmation ? kAEShowShutdownDialog : kAEShutDown;
|
||||
break;
|
||||
}
|
||||
|
||||
err = AECreateDesc (typeProcessSerialNumber, &loginwindow_psn,
|
||||
sizeof (loginwindow_psn), &target);
|
||||
if (err != noErr)
|
||||
{
|
||||
g_warning ("Could not create descriptor for loginwindow: %d", err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
err = AECreateAppleEvent (kCoreEventClass, id, &target,
|
||||
kAutoGenerateReturnID, kAnyTransactionID,
|
||||
&event);
|
||||
AEDisposeDesc (&target);
|
||||
if (err != noErr)
|
||||
{
|
||||
g_warning ("Could not create logout AppleEvent: %d", err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
err = AESend (&event, &reply, kAENoReply, kAENormalPriority,
|
||||
kAEDefaultTimeout, NULL, NULL);
|
||||
AEDisposeDesc (&event);
|
||||
if (err == noErr)
|
||||
AEDisposeDesc (&reply);
|
||||
|
||||
return err == noErr;
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/* eggsmclient-private.h
|
||||
* Copyright (C) 2007 Novell, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __EGG_SM_CLIENT_PRIVATE_H__
|
||||
#define __EGG_SM_CLIENT_PRIVATE_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#if !GTK_CHECK_VERSION(2,91,7) && !GTK_CHECK_VERSION(3,0,0)
|
||||
/* GTK+ 3 includes this automatically */
|
||||
#include <gdkconfig.h>
|
||||
#endif
|
||||
|
||||
#include "eggsmclient.h"
|
||||
|
||||
#undef G_LOG_DOMAIN
|
||||
#define G_LOG_DOMAIN "EggSMClient"
|
||||
|
||||
#if __GNUC__ >= 4
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#endif
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GKeyFile *egg_sm_client_save_state (EggSMClient *client);
|
||||
void egg_sm_client_quit_requested (EggSMClient *client);
|
||||
void egg_sm_client_quit_cancelled (EggSMClient *client);
|
||||
void egg_sm_client_quit (EggSMClient *client);
|
||||
|
||||
#if defined (GDK_WINDOWING_X11)
|
||||
# ifdef EGG_SM_CLIENT_BACKEND_XSMP
|
||||
GType egg_sm_client_xsmp_get_type (void);
|
||||
EggSMClient *egg_sm_client_xsmp_new (void);
|
||||
# endif
|
||||
# ifdef EGG_SM_CLIENT_BACKEND_DBUS
|
||||
GType egg_sm_client_dbus_get_type (void);
|
||||
EggSMClient *egg_sm_client_dbus_new (void);
|
||||
# endif
|
||||
#elif defined (GDK_WINDOWING_WIN32)
|
||||
GType egg_sm_client_win32_get_type (void);
|
||||
EggSMClient *egg_sm_client_win32_new (void);
|
||||
#elif defined (GDK_WINDOWING_QUARTZ)
|
||||
GType egg_sm_client_osx_get_type (void);
|
||||
EggSMClient *egg_sm_client_osx_new (void);
|
||||
#endif
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
#endif /* __EGG_SM_CLIENT_PRIVATE_H__ */
|
|
@ -0,0 +1,351 @@
|
|||
/*
|
||||
* Copyright (C) 2007 Novell, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* EggSMClientWin32
|
||||
*
|
||||
* For details on the Windows XP logout process, see:
|
||||
* http://msdn.microsoft.com/en-us/library/aa376876.aspx.
|
||||
*
|
||||
* Vista adds some new APIs which EggSMClient does not make use of; see
|
||||
* http://msdn.microsoft.com/en-us/library/ms700677(VS.85).aspx
|
||||
*
|
||||
* When shutting down, Windows sends every top-level window a
|
||||
* WM_QUERYENDSESSION event, which the application must respond to
|
||||
* synchronously, saying whether or not it will quit. To avoid main
|
||||
* loop re-entrancy problems (and to avoid having to muck about too
|
||||
* much with the guts of the gdk-win32 main loop), we watch for this
|
||||
* event in a separate thread, which then signals the main thread and
|
||||
* waits for the main thread to handle the event. Since we don't want
|
||||
* to require g_thread_init() to be called, we do this all using
|
||||
* Windows-specific thread methods.
|
||||
*
|
||||
* After the application handles the WM_QUERYENDSESSION event,
|
||||
* Windows then sends it a WM_ENDSESSION event with a TRUE or FALSE
|
||||
* parameter indicating whether the session is or is not actually
|
||||
* going to end now. We handle this from the other thread as well.
|
||||
*
|
||||
* As mentioned above, Vista introduces several additional new APIs
|
||||
* that don't fit into the (current) EggSMClient API. Windows also has
|
||||
* an entirely separate shutdown-notification scheme for non-GUI apps,
|
||||
* which we also don't handle here.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "eggsmclient-private.h"
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
|
||||
#define EGG_TYPE_SM_CLIENT_WIN32 (egg_sm_client_win32_get_type ())
|
||||
#define EGG_SM_CLIENT_WIN32(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SM_CLIENT_WIN32, EggSMClientWin32))
|
||||
#define EGG_SM_CLIENT_WIN32_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SM_CLIENT_WIN32, EggSMClientWin32Class))
|
||||
#define EGG_IS_SM_CLIENT_WIN32(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SM_CLIENT_WIN32))
|
||||
#define EGG_IS_SM_CLIENT_WIN32_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SM_CLIENT_WIN32))
|
||||
#define EGG_SM_CLIENT_WIN32_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SM_CLIENT_WIN32, EggSMClientWin32Class))
|
||||
|
||||
typedef struct _EggSMClientWin32 EggSMClientWin32;
|
||||
typedef struct _EggSMClientWin32Class EggSMClientWin32Class;
|
||||
|
||||
struct _EggSMClientWin32 {
|
||||
EggSMClient parent;
|
||||
|
||||
HANDLE message_event, response_event;
|
||||
|
||||
volatile GSourceFunc event;
|
||||
volatile gboolean will_quit;
|
||||
};
|
||||
|
||||
struct _EggSMClientWin32Class
|
||||
{
|
||||
EggSMClientClass parent_class;
|
||||
|
||||
};
|
||||
|
||||
static void sm_client_win32_startup (EggSMClient *client,
|
||||
const char *client_id);
|
||||
static void sm_client_win32_will_quit (EggSMClient *client,
|
||||
gboolean will_quit);
|
||||
static gboolean sm_client_win32_end_session (EggSMClient *client,
|
||||
EggSMClientEndStyle style,
|
||||
gboolean request_confirmation);
|
||||
|
||||
static GSource *g_win32_handle_source_add (HANDLE handle, GSourceFunc callback,
|
||||
gpointer user_data);
|
||||
static gboolean got_message (gpointer user_data);
|
||||
static void sm_client_thread (gpointer data);
|
||||
|
||||
G_DEFINE_TYPE (EggSMClientWin32, egg_sm_client_win32, EGG_TYPE_SM_CLIENT)
|
||||
|
||||
static void
|
||||
egg_sm_client_win32_init (EggSMClientWin32 *win32)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static void
|
||||
egg_sm_client_win32_class_init (EggSMClientWin32Class *klass)
|
||||
{
|
||||
EggSMClientClass *sm_client_class = EGG_SM_CLIENT_CLASS (klass);
|
||||
|
||||
sm_client_class->startup = sm_client_win32_startup;
|
||||
sm_client_class->will_quit = sm_client_win32_will_quit;
|
||||
sm_client_class->end_session = sm_client_win32_end_session;
|
||||
}
|
||||
|
||||
EggSMClient *
|
||||
egg_sm_client_win32_new (void)
|
||||
{
|
||||
return g_object_new (EGG_TYPE_SM_CLIENT_WIN32, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
sm_client_win32_startup (EggSMClient *client,
|
||||
const char *client_id)
|
||||
{
|
||||
EggSMClientWin32 *win32 = (EggSMClientWin32 *)client;
|
||||
|
||||
win32->message_event = CreateEvent (NULL, FALSE, FALSE, NULL);
|
||||
win32->response_event = CreateEvent (NULL, FALSE, FALSE, NULL);
|
||||
g_win32_handle_source_add (win32->message_event, got_message, win32);
|
||||
_beginthread (sm_client_thread, 0, client);
|
||||
}
|
||||
|
||||
static void
|
||||
sm_client_win32_will_quit (EggSMClient *client,
|
||||
gboolean will_quit)
|
||||
{
|
||||
EggSMClientWin32 *win32 = (EggSMClientWin32 *)client;
|
||||
|
||||
win32->will_quit = will_quit;
|
||||
SetEvent (win32->response_event);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sm_client_win32_end_session (EggSMClient *client,
|
||||
EggSMClientEndStyle style,
|
||||
gboolean request_confirmation)
|
||||
{
|
||||
UINT uFlags = EWX_LOGOFF;
|
||||
|
||||
switch (style)
|
||||
{
|
||||
case EGG_SM_CLIENT_END_SESSION_DEFAULT:
|
||||
case EGG_SM_CLIENT_LOGOUT:
|
||||
uFlags = EWX_LOGOFF;
|
||||
break;
|
||||
case EGG_SM_CLIENT_REBOOT:
|
||||
uFlags = EWX_REBOOT;
|
||||
break;
|
||||
case EGG_SM_CLIENT_SHUTDOWN:
|
||||
uFlags = EWX_POWEROFF;
|
||||
break;
|
||||
}
|
||||
|
||||
/* There's no way to make ExitWindowsEx() show a logout dialog, so
|
||||
* we ignore @request_confirmation.
|
||||
*/
|
||||
|
||||
#ifdef SHTDN_REASON_FLAG_PLANNED
|
||||
ExitWindowsEx (uFlags, SHTDN_REASON_FLAG_PLANNED);
|
||||
#else
|
||||
ExitWindowsEx (uFlags, 0);
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* callbacks from logout-listener thread */
|
||||
|
||||
static gboolean
|
||||
emit_quit_requested (gpointer smclient)
|
||||
{
|
||||
gdk_threads_enter ();
|
||||
egg_sm_client_quit_requested (smclient);
|
||||
gdk_threads_leave ();
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
emit_quit (gpointer smclient)
|
||||
{
|
||||
EggSMClientWin32 *win32 = smclient;
|
||||
|
||||
gdk_threads_enter ();
|
||||
egg_sm_client_quit (smclient);
|
||||
gdk_threads_leave ();
|
||||
|
||||
SetEvent (win32->response_event);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
emit_quit_cancelled (gpointer smclient)
|
||||
{
|
||||
EggSMClientWin32 *win32 = smclient;
|
||||
|
||||
gdk_threads_enter ();
|
||||
egg_sm_client_quit_cancelled (smclient);
|
||||
gdk_threads_leave ();
|
||||
|
||||
SetEvent (win32->response_event);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
got_message (gpointer smclient)
|
||||
{
|
||||
EggSMClientWin32 *win32 = smclient;
|
||||
|
||||
win32->event (win32);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Windows HANDLE GSource */
|
||||
|
||||
typedef struct {
|
||||
GSource source;
|
||||
GPollFD pollfd;
|
||||
} GWin32HandleSource;
|
||||
|
||||
static gboolean
|
||||
g_win32_handle_source_prepare (GSource *source, gint *timeout)
|
||||
{
|
||||
*timeout = -1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_win32_handle_source_check (GSource *source)
|
||||
{
|
||||
GWin32HandleSource *hsource = (GWin32HandleSource *)source;
|
||||
|
||||
return hsource->pollfd.revents;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_win32_handle_source_dispatch (GSource *source, GSourceFunc callback, gpointer user_data)
|
||||
{
|
||||
return (*callback) (user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
g_win32_handle_source_finalize (GSource *source)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
GSourceFuncs g_win32_handle_source_funcs = {
|
||||
g_win32_handle_source_prepare,
|
||||
g_win32_handle_source_check,
|
||||
g_win32_handle_source_dispatch,
|
||||
g_win32_handle_source_finalize
|
||||
};
|
||||
|
||||
static GSource *
|
||||
g_win32_handle_source_add (HANDLE handle, GSourceFunc callback, gpointer user_data)
|
||||
{
|
||||
GWin32HandleSource *hsource;
|
||||
GSource *source;
|
||||
|
||||
source = g_source_new (&g_win32_handle_source_funcs, sizeof (GWin32HandleSource));
|
||||
hsource = (GWin32HandleSource *)source;
|
||||
hsource->pollfd.fd = (int)handle;
|
||||
hsource->pollfd.events = G_IO_IN;
|
||||
hsource->pollfd.revents = 0;
|
||||
g_source_add_poll (source, &hsource->pollfd);
|
||||
|
||||
g_source_set_callback (source, callback, user_data, NULL);
|
||||
g_source_attach (source, NULL);
|
||||
return source;
|
||||
}
|
||||
|
||||
/* logout-listener thread */
|
||||
|
||||
static LRESULT CALLBACK
|
||||
sm_client_win32_window_procedure (HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam)
|
||||
{
|
||||
EggSMClientWin32 *win32 =
|
||||
(EggSMClientWin32 *)GetWindowLongPtr (hwnd, GWLP_USERDATA);
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case WM_QUERYENDSESSION:
|
||||
win32->event = emit_quit_requested;
|
||||
SetEvent (win32->message_event);
|
||||
|
||||
WaitForSingleObject (win32->response_event, INFINITE);
|
||||
return win32->will_quit;
|
||||
|
||||
case WM_ENDSESSION:
|
||||
if (wParam)
|
||||
{
|
||||
/* The session is ending */
|
||||
win32->event = emit_quit;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nope, the session *isn't* ending */
|
||||
win32->event = emit_quit_cancelled;
|
||||
}
|
||||
|
||||
SetEvent (win32->message_event);
|
||||
WaitForSingleObject (win32->response_event, INFINITE);
|
||||
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return DefWindowProc (hwnd, message, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sm_client_thread (gpointer smclient)
|
||||
{
|
||||
HINSTANCE instance;
|
||||
WNDCLASSEXW wcl;
|
||||
ATOM klass;
|
||||
HWND window;
|
||||
MSG msg;
|
||||
|
||||
instance = GetModuleHandle (NULL);
|
||||
|
||||
memset (&wcl, 0, sizeof (WNDCLASSEX));
|
||||
wcl.cbSize = sizeof (WNDCLASSEX);
|
||||
wcl.lpfnWndProc = sm_client_win32_window_procedure;
|
||||
wcl.hInstance = instance;
|
||||
wcl.lpszClassName = L"EggSmClientWindow";
|
||||
klass = RegisterClassEx (&wcl);
|
||||
|
||||
window = CreateWindowEx (0, MAKEINTRESOURCE (klass),
|
||||
L"EggSmClientWindow", 0,
|
||||
10, 10, 50, 50, GetDesktopWindow (),
|
||||
NULL, instance, NULL);
|
||||
SetWindowLongPtr (window, GWLP_USERDATA, (LONG_PTR)smclient);
|
||||
|
||||
/* main loop */
|
||||
while (GetMessage (&msg, NULL, 0, 0))
|
||||
DispatchMessage (&msg);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,604 @@
|
|||
/*
|
||||
* Copyright (C) 2007 Novell, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "eggsmclient.h"
|
||||
#include "eggsmclient-private.h"
|
||||
|
||||
static void egg_sm_client_debug_handler (const char *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
const char *message,
|
||||
gpointer user_data);
|
||||
|
||||
enum {
|
||||
SAVE_STATE,
|
||||
QUIT_REQUESTED,
|
||||
QUIT_CANCELLED,
|
||||
QUIT,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
struct _EggSMClientPrivate {
|
||||
GKeyFile *state_file;
|
||||
};
|
||||
|
||||
#define EGG_SM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), EGG_TYPE_SM_CLIENT, EggSMClientPrivate))
|
||||
|
||||
G_DEFINE_TYPE (EggSMClient, egg_sm_client, G_TYPE_OBJECT)
|
||||
|
||||
static EggSMClient *global_client;
|
||||
static EggSMClientMode global_client_mode = EGG_SM_CLIENT_MODE_NORMAL;
|
||||
|
||||
static void
|
||||
egg_sm_client_init (EggSMClient *client)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static void
|
||||
egg_sm_client_class_init (EggSMClientClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (EggSMClientPrivate));
|
||||
|
||||
/**
|
||||
* EggSMClient::save_state:
|
||||
* @client: the client
|
||||
* @state_file: a #GKeyFile to save state information into
|
||||
*
|
||||
* Emitted when the session manager has requested that the
|
||||
* application save information about its current state. The
|
||||
* application should save its state into @state_file, and then the
|
||||
* session manager may then restart the application in a future
|
||||
* session and tell it to initialize itself from that state.
|
||||
*
|
||||
* You should not save any data into @state_file's "start group"
|
||||
* (ie, the %NULL group). Instead, applications should save their
|
||||
* data into groups with names that start with the application name,
|
||||
* and libraries that connect to this signal should save their data
|
||||
* into groups with names that start with the library name.
|
||||
*
|
||||
* Alternatively, rather than (or in addition to) using @state_file,
|
||||
* the application can save its state by calling
|
||||
* egg_sm_client_set_restart_command() during the processing of this
|
||||
* signal (eg, to include a list of files to open).
|
||||
**/
|
||||
signals[SAVE_STATE] =
|
||||
g_signal_new ("save_state",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (EggSMClientClass, save_state),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__POINTER,
|
||||
G_TYPE_NONE,
|
||||
1, G_TYPE_POINTER);
|
||||
|
||||
/**
|
||||
* EggSMClient::quit_requested:
|
||||
* @client: the client
|
||||
*
|
||||
* Emitted when the session manager requests that the application
|
||||
* exit (generally because the user is logging out). The application
|
||||
* should decide whether or not it is willing to quit (perhaps after
|
||||
* asking the user what to do with documents that have unsaved
|
||||
* changes) and then call egg_sm_client_will_quit(), passing %TRUE
|
||||
* or %FALSE to give its answer to the session manager. (It does not
|
||||
* need to give an answer before returning from the signal handler;
|
||||
* it can interact with the user asynchronously and then give its
|
||||
* answer later on.) If the application does not connect to this
|
||||
* signal, then #EggSMClient will automatically return %TRUE on its
|
||||
* behalf.
|
||||
*
|
||||
* The application should not save its session state as part of
|
||||
* handling this signal; if the user has requested that the session
|
||||
* be saved when logging out, then ::save_state will be emitted
|
||||
* separately.
|
||||
*
|
||||
* If the application agrees to quit, it should then wait for either
|
||||
* the ::quit_cancelled or ::quit signals to be emitted.
|
||||
**/
|
||||
signals[QUIT_REQUESTED] =
|
||||
g_signal_new ("quit_requested",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (EggSMClientClass, quit_requested),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
|
||||
/**
|
||||
* EggSMClient::quit_cancelled:
|
||||
* @client: the client
|
||||
*
|
||||
* Emitted when the session manager decides to cancel a logout after
|
||||
* the application has already agreed to quit. After receiving this
|
||||
* signal, the application can go back to what it was doing before
|
||||
* receiving the ::quit_requested signal.
|
||||
**/
|
||||
signals[QUIT_CANCELLED] =
|
||||
g_signal_new ("quit_cancelled",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (EggSMClientClass, quit_cancelled),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
|
||||
/**
|
||||
* EggSMClient::quit:
|
||||
* @client: the client
|
||||
*
|
||||
* Emitted when the session manager wants the application to quit
|
||||
* (generally because the user is logging out). The application
|
||||
* should exit as soon as possible after receiving this signal; if
|
||||
* it does not, the session manager may choose to forcibly kill it.
|
||||
*
|
||||
* Normally a GUI application would only be sent a ::quit if it
|
||||
* agreed to quit in response to a ::quit_requested signal. However,
|
||||
* this is not guaranteed; in some situations the session manager
|
||||
* may decide to end the session without giving applications a
|
||||
* chance to object.
|
||||
**/
|
||||
signals[QUIT] =
|
||||
g_signal_new ("quit",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (EggSMClientClass, quit),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
}
|
||||
|
||||
static gboolean sm_client_disable = FALSE;
|
||||
static char *sm_client_state_file = NULL;
|
||||
static char *sm_client_id = NULL;
|
||||
static char *sm_config_prefix = NULL;
|
||||
|
||||
static gboolean
|
||||
sm_client_post_parse_func (GOptionContext *context,
|
||||
GOptionGroup *group,
|
||||
gpointer data,
|
||||
GError **error)
|
||||
{
|
||||
EggSMClient *client = egg_sm_client_get ();
|
||||
|
||||
if (sm_client_id == NULL)
|
||||
{
|
||||
const gchar *desktop_autostart_id;
|
||||
|
||||
desktop_autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID");
|
||||
|
||||
if (desktop_autostart_id != NULL)
|
||||
sm_client_id = g_strdup (desktop_autostart_id);
|
||||
}
|
||||
|
||||
/* Unset DESKTOP_AUTOSTART_ID in order to avoid child processes to
|
||||
* use the same client id. */
|
||||
g_unsetenv ("DESKTOP_AUTOSTART_ID");
|
||||
|
||||
if (global_client_mode != EGG_SM_CLIENT_MODE_DISABLED &&
|
||||
EGG_SM_CLIENT_GET_CLASS (client)->startup)
|
||||
EGG_SM_CLIENT_GET_CLASS (client)->startup (client, sm_client_id);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* egg_sm_client_get_option_group:
|
||||
*
|
||||
* Creates a %GOptionGroup containing the session-management-related
|
||||
* options. You should add this group to the application's
|
||||
* %GOptionContext if you want to use #EggSMClient.
|
||||
*
|
||||
* Return value: the %GOptionGroup
|
||||
**/
|
||||
GOptionGroup *
|
||||
egg_sm_client_get_option_group (void)
|
||||
{
|
||||
const GOptionEntry entries[] = {
|
||||
{ "sm-client-disable", 0, 0,
|
||||
G_OPTION_ARG_NONE, &sm_client_disable,
|
||||
N_("Disable connection to session manager"), NULL },
|
||||
{ "sm-client-state-file", 0, 0,
|
||||
G_OPTION_ARG_FILENAME, &sm_client_state_file,
|
||||
N_("Specify file containing saved configuration"), N_("FILE") },
|
||||
{ "sm-client-id", 0, 0,
|
||||
G_OPTION_ARG_STRING, &sm_client_id,
|
||||
N_("Specify session management ID"), N_("ID") },
|
||||
/* GnomeClient compatibility option */
|
||||
{ "sm-disable", 0, G_OPTION_FLAG_HIDDEN,
|
||||
G_OPTION_ARG_NONE, &sm_client_disable,
|
||||
NULL, NULL },
|
||||
/* GnomeClient compatibility option. This is a dummy option that only
|
||||
* exists so that sessions saved by apps with GnomeClient can be restored
|
||||
* later when they've switched to EggSMClient. See bug #575308.
|
||||
*/
|
||||
{ "sm-config-prefix", 0, G_OPTION_FLAG_HIDDEN,
|
||||
G_OPTION_ARG_STRING, &sm_config_prefix,
|
||||
NULL, NULL },
|
||||
{ NULL }
|
||||
};
|
||||
GOptionGroup *group;
|
||||
|
||||
/* Use our own debug handler for the "EggSMClient" domain. */
|
||||
g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
|
||||
egg_sm_client_debug_handler, NULL);
|
||||
|
||||
group = g_option_group_new ("sm-client",
|
||||
_("Session management options:"),
|
||||
_("Show session management options"),
|
||||
NULL, NULL);
|
||||
g_option_group_add_entries (group, entries);
|
||||
g_option_group_set_parse_hooks (group, NULL, sm_client_post_parse_func);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
/**
|
||||
* egg_sm_client_set_mode:
|
||||
* @mode: an #EggSMClient mode
|
||||
*
|
||||
* Sets the "mode" of #EggSMClient as follows:
|
||||
*
|
||||
* %EGG_SM_CLIENT_MODE_DISABLED: Session management is completely
|
||||
* disabled, until the mode is changed again. The application will
|
||||
* not even connect to the session manager. (egg_sm_client_get()
|
||||
* will still return an #EggSMClient object.)
|
||||
*
|
||||
* %EGG_SM_CLIENT_MODE_NO_RESTART: The application will connect to
|
||||
* the session manager (and thus will receive notification when the
|
||||
* user is logging out, etc), but will request to not be
|
||||
* automatically restarted with saved state in future sessions.
|
||||
*
|
||||
* %EGG_SM_CLIENT_MODE_NORMAL: The default. #EggSMCLient will
|
||||
* function normally.
|
||||
*
|
||||
* This must be called before the application's main loop begins and
|
||||
* before any call to egg_sm_client_get(), unless the mode was set
|
||||
* earlier to %EGG_SM_CLIENT_MODE_DISABLED and this call enables
|
||||
* session management. Note that option parsing will call
|
||||
* egg_sm_client_get().
|
||||
**/
|
||||
void
|
||||
egg_sm_client_set_mode (EggSMClientMode mode)
|
||||
{
|
||||
EggSMClientMode old_mode = global_client_mode;
|
||||
|
||||
g_return_if_fail (global_client == NULL || global_client_mode == EGG_SM_CLIENT_MODE_DISABLED);
|
||||
g_return_if_fail (!(global_client != NULL && mode == EGG_SM_CLIENT_MODE_DISABLED));
|
||||
|
||||
global_client_mode = mode;
|
||||
|
||||
if (global_client != NULL && old_mode == EGG_SM_CLIENT_MODE_DISABLED)
|
||||
{
|
||||
if (EGG_SM_CLIENT_GET_CLASS (global_client)->startup)
|
||||
EGG_SM_CLIENT_GET_CLASS (global_client)->startup (global_client, sm_client_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* egg_sm_client_get_mode:
|
||||
*
|
||||
* Gets the global #EggSMClientMode. See egg_sm_client_set_mode()
|
||||
* for details.
|
||||
*
|
||||
* Return value: the global #EggSMClientMode
|
||||
**/
|
||||
EggSMClientMode
|
||||
egg_sm_client_get_mode (void)
|
||||
{
|
||||
return global_client_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* egg_sm_client_get:
|
||||
*
|
||||
* Returns the master #EggSMClient for the application.
|
||||
*
|
||||
* On platforms that support saved sessions (ie, POSIX/X11), the
|
||||
* application will only request to be restarted by the session
|
||||
* manager if you call egg_set_desktop_file() to set an application
|
||||
* desktop file. In particular, if the desktop file contains the key
|
||||
* "X
|
||||
*
|
||||
* Return value: the master #EggSMClient.
|
||||
**/
|
||||
EggSMClient *
|
||||
egg_sm_client_get (void)
|
||||
{
|
||||
if (!global_client)
|
||||
{
|
||||
if (!sm_client_disable)
|
||||
{
|
||||
#if defined (GDK_WINDOWING_WIN32)
|
||||
global_client = egg_sm_client_win32_new ();
|
||||
#elif defined (GDK_WINDOWING_QUARTZ)
|
||||
global_client = egg_sm_client_osx_new ();
|
||||
#else
|
||||
/* If both D-Bus and XSMP are compiled in, try XSMP first
|
||||
* (since it supports state saving) and fall back to D-Bus
|
||||
* if XSMP isn't available.
|
||||
*/
|
||||
# ifdef EGG_SM_CLIENT_BACKEND_XSMP
|
||||
global_client = egg_sm_client_xsmp_new ();
|
||||
# endif
|
||||
# ifdef EGG_SM_CLIENT_BACKEND_DBUS
|
||||
if (!global_client)
|
||||
global_client = egg_sm_client_dbus_new ();
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Fallback: create a dummy client, so that callers don't have
|
||||
* to worry about a %NULL return value.
|
||||
*/
|
||||
if (!global_client)
|
||||
global_client = g_object_new (EGG_TYPE_SM_CLIENT, NULL);
|
||||
}
|
||||
|
||||
return global_client;
|
||||
}
|
||||
|
||||
/**
|
||||
* egg_sm_client_is_resumed:
|
||||
* @client: the client
|
||||
*
|
||||
* Checks whether or not the current session has been resumed from
|
||||
* a previous saved session. If so, the application should call
|
||||
* egg_sm_client_get_state_file() and restore its state from the
|
||||
* returned #GKeyFile.
|
||||
*
|
||||
* Return value: %TRUE if the session has been resumed
|
||||
**/
|
||||
gboolean
|
||||
egg_sm_client_is_resumed (EggSMClient *client)
|
||||
{
|
||||
g_return_val_if_fail (client == global_client, FALSE);
|
||||
|
||||
return sm_client_state_file != NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* egg_sm_client_get_state_file:
|
||||
* @client: the client
|
||||
*
|
||||
* If the application was resumed by the session manager, this will
|
||||
* return the #GKeyFile containing its state from the previous
|
||||
* session.
|
||||
*
|
||||
* Note that other libraries and #EggSMClient itself may also store
|
||||
* state in the key file, so if you call egg_sm_client_get_groups(),
|
||||
* on it, the return value will likely include groups that you did not
|
||||
* put there yourself. (It is also not guaranteed that the first
|
||||
* group created by the application will still be the "start group"
|
||||
* when it is resumed.)
|
||||
*
|
||||
* Return value: the #GKeyFile containing the application's earlier
|
||||
* state, or %NULL on error. You should not free this key file; it
|
||||
* is owned by @client.
|
||||
**/
|
||||
GKeyFile *
|
||||
egg_sm_client_get_state_file (EggSMClient *client)
|
||||
{
|
||||
EggSMClientPrivate *priv = EGG_SM_CLIENT_GET_PRIVATE (client);
|
||||
char *state_file_path;
|
||||
GError *err = NULL;
|
||||
|
||||
g_return_val_if_fail (client == global_client, NULL);
|
||||
|
||||
if (!sm_client_state_file)
|
||||
return NULL;
|
||||
if (priv->state_file)
|
||||
return priv->state_file;
|
||||
|
||||
if (!strncmp (sm_client_state_file, "file://", 7))
|
||||
state_file_path = g_filename_from_uri (sm_client_state_file, NULL, NULL);
|
||||
else
|
||||
state_file_path = g_strdup (sm_client_state_file);
|
||||
|
||||
priv->state_file = g_key_file_new ();
|
||||
if (!g_key_file_load_from_file (priv->state_file, state_file_path, 0, &err))
|
||||
{
|
||||
g_warning ("Could not load SM state file '%s': %s",
|
||||
sm_client_state_file, err->message);
|
||||
g_clear_error (&err);
|
||||
g_key_file_free (priv->state_file);
|
||||
priv->state_file = NULL;
|
||||
}
|
||||
|
||||
g_free (state_file_path);
|
||||
return priv->state_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* egg_sm_client_set_restart_command:
|
||||
* @client: the client
|
||||
* @argc: the length of @argv
|
||||
* @argv: argument vector
|
||||
*
|
||||
* Sets the command used to restart @client if it does not have a
|
||||
* .desktop file that can be used to find its restart command.
|
||||
*
|
||||
* This can also be used when handling the ::save_state signal, to
|
||||
* save the current state via an updated command line. (Eg, providing
|
||||
* a list of filenames to open when the application is resumed.)
|
||||
**/
|
||||
void
|
||||
egg_sm_client_set_restart_command (EggSMClient *client,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
g_return_if_fail (EGG_IS_SM_CLIENT (client));
|
||||
|
||||
if (EGG_SM_CLIENT_GET_CLASS (client)->set_restart_command)
|
||||
EGG_SM_CLIENT_GET_CLASS (client)->set_restart_command (client, argc, argv);
|
||||
}
|
||||
|
||||
/**
|
||||
* egg_sm_client_will_quit:
|
||||
* @client: the client
|
||||
* @will_quit: whether or not the application is willing to quit
|
||||
*
|
||||
* This MUST be called in response to the ::quit_requested signal, to
|
||||
* indicate whether or not the application is willing to quit. The
|
||||
* application may call it either directly from the signal handler, or
|
||||
* at some later point (eg, after asynchronously interacting with the
|
||||
* user).
|
||||
*
|
||||
* If the application does not connect to ::quit_requested,
|
||||
* #EggSMClient will call this method on its behalf (passing %TRUE
|
||||
* for @will_quit).
|
||||
*
|
||||
* After calling this method, the application should wait to receive
|
||||
* either ::quit_cancelled or ::quit.
|
||||
**/
|
||||
void
|
||||
egg_sm_client_will_quit (EggSMClient *client,
|
||||
gboolean will_quit)
|
||||
{
|
||||
g_return_if_fail (EGG_IS_SM_CLIENT (client));
|
||||
|
||||
if (EGG_SM_CLIENT_GET_CLASS (client)->will_quit)
|
||||
EGG_SM_CLIENT_GET_CLASS (client)->will_quit (client, will_quit);
|
||||
}
|
||||
|
||||
/**
|
||||
* egg_sm_client_end_session:
|
||||
* @style: a hint at how to end the session
|
||||
* @request_confirmation: whether or not the user should get a chance
|
||||
* to confirm the action
|
||||
*
|
||||
* Requests that the session manager end the current session. @style
|
||||
* indicates how the session should be ended, and
|
||||
* @request_confirmation indicates whether or not the user should be
|
||||
* given a chance to confirm the logout/reboot/shutdown. Both of these
|
||||
* flags are merely hints though; the session manager may choose to
|
||||
* ignore them.
|
||||
*
|
||||
* Return value: %TRUE if the request was sent; %FALSE if it could not
|
||||
* be (eg, because it could not connect to the session manager).
|
||||
**/
|
||||
gboolean
|
||||
egg_sm_client_end_session (EggSMClientEndStyle style,
|
||||
gboolean request_confirmation)
|
||||
{
|
||||
EggSMClient *client = egg_sm_client_get ();
|
||||
|
||||
g_return_val_if_fail (EGG_IS_SM_CLIENT (client), FALSE);
|
||||
|
||||
if (EGG_SM_CLIENT_GET_CLASS (client)->end_session)
|
||||
{
|
||||
return EGG_SM_CLIENT_GET_CLASS (client)->end_session (client, style,
|
||||
request_confirmation);
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Signal-emitting callbacks from platform-specific code */
|
||||
|
||||
GKeyFile *
|
||||
egg_sm_client_save_state (EggSMClient *client)
|
||||
{
|
||||
GKeyFile *state_file;
|
||||
char *group;
|
||||
|
||||
g_return_val_if_fail (client == global_client, NULL);
|
||||
|
||||
state_file = g_key_file_new ();
|
||||
|
||||
g_debug ("Emitting save_state");
|
||||
g_signal_emit (client, signals[SAVE_STATE], 0, state_file);
|
||||
g_debug ("Done emitting save_state");
|
||||
|
||||
group = g_key_file_get_start_group (state_file);
|
||||
if (group)
|
||||
{
|
||||
g_free (group);
|
||||
return state_file;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_key_file_free (state_file);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
egg_sm_client_quit_requested (EggSMClient *client)
|
||||
{
|
||||
g_return_if_fail (client == global_client);
|
||||
|
||||
if (!g_signal_has_handler_pending (client, signals[QUIT_REQUESTED], 0, FALSE))
|
||||
{
|
||||
g_debug ("Not emitting quit_requested because no one is listening");
|
||||
egg_sm_client_will_quit (client, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
g_debug ("Emitting quit_requested");
|
||||
g_signal_emit (client, signals[QUIT_REQUESTED], 0);
|
||||
g_debug ("Done emitting quit_requested");
|
||||
}
|
||||
|
||||
void
|
||||
egg_sm_client_quit_cancelled (EggSMClient *client)
|
||||
{
|
||||
g_return_if_fail (client == global_client);
|
||||
|
||||
g_debug ("Emitting quit_cancelled");
|
||||
g_signal_emit (client, signals[QUIT_CANCELLED], 0);
|
||||
g_debug ("Done emitting quit_cancelled");
|
||||
}
|
||||
|
||||
void
|
||||
egg_sm_client_quit (EggSMClient *client)
|
||||
{
|
||||
g_return_if_fail (client == global_client);
|
||||
|
||||
g_debug ("Emitting quit");
|
||||
g_signal_emit (client, signals[QUIT], 0);
|
||||
g_debug ("Done emitting quit");
|
||||
|
||||
/* FIXME: should we just call gtk_main_quit() here? */
|
||||
}
|
||||
|
||||
static void
|
||||
egg_sm_client_debug_handler (const char *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
const char *message,
|
||||
gpointer user_data)
|
||||
{
|
||||
static int debug = -1;
|
||||
|
||||
if (debug < 0)
|
||||
debug = (g_getenv ("EGG_SM_CLIENT_DEBUG") != NULL);
|
||||
|
||||
if (debug)
|
||||
g_log_default_handler (log_domain, log_level, message, NULL);
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
SET(eggsmclient_sources
|
||||
eggsmclient/eggsmclient.cmake
|
||||
eggsmclient/eggsmclient.c
|
||||
eggsmclient/eggsmclient.h
|
||||
eggsmclient/eggsmclient-mangle.h
|
||||
eggsmclient/eggsmclient-private.h
|
||||
)
|
||||
|
||||
SET(eggsmclient_extra_dist
|
||||
eggsmclient/eggsmclient-win32.c
|
||||
eggsmclient/eggsmclient-dummy.c
|
||||
eggsmclient/eggsmclient-xsmp.c
|
||||
eggsmclient/eggdesktopfile.h
|
||||
eggsmclient/eggdesktopfile.c
|
||||
)
|
||||
|
||||
if(MOO_OS_WIN32)
|
||||
LIST(APPEND eggsmclient_sources eggsmclient/eggsmclient-win32.c)
|
||||
elseif(MOO_OS_DARWIN)
|
||||
LIST(APPEND eggsmclient_sources eggsmclient/eggsmclient-dummy.c)
|
||||
else(MOO_OS_WIN32)
|
||||
add_definitions(-DEGG_SM_CLIENT_BACKEND_XSMP)
|
||||
LIST(APPEND eggsmclient_sources eggsmclient/eggsmclient-xsmp.c eggsmclient/eggdesktopfile.h eggsmclient/eggdesktopfile.c)
|
||||
endif(MOO_OS_WIN32)
|
||||
|
||||
# -%- strip:true -%-
|
|
@ -0,0 +1,118 @@
|
|||
/* eggsmclient.h
|
||||
* Copyright (C) 2007 Novell, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __EGG_SM_CLIENT_H__
|
||||
#define __EGG_SM_CLIENT_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include "eggsmclient-mangle.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define EGG_TYPE_SM_CLIENT (egg_sm_client_get_type ())
|
||||
#define EGG_SM_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SM_CLIENT, EggSMClient))
|
||||
#define EGG_SM_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SM_CLIENT, EggSMClientClass))
|
||||
#define EGG_IS_SM_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SM_CLIENT))
|
||||
#define EGG_IS_SM_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SM_CLIENT))
|
||||
#define EGG_SM_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SM_CLIENT, EggSMClientClass))
|
||||
|
||||
typedef struct _EggSMClient EggSMClient;
|
||||
typedef struct _EggSMClientClass EggSMClientClass;
|
||||
typedef struct _EggSMClientPrivate EggSMClientPrivate;
|
||||
|
||||
typedef enum {
|
||||
EGG_SM_CLIENT_END_SESSION_DEFAULT,
|
||||
EGG_SM_CLIENT_LOGOUT,
|
||||
EGG_SM_CLIENT_REBOOT,
|
||||
EGG_SM_CLIENT_SHUTDOWN
|
||||
} EggSMClientEndStyle;
|
||||
|
||||
typedef enum {
|
||||
EGG_SM_CLIENT_MODE_DISABLED,
|
||||
EGG_SM_CLIENT_MODE_NO_RESTART,
|
||||
EGG_SM_CLIENT_MODE_NORMAL
|
||||
} EggSMClientMode;
|
||||
|
||||
struct _EggSMClient
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
};
|
||||
|
||||
struct _EggSMClientClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (*save_state) (EggSMClient *client,
|
||||
GKeyFile *state_file);
|
||||
|
||||
void (*quit_requested) (EggSMClient *client);
|
||||
void (*quit_cancelled) (EggSMClient *client);
|
||||
void (*quit) (EggSMClient *client);
|
||||
|
||||
/* virtual methods */
|
||||
void (*startup) (EggSMClient *client,
|
||||
const char *client_id);
|
||||
void (*set_restart_command) (EggSMClient *client,
|
||||
int argc,
|
||||
const char **argv);
|
||||
void (*will_quit) (EggSMClient *client,
|
||||
gboolean will_quit);
|
||||
gboolean (*end_session) (EggSMClient *client,
|
||||
EggSMClientEndStyle style,
|
||||
gboolean request_confirmation);
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (*_egg_reserved1) (void);
|
||||
void (*_egg_reserved2) (void);
|
||||
void (*_egg_reserved3) (void);
|
||||
void (*_egg_reserved4) (void);
|
||||
};
|
||||
|
||||
GType egg_sm_client_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GOptionGroup *egg_sm_client_get_option_group (void);
|
||||
|
||||
/* Initialization */
|
||||
void egg_sm_client_set_mode (EggSMClientMode mode);
|
||||
EggSMClientMode egg_sm_client_get_mode (void);
|
||||
EggSMClient *egg_sm_client_get (void);
|
||||
|
||||
/* Resuming a saved session */
|
||||
gboolean egg_sm_client_is_resumed (EggSMClient *client);
|
||||
GKeyFile *egg_sm_client_get_state_file (EggSMClient *client);
|
||||
|
||||
/* Alternate means of saving state */
|
||||
void egg_sm_client_set_restart_command (EggSMClient *client,
|
||||
int argc,
|
||||
const char **argv);
|
||||
|
||||
/* Handling "quit_requested" signal */
|
||||
void egg_sm_client_will_quit (EggSMClient *client,
|
||||
gboolean will_quit);
|
||||
|
||||
/* Initiate a logout/reboot/shutdown */
|
||||
gboolean egg_sm_client_end_session (EggSMClientEndStyle style,
|
||||
gboolean request_confirmation);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
#endif /* __EGG_SM_CLIENT_H__ */
|
|
@ -0,0 +1,32 @@
|
|||
moo_sources += \
|
||||
gtksourceview/gtksourcecontextengine.c \
|
||||
gtksourceview/gtksourcecontextengine.h \
|
||||
gtksourceview/gtksourceengine.c \
|
||||
gtksourceview/gtksourceengine.h \
|
||||
gtksourceview/gtksourceiter.c \
|
||||
gtksourceview/gtksourceiter.h \
|
||||
gtksourceview/gtksourcelanguage-parser-1.c \
|
||||
gtksourceview/gtksourcelanguage-parser-2.c \
|
||||
gtksourceview/gtksourcelanguage-private.h \
|
||||
gtksourceview/gtksourcelanguage.c \
|
||||
gtksourceview/gtksourcelanguage.h \
|
||||
gtksourceview/gtksourcelanguagemanager.c \
|
||||
gtksourceview/gtksourcelanguagemanager.h \
|
||||
gtksourceview/gtksourcestyle-private.h \
|
||||
gtksourceview/gtksourcestyle.c \
|
||||
gtksourceview/gtksourcestyle.h \
|
||||
gtksourceview/gtksourcestylescheme.c \
|
||||
gtksourceview/gtksourcestylescheme.h \
|
||||
gtksourceview/gtksourcestyleschememanager.c \
|
||||
gtksourceview/gtksourcestyleschememanager.h \
|
||||
gtksourceview/gtksourceview-utils.c \
|
||||
gtksourceview/gtksourceview-utils.h \
|
||||
gtksourceview/gtktextregion.c \
|
||||
gtksourceview/gtktextregion.h \
|
||||
gtksourceview/gtksourceview-i18n.h \
|
||||
gtksourceview/gtksourceview-marshal.h \
|
||||
gtksourceview/gtksourceview-api.h \
|
||||
gtksourceview/gtksourcebuffer.h \
|
||||
gtksourceview/gtksourceview.h
|
||||
|
||||
# -%- strip:true -%-
|
|
@ -0,0 +1 @@
|
|||
#include "mooutils/moocompat.h"
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,124 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
|
||||
* gtksourcecontextengine.h
|
||||
*
|
||||
* Copyright (C) 2003 - Gustavo Giráldez
|
||||
* Copyright (C) 2005 - Marco Barisione, Emanuele Aina
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library 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 __GTK_SOURCE_CONTEXT_ENGINE_H__
|
||||
#define __GTK_SOURCE_CONTEXT_ENGINE_H__
|
||||
|
||||
#include <gtksourceview/gtksourceengine.h>
|
||||
#include <gtksourceview/gtksourcelanguage.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_SOURCE_CONTEXT_ENGINE (_gtk_source_context_engine_get_type ())
|
||||
#define GTK_SOURCE_CONTEXT_ENGINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_CONTEXT_ENGINE, GtkSourceContextEngine))
|
||||
#define GTK_SOURCE_CONTEXT_ENGINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SOURCE_CONTEXT_ENGINE, GtkSourceContextEngineClass))
|
||||
#define GTK_IS_SOURCE_CONTEXT_ENGINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_CONTEXT_ENGINE))
|
||||
#define GTK_IS_SOURCE_CONTEXT_ENGINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_CONTEXT_ENGINE))
|
||||
#define GTK_SOURCE_CONTEXT_ENGINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SOURCE_CONTEXT_ENGINE, GtkSourceContextEngineClass))
|
||||
|
||||
typedef struct _GtkSourceContextData GtkSourceContextData;
|
||||
typedef struct _GtkSourceContextReplace GtkSourceContextReplace;
|
||||
|
||||
typedef struct _GtkSourceContextEngine GtkSourceContextEngine;
|
||||
typedef struct _GtkSourceContextEngineClass GtkSourceContextEngineClass;
|
||||
typedef struct _GtkSourceContextEnginePrivate GtkSourceContextEnginePrivate;
|
||||
|
||||
struct _GtkSourceContextEngine
|
||||
{
|
||||
GtkSourceEngine parent_instance;
|
||||
|
||||
/*< private >*/
|
||||
GtkSourceContextEnginePrivate *priv;
|
||||
};
|
||||
|
||||
struct _GtkSourceContextEngineClass
|
||||
{
|
||||
GtkSourceEngineClass parent_class;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
GTK_SOURCE_CONTEXT_EXTEND_PARENT = 1 << 0,
|
||||
GTK_SOURCE_CONTEXT_END_PARENT = 1 << 1,
|
||||
GTK_SOURCE_CONTEXT_END_AT_LINE_END = 1 << 2,
|
||||
GTK_SOURCE_CONTEXT_FIRST_LINE_ONLY = 1 << 3,
|
||||
GTK_SOURCE_CONTEXT_ONCE_ONLY = 1 << 4,
|
||||
GTK_SOURCE_CONTEXT_STYLE_INSIDE = 1 << 5
|
||||
} GtkSourceContextFlags;
|
||||
|
||||
typedef enum {
|
||||
GTK_SOURCE_CONTEXT_IGNORE_STYLE = 1 << 0,
|
||||
GTK_SOURCE_CONTEXT_OVERRIDE_STYLE = 1 << 1,
|
||||
GTK_SOURCE_CONTEXT_REF_ORIGINAL = 1 << 2
|
||||
} GtkSourceContextRefOptions;
|
||||
|
||||
GType _gtk_source_context_engine_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkSourceContextData *_gtk_source_context_data_new (GtkSourceLanguage *lang);
|
||||
GtkSourceContextData *_gtk_source_context_data_ref (GtkSourceContextData *data);
|
||||
void _gtk_source_context_data_unref (GtkSourceContextData *data);
|
||||
|
||||
GtkSourceContextEngine *_gtk_source_context_engine_new (GtkSourceContextData *data);
|
||||
|
||||
gboolean _gtk_source_context_data_define_context
|
||||
(GtkSourceContextData *data,
|
||||
const gchar *id,
|
||||
const gchar *parent_id,
|
||||
const gchar *match_regex,
|
||||
const gchar *start_regex,
|
||||
const gchar *end_regex,
|
||||
const gchar *style,
|
||||
GtkSourceContextFlags flags,
|
||||
GError **error);
|
||||
|
||||
gboolean _gtk_source_context_data_add_sub_pattern
|
||||
(GtkSourceContextData *data,
|
||||
const gchar *id,
|
||||
const gchar *parent_id,
|
||||
const gchar *name,
|
||||
const gchar *where,
|
||||
const gchar *style,
|
||||
GError **error);
|
||||
|
||||
gboolean _gtk_source_context_data_add_ref (GtkSourceContextData *data,
|
||||
const gchar *parent_id,
|
||||
const gchar *ref_id,
|
||||
GtkSourceContextRefOptions options,
|
||||
const gchar *style,
|
||||
gboolean all,
|
||||
GError **error);
|
||||
|
||||
GtkSourceContextReplace *
|
||||
_gtk_source_context_replace_new (const gchar *to_replace_id,
|
||||
const gchar *replace_with_id);
|
||||
void _gtk_source_context_replace_free (GtkSourceContextReplace *repl);
|
||||
|
||||
gboolean _gtk_source_context_data_finish_parse (GtkSourceContextData *data,
|
||||
GList *overrides,
|
||||
GError **error);
|
||||
|
||||
/* Only for lang files version 1, do not use it */
|
||||
void _gtk_source_context_data_set_escape_char
|
||||
(GtkSourceContextData *data,
|
||||
gunichar esc_char);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_SOURCE_CONTEXT_ENGINE_H__ */
|
|
@ -0,0 +1,106 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
|
||||
*
|
||||
* gtksourceengine.c - Abstract base class for highlighting engines
|
||||
*
|
||||
* Copyright (C) 2003 - Gustavo Giráldez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library 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 "gtksourcebuffer.h"
|
||||
#include "gtksourceengine.h"
|
||||
|
||||
|
||||
G_DEFINE_TYPE (GtkSourceEngine, _gtk_source_engine, G_TYPE_OBJECT)
|
||||
|
||||
|
||||
static void
|
||||
_gtk_source_engine_class_init (GtkSourceEngineClass *klass)
|
||||
{
|
||||
klass->attach_buffer = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_gtk_source_engine_init (G_GNUC_UNUSED GtkSourceEngine *engine)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_source_engine_attach_buffer (GtkSourceEngine *engine,
|
||||
GtkTextBuffer *buffer)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_SOURCE_ENGINE (engine));
|
||||
g_return_if_fail (GTK_SOURCE_ENGINE_GET_CLASS (engine)->attach_buffer != NULL);
|
||||
|
||||
GTK_SOURCE_ENGINE_GET_CLASS (engine)->attach_buffer (engine, buffer);
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_source_engine_text_inserted (GtkSourceEngine *engine,
|
||||
gint start_offset,
|
||||
gint end_offset)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_SOURCE_ENGINE (engine));
|
||||
g_return_if_fail (GTK_SOURCE_ENGINE_GET_CLASS (engine)->text_inserted != NULL);
|
||||
|
||||
GTK_SOURCE_ENGINE_GET_CLASS (engine)->text_inserted (engine,
|
||||
start_offset,
|
||||
end_offset);
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_source_engine_text_deleted (GtkSourceEngine *engine,
|
||||
gint offset,
|
||||
gint length)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_SOURCE_ENGINE (engine));
|
||||
g_return_if_fail (GTK_SOURCE_ENGINE_GET_CLASS (engine)->text_deleted != NULL);
|
||||
|
||||
GTK_SOURCE_ENGINE_GET_CLASS (engine)->text_deleted (engine,
|
||||
offset,
|
||||
length);
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_source_engine_update_highlight (GtkSourceEngine *engine,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end,
|
||||
gboolean synchronous)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_SOURCE_ENGINE (engine));
|
||||
g_return_if_fail (start != NULL && end != NULL);
|
||||
g_return_if_fail (GTK_SOURCE_ENGINE_GET_CLASS (engine)->update_highlight != NULL);
|
||||
|
||||
GTK_SOURCE_ENGINE_GET_CLASS (engine)->update_highlight (engine,
|
||||
start,
|
||||
end,
|
||||
synchronous);
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_source_engine_set_style_scheme (GtkSourceEngine *engine,
|
||||
GtkSourceStyleScheme *scheme)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_SOURCE_ENGINE (engine));
|
||||
g_return_if_fail (GTK_IS_SOURCE_STYLE_SCHEME (scheme));
|
||||
g_return_if_fail (GTK_SOURCE_ENGINE_GET_CLASS (engine)->set_style_scheme != NULL);
|
||||
|
||||
GTK_SOURCE_ENGINE_GET_CLASS (engine)->set_style_scheme (engine, scheme);
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
|
||||
*
|
||||
* gtksourceengine.h - Abstract base class for highlighting engines
|
||||
*
|
||||
* Copyright (C) 2003 - Gustavo Giráldez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library 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 __GTK_SOURCE_ENGINE_H__
|
||||
#define __GTK_SOURCE_ENGINE_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gtksourceview/gtksourcestylescheme.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_SOURCE_ENGINE (_gtk_source_engine_get_type ())
|
||||
#define GTK_SOURCE_ENGINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_ENGINE, GtkSourceEngine))
|
||||
#define GTK_SOURCE_ENGINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SOURCE_ENGINE, GtkSourceEngineClass))
|
||||
#define GTK_IS_SOURCE_ENGINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_ENGINE))
|
||||
#define GTK_IS_SOURCE_ENGINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_ENGINE))
|
||||
#define GTK_SOURCE_ENGINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SOURCE_ENGINE, GtkSourceEngineClass))
|
||||
|
||||
typedef struct _GtkSourceEngine GtkSourceEngine;
|
||||
typedef struct _GtkSourceEngineClass GtkSourceEngineClass;
|
||||
|
||||
struct _GtkSourceEngine
|
||||
{
|
||||
GObject parent_instance;
|
||||
};
|
||||
|
||||
struct _GtkSourceEngineClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* attach_buffer) (GtkSourceEngine *engine,
|
||||
GtkTextBuffer *buffer);
|
||||
|
||||
void (* text_inserted) (GtkSourceEngine *engine,
|
||||
gint start_offset,
|
||||
gint end_offset);
|
||||
void (* text_deleted) (GtkSourceEngine *engine,
|
||||
gint offset,
|
||||
gint length);
|
||||
|
||||
void (* update_highlight) (GtkSourceEngine *engine,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end,
|
||||
gboolean synchronous);
|
||||
|
||||
void (* set_style_scheme) (GtkSourceEngine *engine,
|
||||
GtkSourceStyleScheme *scheme);
|
||||
};
|
||||
|
||||
GType _gtk_source_engine_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void _gtk_source_engine_attach_buffer (GtkSourceEngine *engine,
|
||||
GtkTextBuffer *buffer);
|
||||
void _gtk_source_engine_text_inserted (GtkSourceEngine *engine,
|
||||
gint start_offset,
|
||||
gint end_offset);
|
||||
void _gtk_source_engine_text_deleted (GtkSourceEngine *engine,
|
||||
gint offset,
|
||||
gint length);
|
||||
void _gtk_source_engine_update_highlight (GtkSourceEngine *engine,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end,
|
||||
gboolean synchronous);
|
||||
void _gtk_source_engine_set_style_scheme (GtkSourceEngine *engine,
|
||||
GtkSourceStyleScheme *scheme);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_SOURCE_ENGINE_H__ */
|
|
@ -0,0 +1,801 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
||||
* gtksourceiter.h
|
||||
*
|
||||
* Copyright (C) 2000 - 2005 Paolo Maggi
|
||||
* Copyright (C) 2002, 2003 Jeroen Zwartepoorte
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Parts of this file are copied from the gedit and glimmer project.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include "gtksourceiter.h"
|
||||
|
||||
#define GTK_TEXT_UNKNOWN_CHAR 0xFFFC
|
||||
|
||||
#if GLIB_CHECK_VERSION(2,30,0) && !defined(G_UNICODE_COMBINING_MARK)
|
||||
#define G_UNICODE_COMBINING_MARK G_UNICODE_SPACING_MARK
|
||||
#endif
|
||||
|
||||
/* this function acts like g_utf8_offset_to_pointer() except that if it finds a
|
||||
* decomposable character it consumes the decomposition length from the given
|
||||
* offset. So it's useful when the offset was calculated for the normalized
|
||||
* version of str, but we need a pointer to str itself. */
|
||||
static const gchar *
|
||||
pointer_from_offset_skipping_decomp (const gchar *str, gint offset)
|
||||
{
|
||||
gchar *casefold, *normal;
|
||||
const gchar *p, *q;
|
||||
|
||||
p = str;
|
||||
while (offset > 0)
|
||||
{
|
||||
q = g_utf8_next_char (p);
|
||||
casefold = g_utf8_casefold (p, q - p);
|
||||
normal = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
|
||||
offset -= g_utf8_strlen (normal, -1);
|
||||
g_free (casefold);
|
||||
g_free (normal);
|
||||
p = q;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
exact_prefix_cmp (const gchar *string,
|
||||
const gchar *prefix,
|
||||
guint prefix_len)
|
||||
{
|
||||
GUnicodeType type;
|
||||
|
||||
if (strncmp (string, prefix, prefix_len) != 0)
|
||||
return FALSE;
|
||||
if (string[prefix_len] == '\0')
|
||||
return TRUE;
|
||||
|
||||
type = g_unichar_type (g_utf8_get_char (string + prefix_len));
|
||||
|
||||
/* If string contains prefix, check that prefix is not followed
|
||||
* by a unicode mark symbol, e.g. that trailing 'a' in prefix
|
||||
* is not part of two-char a-with-hat symbol in string. */
|
||||
return type != G_UNICODE_COMBINING_MARK &&
|
||||
type != G_UNICODE_ENCLOSING_MARK &&
|
||||
type != G_UNICODE_NON_SPACING_MARK;
|
||||
}
|
||||
|
||||
static const gchar *
|
||||
utf8_strcasestr (const gchar *haystack, const gchar *needle)
|
||||
{
|
||||
gsize needle_len;
|
||||
gsize haystack_len;
|
||||
const gchar *ret = NULL;
|
||||
gchar *p;
|
||||
gchar *casefold;
|
||||
gchar *caseless_haystack;
|
||||
gint i;
|
||||
|
||||
g_return_val_if_fail (haystack != NULL, NULL);
|
||||
g_return_val_if_fail (needle != NULL, NULL);
|
||||
|
||||
casefold = g_utf8_casefold (haystack, -1);
|
||||
caseless_haystack = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
|
||||
g_free (casefold);
|
||||
|
||||
needle_len = g_utf8_strlen (needle, -1);
|
||||
haystack_len = g_utf8_strlen (caseless_haystack, -1);
|
||||
|
||||
if (needle_len == 0)
|
||||
{
|
||||
ret = (gchar *)haystack;
|
||||
goto finally_1;
|
||||
}
|
||||
|
||||
if (haystack_len < needle_len)
|
||||
{
|
||||
ret = NULL;
|
||||
goto finally_1;
|
||||
}
|
||||
|
||||
p = (gchar*)caseless_haystack;
|
||||
needle_len = strlen (needle);
|
||||
i = 0;
|
||||
|
||||
while (*p)
|
||||
{
|
||||
if (exact_prefix_cmp (p, needle, needle_len))
|
||||
{
|
||||
ret = pointer_from_offset_skipping_decomp (haystack, i);
|
||||
goto finally_1;
|
||||
}
|
||||
|
||||
p = g_utf8_next_char (p);
|
||||
i++;
|
||||
}
|
||||
|
||||
finally_1:
|
||||
g_free (caseless_haystack);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const gchar *
|
||||
utf8_strrcasestr (const gchar *haystack, const gchar *needle)
|
||||
{
|
||||
gsize needle_len;
|
||||
gsize haystack_len;
|
||||
const gchar *ret = NULL;
|
||||
gchar *p;
|
||||
gchar *casefold;
|
||||
gchar *caseless_haystack;
|
||||
gint i;
|
||||
|
||||
g_return_val_if_fail (haystack != NULL, NULL);
|
||||
g_return_val_if_fail (needle != NULL, NULL);
|
||||
|
||||
casefold = g_utf8_casefold (haystack, -1);
|
||||
caseless_haystack = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
|
||||
g_free (casefold);
|
||||
|
||||
needle_len = g_utf8_strlen (needle, -1);
|
||||
haystack_len = g_utf8_strlen (caseless_haystack, -1);
|
||||
|
||||
if (needle_len == 0)
|
||||
{
|
||||
ret = (gchar *)haystack;
|
||||
goto finally_1;
|
||||
}
|
||||
|
||||
if (haystack_len < needle_len)
|
||||
{
|
||||
ret = NULL;
|
||||
goto finally_1;
|
||||
}
|
||||
|
||||
i = haystack_len - needle_len;
|
||||
p = g_utf8_offset_to_pointer (caseless_haystack, i);
|
||||
needle_len = strlen (needle);
|
||||
|
||||
while (p >= caseless_haystack)
|
||||
{
|
||||
if (exact_prefix_cmp (p, needle, needle_len))
|
||||
{
|
||||
ret = pointer_from_offset_skipping_decomp (haystack, i);
|
||||
goto finally_1;
|
||||
}
|
||||
|
||||
p = g_utf8_prev_char (p);
|
||||
i--;
|
||||
}
|
||||
|
||||
finally_1:
|
||||
g_free (caseless_haystack);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
utf8_caselessnmatch (const char *s1, const char *s2,
|
||||
gssize n1, gssize n2)
|
||||
{
|
||||
gchar *casefold;
|
||||
gchar *normalized_s1;
|
||||
gchar *normalized_s2;
|
||||
gssize len_s1;
|
||||
gssize len_s2;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
g_return_val_if_fail (s1 != NULL, FALSE);
|
||||
g_return_val_if_fail (s2 != NULL, FALSE);
|
||||
g_return_val_if_fail (n1 > 0, FALSE);
|
||||
g_return_val_if_fail (n2 > 0, FALSE);
|
||||
|
||||
casefold = g_utf8_casefold (s1, n1);
|
||||
normalized_s1 = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
|
||||
g_free (casefold);
|
||||
|
||||
casefold = g_utf8_casefold (s2, n2);
|
||||
normalized_s2 = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
|
||||
g_free (casefold);
|
||||
|
||||
len_s1 = strlen (normalized_s1);
|
||||
len_s2 = strlen (normalized_s2);
|
||||
|
||||
if (len_s1 < len_s2)
|
||||
goto finally_2;
|
||||
|
||||
ret = (strncmp (normalized_s1, normalized_s2, len_s2) == 0);
|
||||
|
||||
finally_2:
|
||||
g_free (normalized_s1);
|
||||
g_free (normalized_s2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* FIXME: total horror */
|
||||
static gboolean
|
||||
char_is_invisible (const GtkTextIter *iter)
|
||||
{
|
||||
GSList *tags;
|
||||
gboolean invisible = FALSE;
|
||||
tags = gtk_text_iter_get_tags (iter);
|
||||
while (tags)
|
||||
{
|
||||
gboolean this_invisible, invisible_set;
|
||||
g_object_get (tags->data, "invisible", &this_invisible,
|
||||
"invisible-set", &invisible_set, NULL);
|
||||
if (invisible_set)
|
||||
invisible = this_invisible;
|
||||
tags = g_slist_delete_link (tags, tags);
|
||||
}
|
||||
return invisible;
|
||||
}
|
||||
|
||||
static void
|
||||
forward_chars_with_skipping (GtkTextIter *iter,
|
||||
gint count,
|
||||
gboolean skip_invisible,
|
||||
gboolean skip_nontext,
|
||||
gboolean skip_decomp)
|
||||
{
|
||||
gint i;
|
||||
|
||||
g_return_if_fail (count >= 0);
|
||||
|
||||
i = count;
|
||||
|
||||
while (i > 0)
|
||||
{
|
||||
gboolean ignored = FALSE;
|
||||
|
||||
/* minimal workaround to avoid the infinite loop of bug #168247.
|
||||
* It doesn't fix the problemjust the symptom...
|
||||
*/
|
||||
if (gtk_text_iter_is_end (iter))
|
||||
return;
|
||||
|
||||
if (skip_nontext && gtk_text_iter_get_char (iter) == GTK_TEXT_UNKNOWN_CHAR)
|
||||
ignored = TRUE;
|
||||
|
||||
/* FIXME: char_is_invisible() gets list of tags for each char there,
|
||||
and checks every tag. It doesn't sound like a good idea. */
|
||||
if (!ignored && skip_invisible && char_is_invisible (iter))
|
||||
ignored = TRUE;
|
||||
|
||||
if (!ignored && skip_decomp)
|
||||
{
|
||||
/* being UTF8 correct sucks; this accounts for extra
|
||||
offsets coming from canonical decompositions of
|
||||
UTF8 characters (e.g. accented characters) which
|
||||
g_utf8_normalize() performs */
|
||||
gchar *normal;
|
||||
gchar *casefold;
|
||||
gchar buffer[6];
|
||||
gint buffer_len;
|
||||
|
||||
buffer_len = g_unichar_to_utf8 (gtk_text_iter_get_char (iter), buffer);
|
||||
casefold = g_utf8_casefold (buffer, buffer_len);
|
||||
normal = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
|
||||
i -= (g_utf8_strlen (normal, -1) - 1);
|
||||
g_free (normal);
|
||||
g_free (casefold);
|
||||
}
|
||||
|
||||
gtk_text_iter_forward_char (iter);
|
||||
|
||||
if (!ignored)
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
lines_match (const GtkTextIter *start,
|
||||
const gchar **lines,
|
||||
gboolean visible_only,
|
||||
gboolean slice,
|
||||
GtkTextIter *match_start,
|
||||
GtkTextIter *match_end)
|
||||
{
|
||||
GtkTextIter next;
|
||||
gchar *line_text;
|
||||
const gchar *found;
|
||||
gint offset;
|
||||
|
||||
if (*lines == NULL || **lines == '\0')
|
||||
{
|
||||
if (match_start)
|
||||
*match_start = *start;
|
||||
if (match_end)
|
||||
*match_end = *start;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
next = *start;
|
||||
gtk_text_iter_forward_line (&next);
|
||||
|
||||
/* No more text in buffer, but *lines is nonempty */
|
||||
if (gtk_text_iter_equal (start, &next))
|
||||
return FALSE;
|
||||
|
||||
if (slice)
|
||||
{
|
||||
if (visible_only)
|
||||
line_text = gtk_text_iter_get_visible_slice (start, &next);
|
||||
else
|
||||
line_text = gtk_text_iter_get_slice (start, &next);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (visible_only)
|
||||
line_text = gtk_text_iter_get_visible_text (start, &next);
|
||||
else
|
||||
line_text = gtk_text_iter_get_text (start, &next);
|
||||
}
|
||||
|
||||
if (match_start) /* if this is the first line we're matching */
|
||||
{
|
||||
found = utf8_strcasestr (line_text, *lines);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If it's not the first line, we have to match from the
|
||||
* start of the line.
|
||||
*/
|
||||
if (utf8_caselessnmatch (line_text, *lines, strlen (line_text),
|
||||
strlen (*lines)))
|
||||
found = line_text;
|
||||
else
|
||||
found = NULL;
|
||||
}
|
||||
|
||||
if (found == NULL)
|
||||
{
|
||||
g_free (line_text);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Get offset to start of search string */
|
||||
offset = g_utf8_strlen (line_text, found - line_text);
|
||||
|
||||
next = *start;
|
||||
|
||||
/* If match start needs to be returned, set it to the
|
||||
* start of the search string.
|
||||
*/
|
||||
forward_chars_with_skipping (&next, offset, visible_only, !slice, FALSE);
|
||||
if (match_start)
|
||||
{
|
||||
*match_start = next;
|
||||
}
|
||||
|
||||
/* Go to end of search string */
|
||||
forward_chars_with_skipping (&next, g_utf8_strlen (*lines, -1), visible_only, !slice, TRUE);
|
||||
|
||||
g_free (line_text);
|
||||
|
||||
++lines;
|
||||
|
||||
if (match_end)
|
||||
*match_end = next;
|
||||
|
||||
/* pass NULL for match_start, since we don't need to find the
|
||||
* start again.
|
||||
*/
|
||||
return lines_match (&next, lines, visible_only, slice, NULL, match_end);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
backward_lines_match (const GtkTextIter *start,
|
||||
const gchar **lines,
|
||||
gboolean visible_only,
|
||||
gboolean slice,
|
||||
GtkTextIter *match_start,
|
||||
GtkTextIter *match_end)
|
||||
{
|
||||
GtkTextIter line, next;
|
||||
gchar *line_text;
|
||||
const gchar *found;
|
||||
gint offset;
|
||||
|
||||
if (*lines == NULL || **lines == '\0')
|
||||
{
|
||||
if (match_start)
|
||||
*match_start = *start;
|
||||
if (match_end)
|
||||
*match_end = *start;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
line = next = *start;
|
||||
if (gtk_text_iter_get_line_offset (&next) == 0)
|
||||
{
|
||||
if (!gtk_text_iter_backward_line (&next))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
gtk_text_iter_set_line_offset (&next, 0);
|
||||
|
||||
if (slice)
|
||||
{
|
||||
if (visible_only)
|
||||
line_text = gtk_text_iter_get_visible_slice (&next, &line);
|
||||
else
|
||||
line_text = gtk_text_iter_get_slice (&next, &line);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (visible_only)
|
||||
line_text = gtk_text_iter_get_visible_text (&next, &line);
|
||||
else
|
||||
line_text = gtk_text_iter_get_text (&next, &line);
|
||||
}
|
||||
|
||||
if (match_start) /* if this is the first line we're matching */
|
||||
{
|
||||
found = utf8_strrcasestr (line_text, *lines);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If it's not the first line, we have to match from the
|
||||
* start of the line.
|
||||
*/
|
||||
if (utf8_caselessnmatch (line_text, *lines, strlen (line_text),
|
||||
strlen (*lines)))
|
||||
found = line_text;
|
||||
else
|
||||
found = NULL;
|
||||
}
|
||||
|
||||
if (found == NULL)
|
||||
{
|
||||
g_free (line_text);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Get offset to start of search string */
|
||||
offset = g_utf8_strlen (line_text, found - line_text);
|
||||
|
||||
forward_chars_with_skipping (&next, offset, visible_only, !slice, FALSE);
|
||||
|
||||
/* If match start needs to be returned, set it to the
|
||||
* start of the search string.
|
||||
*/
|
||||
if (match_start)
|
||||
{
|
||||
*match_start = next;
|
||||
}
|
||||
|
||||
/* Go to end of search string */
|
||||
forward_chars_with_skipping (&next, g_utf8_strlen (*lines, -1), visible_only, !slice, TRUE);
|
||||
|
||||
g_free (line_text);
|
||||
|
||||
++lines;
|
||||
|
||||
if (match_end)
|
||||
*match_end = next;
|
||||
|
||||
/* try to match the rest of the lines forward, passing NULL
|
||||
* for match_start so lines_match will try to match the entire
|
||||
* line */
|
||||
return lines_match (&next, lines, visible_only,
|
||||
slice, NULL, match_end);
|
||||
}
|
||||
|
||||
/* strsplit () that retains the delimiter as part of the string. */
|
||||
static gchar **
|
||||
breakup_string (const char *string,
|
||||
const char *delimiter,
|
||||
gint max_tokens)
|
||||
{
|
||||
GSList *string_list = NULL, *slist;
|
||||
gchar **str_array, *s, *casefold, *new_string;
|
||||
guint i, n = 1;
|
||||
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
g_return_val_if_fail (delimiter != NULL, NULL);
|
||||
|
||||
if (max_tokens < 1)
|
||||
max_tokens = G_MAXINT;
|
||||
|
||||
s = strstr (string, delimiter);
|
||||
if (s)
|
||||
{
|
||||
gsize delimiter_len = strlen (delimiter);
|
||||
|
||||
do
|
||||
{
|
||||
guint len;
|
||||
|
||||
len = s - string + delimiter_len;
|
||||
new_string = g_new (gchar, len + 1);
|
||||
strncpy (new_string, string, len);
|
||||
new_string[len] = 0;
|
||||
casefold = g_utf8_casefold (new_string, -1);
|
||||
g_free (new_string);
|
||||
new_string = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
|
||||
g_free (casefold);
|
||||
string_list = g_slist_prepend (string_list, new_string);
|
||||
n++;
|
||||
string = s + delimiter_len;
|
||||
s = strstr (string, delimiter);
|
||||
} while (--max_tokens && s);
|
||||
}
|
||||
|
||||
if (*string)
|
||||
{
|
||||
n++;
|
||||
casefold = g_utf8_casefold (string, -1);
|
||||
new_string = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
|
||||
g_free (casefold);
|
||||
string_list = g_slist_prepend (string_list, new_string);
|
||||
}
|
||||
|
||||
str_array = g_new (gchar*, n);
|
||||
|
||||
i = n - 1;
|
||||
|
||||
str_array[i--] = NULL;
|
||||
for (slist = string_list; slist; slist = slist->next)
|
||||
str_array[i--] = slist->data;
|
||||
|
||||
g_slist_free (string_list);
|
||||
|
||||
return str_array;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_iter_forward_search:
|
||||
* @iter: start of search.
|
||||
* @str: a search string.
|
||||
* @flags: flags affecting how the search is done.
|
||||
* @match_start: return location for start of match, or %%NULL.
|
||||
* @match_end: return location for end of match, or %%NULL.
|
||||
* @limit: bound for the search, or %%NULL for the end of the buffer.
|
||||
*
|
||||
* Searches forward for @str. Any match is returned by setting
|
||||
* @match_start to the first character of the match and @match_end to the
|
||||
* first character after the match. The search will not continue past
|
||||
* @limit. Note that a search is a linear or O(n) operation, so you
|
||||
* may wish to use @limit to avoid locking up your UI on large
|
||||
* buffers.
|
||||
*
|
||||
* If the #GTK_SOURCE_SEARCH_VISIBLE_ONLY flag is present, the match may
|
||||
* have invisible text interspersed in @str. i.e. @str will be a
|
||||
* possibly-noncontiguous subsequence of the matched range. similarly,
|
||||
* if you specify #GTK_SOURCE_SEARCH_TEXT_ONLY, the match may have
|
||||
* pixbufs or child widgets mixed inside the matched range. If these
|
||||
* flags are not given, the match must be exact; the special 0xFFFC
|
||||
* character in @str will match embedded pixbufs or child widgets.
|
||||
* If you specify the #GTK_SOURCE_SEARCH_CASE_INSENSITIVE flag, the text will
|
||||
* be matched regardless of what case it is in.
|
||||
*
|
||||
* Same as gtk_text_iter_forward_search(), but supports case insensitive
|
||||
* searching.
|
||||
*
|
||||
* Return value: whether a match was found.
|
||||
**/
|
||||
gboolean
|
||||
gtk_source_iter_forward_search (const GtkTextIter *iter,
|
||||
const gchar *str,
|
||||
GtkSourceSearchFlags flags,
|
||||
GtkTextIter *match_start,
|
||||
GtkTextIter *match_end,
|
||||
const GtkTextIter *limit)
|
||||
{
|
||||
gchar **lines = NULL;
|
||||
GtkTextIter match;
|
||||
gboolean retval = FALSE;
|
||||
GtkTextIter search;
|
||||
gboolean visible_only;
|
||||
gboolean slice;
|
||||
|
||||
g_return_val_if_fail (iter != NULL, FALSE);
|
||||
g_return_val_if_fail (str != NULL, FALSE);
|
||||
|
||||
if ((flags & GTK_SOURCE_SEARCH_CASE_INSENSITIVE) == 0)
|
||||
return gtk_text_iter_forward_search (iter, str, flags,
|
||||
match_start, match_end,
|
||||
limit);
|
||||
|
||||
if (limit && gtk_text_iter_compare (iter, limit) >= 0)
|
||||
return FALSE;
|
||||
|
||||
if (*str == '\0')
|
||||
{
|
||||
/* If we can move one char, return the empty string there */
|
||||
match = *iter;
|
||||
|
||||
if (gtk_text_iter_forward_char (&match))
|
||||
{
|
||||
if (limit && gtk_text_iter_equal (&match, limit))
|
||||
return FALSE;
|
||||
|
||||
if (match_start)
|
||||
*match_start = match;
|
||||
if (match_end)
|
||||
*match_end = match;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
visible_only = (flags & GTK_SOURCE_SEARCH_VISIBLE_ONLY) != 0;
|
||||
slice = (flags & GTK_SOURCE_SEARCH_TEXT_ONLY) == 0;
|
||||
|
||||
/* locate all lines */
|
||||
lines = breakup_string (str, "\n", -1);
|
||||
|
||||
search = *iter;
|
||||
|
||||
do
|
||||
{
|
||||
/* This loop has an inefficient worst-case, where
|
||||
* gtk_text_iter_get_text () is called repeatedly on
|
||||
* a single line.
|
||||
*/
|
||||
GtkTextIter end;
|
||||
|
||||
if (limit && gtk_text_iter_compare (&search, limit) >= 0)
|
||||
break;
|
||||
|
||||
if (lines_match (&search, (const gchar**)lines,
|
||||
visible_only, slice, &match, &end))
|
||||
{
|
||||
if (limit == NULL ||
|
||||
(limit && gtk_text_iter_compare (&end, limit) <= 0))
|
||||
{
|
||||
retval = TRUE;
|
||||
|
||||
if (match_start)
|
||||
*match_start = match;
|
||||
if (match_end)
|
||||
*match_end = end;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while (gtk_text_iter_forward_line (&search));
|
||||
|
||||
g_strfreev ((gchar**)lines);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_iter_backward_search:
|
||||
* @iter: a #GtkTextIter where the search begins.
|
||||
* @str: search string.
|
||||
* @flags: bitmask of flags affecting the search.
|
||||
* @match_start: return location for start of match, or %%NULL.
|
||||
* @match_end: return location for end of match, or %%NULL.
|
||||
* @limit: location of last possible @match_start, or %%NULL for start of buffer.
|
||||
*
|
||||
* Same as gtk_text_iter_backward_search(), but supports case insensitive
|
||||
* searching.
|
||||
*
|
||||
* Return value: whether a match was found.
|
||||
**/
|
||||
gboolean
|
||||
gtk_source_iter_backward_search (const GtkTextIter *iter,
|
||||
const gchar *str,
|
||||
GtkSourceSearchFlags flags,
|
||||
GtkTextIter *match_start,
|
||||
GtkTextIter *match_end,
|
||||
const GtkTextIter *limit)
|
||||
{
|
||||
gchar **lines = NULL;
|
||||
GtkTextIter match;
|
||||
gboolean retval = FALSE;
|
||||
GtkTextIter search;
|
||||
gboolean visible_only;
|
||||
gboolean slice;
|
||||
|
||||
g_return_val_if_fail (iter != NULL, FALSE);
|
||||
g_return_val_if_fail (str != NULL, FALSE);
|
||||
|
||||
if ((flags & GTK_SOURCE_SEARCH_CASE_INSENSITIVE) == 0)
|
||||
return gtk_text_iter_backward_search (iter, str, flags,
|
||||
match_start, match_end,
|
||||
limit);
|
||||
|
||||
if (limit && gtk_text_iter_compare (iter, limit) <= 0)
|
||||
return FALSE;
|
||||
|
||||
if (*str == '\0')
|
||||
{
|
||||
/* If we can move one char, return the empty string there */
|
||||
match = *iter;
|
||||
|
||||
if (gtk_text_iter_backward_char (&match))
|
||||
{
|
||||
if (limit && gtk_text_iter_equal (&match, limit))
|
||||
return FALSE;
|
||||
|
||||
if (match_start)
|
||||
*match_start = match;
|
||||
if (match_end)
|
||||
*match_end = match;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
visible_only = (flags & GTK_SOURCE_SEARCH_VISIBLE_ONLY) != 0;
|
||||
slice = (flags & GTK_SOURCE_SEARCH_TEXT_ONLY) == 0;
|
||||
|
||||
/* locate all lines */
|
||||
lines = breakup_string (str, "\n", -1);
|
||||
|
||||
search = *iter;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
/* This loop has an inefficient worst-case, where
|
||||
* gtk_text_iter_get_text () is called repeatedly on
|
||||
* a single line.
|
||||
*/
|
||||
GtkTextIter end;
|
||||
|
||||
if (limit && gtk_text_iter_compare (&search, limit) <= 0)
|
||||
break;
|
||||
|
||||
if (backward_lines_match (&search, (const gchar**)lines,
|
||||
visible_only, slice, &match, &end))
|
||||
{
|
||||
if (limit == NULL || (limit &&
|
||||
gtk_text_iter_compare (&end, limit) > 0))
|
||||
{
|
||||
retval = TRUE;
|
||||
|
||||
if (match_start)
|
||||
*match_start = match;
|
||||
if (match_end)
|
||||
*match_end = end;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (gtk_text_iter_get_line_offset (&search) == 0)
|
||||
{
|
||||
if (!gtk_text_iter_backward_line (&search))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_text_iter_set_line_offset (&search, 0);
|
||||
}
|
||||
}
|
||||
|
||||
g_strfreev ((gchar**)lines);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* gtk_source_iter_find_matching_bracket is implemented in gtksourcebuffer.c
|
||||
*/
|
|
@ -0,0 +1,53 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
||||
* gtksourceiter.h
|
||||
*
|
||||
* Copyright (C) 2000, 2002 Paolo Maggi
|
||||
* Copyright (C) 2002, 2003 Jeroen Zwartepoorte
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library 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 __GTK_SOURCE_ITER_H__
|
||||
#define __GTK_SOURCE_ITER_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GTK_SOURCE_SEARCH_VISIBLE_ONLY = 1 << 0,
|
||||
GTK_SOURCE_SEARCH_TEXT_ONLY = 1 << 1,
|
||||
GTK_SOURCE_SEARCH_CASE_INSENSITIVE = 1 << 2
|
||||
/* Possible future plans: SEARCH_REGEXP */
|
||||
} GtkSourceSearchFlags;
|
||||
|
||||
gboolean gtk_source_iter_forward_search (const GtkTextIter *iter,
|
||||
const gchar *str,
|
||||
GtkSourceSearchFlags flags,
|
||||
GtkTextIter *match_start,
|
||||
GtkTextIter *match_end,
|
||||
const GtkTextIter *limit);
|
||||
|
||||
gboolean gtk_source_iter_backward_search (const GtkTextIter *iter,
|
||||
const gchar *str,
|
||||
GtkSourceSearchFlags flags,
|
||||
GtkTextIter *match_start,
|
||||
GtkTextIter *match_end,
|
||||
const GtkTextIter *limit);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_SOURCE_ITER_H__ */
|
|
@ -0,0 +1,793 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
|
||||
* gtksourcelanguage-parser-ver1.c
|
||||
* Language specification parser for 1.0 version .lang files
|
||||
*
|
||||
* Copyright (C) 2003 - Paolo Maggi <paolo.maggi@polito.it>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library 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 <string.h>
|
||||
|
||||
#include <libxml/parser.h>
|
||||
#include "gtksourceview-i18n.h"
|
||||
#include "gtksourcebuffer.h"
|
||||
#include "gtksourcelanguage.h"
|
||||
#include "gtksourcelanguage-private.h"
|
||||
|
||||
static gchar *
|
||||
fix_pattern (const gchar *pattern,
|
||||
gboolean *end_at_line_end)
|
||||
{
|
||||
char *slash;
|
||||
|
||||
if (pattern == NULL)
|
||||
return NULL;
|
||||
|
||||
slash = strchr (pattern, '/');
|
||||
|
||||
if (slash != NULL)
|
||||
{
|
||||
GString *str;
|
||||
|
||||
str = g_string_new_len (pattern, slash - pattern);
|
||||
g_string_append (str, "\\/");
|
||||
pattern = slash + 1;
|
||||
|
||||
while ((slash = strchr (pattern, '/')) != NULL)
|
||||
{
|
||||
g_string_append_len (str, pattern, slash - pattern);
|
||||
g_string_append (str, "\\/");
|
||||
pattern = slash + 1;
|
||||
}
|
||||
|
||||
if (g_str_has_suffix (pattern, "\\n"))
|
||||
g_string_append_len (str, pattern, strlen(pattern) - 2);
|
||||
else
|
||||
g_string_append (str, pattern);
|
||||
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
||||
else if (g_str_has_suffix (pattern, "\\n"))
|
||||
{
|
||||
if (end_at_line_end)
|
||||
*end_at_line_end = TRUE;
|
||||
return g_strndup (pattern, strlen (pattern) - 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
return g_strdup (pattern);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ctx_data_add_simple_pattern (GtkSourceContextData *ctx_data,
|
||||
GtkSourceLanguage *language,
|
||||
const gchar *id,
|
||||
const gchar *style,
|
||||
const gchar *pattern)
|
||||
{
|
||||
gboolean result;
|
||||
gchar *real_id, *root_id, *fixed;
|
||||
GError *error = NULL;
|
||||
|
||||
g_return_val_if_fail (id != NULL, FALSE);
|
||||
|
||||
root_id = g_strdup_printf ("%s:%s", language->priv->id, language->priv->id);
|
||||
real_id = g_strdup_printf ("%s:%s", language->priv->id, id);
|
||||
|
||||
fixed = fix_pattern (pattern, NULL);
|
||||
|
||||
result = _gtk_source_context_data_define_context (ctx_data, real_id,
|
||||
root_id,
|
||||
fixed, NULL, NULL,
|
||||
style,
|
||||
GTK_SOURCE_CONTEXT_EXTEND_PARENT |
|
||||
GTK_SOURCE_CONTEXT_END_AT_LINE_END,
|
||||
&error);
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
g_warning ("%s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_free (fixed);
|
||||
g_free (real_id);
|
||||
g_free (root_id);
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ctx_data_add_syntax_pattern (GtkSourceContextData *ctx_data,
|
||||
GtkSourceLanguage *language,
|
||||
const gchar *id,
|
||||
const gchar *style,
|
||||
const gchar *pattern_start,
|
||||
const gchar *pattern_end,
|
||||
gboolean end_at_line_end)
|
||||
{
|
||||
gboolean result;
|
||||
gchar *real_id, *root_id;
|
||||
gchar *fixed_start, *fixed_end;
|
||||
GError *error = NULL;
|
||||
GtkSourceContextFlags flags = GTK_SOURCE_CONTEXT_EXTEND_PARENT;
|
||||
|
||||
g_return_val_if_fail (id != NULL, FALSE);
|
||||
|
||||
root_id = g_strdup_printf ("%s:%s", language->priv->id, language->priv->id);
|
||||
real_id = g_strdup_printf ("%s:%s", language->priv->id, id);
|
||||
|
||||
fixed_start = fix_pattern (pattern_start, &end_at_line_end);
|
||||
fixed_end = fix_pattern (pattern_end, &end_at_line_end);
|
||||
|
||||
if (end_at_line_end)
|
||||
flags |= GTK_SOURCE_CONTEXT_END_AT_LINE_END;
|
||||
|
||||
result = _gtk_source_context_data_define_context (ctx_data, real_id, root_id,
|
||||
NULL,
|
||||
pattern_start,
|
||||
pattern_end,
|
||||
style,
|
||||
flags,
|
||||
&error);
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
g_warning ("%s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_free (real_id);
|
||||
g_free (root_id);
|
||||
g_free (fixed_start);
|
||||
g_free (fixed_end);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
build_keyword_list (const GSList *keywords,
|
||||
gboolean case_sensitive,
|
||||
gboolean match_empty_string_at_beginning,
|
||||
gboolean match_empty_string_at_end,
|
||||
const gchar *beginning_regex,
|
||||
const gchar *end_regex)
|
||||
{
|
||||
GString *str;
|
||||
|
||||
g_return_val_if_fail (keywords != NULL, NULL);
|
||||
|
||||
str = g_string_new ("");
|
||||
|
||||
if (keywords != NULL)
|
||||
{
|
||||
if (match_empty_string_at_beginning)
|
||||
g_string_append (str, "\\b");
|
||||
|
||||
if (beginning_regex != NULL)
|
||||
g_string_append (str, beginning_regex);
|
||||
|
||||
if (case_sensitive)
|
||||
g_string_append (str, "(?:");
|
||||
else
|
||||
g_string_append (str, "(?i:");
|
||||
|
||||
/* TODO Make sure pcre can handle big lists, and split lists if necessary.
|
||||
* See #110991 */
|
||||
while (keywords != NULL)
|
||||
{
|
||||
g_string_append (str, (gchar*) keywords->data);
|
||||
|
||||
keywords = g_slist_next (keywords);
|
||||
|
||||
if (keywords != NULL)
|
||||
g_string_append (str, "|");
|
||||
}
|
||||
g_string_append (str, ")");
|
||||
|
||||
if (end_regex != NULL)
|
||||
g_string_append (str, end_regex);
|
||||
|
||||
if (match_empty_string_at_end)
|
||||
g_string_append (str, "\\b");
|
||||
}
|
||||
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
parseLineComment (xmlNodePtr cur,
|
||||
gchar *id,
|
||||
xmlChar *style,
|
||||
GtkSourceContextData *ctx_data,
|
||||
GtkSourceLanguage *language)
|
||||
{
|
||||
xmlNodePtr child;
|
||||
|
||||
child = cur->xmlChildrenNode;
|
||||
|
||||
if ((child != NULL) && !xmlStrcmp (child->name, (const xmlChar *)"start-regex"))
|
||||
{
|
||||
xmlChar *start_regex;
|
||||
|
||||
start_regex = xmlNodeListGetString (child->doc, child->xmlChildrenNode, 1);
|
||||
|
||||
ctx_data_add_syntax_pattern (ctx_data, language, id,
|
||||
(gchar*) style,
|
||||
(gchar*) start_regex,
|
||||
NULL, TRUE);
|
||||
|
||||
xmlFree (start_regex);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Missing start-regex in tag 'line-comment' (%s, line %ld)",
|
||||
child->doc->name, xmlGetLineNo (child));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parseBlockComment (xmlNodePtr cur,
|
||||
gchar *id,
|
||||
xmlChar *style,
|
||||
GtkSourceContextData *ctx_data,
|
||||
GtkSourceLanguage *language)
|
||||
{
|
||||
xmlChar *start_regex = NULL;
|
||||
xmlChar *end_regex = NULL;
|
||||
|
||||
xmlNodePtr child;
|
||||
|
||||
child = cur->xmlChildrenNode;
|
||||
|
||||
while (child != NULL)
|
||||
{
|
||||
if (!xmlStrcmp (child->name, (const xmlChar *)"start-regex"))
|
||||
{
|
||||
start_regex = xmlNodeListGetString (child->doc, child->xmlChildrenNode, 1);
|
||||
}
|
||||
else
|
||||
if (!xmlStrcmp (child->name, (const xmlChar *)"end-regex"))
|
||||
{
|
||||
end_regex = xmlNodeListGetString (child->doc, child->xmlChildrenNode, 1);
|
||||
}
|
||||
|
||||
child = child->next;
|
||||
}
|
||||
|
||||
if (start_regex == NULL)
|
||||
{
|
||||
g_warning ("Missing start-regex in tag 'block-comment' (%s, line %ld)",
|
||||
child->doc->name, xmlGetLineNo (cur));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (end_regex == NULL)
|
||||
{
|
||||
xmlFree (start_regex);
|
||||
|
||||
g_warning ("Missing end-regex in tag 'block-comment' (%s, line %ld)",
|
||||
child->doc->name, xmlGetLineNo (cur));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ctx_data_add_syntax_pattern (ctx_data, language, id,
|
||||
(gchar*) style,
|
||||
(gchar*) start_regex,
|
||||
(gchar*) end_regex,
|
||||
FALSE);
|
||||
|
||||
xmlFree (start_regex);
|
||||
xmlFree (end_regex);
|
||||
}
|
||||
|
||||
static void
|
||||
parseString (xmlNodePtr cur,
|
||||
gchar *id,
|
||||
xmlChar *style,
|
||||
GtkSourceContextData *ctx_data,
|
||||
GtkSourceLanguage *language)
|
||||
{
|
||||
xmlChar *start_regex = NULL;
|
||||
xmlChar *end_regex = NULL;
|
||||
|
||||
xmlChar *prop = NULL;
|
||||
gboolean end_at_line_end = TRUE;
|
||||
|
||||
xmlNodePtr child;
|
||||
|
||||
prop = xmlGetProp (cur, BAD_CAST "end-at-line-end");
|
||||
if (prop != NULL)
|
||||
{
|
||||
if (!xmlStrcasecmp (prop, (const xmlChar *)"TRUE") ||
|
||||
!xmlStrcmp (prop, (const xmlChar *)"1"))
|
||||
|
||||
end_at_line_end = TRUE;
|
||||
else
|
||||
end_at_line_end = FALSE;
|
||||
|
||||
xmlFree (prop);
|
||||
}
|
||||
|
||||
child = cur->xmlChildrenNode;
|
||||
|
||||
while (child != NULL)
|
||||
{
|
||||
if (!xmlStrcmp (child->name, (const xmlChar *)"start-regex"))
|
||||
{
|
||||
start_regex = xmlNodeListGetString (child->doc, child->xmlChildrenNode, 1);
|
||||
}
|
||||
else
|
||||
if (!xmlStrcmp (child->name, (const xmlChar *)"end-regex"))
|
||||
{
|
||||
end_regex = xmlNodeListGetString (child->doc, child->xmlChildrenNode, 1);
|
||||
}
|
||||
|
||||
child = child->next;
|
||||
}
|
||||
|
||||
if (start_regex == NULL)
|
||||
{
|
||||
g_warning ("Missing start-regex in tag 'string' (%s, line %ld)",
|
||||
child->doc->name, xmlGetLineNo (cur));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (end_regex == NULL)
|
||||
{
|
||||
xmlFree (start_regex);
|
||||
|
||||
g_warning ("Missing end-regex in tag 'string' (%s, line %ld)",
|
||||
child->doc->name, xmlGetLineNo (cur));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ctx_data_add_syntax_pattern (ctx_data, language, id,
|
||||
(gchar*) style,
|
||||
(gchar*) start_regex,
|
||||
(gchar*) end_regex,
|
||||
end_at_line_end);
|
||||
|
||||
xmlFree (start_regex);
|
||||
xmlFree (end_regex);
|
||||
}
|
||||
|
||||
static void
|
||||
parseKeywordList (xmlNodePtr cur,
|
||||
gchar *id,
|
||||
xmlChar *style,
|
||||
GtkSourceContextData *ctx_data,
|
||||
GtkSourceLanguage *language)
|
||||
{
|
||||
gboolean case_sensitive = TRUE;
|
||||
gboolean match_empty_string_at_beginning = TRUE;
|
||||
gboolean match_empty_string_at_end = TRUE;
|
||||
gchar *beginning_regex = NULL;
|
||||
gchar *end_regex = NULL;
|
||||
|
||||
GSList *list = NULL;
|
||||
gchar *regex;
|
||||
|
||||
xmlChar *prop;
|
||||
|
||||
xmlNodePtr child;
|
||||
|
||||
prop = xmlGetProp (cur, BAD_CAST "case-sensitive");
|
||||
if (prop != NULL)
|
||||
{
|
||||
if (!xmlStrcasecmp (prop, (const xmlChar *)"TRUE") ||
|
||||
!xmlStrcmp (prop, (const xmlChar *)"1"))
|
||||
|
||||
case_sensitive = TRUE;
|
||||
else
|
||||
case_sensitive = FALSE;
|
||||
|
||||
xmlFree (prop);
|
||||
}
|
||||
|
||||
prop = xmlGetProp (cur, BAD_CAST "match-empty-string-at-beginning");
|
||||
if (prop != NULL)
|
||||
{
|
||||
if (!xmlStrcasecmp (prop, (const xmlChar *)"TRUE") ||
|
||||
!xmlStrcmp (prop, (const xmlChar *)"1"))
|
||||
|
||||
match_empty_string_at_beginning = TRUE;
|
||||
else
|
||||
match_empty_string_at_beginning = FALSE;
|
||||
|
||||
xmlFree (prop);
|
||||
}
|
||||
|
||||
prop = xmlGetProp (cur, BAD_CAST "match-empty-string-at-end");
|
||||
if (prop != NULL)
|
||||
{
|
||||
if (!xmlStrcasecmp (prop, (const xmlChar *)"TRUE") ||
|
||||
!xmlStrcmp (prop, (const xmlChar *)"1"))
|
||||
|
||||
match_empty_string_at_end = TRUE;
|
||||
else
|
||||
match_empty_string_at_end = FALSE;
|
||||
|
||||
xmlFree (prop);
|
||||
}
|
||||
|
||||
prop = xmlGetProp (cur, BAD_CAST "beginning-regex");
|
||||
if (prop != NULL)
|
||||
{
|
||||
beginning_regex = g_strdup ((gchar *)prop);
|
||||
|
||||
xmlFree (prop);
|
||||
}
|
||||
|
||||
prop = xmlGetProp (cur, BAD_CAST "end-regex");
|
||||
if (prop != NULL)
|
||||
{
|
||||
end_regex = g_strdup ((gchar *)prop);
|
||||
|
||||
xmlFree (prop);
|
||||
}
|
||||
|
||||
child = cur->xmlChildrenNode;
|
||||
|
||||
while (child != NULL)
|
||||
{
|
||||
if (!xmlStrcmp (child->name, BAD_CAST "keyword"))
|
||||
{
|
||||
xmlChar *keyword;
|
||||
keyword = xmlNodeListGetString (child->doc, child->xmlChildrenNode, 1);
|
||||
list = g_slist_prepend (list, keyword);
|
||||
}
|
||||
|
||||
child = child->next;
|
||||
}
|
||||
|
||||
list = g_slist_reverse (list);
|
||||
|
||||
if (list == NULL)
|
||||
{
|
||||
g_warning ("No keywords in tag 'keyword-list' (%s, line %ld)",
|
||||
child->doc->name, xmlGetLineNo (cur));
|
||||
|
||||
g_free (beginning_regex),
|
||||
g_free (end_regex);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
regex = build_keyword_list (list,
|
||||
case_sensitive,
|
||||
match_empty_string_at_beginning,
|
||||
match_empty_string_at_end,
|
||||
beginning_regex,
|
||||
end_regex);
|
||||
|
||||
g_free (beginning_regex),
|
||||
g_free (end_regex);
|
||||
|
||||
g_slist_foreach (list, (GFunc) xmlFree, NULL);
|
||||
g_slist_free (list);
|
||||
|
||||
ctx_data_add_simple_pattern (ctx_data, language, id, (gchar*) style, regex);
|
||||
|
||||
g_free (regex);
|
||||
}
|
||||
|
||||
static void
|
||||
parsePatternItem (xmlNodePtr cur,
|
||||
gchar *id,
|
||||
xmlChar *style,
|
||||
GtkSourceContextData *ctx_data,
|
||||
GtkSourceLanguage *language)
|
||||
{
|
||||
xmlNodePtr child;
|
||||
|
||||
child = cur->xmlChildrenNode;
|
||||
|
||||
if ((child != NULL) && !xmlStrcmp (child->name, (const xmlChar *)"regex"))
|
||||
{
|
||||
xmlChar *regex;
|
||||
|
||||
regex = xmlNodeListGetString (child->doc, child->xmlChildrenNode, 1);
|
||||
|
||||
ctx_data_add_simple_pattern (ctx_data, language, id,
|
||||
(gchar*) style,
|
||||
(gchar*) regex);
|
||||
|
||||
xmlFree (regex);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Missing regex in tag 'pattern-item' (%s, line %ld)",
|
||||
child->doc->name, xmlGetLineNo (child));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parseSyntaxItem (xmlNodePtr cur,
|
||||
const gchar *id,
|
||||
xmlChar *style,
|
||||
GtkSourceContextData *ctx_data,
|
||||
GtkSourceLanguage *language)
|
||||
{
|
||||
xmlChar *start_regex = NULL;
|
||||
xmlChar *end_regex = NULL;
|
||||
|
||||
xmlNodePtr child;
|
||||
|
||||
child = cur->xmlChildrenNode;
|
||||
|
||||
while (child != NULL)
|
||||
{
|
||||
if (!xmlStrcmp (child->name, (const xmlChar *)"start-regex"))
|
||||
{
|
||||
start_regex = xmlNodeListGetString (child->doc, child->xmlChildrenNode, 1);
|
||||
}
|
||||
else
|
||||
if (!xmlStrcmp (child->name, (const xmlChar *)"end-regex"))
|
||||
{
|
||||
end_regex = xmlNodeListGetString (child->doc, child->xmlChildrenNode, 1);
|
||||
}
|
||||
|
||||
child = child->next;
|
||||
}
|
||||
|
||||
if (start_regex == NULL)
|
||||
{
|
||||
g_warning ("Missing start-regex in tag 'syntax-item' (%s, line %ld)",
|
||||
child->doc->name, xmlGetLineNo (cur));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (end_regex == NULL)
|
||||
{
|
||||
xmlFree (start_regex);
|
||||
|
||||
g_warning ("Missing end-regex in tag 'syntax-item' (%s, line %ld)",
|
||||
child->doc->name, xmlGetLineNo (cur));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ctx_data_add_syntax_pattern (ctx_data, language, id,
|
||||
(gchar*) style,
|
||||
(gchar*) start_regex,
|
||||
(gchar*) end_regex,
|
||||
FALSE);
|
||||
|
||||
xmlFree (start_regex);
|
||||
xmlFree (end_regex);
|
||||
}
|
||||
|
||||
static void
|
||||
parseTag (GtkSourceLanguage *language,
|
||||
xmlNodePtr cur,
|
||||
GtkSourceContextData *ctx_data)
|
||||
{
|
||||
xmlChar *name;
|
||||
xmlChar *style;
|
||||
xmlChar *id;
|
||||
|
||||
name = xmlGetProp (cur, BAD_CAST "_name");
|
||||
if (name == NULL)
|
||||
{
|
||||
name = xmlGetProp (cur, BAD_CAST "name");
|
||||
id = xmlStrdup (name);
|
||||
}
|
||||
else
|
||||
{
|
||||
gchar *tmp1 = _gtk_source_language_translate_string (language, (gchar*) name);
|
||||
xmlChar *tmp2 = xmlStrdup (BAD_CAST tmp1);
|
||||
id = name;
|
||||
name = tmp2;
|
||||
g_free (tmp1);
|
||||
}
|
||||
|
||||
if (name == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
style = xmlGetProp (cur, BAD_CAST "style");
|
||||
|
||||
if (!xmlStrcmp (cur->name, (const xmlChar*) "line-comment"))
|
||||
{
|
||||
parseLineComment (cur, (gchar*) id, style, ctx_data, language);
|
||||
}
|
||||
else if (!xmlStrcmp (cur->name, (const xmlChar*) "block-comment"))
|
||||
{
|
||||
parseBlockComment (cur, (gchar*) id, style, ctx_data, language);
|
||||
}
|
||||
else if (!xmlStrcmp (cur->name, (const xmlChar*) "string"))
|
||||
{
|
||||
parseString (cur, (gchar*) id, style, ctx_data, language);
|
||||
}
|
||||
else if (!xmlStrcmp (cur->name, (const xmlChar*) "keyword-list"))
|
||||
{
|
||||
parseKeywordList (cur, (gchar*) id, style, ctx_data, language);
|
||||
}
|
||||
else if (!xmlStrcmp (cur->name, (const xmlChar*) "pattern-item"))
|
||||
{
|
||||
parsePatternItem (cur, (gchar*) id, style, ctx_data, language);
|
||||
}
|
||||
else if (!xmlStrcmp (cur->name, (const xmlChar*) "syntax-item"))
|
||||
{
|
||||
parseSyntaxItem (cur, (gchar*) id, style, ctx_data, language);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_print ("Unknown tag: %s\n", cur->name);
|
||||
}
|
||||
|
||||
xmlFree (name);
|
||||
xmlFree (style);
|
||||
xmlFree (id);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
define_root_context (GtkSourceContextData *ctx_data,
|
||||
GtkSourceLanguage *language)
|
||||
{
|
||||
gboolean result;
|
||||
gchar *id;
|
||||
GError *error = NULL;
|
||||
|
||||
g_return_val_if_fail (language->priv->id != NULL, FALSE);
|
||||
|
||||
id = g_strdup_printf ("%s:%s", language->priv->id, language->priv->id);
|
||||
result = _gtk_source_context_data_define_context (ctx_data, id,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL,
|
||||
GTK_SOURCE_CONTEXT_EXTEND_PARENT,
|
||||
&error);
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
g_warning ("%s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_free (id);
|
||||
return result;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gtk_source_language_file_parse_version1 (GtkSourceLanguage *language,
|
||||
GtkSourceContextData *ctx_data)
|
||||
{
|
||||
xmlDocPtr doc;
|
||||
xmlNodePtr cur;
|
||||
GMappedFile *mf;
|
||||
gunichar esc_char = 0;
|
||||
xmlChar *lang_version = NULL;
|
||||
|
||||
xmlKeepBlanksDefault (0);
|
||||
|
||||
mf = g_mapped_file_new (language->priv->lang_file_name, FALSE, NULL);
|
||||
|
||||
if (mf == NULL)
|
||||
{
|
||||
doc = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
doc = xmlParseMemory (g_mapped_file_get_contents (mf),
|
||||
g_mapped_file_get_length (mf));
|
||||
|
||||
g_mapped_file_unref (mf);
|
||||
}
|
||||
|
||||
if (doc == NULL)
|
||||
{
|
||||
g_warning ("Impossible to parse file '%s'",
|
||||
language->priv->lang_file_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
cur = xmlDocGetRootElement (doc);
|
||||
|
||||
if (cur == NULL)
|
||||
{
|
||||
g_warning ("The lang file '%s' is empty",
|
||||
language->priv->lang_file_name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (xmlStrcmp (cur->name, (const xmlChar *) "language") != 0)
|
||||
{
|
||||
g_warning ("File '%s' is of the wrong type",
|
||||
language->priv->lang_file_name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
lang_version = xmlGetProp (cur, BAD_CAST "version");
|
||||
|
||||
if (lang_version == NULL || strcmp ("1.0", (char*) lang_version) != 0)
|
||||
{
|
||||
if (lang_version != NULL)
|
||||
g_warning ("Wrong language version '%s' in file '%s', expected '%s'",
|
||||
(char*) lang_version, language->priv->lang_file_name, "1.0");
|
||||
else
|
||||
g_warning ("Language version missing in file '%s'",
|
||||
language->priv->lang_file_name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!define_root_context (ctx_data, language))
|
||||
{
|
||||
g_warning ("Could not create root context for file '%s'",
|
||||
language->priv->lang_file_name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* FIXME: check that the language name, version, etc. are the
|
||||
* right ones - Paolo */
|
||||
|
||||
cur = xmlDocGetRootElement (doc);
|
||||
cur = cur->xmlChildrenNode;
|
||||
g_return_val_if_fail (cur != NULL, FALSE);
|
||||
|
||||
while (cur != NULL)
|
||||
{
|
||||
if (!xmlStrcmp (cur->name, (const xmlChar *)"escape-char"))
|
||||
{
|
||||
xmlChar *escape;
|
||||
|
||||
escape = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
|
||||
esc_char = g_utf8_get_char_validated ((gchar*) escape, -1);
|
||||
|
||||
if (esc_char == (gunichar) -1 || esc_char == (gunichar) -2)
|
||||
{
|
||||
g_warning ("Invalid (non UTF8) escape character in file '%s'",
|
||||
language->priv->lang_file_name);
|
||||
esc_char = 0;
|
||||
}
|
||||
|
||||
xmlFree (escape);
|
||||
}
|
||||
else
|
||||
{
|
||||
parseTag (language, cur, ctx_data);
|
||||
}
|
||||
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
if (esc_char != 0)
|
||||
_gtk_source_context_data_set_escape_char (ctx_data, esc_char);
|
||||
|
||||
_gtk_source_context_data_finish_parse (ctx_data, NULL, NULL);
|
||||
_gtk_source_language_define_language_styles (language);
|
||||
|
||||
xmlFreeDoc (doc);
|
||||
xmlFree (lang_version);
|
||||
return TRUE;
|
||||
|
||||
error:
|
||||
if (doc)
|
||||
xmlFreeDoc (doc);
|
||||
xmlFree (lang_version);
|
||||
return FALSE;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,94 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
|
||||
* gtksourcelanguage-private.h
|
||||
*
|
||||
* Copyright (C) 2003 - Paolo Maggi <paolo.maggi@polito.it>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library 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 __GTK_SOURCE_LANGUAGE_PRIVATE_H__
|
||||
#define __GTK_SOURCE_LANGUAGE_PRIVATE_H__
|
||||
|
||||
#include <mooglib/moo-glib.h>
|
||||
#include "gtksourcecontextengine.h"
|
||||
#include "gtksourcelanguagemanager.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_SOURCE_LANGUAGE_VERSION_1_0 100
|
||||
#define GTK_SOURCE_LANGUAGE_VERSION_2_0 200
|
||||
|
||||
typedef struct _GtkSourceStyleInfo GtkSourceStyleInfo;
|
||||
|
||||
struct _GtkSourceStyleInfo
|
||||
{
|
||||
gchar *name;
|
||||
gchar *map_to;
|
||||
};
|
||||
|
||||
struct _GtkSourceLanguagePrivate
|
||||
{
|
||||
gchar *lang_file_name;
|
||||
gchar *translation_domain;
|
||||
|
||||
gchar *id;
|
||||
gchar *name;
|
||||
gchar *section;
|
||||
|
||||
/* Maps ids to GtkSourceStyleInfo objects */
|
||||
/* Names of styles defined in other lang files are not stored */
|
||||
GHashTable *styles;
|
||||
gboolean styles_loaded;
|
||||
|
||||
gint version;
|
||||
gboolean hidden;
|
||||
|
||||
GHashTable *properties;
|
||||
|
||||
GtkSourceLanguageManager *language_manager;
|
||||
|
||||
GtkSourceContextData *ctx_data;
|
||||
};
|
||||
|
||||
GtkSourceLanguage *_gtk_source_language_new_from_file (const gchar *filename,
|
||||
GtkSourceLanguageManager *lm);
|
||||
|
||||
GtkSourceLanguageManager *_gtk_source_language_get_language_manager (GtkSourceLanguage *language);
|
||||
|
||||
const gchar *_gtk_source_language_manager_get_rng_file (GtkSourceLanguageManager *lm);
|
||||
|
||||
gchar *_gtk_source_language_translate_string (GtkSourceLanguage *language,
|
||||
const gchar *string);
|
||||
|
||||
void _gtk_source_language_define_language_styles (GtkSourceLanguage *language);
|
||||
|
||||
gboolean _gtk_source_language_file_parse_version1 (GtkSourceLanguage *language,
|
||||
GtkSourceContextData *ctx_data);
|
||||
|
||||
gboolean _gtk_source_language_file_parse_version2 (GtkSourceLanguage *language,
|
||||
GtkSourceContextData *ctx_data);
|
||||
|
||||
GtkSourceEngine *_gtk_source_language_create_engine (GtkSourceLanguage *language);
|
||||
|
||||
/* Utility functions for GtkSourceStyleInfo */
|
||||
GtkSourceStyleInfo *_gtk_source_style_info_new (const gchar *name,
|
||||
const gchar *map_to);
|
||||
GtkSourceStyleInfo *_gtk_source_style_info_copy (GtkSourceStyleInfo *info);
|
||||
void _gtk_source_style_info_free (GtkSourceStyleInfo *info);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_SOURCE_LANGUAGE_PRIVATE_H__ */
|
||||
|
|
@ -0,0 +1,906 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
|
||||
* gtksourcelanguage.c
|
||||
*
|
||||
* Copyright (C) 2003 - Paolo Maggi <paolo.maggi@polito.it>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library 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_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef G_OS_WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <libxml/xmlreader.h>
|
||||
#include <mooglib/moo-glib.h>
|
||||
#include "gtksourceview-i18n.h"
|
||||
#include "gtksourcelanguage-private.h"
|
||||
#include "gtksourcelanguage.h"
|
||||
#include "gtksourceview-marshal.h"
|
||||
|
||||
#define DEFAULT_SECTION _("Others")
|
||||
|
||||
/* Properties */
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_ID,
|
||||
PROP_NAME,
|
||||
PROP_SECTION,
|
||||
PROP_HIDDEN
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkSourceLanguage, gtk_source_language, G_TYPE_OBJECT)
|
||||
|
||||
static GtkSourceLanguage *process_language_node (xmlTextReaderPtr reader,
|
||||
const gchar *filename);
|
||||
static gboolean force_styles (GtkSourceLanguage *language);
|
||||
|
||||
GtkSourceLanguage *
|
||||
_gtk_source_language_new_from_file (const gchar *filename,
|
||||
GtkSourceLanguageManager *lm)
|
||||
{
|
||||
GtkSourceLanguage *lang = NULL;
|
||||
xmlTextReaderPtr reader = NULL;
|
||||
gint ret;
|
||||
|
||||
g_return_val_if_fail (filename != NULL, NULL);
|
||||
g_return_val_if_fail (lm != NULL, NULL);
|
||||
|
||||
reader = xmlReaderForFile (filename, NULL, 0);
|
||||
|
||||
if (reader != NULL)
|
||||
{
|
||||
ret = xmlTextReaderRead (reader);
|
||||
|
||||
while (ret == 1)
|
||||
{
|
||||
if (xmlTextReaderNodeType (reader) == 1)
|
||||
{
|
||||
xmlChar *name;
|
||||
|
||||
name = xmlTextReaderName (reader);
|
||||
|
||||
if (xmlStrcmp (name, BAD_CAST "language") == 0)
|
||||
{
|
||||
lang = process_language_node (reader, filename);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
xmlFree (name);
|
||||
}
|
||||
|
||||
if (ret == 1)
|
||||
ret = xmlTextReaderRead (reader);
|
||||
}
|
||||
|
||||
xmlFreeTextReader (reader);
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
g_warning("Failed to parse '%s'", filename);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning("Unable to open '%s'", filename);
|
||||
|
||||
}
|
||||
|
||||
if (lang != NULL)
|
||||
{
|
||||
lang->priv->language_manager = lm;
|
||||
g_object_add_weak_pointer (G_OBJECT (lm),
|
||||
(gpointer) &lang->priv->language_manager);
|
||||
}
|
||||
|
||||
return lang;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_source_language_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkSourceLanguage *language;
|
||||
|
||||
g_return_if_fail (GTK_IS_SOURCE_LANGUAGE (object));
|
||||
|
||||
language = GTK_SOURCE_LANGUAGE (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ID:
|
||||
g_value_set_string (value, language->priv->id);
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, language->priv->name);
|
||||
break;
|
||||
|
||||
case PROP_SECTION:
|
||||
g_value_set_string (value, language->priv->section);
|
||||
break;
|
||||
|
||||
case PROP_HIDDEN:
|
||||
g_value_set_boolean (value, language->priv->hidden);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_source_language_dispose (GObject *object)
|
||||
{
|
||||
GtkSourceLanguage *lang;
|
||||
|
||||
lang = GTK_SOURCE_LANGUAGE (object);
|
||||
|
||||
if (lang->priv->language_manager != NULL)
|
||||
{
|
||||
g_object_remove_weak_pointer (G_OBJECT (lang->priv->language_manager),
|
||||
(gpointer) &lang->priv->language_manager);
|
||||
lang->priv->language_manager = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gtk_source_language_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_source_language_finalize (GObject *object)
|
||||
{
|
||||
GtkSourceLanguage *lang;
|
||||
|
||||
lang = GTK_SOURCE_LANGUAGE (object);
|
||||
|
||||
if (lang->priv->ctx_data != NULL)
|
||||
g_critical ("context data not freed in gtk_source_language_finalize");
|
||||
|
||||
g_free (lang->priv->lang_file_name);
|
||||
g_free (lang->priv->translation_domain);
|
||||
g_free (lang->priv->name);
|
||||
g_free (lang->priv->section);
|
||||
g_free (lang->priv->id);
|
||||
g_hash_table_destroy (lang->priv->properties);
|
||||
|
||||
g_hash_table_destroy (lang->priv->styles);
|
||||
|
||||
G_OBJECT_CLASS (gtk_source_language_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_source_language_class_init (GtkSourceLanguageClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->get_property = gtk_source_language_get_property;
|
||||
object_class->dispose = gtk_source_language_dispose;
|
||||
object_class->finalize = gtk_source_language_finalize;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_ID,
|
||||
g_param_spec_string ("id",
|
||||
_("Language id"),
|
||||
_("Language id"),
|
||||
NULL,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_NAME,
|
||||
g_param_spec_string ("name",
|
||||
_("Language name"),
|
||||
_("Language name"),
|
||||
NULL,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_SECTION,
|
||||
g_param_spec_string ("section",
|
||||
_("Language section"),
|
||||
_("Language section"),
|
||||
NULL,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_HIDDEN,
|
||||
g_param_spec_boolean ("hidden",
|
||||
_("Hidden"),
|
||||
_("Whether the language should be hidden from the user"),
|
||||
FALSE,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_type_class_add_private (object_class, sizeof(GtkSourceLanguagePrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_source_language_init (GtkSourceLanguage *lang)
|
||||
{
|
||||
lang->priv = G_TYPE_INSTANCE_GET_PRIVATE (lang, GTK_TYPE_SOURCE_LANGUAGE,
|
||||
GtkSourceLanguagePrivate);
|
||||
lang->priv->styles = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
(GDestroyNotify)_gtk_source_style_info_free);
|
||||
lang->priv->properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
string_to_bool (const gchar *string)
|
||||
{
|
||||
if (!g_ascii_strcasecmp (string, "yes") ||
|
||||
!g_ascii_strcasecmp (string, "true") ||
|
||||
!g_ascii_strcasecmp (string, "1"))
|
||||
return TRUE;
|
||||
else if (!g_ascii_strcasecmp (string, "no") ||
|
||||
!g_ascii_strcasecmp (string, "false") ||
|
||||
!g_ascii_strcasecmp (string, "0"))
|
||||
return FALSE;
|
||||
else
|
||||
g_return_val_if_reached (FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
process_properties (xmlTextReaderPtr reader,
|
||||
GtkSourceLanguage *language)
|
||||
{
|
||||
xmlNodePtr child;
|
||||
xmlNodePtr node = NULL;
|
||||
|
||||
while (node == NULL && xmlTextReaderRead (reader) == 1)
|
||||
{
|
||||
xmlChar *name;
|
||||
|
||||
if (xmlTextReaderNodeType (reader) != 1)
|
||||
continue;
|
||||
|
||||
name = xmlTextReaderName (reader);
|
||||
|
||||
if (xmlStrcmp (name, BAD_CAST "metadata") != 0)
|
||||
{
|
||||
xmlFree (name);
|
||||
continue;
|
||||
}
|
||||
|
||||
xmlFree (name);
|
||||
|
||||
node = xmlTextReaderExpand (reader);
|
||||
|
||||
if (node == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
if (node == NULL)
|
||||
return;
|
||||
|
||||
for (child = node->children; child != NULL; child = child->next)
|
||||
{
|
||||
xmlChar *name;
|
||||
xmlChar *content;
|
||||
|
||||
if (child->type != XML_ELEMENT_NODE ||
|
||||
xmlStrcmp (child->name, BAD_CAST "property") != 0)
|
||||
continue;
|
||||
|
||||
name = xmlGetProp (child, BAD_CAST "name");
|
||||
content = xmlNodeGetContent (child);
|
||||
|
||||
if (name != NULL && content != NULL)
|
||||
g_hash_table_insert (language->priv->properties,
|
||||
g_strdup ((gchar *) name),
|
||||
g_strdup ((gchar *) content));
|
||||
|
||||
xmlFree (name);
|
||||
xmlFree (content);
|
||||
}
|
||||
}
|
||||
|
||||
static GtkSourceLanguage *
|
||||
process_language_node (xmlTextReaderPtr reader, const gchar *filename)
|
||||
{
|
||||
xmlChar *version;
|
||||
xmlChar *tmp;
|
||||
xmlChar *untranslated_name;
|
||||
GtkSourceLanguage *lang;
|
||||
|
||||
lang = g_object_new (GTK_TYPE_SOURCE_LANGUAGE, NULL);
|
||||
|
||||
lang->priv->lang_file_name = g_strdup (filename);
|
||||
|
||||
tmp = xmlTextReaderGetAttribute (reader, BAD_CAST "translation-domain");
|
||||
lang->priv->translation_domain = g_strdup ((gchar*) tmp);
|
||||
xmlFree (tmp);
|
||||
|
||||
tmp = xmlTextReaderGetAttribute (reader, BAD_CAST "hidden");
|
||||
if (tmp != NULL)
|
||||
lang->priv->hidden = string_to_bool ((gchar*) tmp);
|
||||
else
|
||||
lang->priv->hidden = FALSE;
|
||||
xmlFree (tmp);
|
||||
|
||||
tmp = xmlTextReaderGetAttribute (reader, BAD_CAST "mimetypes");
|
||||
if (tmp != NULL)
|
||||
g_hash_table_insert (lang->priv->properties,
|
||||
g_strdup ("mimetypes"),
|
||||
g_strdup ((char*) tmp));
|
||||
xmlFree (tmp);
|
||||
|
||||
tmp = xmlTextReaderGetAttribute (reader, BAD_CAST "globs");
|
||||
if (tmp != NULL)
|
||||
g_hash_table_insert (lang->priv->properties,
|
||||
g_strdup ("globs"),
|
||||
g_strdup ((char*) tmp));
|
||||
xmlFree (tmp);
|
||||
|
||||
tmp = xmlTextReaderGetAttribute (reader, BAD_CAST "_name");
|
||||
if (tmp == NULL)
|
||||
{
|
||||
tmp = xmlTextReaderGetAttribute (reader, BAD_CAST "name");
|
||||
|
||||
if (tmp == NULL)
|
||||
{
|
||||
g_warning ("Impossible to get language name from file '%s'",
|
||||
filename);
|
||||
g_object_unref (lang);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lang->priv->name = g_strdup ((char*) tmp);
|
||||
untranslated_name = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
lang->priv->name = _gtk_source_language_translate_string (lang, (gchar*) tmp);
|
||||
untranslated_name = tmp;
|
||||
}
|
||||
|
||||
tmp = xmlTextReaderGetAttribute (reader, BAD_CAST "id");
|
||||
if (tmp != NULL)
|
||||
{
|
||||
lang->priv->id = g_ascii_strdown ((gchar*) tmp, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
lang->priv->id = g_ascii_strdown ((gchar*) untranslated_name, -1);
|
||||
}
|
||||
xmlFree (tmp);
|
||||
xmlFree (untranslated_name);
|
||||
|
||||
tmp = xmlTextReaderGetAttribute (reader, BAD_CAST "_section");
|
||||
if (tmp == NULL)
|
||||
{
|
||||
tmp = xmlTextReaderGetAttribute (reader, BAD_CAST "section");
|
||||
|
||||
if (tmp == NULL)
|
||||
lang->priv->section = g_strdup (DEFAULT_SECTION);
|
||||
else
|
||||
lang->priv->section = g_strdup ((gchar *) tmp);
|
||||
|
||||
xmlFree (tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
lang->priv->section = _gtk_source_language_translate_string (lang, (gchar*) tmp);
|
||||
xmlFree (tmp);
|
||||
}
|
||||
|
||||
version = xmlTextReaderGetAttribute (reader, BAD_CAST "version");
|
||||
|
||||
if (version == NULL)
|
||||
{
|
||||
g_warning ("Impossible to get version number from file '%s'",
|
||||
filename);
|
||||
g_object_unref (lang);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (xmlStrcmp (version , BAD_CAST "1.0") == 0)
|
||||
{
|
||||
lang->priv->version = GTK_SOURCE_LANGUAGE_VERSION_1_0;
|
||||
}
|
||||
else if (xmlStrcmp (version, BAD_CAST "2.0") == 0)
|
||||
{
|
||||
lang->priv->version = GTK_SOURCE_LANGUAGE_VERSION_2_0;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Unsupported language spec version '%s' in file '%s'",
|
||||
(gchar*) version, filename);
|
||||
xmlFree (version);
|
||||
g_object_unref (lang);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xmlFree (version);
|
||||
|
||||
if (lang->priv->version == GTK_SOURCE_LANGUAGE_VERSION_2_0)
|
||||
process_properties (reader, lang);
|
||||
|
||||
return lang;
|
||||
}
|
||||
|
||||
gchar *
|
||||
_gtk_source_language_translate_string (GtkSourceLanguage *language,
|
||||
const gchar *string)
|
||||
{
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
return GD_(language->priv->translation_domain, string);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_language_get_id:
|
||||
* @language: a #GtkSourceLanguage.
|
||||
*
|
||||
* Returns the ID of the language. The ID is not locale-dependent.
|
||||
*
|
||||
* Returns: the ID of @language.
|
||||
* The returned string is owned by @language and should not be freed
|
||||
* or modified.
|
||||
**/
|
||||
const gchar *
|
||||
gtk_source_language_get_id (GtkSourceLanguage *language)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE (language), NULL);
|
||||
g_return_val_if_fail (language->priv->id != NULL, NULL);
|
||||
|
||||
return language->priv->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_language_get_name:
|
||||
* @language: a #GtkSourceLanguage.
|
||||
*
|
||||
* Returns the localized name of the language.
|
||||
*
|
||||
* Returns: the name of @language.
|
||||
* The returned string is owned by @language and should not be freed
|
||||
* or modified.
|
||||
**/
|
||||
const gchar *
|
||||
gtk_source_language_get_name (GtkSourceLanguage *language)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE (language), NULL);
|
||||
g_return_val_if_fail (language->priv->name != NULL, NULL);
|
||||
|
||||
return language->priv->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_language_get_section:
|
||||
* @language: a #GtkSourceLanguage.
|
||||
*
|
||||
* Returns the localized section of the language.
|
||||
* Each language belong to a section (ex. HTML belogs to the
|
||||
* Markup section).
|
||||
*
|
||||
* Returns: the section of @language.
|
||||
* The returned string is owned by @language and should not be freed
|
||||
* or modified.
|
||||
**/
|
||||
const gchar *
|
||||
gtk_source_language_get_section (GtkSourceLanguage *language)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE (language), NULL);
|
||||
g_return_val_if_fail (language->priv->section != NULL, NULL);
|
||||
|
||||
return language->priv->section;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_language_get_hidden:
|
||||
* @language: a #GtkSourceLanguage
|
||||
*
|
||||
* Returns whether the language should be hidden from the user.
|
||||
*
|
||||
* Returns: TRUE if the language should be hidden, FALSE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
gtk_source_language_get_hidden (GtkSourceLanguage *language)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE (language), FALSE);
|
||||
|
||||
return language->priv->hidden;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_language_get_metadata:
|
||||
* @language: a #GtkSourceLanguage.
|
||||
* @name: metadata property name.
|
||||
*
|
||||
* Returns: value of property @name stored in the metadata of @language
|
||||
* or %NULL if language doesn't contain that metadata property.
|
||||
* The returned string is owned by @language and should not be freed
|
||||
* or modified.
|
||||
**/
|
||||
const gchar *
|
||||
gtk_source_language_get_metadata (GtkSourceLanguage *language,
|
||||
const gchar *name)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE (language), NULL);
|
||||
g_return_val_if_fail (name != NULL, NULL);
|
||||
|
||||
return g_hash_table_lookup (language->priv->properties, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_language_get_mime_types:
|
||||
* @language: a #GtkSourceLanguage.
|
||||
*
|
||||
* Returns the mime types associated to this language. This is just
|
||||
* an utility wrapper around gtk_source_language_get_metadata() to
|
||||
* retrieve the "mimetypes" metadata property and split it into an
|
||||
* array.
|
||||
*
|
||||
* Returns: a newly-allocated %NULL terminated array containing
|
||||
* the mime types or %NULL if no mime types are found.
|
||||
* The returned array must be freed with g_strfreev().
|
||||
**/
|
||||
gchar **
|
||||
gtk_source_language_get_mime_types (GtkSourceLanguage *language)
|
||||
{
|
||||
const gchar *mimetypes;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE (language), NULL);
|
||||
|
||||
mimetypes = gtk_source_language_get_metadata (language, "mimetypes");
|
||||
if (mimetypes == NULL)
|
||||
return NULL;
|
||||
|
||||
return g_strsplit (mimetypes, ";", 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_language_get_globs:
|
||||
* @language: a #GtkSourceLanguage.
|
||||
*
|
||||
* Returns the globs associated to this language. This is just
|
||||
* an utility wrapper around gtk_source_language_get_metadata() to
|
||||
* retrieve the "globs" metadata property and split it into an array.
|
||||
*
|
||||
* Returns: a newly-allocated %NULL terminated array containing
|
||||
* the globs or %NULL if no globs are found.
|
||||
* The returned array must be freed with g_strfreev().
|
||||
**/
|
||||
gchar **
|
||||
gtk_source_language_get_globs (GtkSourceLanguage *language)
|
||||
{
|
||||
const gchar *globs;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE (language), NULL);
|
||||
|
||||
globs = gtk_source_language_get_metadata (language, "globs");
|
||||
if (globs == NULL)
|
||||
return NULL;
|
||||
|
||||
return g_strsplit (globs, ";", 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_source_language_get_language_manager:
|
||||
* @language: a #GtkSourceLanguage.
|
||||
*
|
||||
* Returns: #GtkSourceLanguageManager for @language.
|
||||
**/
|
||||
GtkSourceLanguageManager *
|
||||
_gtk_source_language_get_language_manager (GtkSourceLanguage *language)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE (language), NULL);
|
||||
g_return_val_if_fail (language->priv->id != NULL, NULL);
|
||||
|
||||
return language->priv->language_manager;
|
||||
}
|
||||
|
||||
/* Highlighting engine creation ------------------------------------------ */
|
||||
|
||||
static void
|
||||
copy_style_info (const char *style_id,
|
||||
GtkSourceStyleInfo *info,
|
||||
GHashTable *dest)
|
||||
{
|
||||
g_hash_table_insert (dest, g_strdup (style_id),
|
||||
_gtk_source_style_info_copy (info));
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_source_language_define_language_styles (GtkSourceLanguage *lang)
|
||||
{
|
||||
static const gchar *alias[][2] = {
|
||||
{"Base-N Integer", "def:base-n-integer"},
|
||||
{"Character", "def:character"},
|
||||
{"Comment", "def:comment"},
|
||||
{"Function", "def:function"},
|
||||
{"Decimal", "def:decimal"},
|
||||
{"Floating Point", "def:floating-point"},
|
||||
{"Keyword", "def:keyword"},
|
||||
{"Preprocessor", "def:preprocessor"},
|
||||
{"String", "def:string"},
|
||||
{"Specials", "def:specials"},
|
||||
{"Data Type", "def:type"},
|
||||
{NULL, NULL}};
|
||||
|
||||
gint i = 0;
|
||||
GtkSourceLanguageManager *lm;
|
||||
GtkSourceLanguage *def_lang;
|
||||
|
||||
while (alias[i][0] != NULL)
|
||||
{
|
||||
GtkSourceStyleInfo *info;
|
||||
|
||||
info = _gtk_source_style_info_new (alias[i][0], alias[i][1]);
|
||||
|
||||
g_hash_table_insert (lang->priv->styles,
|
||||
g_strdup (alias[i][0]),
|
||||
info);
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
/* We translate String to def:string, but def:string is mapped-to
|
||||
* def:constant in def.lang, so we got to take style mappings from def.lang */
|
||||
|
||||
lm = _gtk_source_language_get_language_manager (lang);
|
||||
def_lang = gtk_source_language_manager_get_language (lm, "def");
|
||||
|
||||
if (def_lang != NULL)
|
||||
{
|
||||
force_styles (def_lang);
|
||||
g_hash_table_foreach (def_lang->priv->styles,
|
||||
(GHFunc) copy_style_info,
|
||||
lang->priv->styles);
|
||||
}
|
||||
}
|
||||
|
||||
/* returns new reference, which _must_ be unref'ed */
|
||||
static GtkSourceContextData *
|
||||
gtk_source_language_parse_file (GtkSourceLanguage *language)
|
||||
{
|
||||
if (language->priv->ctx_data == NULL)
|
||||
{
|
||||
gboolean success = FALSE;
|
||||
GtkSourceContextData *ctx_data;
|
||||
|
||||
if (language->priv->language_manager == NULL)
|
||||
{
|
||||
g_critical ("_gtk_source_language_create_engine() is called after "
|
||||
"language manager was finalized");
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx_data = _gtk_source_context_data_new (language);
|
||||
|
||||
switch (language->priv->version)
|
||||
{
|
||||
case GTK_SOURCE_LANGUAGE_VERSION_1_0:
|
||||
success = _gtk_source_language_file_parse_version1 (language, ctx_data);
|
||||
break;
|
||||
|
||||
case GTK_SOURCE_LANGUAGE_VERSION_2_0:
|
||||
success = _gtk_source_language_file_parse_version2 (language, ctx_data);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!success)
|
||||
_gtk_source_context_data_unref (ctx_data);
|
||||
else
|
||||
language->priv->ctx_data = ctx_data;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_gtk_source_context_data_ref (language->priv->ctx_data);
|
||||
}
|
||||
|
||||
return language->priv->ctx_data;
|
||||
}
|
||||
|
||||
GtkSourceEngine *
|
||||
_gtk_source_language_create_engine (GtkSourceLanguage *language)
|
||||
{
|
||||
GtkSourceContextEngine *ce = NULL;
|
||||
GtkSourceContextData *ctx_data;
|
||||
|
||||
ctx_data = gtk_source_language_parse_file (language);
|
||||
|
||||
if (ctx_data != NULL)
|
||||
{
|
||||
ce = _gtk_source_context_engine_new (ctx_data);
|
||||
_gtk_source_context_data_unref (ctx_data);
|
||||
}
|
||||
|
||||
return ce ? GTK_SOURCE_ENGINE (ce) : NULL;
|
||||
}
|
||||
|
||||
typedef struct _AddStyleIdData AddStyleIdData;
|
||||
|
||||
struct _AddStyleIdData
|
||||
{
|
||||
gchar *language_id;
|
||||
GPtrArray *ids_array;
|
||||
};
|
||||
|
||||
static void
|
||||
add_style_id (gchar *id, G_GNUC_UNUSED gpointer value, AddStyleIdData *data)
|
||||
{
|
||||
if (g_str_has_prefix (id, data->language_id))
|
||||
g_ptr_array_add (data->ids_array, g_strdup (id));
|
||||
}
|
||||
|
||||
static gchar **
|
||||
get_style_ids (GtkSourceLanguage *language)
|
||||
{
|
||||
GPtrArray *ids_array;
|
||||
AddStyleIdData data;
|
||||
|
||||
g_return_val_if_fail (language->priv->styles != NULL, NULL);
|
||||
|
||||
ids_array = g_ptr_array_new ();
|
||||
|
||||
data.language_id = g_strdup_printf ("%s:", language->priv->id);
|
||||
data.ids_array = ids_array;
|
||||
|
||||
g_hash_table_foreach (language->priv->styles,
|
||||
(GHFunc) add_style_id,
|
||||
&data);
|
||||
|
||||
g_free (data.language_id);
|
||||
|
||||
if (ids_array->len == 0)
|
||||
{
|
||||
/* No style defined in this language */
|
||||
g_ptr_array_free (ids_array, TRUE);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Terminate the array with NULL */
|
||||
g_ptr_array_add (ids_array, NULL);
|
||||
|
||||
return (gchar **)g_ptr_array_free (ids_array, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
force_styles (GtkSourceLanguage *language)
|
||||
{
|
||||
/* To be sure to have the list of styles we need to parse lang file
|
||||
* as if we were to create an engine. In the future we can improve
|
||||
* this by parsing styles only.
|
||||
*/
|
||||
if (!language->priv->styles_loaded && language->priv->ctx_data == NULL)
|
||||
{
|
||||
GtkSourceContextData *ctx_data;
|
||||
|
||||
ctx_data = gtk_source_language_parse_file (language);
|
||||
if (ctx_data == NULL)
|
||||
return FALSE;
|
||||
|
||||
language->priv->styles_loaded = TRUE;
|
||||
_gtk_source_context_data_unref (ctx_data);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_language_get_style_ids:
|
||||
* @language: a #GtkSourceLanguage
|
||||
*
|
||||
* Returns the ids of the styles defined by this @language.
|
||||
*
|
||||
* Returns: a %NULL terminated array containing
|
||||
* ids of the styles defined by this @language or %NULL if no style is
|
||||
* defined. The returned array must be freed with g_strfreev().
|
||||
*/
|
||||
gchar **
|
||||
gtk_source_language_get_style_ids (GtkSourceLanguage *language)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE (language), NULL);
|
||||
g_return_val_if_fail (language->priv->id != NULL, NULL);
|
||||
|
||||
if (!force_styles (language))
|
||||
return NULL;
|
||||
|
||||
return get_style_ids (language);
|
||||
}
|
||||
|
||||
static GtkSourceStyleInfo *
|
||||
get_style_info (GtkSourceLanguage *language, const char *style_id)
|
||||
{
|
||||
GtkSourceStyleInfo *info;
|
||||
|
||||
if (!force_styles (language))
|
||||
return NULL;
|
||||
|
||||
g_return_val_if_fail (language->priv->styles != NULL, NULL);
|
||||
|
||||
info = g_hash_table_lookup (language->priv->styles, style_id);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_language_get_style_name:
|
||||
* @language: a #GtkSourceLanguage
|
||||
* @style_id: a style ID
|
||||
*
|
||||
* Returns the name of the style with ID @style_id defined by this @language.
|
||||
*
|
||||
* Returns: the name of the style with ID @style_id defined by this @language or
|
||||
* %NULL if the style has no name or there is no style with ID @style_id defined
|
||||
* by this @language. The returned string is owned by the @language and must
|
||||
* not be modified.
|
||||
*/
|
||||
const char *
|
||||
gtk_source_language_get_style_name (GtkSourceLanguage *language,
|
||||
const char *style_id)
|
||||
{
|
||||
GtkSourceStyleInfo *info;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE (language), NULL);
|
||||
g_return_val_if_fail (language->priv->id != NULL, NULL);
|
||||
g_return_val_if_fail (style_id != NULL, NULL);
|
||||
|
||||
info = get_style_info (language, style_id);
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
|
||||
return info->name;
|
||||
}
|
||||
|
||||
/* Utility functions for GtkSourceStyleInfo */
|
||||
|
||||
GtkSourceStyleInfo *
|
||||
_gtk_source_style_info_new (const gchar *name, const gchar *map_to)
|
||||
{
|
||||
GtkSourceStyleInfo *info = g_new0 (GtkSourceStyleInfo, 1);
|
||||
|
||||
info->name = g_strdup (name);
|
||||
info->map_to = g_strdup (map_to);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
GtkSourceStyleInfo *
|
||||
_gtk_source_style_info_copy (GtkSourceStyleInfo *info)
|
||||
{
|
||||
g_return_val_if_fail (info != NULL, NULL);
|
||||
return _gtk_source_style_info_new (info->name, info->map_to);
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_source_style_info_free (GtkSourceStyleInfo *info)
|
||||
{
|
||||
if (info == NULL)
|
||||
return;
|
||||
|
||||
g_free (info->name);
|
||||
g_free (info->map_to);
|
||||
|
||||
g_free (info);
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
|
||||
* gtksourcelanguage.h
|
||||
*
|
||||
* Copyright (C) 2003 - Paolo Maggi <paolo.maggi@polito.it>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library 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 __GTK_SOURCE_LANGUAGE_H__
|
||||
#define __GTK_SOURCE_LANGUAGE_H__
|
||||
|
||||
#include <mooglib/moo-glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_SOURCE_LANGUAGE (gtk_source_language_get_type ())
|
||||
#define GTK_SOURCE_LANGUAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_SOURCE_LANGUAGE, GtkSourceLanguage))
|
||||
#define GTK_SOURCE_LANGUAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_SOURCE_LANGUAGE, GtkSourceLanguageClass))
|
||||
#define GTK_IS_SOURCE_LANGUAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_SOURCE_LANGUAGE))
|
||||
#define GTK_IS_SOURCE_LANGUAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_LANGUAGE))
|
||||
#define GTK_SOURCE_LANGUAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SOURCE_LANGUAGE, GtkSourceLanguageClass))
|
||||
|
||||
|
||||
typedef struct _GtkSourceLanguage GtkSourceLanguage;
|
||||
typedef struct _GtkSourceLanguageClass GtkSourceLanguageClass;
|
||||
typedef struct _GtkSourceLanguagePrivate GtkSourceLanguagePrivate;
|
||||
|
||||
struct _GtkSourceLanguage
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GtkSourceLanguagePrivate *priv;
|
||||
};
|
||||
|
||||
struct _GtkSourceLanguageClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (*_gtk_source_reserved1) (void);
|
||||
void (*_gtk_source_reserved2) (void);
|
||||
};
|
||||
|
||||
GType gtk_source_language_get_type (void) G_GNUC_CONST;
|
||||
|
||||
const gchar *gtk_source_language_get_id (GtkSourceLanguage *language);
|
||||
|
||||
const gchar *gtk_source_language_get_name (GtkSourceLanguage *language);
|
||||
|
||||
const gchar *gtk_source_language_get_section (GtkSourceLanguage *language);
|
||||
|
||||
gboolean gtk_source_language_get_hidden (GtkSourceLanguage *language);
|
||||
|
||||
const gchar *gtk_source_language_get_metadata (GtkSourceLanguage *language,
|
||||
const gchar *name);
|
||||
|
||||
gchar **gtk_source_language_get_mime_types (GtkSourceLanguage *language);
|
||||
|
||||
gchar **gtk_source_language_get_globs (GtkSourceLanguage *language);
|
||||
|
||||
gchar **gtk_source_language_get_style_ids (GtkSourceLanguage *language);
|
||||
|
||||
const char *gtk_source_language_get_style_name (GtkSourceLanguage *language,
|
||||
const char *style_id);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_SOURCE_LANGUAGE_H__ */
|
||||
|
|
@ -0,0 +1,409 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
|
||||
* gtksourcelanguagemanager.c
|
||||
*
|
||||
* Copyright (C) 2003-2007 - Paolo Maggi <paolo.maggi@polito.it>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library 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 <string.h>
|
||||
#include "gtksourceview-i18n.h"
|
||||
#include "gtksourcelanguage-private.h"
|
||||
#include "gtksourcelanguage.h"
|
||||
#include "gtksourceview-utils.h"
|
||||
|
||||
#define RNG_SCHEMA_FILE "language2.rng"
|
||||
#define LANGUAGE_DIR "language-specs"
|
||||
#define LANG_FILE_SUFFIX ".lang"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_SEARCH_PATH,
|
||||
PROP_LANGUAGE_IDS
|
||||
};
|
||||
|
||||
struct _GtkSourceLanguageManagerPrivate
|
||||
{
|
||||
GHashTable *language_ids;
|
||||
|
||||
gchar **lang_dirs;
|
||||
gchar *rng_file;
|
||||
|
||||
gchar **ids; /* Cache the IDs of the available languages */
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkSourceLanguageManager, gtk_source_language_manager, G_TYPE_OBJECT)
|
||||
|
||||
|
||||
static void
|
||||
gtk_source_language_manager_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkSourceLanguageManager *lm;
|
||||
|
||||
lm = GTK_SOURCE_LANGUAGE_MANAGER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SEARCH_PATH:
|
||||
gtk_source_language_manager_set_search_path (lm, g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_source_language_manager_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkSourceLanguageManager *lm;
|
||||
|
||||
lm = GTK_SOURCE_LANGUAGE_MANAGER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SEARCH_PATH:
|
||||
g_value_set_boxed (value, gtk_source_language_manager_get_search_path (lm));
|
||||
break;
|
||||
|
||||
case PROP_LANGUAGE_IDS:
|
||||
g_value_set_boxed (value, gtk_source_language_manager_get_language_ids (lm));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_source_language_manager_finalize (GObject *object)
|
||||
{
|
||||
GtkSourceLanguageManager *lm;
|
||||
|
||||
lm = GTK_SOURCE_LANGUAGE_MANAGER (object);
|
||||
|
||||
if (lm->priv->language_ids)
|
||||
g_hash_table_destroy (lm->priv->language_ids);
|
||||
|
||||
g_strfreev (lm->priv->ids);
|
||||
|
||||
g_strfreev (lm->priv->lang_dirs);
|
||||
g_free (lm->priv->rng_file);
|
||||
|
||||
G_OBJECT_CLASS (gtk_source_language_manager_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_source_language_manager_class_init (GtkSourceLanguageManagerClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gtk_source_language_manager_finalize;
|
||||
|
||||
object_class->set_property = gtk_source_language_manager_set_property;
|
||||
object_class->get_property = gtk_source_language_manager_get_property;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_SEARCH_PATH,
|
||||
g_param_spec_boxed ("search-path",
|
||||
_("Language specification directories"),
|
||||
_("List of directories where the "
|
||||
"language specification files (.lang) "
|
||||
"are located"),
|
||||
G_TYPE_STRV,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_LANGUAGE_IDS,
|
||||
g_param_spec_boxed ("language-ids",
|
||||
_("Language ids"),
|
||||
_("List of the ids of the available "
|
||||
"languages"),
|
||||
G_TYPE_STRV,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_type_class_add_private (object_class, sizeof(GtkSourceLanguageManagerPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_source_language_manager_init (GtkSourceLanguageManager *lm)
|
||||
{
|
||||
lm->priv = G_TYPE_INSTANCE_GET_PRIVATE (lm, GTK_TYPE_SOURCE_LANGUAGE_MANAGER,
|
||||
GtkSourceLanguageManagerPrivate);
|
||||
lm->priv->language_ids = NULL;
|
||||
lm->priv->ids = NULL;
|
||||
lm->priv->lang_dirs = NULL;
|
||||
lm->priv->rng_file = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_language_manager_new:
|
||||
*
|
||||
* Creates a new language manager. If you do not need more than one language
|
||||
* manager or a private language manager instance then use
|
||||
* gtk_source_language_manager_get_default() instead.
|
||||
*
|
||||
* Returns: a #GtkSourceLanguageManager.
|
||||
*/
|
||||
GtkSourceLanguageManager *
|
||||
gtk_source_language_manager_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_SOURCE_LANGUAGE_MANAGER, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_language_manager_get_default:
|
||||
*
|
||||
* Returns the default #GtkSourceLanguageManager instance.
|
||||
*
|
||||
* Returns: a #GtkSourceLanguageManager. Return value is owned
|
||||
* by GtkSourceView library and must not be unref'ed.
|
||||
*/
|
||||
GtkSourceLanguageManager *
|
||||
gtk_source_language_manager_get_default (void)
|
||||
{
|
||||
static GtkSourceLanguageManager *instance;
|
||||
|
||||
if (instance == NULL)
|
||||
{
|
||||
instance = gtk_source_language_manager_new ();
|
||||
g_object_add_weak_pointer (G_OBJECT (instance),
|
||||
(gpointer) &instance);
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
static void
|
||||
notify_search_path (GtkSourceLanguageManager *mgr)
|
||||
{
|
||||
g_object_notify (G_OBJECT (mgr), "search-path");
|
||||
g_object_notify (G_OBJECT (mgr), "language-ids");
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_language_manager_set_search_path:
|
||||
* @lm: a #GtkSourceLanguageManager.
|
||||
* @dirs: a %NULL-terminated array of strings or %NULL.
|
||||
*
|
||||
* Sets the list of directories where the @lm looks for
|
||||
* language files.
|
||||
* If @dirs is %NULL, the search path is reset to default.
|
||||
*
|
||||
* <note>
|
||||
* <para>
|
||||
* At the moment this function can be called only before the
|
||||
* language files are loaded for the first time. In practice
|
||||
* to set a custom search path for a #GtkSourceLanguageManager,
|
||||
* you have to call this function right after creating it.
|
||||
* </para>
|
||||
* </note>
|
||||
*/
|
||||
void
|
||||
gtk_source_language_manager_set_search_path (GtkSourceLanguageManager *lm,
|
||||
gchar **dirs)
|
||||
{
|
||||
gchar **tmp;
|
||||
|
||||
g_return_if_fail (GTK_IS_SOURCE_LANGUAGE_MANAGER (lm));
|
||||
|
||||
/* Search path cannot be changed in the list of available languages
|
||||
* as been already computed */
|
||||
g_return_if_fail (lm->priv->ids == NULL);
|
||||
|
||||
tmp = lm->priv->lang_dirs;
|
||||
|
||||
if (dirs == NULL)
|
||||
lm->priv->lang_dirs = _gtk_source_view_get_default_dirs (LANGUAGE_DIR);
|
||||
else
|
||||
lm->priv->lang_dirs = g_strdupv (dirs);
|
||||
|
||||
g_strfreev (tmp);
|
||||
|
||||
notify_search_path (lm);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_language_manager_get_search_path:
|
||||
* @lm: a #GtkSourceLanguageManager.
|
||||
*
|
||||
* Gets the list directories where @lm looks for language files.
|
||||
*
|
||||
* Returns: %NULL-terminated array containg a list of language files directories.
|
||||
* The array is owned by @lm and must not be modified.
|
||||
*/
|
||||
const gchar* const *
|
||||
gtk_source_language_manager_get_search_path (GtkSourceLanguageManager *lm)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE_MANAGER (lm), NULL);
|
||||
|
||||
if (lm->priv->lang_dirs == NULL)
|
||||
lm->priv->lang_dirs = _gtk_source_view_get_default_dirs (LANGUAGE_DIR);
|
||||
|
||||
return (const gchar * const *)lm->priv->lang_dirs;
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_source_language_manager_get_rng_file:
|
||||
* @lm: a #GtkSourceLanguageManager.
|
||||
*
|
||||
* Returns location of the RNG schema file for lang files version 2.
|
||||
*
|
||||
* Returns: path to RNG file. It belongs to %lm and must not be freed or modified.
|
||||
*/
|
||||
const char *
|
||||
_gtk_source_language_manager_get_rng_file (GtkSourceLanguageManager *lm)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE_MANAGER (lm), NULL);
|
||||
|
||||
if (lm->priv->rng_file == NULL)
|
||||
{
|
||||
const gchar * const *dirs;
|
||||
|
||||
for (dirs = gtk_source_language_manager_get_search_path (lm);
|
||||
dirs != NULL && *dirs != NULL;
|
||||
++dirs)
|
||||
{
|
||||
gchar *file;
|
||||
|
||||
file = g_build_filename (*dirs, RNG_SCHEMA_FILE, NULL);
|
||||
if (g_file_test (file, G_FILE_TEST_EXISTS))
|
||||
{
|
||||
lm->priv->rng_file = file;
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (file);
|
||||
}
|
||||
}
|
||||
|
||||
return lm->priv->rng_file;
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_languages (GtkSourceLanguageManager *lm)
|
||||
{
|
||||
GSList *filenames, *l;
|
||||
GPtrArray *ids_array = NULL;
|
||||
|
||||
if (lm->priv->language_ids != NULL)
|
||||
return;
|
||||
|
||||
lm->priv->language_ids = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, g_object_unref);
|
||||
|
||||
filenames = _gtk_source_view_get_file_list ((gchar **)gtk_source_language_manager_get_search_path (lm),
|
||||
LANG_FILE_SUFFIX,
|
||||
FALSE);
|
||||
|
||||
for (l = filenames; l != NULL; l = l->next)
|
||||
{
|
||||
GtkSourceLanguage *lang;
|
||||
gchar *filename;
|
||||
|
||||
filename = l->data;
|
||||
|
||||
lang = _gtk_source_language_new_from_file (filename, lm);
|
||||
|
||||
if (lang == NULL)
|
||||
{
|
||||
g_warning ("Error reading language specification file '%s'", filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (g_hash_table_lookup (lm->priv->language_ids, lang->priv->id) == NULL)
|
||||
{
|
||||
g_hash_table_insert (lm->priv->language_ids,
|
||||
g_strdup (lang->priv->id),
|
||||
lang);
|
||||
|
||||
if (ids_array == NULL)
|
||||
ids_array = g_ptr_array_new ();
|
||||
|
||||
g_ptr_array_add (ids_array, g_strdup (lang->priv->id));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_object_unref (lang);
|
||||
}
|
||||
}
|
||||
|
||||
if (ids_array != NULL)
|
||||
{
|
||||
/* Ensure the array is NULL terminated */
|
||||
g_ptr_array_add (ids_array, NULL);
|
||||
lm->priv->ids = (gchar **)g_ptr_array_free (ids_array, FALSE);
|
||||
}
|
||||
|
||||
g_slist_foreach (filenames, (GFunc) g_free, NULL);
|
||||
g_slist_free (filenames);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gtk_source_language_manager_get_language_ids:
|
||||
* @lm: a #GtkSourceLanguageManager
|
||||
*
|
||||
* Returns the ids of the available languages.
|
||||
*
|
||||
* Returns: a %NULL-terminated array of string containing the ids of the
|
||||
* available languages or %NULL if no language is available. The array
|
||||
* is owned by @lm and must not be modified.
|
||||
*/
|
||||
const gchar* const *
|
||||
gtk_source_language_manager_get_language_ids (GtkSourceLanguageManager *lm)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE_MANAGER (lm), NULL);
|
||||
|
||||
ensure_languages (lm);
|
||||
|
||||
return (const gchar * const *)lm->priv->ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_language_manager_get_language:
|
||||
* @lm: a #GtkSourceLanguageManager.
|
||||
* @id: a language id.
|
||||
*
|
||||
* Gets the #GtkSourceLanguage identified by the given @id in the language
|
||||
* manager.
|
||||
*
|
||||
* Returns: a #GtkSourceLanguage, or %NULL if there is no language
|
||||
* identified by the given @id. Return value is owned by @lm and should not
|
||||
* be freed.
|
||||
*/
|
||||
GtkSourceLanguage *
|
||||
gtk_source_language_manager_get_language (GtkSourceLanguageManager *lm,
|
||||
const gchar *id)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE_MANAGER (lm), NULL);
|
||||
g_return_val_if_fail (id != NULL, NULL);
|
||||
|
||||
ensure_languages (lm);
|
||||
|
||||
return g_hash_table_lookup (lm->priv->language_ids, id);
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
|
||||
* gtksourcelanguagemanager.h
|
||||
*
|
||||
* Copyright (C) 2003 - Paolo Maggi <paolo.maggi@polito.it>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library 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 __GTK_SOURCE_LANGUAGE_MANAGER_H__
|
||||
#define __GTK_SOURCE_LANGUAGE_MANAGER_H__
|
||||
|
||||
#include <gtksourceview/gtksourcelanguage.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_SOURCE_LANGUAGE_MANAGER (gtk_source_language_manager_get_type ())
|
||||
#define GTK_SOURCE_LANGUAGE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_SOURCE_LANGUAGE_MANAGER, GtkSourceLanguageManager))
|
||||
#define GTK_SOURCE_LANGUAGE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_SOURCE_LANGUAGE_MANAGER, GtkSourceLanguageManagerClass))
|
||||
#define GTK_IS_SOURCE_LANGUAGE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_SOURCE_LANGUAGE_MANAGER))
|
||||
#define GTK_IS_SOURCE_LANGUAGE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_LANGUAGE_MANAGER))
|
||||
#define GTK_SOURCE_LANGUAGE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_SOURCE_LANGUAGE_MANAGER, GtkSourceLanguageManagerClass))
|
||||
|
||||
|
||||
typedef struct _GtkSourceLanguageManager GtkSourceLanguageManager;
|
||||
typedef struct _GtkSourceLanguageManagerClass GtkSourceLanguageManagerClass;
|
||||
typedef struct _GtkSourceLanguageManagerPrivate GtkSourceLanguageManagerPrivate;
|
||||
|
||||
struct _GtkSourceLanguageManager
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GtkSourceLanguageManagerPrivate *priv;
|
||||
};
|
||||
|
||||
struct _GtkSourceLanguageManagerClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (*_gtk_source_reserved1) (void);
|
||||
void (*_gtk_source_reserved2) (void);
|
||||
void (*_gtk_source_reserved3) (void);
|
||||
void (*_gtk_source_reserved4) (void);
|
||||
};
|
||||
|
||||
|
||||
GType gtk_source_language_manager_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkSourceLanguageManager *gtk_source_language_manager_new (void);
|
||||
|
||||
GtkSourceLanguageManager *gtk_source_language_manager_get_default (void);
|
||||
|
||||
const gchar* const *
|
||||
gtk_source_language_manager_get_search_path (GtkSourceLanguageManager *lm);
|
||||
|
||||
void gtk_source_language_manager_set_search_path (GtkSourceLanguageManager *lm,
|
||||
gchar **dirs);
|
||||
|
||||
const gchar* const *
|
||||
gtk_source_language_manager_get_language_ids (GtkSourceLanguageManager *lm);
|
||||
|
||||
GtkSourceLanguage *gtk_source_language_manager_get_language (GtkSourceLanguageManager *lm,
|
||||
const gchar *id);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_SOURCE_LANGUAGE_MANAGER_H__ */
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
|
||||
* gtksourcestyle-private.h
|
||||
*
|
||||
* Copyright (C) 2003 - Paolo Maggi <paolo.maggi@polito.it>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library 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 __GTK_SOURCE_STYLE_PRIVATE_H__
|
||||
#define __GTK_SOURCE_STYLE_PRIVATE_H__
|
||||
|
||||
#include "gtksourcestyle.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_SOURCE_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SOURCE_STYLE, GtkSourceStyleClass))
|
||||
#define GTK_IS_SOURCE_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_STYLE))
|
||||
#define GTK_SOURCE_STYLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SOURCE_STYLE, GtkSourceStyleClass))
|
||||
|
||||
enum {
|
||||
GTK_SOURCE_STYLE_USE_LINE_BACKGROUND = 1 << 0, /*< nick=use_line_background >*/
|
||||
GTK_SOURCE_STYLE_USE_BACKGROUND = 1 << 1, /*< nick=use_background >*/
|
||||
GTK_SOURCE_STYLE_USE_FOREGROUND = 1 << 2, /*< nick=use_foreground >*/
|
||||
GTK_SOURCE_STYLE_USE_ITALIC = 1 << 3, /*< nick=use_italic >*/
|
||||
GTK_SOURCE_STYLE_USE_BOLD = 1 << 4, /*< nick=use_bold >*/
|
||||
GTK_SOURCE_STYLE_USE_UNDERLINE = 1 << 5, /*< nick=use_underline >*/
|
||||
GTK_SOURCE_STYLE_USE_STRIKETHROUGH = 1 << 6 /*< nick=use_strikethrough >*/
|
||||
};
|
||||
|
||||
struct _GtkSourceStyle
|
||||
{
|
||||
GObject base_instance;
|
||||
/* foreground and background are strings interned with
|
||||
* with g_intern_string(), so we don't need to copy/free
|
||||
* them. */
|
||||
const gchar *foreground;
|
||||
const gchar *background;
|
||||
const gchar *line_background;
|
||||
guint italic : 1;
|
||||
guint bold : 1;
|
||||
guint underline : 1;
|
||||
guint strikethrough : 1;
|
||||
guint mask : 12;
|
||||
};
|
||||
|
||||
void _gtk_source_style_apply (const GtkSourceStyle *style,
|
||||
GtkTextTag *tag);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_SOURCE_STYLE_PRIVATE_H__ */
|
|
@ -0,0 +1,447 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
|
||||
* gtksourcestyle.c
|
||||
*
|
||||
* Copyright (C) 2003 - Paolo Maggi <paolo.maggi@polito.it>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "gtksourcestyle-private.h"
|
||||
#include "gtksourceview-i18n.h"
|
||||
|
||||
|
||||
static void gtk_source_style_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void gtk_source_style_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
typedef GObjectClass GtkSourceStyleClass;
|
||||
G_DEFINE_TYPE (GtkSourceStyle, gtk_source_style, G_TYPE_OBJECT)
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_LINE_BACKGROUND,
|
||||
PROP_LINE_BACKGROUND_SET,
|
||||
PROP_BACKGROUND,
|
||||
PROP_BACKGROUND_SET,
|
||||
PROP_FOREGROUND,
|
||||
PROP_FOREGROUND_SET,
|
||||
PROP_BOLD,
|
||||
PROP_BOLD_SET,
|
||||
PROP_ITALIC,
|
||||
PROP_ITALIC_SET,
|
||||
PROP_UNDERLINE,
|
||||
PROP_UNDERLINE_SET,
|
||||
PROP_STRIKETHROUGH,
|
||||
PROP_STRIKETHROUGH_SET
|
||||
};
|
||||
|
||||
static void
|
||||
gtk_source_style_class_init (GtkSourceStyleClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = gtk_source_style_set_property;
|
||||
object_class->get_property = gtk_source_style_get_property;
|
||||
|
||||
/* All properties are CONSTRUCT_ONLY so we can safely return references
|
||||
* from style_scheme_get_style(). But style scheme is of course cheating
|
||||
* and sets everything after construction (but nobody can notice it). */
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_LINE_BACKGROUND,
|
||||
g_param_spec_string ("line-background",
|
||||
_("Line background"),
|
||||
_("Line background color"),
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_BACKGROUND,
|
||||
g_param_spec_string ("background",
|
||||
_("Background"),
|
||||
_("Background color"),
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_FOREGROUND,
|
||||
g_param_spec_string ("foreground",
|
||||
_("Foreground"),
|
||||
_("Foreground color"),
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_BOLD,
|
||||
g_param_spec_boolean ("bold",
|
||||
_("Bold"),
|
||||
_("Bold"),
|
||||
FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_ITALIC,
|
||||
g_param_spec_boolean ("italic",
|
||||
_("Italic"),
|
||||
_("Italic"),
|
||||
FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_UNDERLINE,
|
||||
g_param_spec_boolean ("underline",
|
||||
_("Underline"),
|
||||
_("Underline"),
|
||||
FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_STRIKETHROUGH,
|
||||
g_param_spec_boolean ("strikethrough",
|
||||
_("Strikethrough"),
|
||||
_("Strikethrough"),
|
||||
FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_LINE_BACKGROUND_SET,
|
||||
g_param_spec_boolean ("line-background-set",
|
||||
_("Line background set"),
|
||||
_("Whether line background color is set"),
|
||||
FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_FOREGROUND_SET,
|
||||
g_param_spec_boolean ("foreground-set",
|
||||
_("Foreground set"),
|
||||
_("Whether foreground color is set"),
|
||||
FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_BACKGROUND_SET,
|
||||
g_param_spec_boolean ("background-set",
|
||||
_("Background set"),
|
||||
_("Whether background color is set"),
|
||||
FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_BOLD_SET,
|
||||
g_param_spec_boolean ("bold-set",
|
||||
_("Bold set"),
|
||||
_("Whether bold attribute is set"),
|
||||
FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_ITALIC_SET,
|
||||
g_param_spec_boolean ("italic-set",
|
||||
_("Italic set"),
|
||||
_("Whether italic attribute is set"),
|
||||
FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_UNDERLINE_SET,
|
||||
g_param_spec_boolean ("underline-set",
|
||||
_("Underline set"),
|
||||
_("Whether underline attribute is set"),
|
||||
FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_STRIKETHROUGH_SET,
|
||||
g_param_spec_boolean ("strikethrough-set",
|
||||
_("Strikethrough set"),
|
||||
_("Whether strikethrough attribute is set"),
|
||||
FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_source_style_init (GtkSourceStyle *style)
|
||||
{
|
||||
style->foreground = NULL;
|
||||
style->background = NULL;
|
||||
style->line_background = NULL;
|
||||
}
|
||||
|
||||
#define SET_MASK(style,name) (style)->mask |= (GTK_SOURCE_STYLE_USE_##name)
|
||||
#define UNSET_MASK(style,name) (style)->mask &= (GTK_SOURCE_STYLE_USE_##name)
|
||||
|
||||
#define MODIFY_MASK(style,value,name) \
|
||||
G_STMT_START { \
|
||||
if (g_value_get_boolean (value)) \
|
||||
SET_MASK (style, name); \
|
||||
else \
|
||||
UNSET_MASK (style, name); \
|
||||
} G_STMT_END
|
||||
|
||||
#define GET_MASK(style,value,name) \
|
||||
g_value_set_boolean (value, ((style)->mask & GTK_SOURCE_STYLE_USE_##name) != 0)
|
||||
|
||||
static void
|
||||
gtk_source_style_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkSourceStyle *style = GTK_SOURCE_STYLE (object);
|
||||
const gchar *string;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_FOREGROUND:
|
||||
string = g_value_get_string (value);
|
||||
if (string != NULL)
|
||||
{
|
||||
style->foreground = g_intern_string (string);
|
||||
SET_MASK (style, FOREGROUND);
|
||||
}
|
||||
else
|
||||
{
|
||||
style->foreground = NULL;
|
||||
UNSET_MASK (style, FOREGROUND);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_BACKGROUND:
|
||||
string = g_value_get_string (value);
|
||||
if (string != NULL)
|
||||
{
|
||||
style->background = g_intern_string (string);
|
||||
SET_MASK (style, BACKGROUND);
|
||||
}
|
||||
else
|
||||
{
|
||||
style->background = NULL;
|
||||
UNSET_MASK (style, BACKGROUND);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_LINE_BACKGROUND:
|
||||
string = g_value_get_string (value);
|
||||
if (string != NULL)
|
||||
{
|
||||
style->line_background = g_intern_string (string);
|
||||
SET_MASK (style, LINE_BACKGROUND);
|
||||
}
|
||||
else
|
||||
{
|
||||
style->line_background = NULL;
|
||||
UNSET_MASK (style, LINE_BACKGROUND);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_BOLD:
|
||||
style->bold = g_value_get_boolean (value) != 0;
|
||||
SET_MASK (style, BOLD);
|
||||
break;
|
||||
case PROP_ITALIC:
|
||||
style->italic = g_value_get_boolean (value) != 0;
|
||||
SET_MASK (style, ITALIC);
|
||||
break;
|
||||
case PROP_UNDERLINE:
|
||||
style->underline = g_value_get_boolean (value) != 0;
|
||||
SET_MASK (style, UNDERLINE);
|
||||
break;
|
||||
case PROP_STRIKETHROUGH:
|
||||
style->strikethrough = g_value_get_boolean (value) != 0;
|
||||
SET_MASK (style, STRIKETHROUGH);
|
||||
break;
|
||||
|
||||
case PROP_FOREGROUND_SET:
|
||||
MODIFY_MASK (style, value, FOREGROUND);
|
||||
break;
|
||||
case PROP_BACKGROUND_SET:
|
||||
MODIFY_MASK (style, value, BACKGROUND);
|
||||
break;
|
||||
case PROP_LINE_BACKGROUND_SET:
|
||||
MODIFY_MASK (style, value, LINE_BACKGROUND);
|
||||
break;
|
||||
case PROP_BOLD_SET:
|
||||
MODIFY_MASK (style, value, BOLD);
|
||||
break;
|
||||
case PROP_ITALIC_SET:
|
||||
MODIFY_MASK (style, value, ITALIC);
|
||||
break;
|
||||
case PROP_UNDERLINE_SET:
|
||||
MODIFY_MASK (style, value, UNDERLINE);
|
||||
break;
|
||||
case PROP_STRIKETHROUGH_SET:
|
||||
MODIFY_MASK (style, value, STRIKETHROUGH);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_source_style_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkSourceStyle *style = GTK_SOURCE_STYLE (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_FOREGROUND:
|
||||
g_value_set_string (value, style->foreground);
|
||||
break;
|
||||
case PROP_BACKGROUND:
|
||||
g_value_set_string (value, style->background);
|
||||
break;
|
||||
case PROP_LINE_BACKGROUND:
|
||||
g_value_set_string (value, style->line_background);
|
||||
break;
|
||||
case PROP_BOLD:
|
||||
g_value_set_boolean (value, style->bold);
|
||||
break;
|
||||
case PROP_ITALIC:
|
||||
g_value_set_boolean (value, style->italic);
|
||||
break;
|
||||
case PROP_UNDERLINE:
|
||||
g_value_set_boolean (value, style->underline);
|
||||
break;
|
||||
case PROP_STRIKETHROUGH:
|
||||
g_value_set_boolean (value, style->strikethrough);
|
||||
break;
|
||||
|
||||
case PROP_FOREGROUND_SET:
|
||||
GET_MASK (style, value, FOREGROUND);
|
||||
break;
|
||||
case PROP_BACKGROUND_SET:
|
||||
GET_MASK (style, value, BACKGROUND);
|
||||
break;
|
||||
case PROP_LINE_BACKGROUND_SET:
|
||||
GET_MASK (style, value, LINE_BACKGROUND);
|
||||
break;
|
||||
case PROP_BOLD_SET:
|
||||
GET_MASK (style, value, BOLD);
|
||||
break;
|
||||
case PROP_ITALIC_SET:
|
||||
GET_MASK (style, value, ITALIC);
|
||||
break;
|
||||
case PROP_UNDERLINE_SET:
|
||||
GET_MASK (style, value, UNDERLINE);
|
||||
break;
|
||||
case PROP_STRIKETHROUGH_SET:
|
||||
GET_MASK (style, value, STRIKETHROUGH);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gtk_source_style_copy:
|
||||
* @style: a #GtkSourceStyle structure to copy.
|
||||
*
|
||||
* Creates a copy of @style, that is a new #GtkSourceStyle instance which
|
||||
* has the same attributes set.
|
||||
*
|
||||
* Returns: copy of @style, call g_object_unref() when you are done with it.
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
GtkSourceStyle *
|
||||
gtk_source_style_copy (const GtkSourceStyle *style)
|
||||
{
|
||||
GtkSourceStyle *copy;
|
||||
|
||||
g_return_val_if_fail (style != NULL, NULL);
|
||||
|
||||
copy = g_object_new (GTK_TYPE_SOURCE_STYLE, NULL);
|
||||
|
||||
copy->foreground = style->foreground;
|
||||
copy->background = style->background;
|
||||
copy->line_background = style->line_background;
|
||||
copy->italic = style->italic;
|
||||
copy->bold = style->bold;
|
||||
copy->underline = style->underline;
|
||||
copy->strikethrough = style->strikethrough;
|
||||
copy->mask = style->mask;
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_source_style_apply:
|
||||
* @style: a #GtkSourceStyle to apply.
|
||||
* @tag: a #GtkTextTag to apply styles to.
|
||||
*
|
||||
* Applies text styles set in @style if it's not %NULL, or
|
||||
* unsets style fields in @tag set with _gtk_source_style_apply()
|
||||
* if @style is %NULL. Note that it does not touch fields which
|
||||
* are not set in @style. To reset everything use @style == %NULL.
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
void
|
||||
_gtk_source_style_apply (const GtkSourceStyle *style,
|
||||
GtkTextTag *tag)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_TEXT_TAG (tag));
|
||||
|
||||
if (style != NULL)
|
||||
{
|
||||
g_object_freeze_notify (G_OBJECT (tag));
|
||||
|
||||
if (style->mask & GTK_SOURCE_STYLE_USE_BACKGROUND)
|
||||
g_object_set (tag, "background", style->background, NULL);
|
||||
|
||||
if (style->mask & GTK_SOURCE_STYLE_USE_FOREGROUND)
|
||||
g_object_set (tag, "foreground", style->foreground, NULL);
|
||||
|
||||
if (style->mask & GTK_SOURCE_STYLE_USE_LINE_BACKGROUND)
|
||||
g_object_set (tag, "paragraph-background", style->line_background, NULL);
|
||||
|
||||
if (style->mask & GTK_SOURCE_STYLE_USE_ITALIC)
|
||||
g_object_set (tag, "style", style->italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL, NULL);
|
||||
if (style->mask & GTK_SOURCE_STYLE_USE_BOLD)
|
||||
g_object_set (tag, "weight", style->bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, NULL);
|
||||
if (style->mask & GTK_SOURCE_STYLE_USE_UNDERLINE)
|
||||
g_object_set (tag, "underline", style->underline ? PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE, NULL);
|
||||
if (style->mask & GTK_SOURCE_STYLE_USE_STRIKETHROUGH)
|
||||
g_object_set (tag, "strikethrough", style->strikethrough != 0, NULL);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (tag));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_object_set (tag,
|
||||
"background-set", FALSE,
|
||||
"foreground-set", FALSE,
|
||||
"paragraph-background-set", FALSE,
|
||||
"style-set", FALSE,
|
||||
"weight-set", FALSE,
|
||||
"underline-set", FALSE,
|
||||
"strikethrough-set", FALSE,
|
||||
NULL);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
|
||||
* gtksourcestyle.h
|
||||
*
|
||||
* Copyright (C) 2003 - Paolo Maggi <paolo.maggi@polito.it>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library 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 __GTK_SOURCE_STYLE_H__
|
||||
#define __GTK_SOURCE_STYLE_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_SOURCE_STYLE (gtk_source_style_get_type ())
|
||||
#define GTK_SOURCE_STYLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_STYLE, GtkSourceStyle))
|
||||
#define GTK_IS_SOURCE_STYLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_STYLE))
|
||||
|
||||
typedef struct _GtkSourceStyle GtkSourceStyle;
|
||||
|
||||
GType gtk_source_style_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkSourceStyle *gtk_source_style_copy (const GtkSourceStyle *style);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_SOURCE_STYLE_H__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,88 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
|
||||
* gtksourcestylescheme.h
|
||||
*
|
||||
* Copyright (C) 2003 - Paolo Maggi <paolo.maggi@polito.it>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __GTK_SOURCE_STYLE_SCHEME_H__
|
||||
#define __GTK_SOURCE_STYLE_SCHEME_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gtksourceview/gtksourcestyle.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_SOURCE_STYLE_SCHEME (gtk_source_style_scheme_get_type ())
|
||||
#define GTK_SOURCE_STYLE_SCHEME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_STYLE_SCHEME, GtkSourceStyleScheme))
|
||||
#define GTK_SOURCE_STYLE_SCHEME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SOURCE_STYLE_SCHEME, GtkSourceStyleSchemeClass))
|
||||
#define GTK_IS_SOURCE_STYLE_SCHEME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_STYLE_SCHEME))
|
||||
#define GTK_IS_SOURCE_STYLE_SCHEME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_STYLE_SCHEME))
|
||||
#define GTK_SOURCE_STYLE_SCHEME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SOURCE_STYLE_SCHEME, GtkSourceStyleSchemeClass))
|
||||
|
||||
typedef struct _GtkSourceStyleScheme GtkSourceStyleScheme;
|
||||
typedef struct _GtkSourceStyleSchemePrivate GtkSourceStyleSchemePrivate;
|
||||
typedef struct _GtkSourceStyleSchemeClass GtkSourceStyleSchemeClass;
|
||||
|
||||
struct _GtkSourceStyleScheme
|
||||
{
|
||||
GObject base;
|
||||
GtkSourceStyleSchemePrivate *priv;
|
||||
};
|
||||
|
||||
struct _GtkSourceStyleSchemeClass
|
||||
{
|
||||
GObjectClass base_class;
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (*_gtk_source_reserved1) (void);
|
||||
void (*_gtk_source_reserved2) (void);
|
||||
};
|
||||
|
||||
GType gtk_source_style_scheme_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkSourceStyleScheme *_gtk_source_style_scheme_new (const gchar *id,
|
||||
const gchar *name);
|
||||
|
||||
const gchar *gtk_source_style_scheme_get_id (GtkSourceStyleScheme *scheme);
|
||||
const gchar *gtk_source_style_scheme_get_name (GtkSourceStyleScheme *scheme);
|
||||
const gchar *gtk_source_style_scheme_get_description(GtkSourceStyleScheme *scheme);
|
||||
|
||||
const gchar* const * gtk_source_style_scheme_get_authors (GtkSourceStyleScheme *scheme);
|
||||
|
||||
const gchar *gtk_source_style_scheme_get_filename (GtkSourceStyleScheme *scheme);
|
||||
|
||||
GtkSourceStyle *gtk_source_style_scheme_get_style (GtkSourceStyleScheme *scheme,
|
||||
const gchar *style_id);
|
||||
GtkSourceStyleScheme *_gtk_source_style_scheme_new_from_file (const gchar *filename);
|
||||
GtkSourceStyleScheme *_gtk_source_style_scheme_get_default (void);
|
||||
const gchar *_gtk_source_style_scheme_get_parent_id (GtkSourceStyleScheme *scheme);
|
||||
void _gtk_source_style_scheme_set_parent (GtkSourceStyleScheme *scheme,
|
||||
GtkSourceStyleScheme *parent_scheme);
|
||||
|
||||
/* private */
|
||||
void _gtk_source_style_scheme_apply (GtkSourceStyleScheme *scheme,
|
||||
GtkWidget *widget);
|
||||
GtkSourceStyle *_gtk_source_style_scheme_get_matching_brackets_style
|
||||
(GtkSourceStyleScheme *scheme);
|
||||
GtkSourceStyle *_gtk_source_style_scheme_get_right_margin_style
|
||||
(GtkSourceStyleScheme *scheme);
|
||||
gboolean _gtk_source_style_scheme_get_current_line_color
|
||||
(GtkSourceStyleScheme *scheme,
|
||||
GdkColor *color);
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_SOURCE_STYLE_SCHEME_H__ */
|
|
@ -0,0 +1,577 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
|
||||
* gtksourcestyleschememanager.c
|
||||
*
|
||||
* Copyright (C) 2003-2007 - Paolo Maggi <paolo@gnome.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "gtksourcestyleschememanager.h"
|
||||
#include "gtksourceview-marshal.h"
|
||||
#include "gtksourceview-i18n.h"
|
||||
#include "gtksourceview-utils.h"
|
||||
#include <string.h>
|
||||
|
||||
#define SCHEME_FILE_SUFFIX ".xml"
|
||||
#define STYLES_DIR "styles"
|
||||
|
||||
|
||||
struct _GtkSourceStyleSchemeManagerPrivate
|
||||
{
|
||||
GHashTable *schemes_hash;
|
||||
|
||||
gchar **search_path;
|
||||
gboolean need_reload;
|
||||
|
||||
gchar **ids; /* Cache the IDs of the available schemes */
|
||||
};
|
||||
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_SEARCH_PATH,
|
||||
PROP_SCHEME_IDS
|
||||
};
|
||||
|
||||
|
||||
G_DEFINE_TYPE (GtkSourceStyleSchemeManager, gtk_source_style_scheme_manager, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gtk_source_style_scheme_manager_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkSourceStyleSchemeManager *sm;
|
||||
|
||||
sm = GTK_SOURCE_STYLE_SCHEME_MANAGER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SEARCH_PATH:
|
||||
gtk_source_style_scheme_manager_set_search_path
|
||||
(sm, g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
|
||||
prop_id,
|
||||
pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_source_style_scheme_manager_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkSourceStyleSchemeManager *sm;
|
||||
|
||||
sm = GTK_SOURCE_STYLE_SCHEME_MANAGER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SEARCH_PATH:
|
||||
g_value_set_boxed (value,
|
||||
gtk_source_style_scheme_manager_get_search_path (sm));
|
||||
break;
|
||||
|
||||
case PROP_SCHEME_IDS:
|
||||
g_value_set_boxed (value,
|
||||
gtk_source_style_scheme_manager_get_scheme_ids (sm));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
|
||||
prop_id,
|
||||
pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
free_schemes (GtkSourceStyleSchemeManager *mgr)
|
||||
{
|
||||
if (mgr->priv->schemes_hash != NULL)
|
||||
{
|
||||
g_hash_table_destroy (mgr->priv->schemes_hash);
|
||||
mgr->priv->schemes_hash = NULL;
|
||||
}
|
||||
|
||||
g_strfreev (mgr->priv->ids);
|
||||
mgr->priv->ids = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_source_style_scheme_manager_finalize (GObject *object)
|
||||
{
|
||||
GtkSourceStyleSchemeManager *mgr;
|
||||
|
||||
mgr = GTK_SOURCE_STYLE_SCHEME_MANAGER (object);
|
||||
|
||||
free_schemes (mgr);
|
||||
|
||||
g_strfreev (mgr->priv->search_path);
|
||||
|
||||
G_OBJECT_CLASS (gtk_source_style_scheme_manager_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_source_style_scheme_manager_class_init (GtkSourceStyleSchemeManagerClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gtk_source_style_scheme_manager_finalize;
|
||||
object_class->set_property = gtk_source_style_scheme_manager_set_property;
|
||||
object_class->get_property = gtk_source_style_scheme_manager_get_property;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_SEARCH_PATH,
|
||||
g_param_spec_boxed ("search-path",
|
||||
_("Style scheme search path"),
|
||||
_("List of directories and files where the "
|
||||
"style schemes are located"),
|
||||
G_TYPE_STRV,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_SCHEME_IDS,
|
||||
g_param_spec_boxed ("scheme-ids",
|
||||
_("Scheme ids"),
|
||||
_("List of the ids of the available "
|
||||
"style schemes"),
|
||||
G_TYPE_STRV,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_type_class_add_private (object_class, sizeof(GtkSourceStyleSchemeManagerPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_source_style_scheme_manager_init (GtkSourceStyleSchemeManager *mgr)
|
||||
{
|
||||
mgr->priv = G_TYPE_INSTANCE_GET_PRIVATE (mgr,
|
||||
GTK_TYPE_SOURCE_STYLE_SCHEME_MANAGER,
|
||||
GtkSourceStyleSchemeManagerPrivate);
|
||||
mgr->priv->schemes_hash = NULL;
|
||||
mgr->priv->ids = NULL;
|
||||
mgr->priv->search_path = NULL;
|
||||
mgr->priv->need_reload = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_style_scheme_manager_new:
|
||||
*
|
||||
* Creates a new style manager. If you do not need more than one style
|
||||
* manager then use gtk_source_style_scheme_manager_get_default() instead.
|
||||
*
|
||||
* Returns: a #GtkSourceStyleSchemeManager.
|
||||
*/
|
||||
GtkSourceStyleSchemeManager *
|
||||
gtk_source_style_scheme_manager_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_SOURCE_STYLE_SCHEME_MANAGER, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_style_scheme_manager_get_default:
|
||||
*
|
||||
* Returns the default #GtkSourceStyleSchemeManager instance.
|
||||
*
|
||||
* Returns: a #GtkSourceStyleSchemeManager. Return value is owned
|
||||
* by GtkSourceView library and must not be unref'ed.
|
||||
*/
|
||||
GtkSourceStyleSchemeManager *
|
||||
gtk_source_style_scheme_manager_get_default (void)
|
||||
{
|
||||
static GtkSourceStyleSchemeManager *instance;
|
||||
|
||||
if (instance == NULL)
|
||||
{
|
||||
instance = gtk_source_style_scheme_manager_new ();
|
||||
g_object_add_weak_pointer (G_OBJECT (instance),
|
||||
(gpointer) &instance);
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
static GSList *
|
||||
ids_list_remove (GSList *ids, const gchar *id, gboolean free_data)
|
||||
{
|
||||
GSList *o = g_slist_find_custom (ids, id, (GCompareFunc) strcmp);
|
||||
|
||||
if (o != NULL)
|
||||
{
|
||||
if (free_data)
|
||||
g_free (o->data);
|
||||
ids = g_slist_delete_link (ids, o);
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
build_reference_chain (GtkSourceStyleScheme *scheme,
|
||||
GHashTable *hash,
|
||||
GSList **ret)
|
||||
{
|
||||
GSList *chain;
|
||||
gboolean retval = TRUE;
|
||||
|
||||
chain = g_slist_prepend (NULL, scheme);
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
GtkSourceStyleScheme *parent_scheme;
|
||||
const gchar *parent_id;
|
||||
|
||||
parent_id = _gtk_source_style_scheme_get_parent_id (scheme);
|
||||
|
||||
if (parent_id == NULL)
|
||||
break;
|
||||
|
||||
parent_scheme = g_hash_table_lookup (hash, parent_id);
|
||||
|
||||
if (parent_scheme == NULL)
|
||||
{
|
||||
g_warning ("Unknown parent scheme '%s' in scheme '%s'",
|
||||
parent_id, gtk_source_style_scheme_get_id (scheme));
|
||||
retval = FALSE;
|
||||
break;
|
||||
}
|
||||
else if (g_slist_find (chain, parent_scheme) != NULL)
|
||||
{
|
||||
g_warning ("Reference cycle in scheme '%s'", parent_id);
|
||||
retval = FALSE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
_gtk_source_style_scheme_set_parent (scheme, parent_scheme);
|
||||
}
|
||||
|
||||
chain = g_slist_prepend (chain, parent_scheme);
|
||||
scheme = parent_scheme;
|
||||
}
|
||||
|
||||
*ret = chain;
|
||||
return retval;
|
||||
}
|
||||
|
||||
static GSList *
|
||||
check_parents (GSList *ids,
|
||||
GHashTable *hash)
|
||||
{
|
||||
GSList *to_check;
|
||||
|
||||
to_check = g_slist_copy (ids);
|
||||
|
||||
while (to_check != NULL)
|
||||
{
|
||||
GSList *chain;
|
||||
gboolean valid;
|
||||
GtkSourceStyleScheme *scheme_to_check;
|
||||
|
||||
scheme_to_check = g_hash_table_lookup (hash, to_check->data);
|
||||
g_return_val_if_fail (scheme_to_check != NULL, NULL);
|
||||
|
||||
valid = build_reference_chain (scheme_to_check, hash, &chain);
|
||||
|
||||
while (chain != NULL)
|
||||
{
|
||||
const gchar *id;
|
||||
GtkSourceStyleScheme *scheme = chain->data;
|
||||
|
||||
id = gtk_source_style_scheme_get_id (scheme);
|
||||
|
||||
to_check = ids_list_remove (to_check, id, FALSE);
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
ids = ids_list_remove (ids, id, TRUE);
|
||||
g_hash_table_remove (hash, id);
|
||||
}
|
||||
|
||||
chain = g_slist_delete_link (chain, chain);
|
||||
}
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
static gchar **
|
||||
slist_to_strv (GSList *list)
|
||||
{
|
||||
gchar **res;
|
||||
guint i = 0;
|
||||
|
||||
res = g_new (gchar *, g_slist_length (list) + 1);
|
||||
|
||||
for ( ; list != NULL; list = list->next)
|
||||
{
|
||||
res[i] = list->data;
|
||||
++i;
|
||||
}
|
||||
|
||||
res[i] = NULL;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
reload_if_needed (GtkSourceStyleSchemeManager *mgr)
|
||||
{
|
||||
GSList *ids = NULL;
|
||||
GSList *files;
|
||||
GSList *l;
|
||||
GHashTable *schemes_hash;
|
||||
|
||||
if (!mgr->priv->need_reload)
|
||||
return;
|
||||
|
||||
schemes_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
|
||||
|
||||
files = _gtk_source_view_get_file_list ((gchar **)gtk_source_style_scheme_manager_get_search_path (mgr),
|
||||
SCHEME_FILE_SUFFIX,
|
||||
FALSE);
|
||||
|
||||
for (l = files; l != NULL; l = l->next)
|
||||
{
|
||||
GtkSourceStyleScheme *scheme;
|
||||
gchar *filename;
|
||||
|
||||
filename = l->data;
|
||||
|
||||
scheme = _gtk_source_style_scheme_new_from_file (filename);
|
||||
|
||||
if (scheme != NULL)
|
||||
{
|
||||
const gchar *id = gtk_source_style_scheme_get_id (scheme);
|
||||
GtkSourceStyleScheme *old;
|
||||
|
||||
old = g_hash_table_lookup (schemes_hash, id);
|
||||
|
||||
if (old != NULL)
|
||||
ids = ids_list_remove (ids, id, TRUE);
|
||||
|
||||
ids = g_slist_prepend (ids, g_strdup (id));
|
||||
g_hash_table_insert (schemes_hash, g_strdup (id), scheme);
|
||||
}
|
||||
}
|
||||
|
||||
ids = check_parents (ids, schemes_hash);
|
||||
|
||||
g_slist_foreach (files, (GFunc) g_free, NULL);
|
||||
g_slist_free (files);
|
||||
|
||||
free_schemes (mgr);
|
||||
|
||||
mgr->priv->need_reload = FALSE;
|
||||
mgr->priv->schemes_hash = schemes_hash;
|
||||
|
||||
mgr->priv->ids = slist_to_strv (ids);
|
||||
g_slist_free (ids); /* slist_to_strv trasfer the onwnership of the strings
|
||||
to the string array */
|
||||
}
|
||||
|
||||
static void
|
||||
notify_search_path (GtkSourceStyleSchemeManager *mgr)
|
||||
{
|
||||
mgr->priv->need_reload = TRUE;
|
||||
|
||||
g_object_notify (G_OBJECT (mgr), "search-path");
|
||||
g_object_notify (G_OBJECT (mgr), "scheme-ids");
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_style_scheme_manager_set_search_path:
|
||||
* @manager: a #GtkSourceStyleSchemeManager.
|
||||
* @path: a %NULL-terminated array of strings or %NULL.
|
||||
*
|
||||
* Sets the list of directories where the @manager looks for
|
||||
* style scheme files.
|
||||
* If @dirs is %NULL, the search path is reset to default.
|
||||
*/
|
||||
void
|
||||
gtk_source_style_scheme_manager_set_search_path (GtkSourceStyleSchemeManager *manager,
|
||||
gchar **path)
|
||||
{
|
||||
gchar **tmp;
|
||||
|
||||
g_return_if_fail (GTK_IS_SOURCE_STYLE_SCHEME_MANAGER (manager));
|
||||
|
||||
tmp = manager->priv->search_path;
|
||||
|
||||
if (path == NULL)
|
||||
manager->priv->search_path = _gtk_source_view_get_default_dirs (STYLES_DIR);
|
||||
else
|
||||
manager->priv->search_path = g_strdupv (path);
|
||||
|
||||
g_strfreev (tmp);
|
||||
|
||||
notify_search_path (manager);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_style_scheme_manager_append_search_path:
|
||||
* @manager: a #GtkSourceStyleSchemeManager.
|
||||
* @path: a directory or a filename.
|
||||
*
|
||||
* Appends @path to the list of directories where the @manager looks for
|
||||
* style scheme files.
|
||||
* See gtk_source_style_scheme_manager_set_search_path() for details.
|
||||
*/
|
||||
void
|
||||
gtk_source_style_scheme_manager_append_search_path (GtkSourceStyleSchemeManager *manager,
|
||||
const gchar *path)
|
||||
{
|
||||
guint len = 0;
|
||||
|
||||
g_return_if_fail (GTK_IS_SOURCE_STYLE_SCHEME_MANAGER (manager));
|
||||
g_return_if_fail (path != NULL);
|
||||
|
||||
if (manager->priv->search_path == NULL)
|
||||
manager->priv->search_path = _gtk_source_view_get_default_dirs (STYLES_DIR);
|
||||
|
||||
g_return_if_fail (manager->priv->search_path != NULL);
|
||||
|
||||
len = g_strv_length (manager->priv->search_path);
|
||||
|
||||
manager->priv->search_path = g_renew (gchar *,
|
||||
manager->priv->search_path,
|
||||
len + 2); /* old path + new entry + NULL */
|
||||
|
||||
manager->priv->search_path[len] = g_strdup (path);
|
||||
manager->priv->search_path[len + 1] = NULL;
|
||||
|
||||
notify_search_path (manager);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_style_scheme_manager_prepend_search_path:
|
||||
* @manager: a #GtkSourceStyleSchemeManager.
|
||||
* @path: a directory or a filename.
|
||||
*
|
||||
* Prepends @path to the list of directories where the @manager looks
|
||||
* for style scheme files.
|
||||
* See gtk_source_style_scheme_manager_set_search_path() for details.
|
||||
*/
|
||||
void
|
||||
gtk_source_style_scheme_manager_prepend_search_path (GtkSourceStyleSchemeManager *manager,
|
||||
const gchar *path)
|
||||
{
|
||||
guint len = 0;
|
||||
gchar **new_search_path;
|
||||
|
||||
g_return_if_fail (GTK_IS_SOURCE_STYLE_SCHEME_MANAGER (manager));
|
||||
g_return_if_fail (path != NULL);
|
||||
|
||||
if (manager->priv->search_path == NULL)
|
||||
manager->priv->search_path = _gtk_source_view_get_default_dirs (STYLES_DIR);
|
||||
|
||||
g_return_if_fail (manager->priv->search_path != NULL);
|
||||
|
||||
len = g_strv_length (manager->priv->search_path);
|
||||
|
||||
new_search_path = g_new (gchar *, len + 2);
|
||||
new_search_path[0] = g_strdup (path);
|
||||
memcpy (new_search_path + 1, manager->priv->search_path, (len + 1) * sizeof (gchar*));
|
||||
|
||||
g_free (manager->priv->search_path);
|
||||
manager->priv->search_path = new_search_path;
|
||||
|
||||
notify_search_path (manager);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_style_scheme_manager_get_search_path:
|
||||
* @manager: a #GtkSourceStyleSchemeManager.
|
||||
*
|
||||
* Returns the current search path for the @manager.
|
||||
* See gtk_source_style_scheme_manager_set_search_path() for details.
|
||||
*
|
||||
* Returns: a NULL-terminated array of string containing the search path.
|
||||
* The array is owned by the @manager and must not be modified.
|
||||
*/
|
||||
const gchar* const *
|
||||
gtk_source_style_scheme_manager_get_search_path (GtkSourceStyleSchemeManager *manager)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_SOURCE_STYLE_SCHEME_MANAGER (manager), NULL);
|
||||
|
||||
if (manager->priv->search_path == NULL)
|
||||
manager->priv->search_path = _gtk_source_view_get_default_dirs (STYLES_DIR);
|
||||
|
||||
return (const gchar * const *)manager->priv->search_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_style_scheme_manager_force_rescan:
|
||||
* @manager: a #GtkSourceStyleSchemeManager
|
||||
*
|
||||
* Mark any currently cached information about the available style scehems
|
||||
* as invalid. All the available style schemes will be reloaded next time
|
||||
* the @manager is accessed.
|
||||
*/
|
||||
void
|
||||
gtk_source_style_scheme_manager_force_rescan (GtkSourceStyleSchemeManager *manager)
|
||||
{
|
||||
manager->priv->need_reload = TRUE;
|
||||
|
||||
g_object_notify (G_OBJECT (manager), "scheme-ids");
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_style_scheme_manager_get_scheme_ids:
|
||||
* @manager: a #GtkSourceStyleSchemeManager
|
||||
*
|
||||
* Returns the ids of the available style schemes.
|
||||
*
|
||||
* Returns: a %NULL-terminated array of string containing the ids of the
|
||||
* available style schemes or %NULL if no style scheme is available. The array
|
||||
* is owned by the @manager and must not be modified.
|
||||
*/
|
||||
const gchar* const *
|
||||
gtk_source_style_scheme_manager_get_scheme_ids (GtkSourceStyleSchemeManager *manager)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_SOURCE_STYLE_SCHEME_MANAGER (manager), NULL);
|
||||
|
||||
reload_if_needed (manager);
|
||||
|
||||
return (const gchar * const *)manager->priv->ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_source_style_scheme_manager_get_scheme:
|
||||
* @manager: a #GtkSourceStyleSchemeManager
|
||||
* @scheme_id: style scheme id to find
|
||||
*
|
||||
* Looks up style scheme by id.
|
||||
*
|
||||
* Returns: a #GtkSourceStyleScheme object. Returned value is owned by
|
||||
* @manager and must not be unref'ed.
|
||||
*/
|
||||
GtkSourceStyleScheme *
|
||||
gtk_source_style_scheme_manager_get_scheme (GtkSourceStyleSchemeManager *manager,
|
||||
const gchar *scheme_id)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_SOURCE_STYLE_SCHEME_MANAGER (manager), NULL);
|
||||
g_return_val_if_fail (scheme_id != NULL, NULL);
|
||||
|
||||
reload_if_needed (manager);
|
||||
|
||||
return g_hash_table_lookup (manager->priv->schemes_hash, scheme_id);
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
|
||||
* gtksourcestyleschememanager.h
|
||||
*
|
||||
* Copyright (C) 2003-2007 - Paolo Maggi <paolo.maggi@polito.it>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library 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 __GTK_SOURCE_STYLE_SCHEME_MANAGER_H__
|
||||
#define __GTK_SOURCE_STYLE_SCHEME_MANAGER_H__
|
||||
|
||||
#include <gtksourceview/gtksourcestylescheme.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_SOURCE_STYLE_SCHEME_MANAGER (gtk_source_style_scheme_manager_get_type ())
|
||||
#define GTK_SOURCE_STYLE_SCHEME_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_SOURCE_STYLE_SCHEME_MANAGER, GtkSourceStyleSchemeManager))
|
||||
#define GTK_SOURCE_STYLE_SCHEME_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_SOURCE_STYLE_SCHEME_MANAGER, GtkSourceStyleSchemeManagerClass))
|
||||
#define GTK_IS_SOURCE_STYLE_SCHEME_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_SOURCE_STYLE_SCHEME_MANAGER))
|
||||
#define GTK_IS_SOURCE_STYLE_SCHEME_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_STYLE_SCHEME_MANAGER))
|
||||
#define GTK_SOURCE_STYLE_SCHEME_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_SOURCE_STYLE_SCHEME_MANAGER, GtkSourceStyleSchemeManagerClass))
|
||||
|
||||
|
||||
typedef struct _GtkSourceStyleSchemeManager GtkSourceStyleSchemeManager;
|
||||
typedef struct _GtkSourceStyleSchemeManagerClass GtkSourceStyleSchemeManagerClass;
|
||||
typedef struct _GtkSourceStyleSchemeManagerPrivate GtkSourceStyleSchemeManagerPrivate;
|
||||
|
||||
struct _GtkSourceStyleSchemeManager
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
GtkSourceStyleSchemeManagerPrivate *priv;
|
||||
};
|
||||
|
||||
struct _GtkSourceStyleSchemeManagerClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (*_gtk_source_reserved1) (void);
|
||||
void (*_gtk_source_reserved2) (void);
|
||||
void (*_gtk_source_reserved3) (void);
|
||||
void (*_gtk_source_reserved4) (void);
|
||||
};
|
||||
|
||||
|
||||
GType gtk_source_style_scheme_manager_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkSourceStyleSchemeManager *
|
||||
gtk_source_style_scheme_manager_new (void);
|
||||
|
||||
GtkSourceStyleSchemeManager *
|
||||
gtk_source_style_scheme_manager_get_default (void);
|
||||
|
||||
void gtk_source_style_scheme_manager_set_search_path (GtkSourceStyleSchemeManager *manager,
|
||||
gchar **path);
|
||||
|
||||
void gtk_source_style_scheme_manager_append_search_path (GtkSourceStyleSchemeManager *manager,
|
||||
const gchar *path);
|
||||
|
||||
void gtk_source_style_scheme_manager_prepend_search_path (GtkSourceStyleSchemeManager *manager,
|
||||
const gchar *path);
|
||||
|
||||
const gchar* const *
|
||||
gtk_source_style_scheme_manager_get_search_path (GtkSourceStyleSchemeManager *manager);
|
||||
|
||||
void gtk_source_style_scheme_manager_force_rescan (GtkSourceStyleSchemeManager *manager);
|
||||
|
||||
const gchar* const *
|
||||
gtk_source_style_scheme_manager_get_scheme_ids (GtkSourceStyleSchemeManager *manager);
|
||||
|
||||
GtkSourceStyleScheme *gtk_source_style_scheme_manager_get_scheme (GtkSourceStyleSchemeManager *manager,
|
||||
const gchar *scheme_id);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_SOURCE_STYLE_SCHEME_MANAGER_H__ */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue