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