1
0
forked from vitrine/wmaker

48 Commits

Author SHA1 Message Date
Dan Cross
d91275d959 memory: replace most of memory.c with Rust mem
Replace `wmalloc` et al with wrappers around the Rust allocation
library.
2025-10-14 02:55:03 +00:00
5325e2d455 Improve automake integration with Rust build.
Now ./configure checks for cargo and rustc, and `make` will rebuild wmaker-rs if
any of its source code has changed.

There are still some steps to take for better integration (like ensuring that
deps are vendored correctly). See
https://viruta.org/librsvgs-build-infrastructure-autotools-and-rust.html for
suggestions on what else to do.
2025-09-19 20:02:54 -04:00
82c8b0c9b4 Rename wmakerlib dir to wmaker-rs for econsistency with future libs. 2025-09-13 14:54:13 -04:00
a67f7483fd Clean up parameters that were commented out. 2025-09-09 22:27:55 -04:00
cf87f7e83b Finish moving WApplication struct defn and methods into Rust. 2025-09-09 22:23:59 -04:00
b569889f21 Expose RRetainImage from wrlib for Rust. 2025-09-09 22:21:15 -04:00
383b3a1a7b Expose some WMHandlerID methods from WINGs for Rust. 2025-09-09 22:20:07 -04:00
4fd7d1e2c1 Forgot to include screen.rs earlier. 2025-09-09 22:19:41 -04:00
0131c493c0 Expose PropGetWMClass for Rust. 2025-09-09 22:19:16 -04:00
5f1317b885 Forgot to include global module in lib.rs. 2025-09-09 22:18:49 -04:00
5817c1f032 Expose a Rust type for WMenu. 2025-09-09 22:18:30 -04:00
6d09fbff93 Expose wDockFinishLaunch for WApplication. 2025-09-09 22:18:03 -04:00
b38fa197d7 Expose wDefaultFillAttributes for Rust. 2025-09-09 22:17:46 -04:00
4c617034b4 Expose AppMenu method used by WApplication. 2025-09-09 22:17:22 -04:00
f5daf2a76a Expose WAppIcon methods used by WApplication. 2025-09-09 22:16:31 -04:00
05895b40a2 Forgot to add wrlib module to lib.rs. 2025-09-09 22:07:37 -04:00
4f4ef94400 Expose start_hidden and emulate_appicon attrs of WWindow. 2025-09-09 21:57:17 -04:00
023ab177b2 Expose WWindow attributes so they can be seen from Rust. 2025-09-09 21:56:30 -04:00
279f369256 Expose w_global.context so it can be seen from Rust. 2025-09-09 20:16:02 -04:00
0a2ff4f055 Expose various other WWindow fields so they can be seen from Rust.
Fields: client_win, screen_ptr, wm_hints, wm_class, wm_instance,
defined_user_flags.
2025-09-09 19:41:12 -04:00
108c913c1d Expose WWindow::user_flags so that it can be seen from Rust. 2025-09-09 19:36:36 -04:00
8c669d57b2 Expose WWindow::net_icon_image so that it can be seen from Rust. 2025-09-09 19:34:57 -04:00
83fa8119d9 Expose WWindow::main_windowc so that it can be seen from Rust. 2025-09-09 17:00:57 -04:00
507e69e209 Expose WWindow::fake_group so that it can be seen from Rust. 2025-09-09 16:54:30 -04:00
70814cc235 Add a module for the WWindow type. 2025-09-09 16:52:21 -04:00
2ef6720890 Expose WIcon::highlighted so that it can be seen from Rust. 2025-09-09 15:52:33 -04:00
493d3c9738 Expose WScreen::root_win so that it can be seen from Rust. 2025-09-09 15:49:52 -04:00
917cc29160 Use repr(C) for Application flags to use them from an FFI interace. 2025-09-09 15:45:57 -04:00
3234e15388 Move WApplication refcount maintenance into Rust. 2025-09-05 02:24:03 -04:00
394b4d23cb Add forgotten use std::ptr. 2025-09-05 02:05:04 -04:00
274d1459aa Move wApplicationClearUrgentBounceTimer into Rust. 2025-09-05 02:02:34 -04:00
9a886baef8 Ditch linked list pointers in Rust application struct, too. 2025-09-05 02:00:48 -04:00
7ba66fbc00 Get rid of unused intrusive linked list in WApplication.
There is code to maintain this list in wApplicationDestroy, but use of it was
removed in 2001 (see commit 672c42cc48). So let's do some cleanup.
2025-09-05 01:49:20 -04:00
289ceb2991 First stab at defining WApplication methods in Rust.
This builds and appears to run.
2025-09-03 21:38:35 -04:00
ab7e188334 Add Cargo build outputs at prospective build path to .gitignore. 2025-09-03 20:59:39 -04:00
55d34ff0a1 Make bitfields in WApplication's flags struct into real fields.
This will ease interop with Rust.
2025-09-03 20:58:31 -04:00
0e7f125494 Move WApplication definition and remaining methods into a separate file.
This should provide a more solid interface boundary for a WApplication
replacement written in Rust.
2025-09-03 20:55:12 -04:00
9404c21fa8 Duplicate src/application.c to preserve revision history. 2025-09-03 20:43:59 -04:00
455aa71c19 Hide WAppIcon fields in favor of accessors. 2025-09-01 21:20:22 -04:00
18db22063c Hide WDock fields in favor of accessors. 2025-08-25 22:46:23 -04:00
b4d1dbe953 Hide WApplication fields in favor of accessors. 2025-08-24 23:41:16 -04:00
Doug Torrance
da676c9e9e Add WPrefs Serbian translation to EXTRA_DIST
Otherwise "make check" fails (script/check-translation-sources.sh).
2024-11-12 10:15:17 +00:00
Doug Torrance
4edf589a5b Remove cruft from autogen.sh 2024-11-12 10:15:17 +00:00
Doug Torrance
709eec4bce Update autogen.sh so that it can be run from build directory 2024-11-12 10:15:17 +00:00
Jeremy Sowden
b179803c11 Fix spelling errors
* "unknow" -> "unknown"
* "occured" -> "occurred"

Remove some entries from PO files where these entries contain spelling errors
and there are other entries that are identical except for these mistakes.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
2024-11-10 16:59:03 +00:00
Jeremy Sowden
5cd40deb20 Add missing Language: headers to PO files
msgfmt complains.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
2024-11-10 16:59:03 +00:00
Jeremy Sowden
9db1ea580d Ignore wrlib gettext artefacts
Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
2024-11-10 16:59:03 +00:00
Jeremy Sowden
9e56f58742 Remove obsolete autoconf macro
`AC_PROG_GCC_TRADITIONAL` is obsolete and is now just an alias for `AC_PROG_CC`,
which is already defined.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
2024-11-10 16:59:03 +00:00
709 changed files with 2938 additions and 172491 deletions

11
.gitignore vendored
View File

@@ -133,16 +133,13 @@ WPrefs.app/WPrefs.desktop
/WPrefs.app/po/*.mo
/util/po/*.pot
/util/po/*.mo
/wrlib/po/*.pot
/wrlib/po/*.mo
# Some text editors generate backup files
*~
.pc
# Bazel's build symlinks shouldn't be committed.
bazel-bazel
bazel-bin
bazel-out
bazel-testlogs
# Don't commit lockfile until things are more stable.
MODULE.bazel.lock
# Rust stuff.
/*/target/**

View File

@@ -21,7 +21,7 @@ Changes since version 0.95.7:
- debian: Ignore missing documentation for --runstatedir.
- debian: Use dh_autoreconf.
- debian: Simplify debian/rules.
- debian: Fix typo occured. (Thanks, lintian.)
- debian: Fix typo occurred. (Thanks, lintian.)
- debian: wmaker manpage moved from 1x to 1.
(Andreas Metzler <ametzler@bebt.de>)
- debian: Add wmiv to wmaker package.
@@ -498,7 +498,7 @@ Changes since version 0.95.6:
- doc: Add manpage for wmiv.
(Doug Torrance <dtorrance@monmouthcollege.edu>)
- wmaker: replaced old email address with the official one
- WINGs: Updated news with the API changes that occured between 0.95.6 and
- WINGs: Updated news with the API changes that occurred between 0.95.6 and
0.95.7
- WINGs: ran spell checker on the NEWS file
- WINGs: fix non-portable int conversion for printf in font panel size handling
@@ -969,7 +969,7 @@ Changes since version 0.95.5:
- WMaker: moved XGrab/XUngrabPointer into the conditional code
- News: created section dedicated to the changes related to 0.95.3
- News: added description of a change that may be interesting to users
- News: added section to describe the changes that have occured in 0.95.4
- News: added section to describe the changes that have occurred in 0.95.4
- News: marked the current changes as part of 0.95.5 and describe the drawers
feature
- News: described the new features for future 0.95.6 release
@@ -1103,7 +1103,7 @@ Changes since version 0.95.5:
#50158)
- WPrefs: fix NULL pointer handling when getting the Modifiers (Coverity
#50200)
- WPrefs: add warning when renderTexture encounters some unknow settings
- WPrefs: add warning when renderTexture encounters some unknown settings
(Christophe CURIS <christophe.curis@free.fr>)
- util/wmiv: add image auto orientation detection
(David Maciejak <david.maciejak@gmail.com>)

View File

@@ -39,7 +39,7 @@ ACLOCAL_AMFLAGS = -I m4
AM_DISTCHECK_CONFIGURE_FLAGS = --enable-silent-rules LINGUAS='*'
SUBDIRS = wrlib WINGs src util po WindowMaker wmlib WPrefs.app doc
SUBDIRS = wrlib WINGs wmaker-rs src util po WindowMaker wmlib WPrefs.app doc
DIST_SUBDIRS = $(SUBDIRS) test
EXTRA_DIST = TODO BUGS BUGFORM FAQ INSTALL \

View File

@@ -140,7 +140,7 @@ Changes since wmaker 0.64.0:
- Moved all internal handlers (timer, idle and input) to handlers.c
- simplified wevent.c and wutil.c.
- fixed handling of input with poll (was broken)
- fixed mem leak that occured when input handling was done with poll
- fixed mem leak that occurred when input handling was done with poll
- simpler and more straightforward event handling for timer, idle, input
and X events (also fixed some problems the old handling logic had)
- moved timer, idle and input handler definitions and prototypes from

View File

@@ -456,7 +456,7 @@ int wcopy_file(const char *dest_dir, const char *src_file, const char *dest_file
return -1;
}
buffer = malloc(buffer_size); /* Don't use wmalloc to avoid the memset(0) we don't need */
buffer = wmalloc(buffer_size);
if (buffer == NULL) {
werror(_("could not allocate memory for the copy buffer"));
close(fd_dst);
@@ -508,14 +508,14 @@ int wcopy_file(const char *dest_dir, const char *src_file, const char *dest_file
if (close(fd_dst) != 0) {
werror(_("could not close the file \"%s\": %s"), path_dst, strerror(errno));
cleanup_and_return_failure:
free(buffer);
wfree(buffer);
close(fd_src);
unlink(path_dst);
wfree(path_dst);
return -1;
}
free(buffer);
wfree(buffer);
wfree(path_dst);
close(fd_src);

View File

@@ -126,7 +126,7 @@ WMHandlerID WMAddTimerHandler(int milliseconds, WMCallback * callback, void *cda
{
TimerHandler *handler;
handler = malloc(sizeof(TimerHandler));
handler = wmalloc(sizeof(TimerHandler));
if (!handler)
return NULL;
@@ -214,7 +214,7 @@ WMHandlerID WMAddIdleHandler(WMCallback * callback, void *cdata)
{
IdleHandler *handler;
handler = malloc(sizeof(IdleHandler));
handler = wmalloc(sizeof(IdleHandler));
if (!handler)
return NULL;

View File

@@ -19,34 +19,15 @@
* MA 02110-1301, USA.
*/
#include "wconfig.h"
#include <sys/types.h>
#include "WUtil.h"
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <signal.h>
#ifdef HAVE_STDNORETURN
#include <stdlib.h>
#include <stdnoreturn.h>
#endif
#ifdef USE_BOEHM_GC
#ifndef GC_DEBUG
#define GC_DEBUG
#endif /* !GC_DEBUG */
#include <gc/gc.h>
#endif /* USE_BOEHM_GC */
#ifndef False
# define False 0
#endif
#ifndef True
# define True 1
#endif
#include <unistd.h>
static void defaultHandler(int bla)
{
@@ -72,152 +53,3 @@ waborthandler *wsetabort(waborthandler * handler)
return old;
}
static int Aborting = 0; /* if we're in the middle of an emergency exit */
static WMHashTable *table = NULL;
void *wmalloc(size_t size)
{
void *tmp;
assert(size > 0);
#ifdef USE_BOEHM_GC
tmp = GC_MALLOC(size);
#else
tmp = malloc(size);
#endif
if (tmp == NULL) {
wwarning("malloc() failed. Retrying after 2s.");
sleep(2);
#ifdef USE_BOEHM_GC
tmp = GC_MALLOC(size);
#else
tmp = malloc(size);
#endif
if (tmp == NULL) {
if (Aborting) {
fputs("Really Bad Error: recursive malloc() failure.", stderr);
exit(-1);
} else {
wfatal("virtual memory exhausted");
Aborting = 1;
wAbort(False);
}
}
}
if (tmp != NULL)
memset(tmp, 0, size);
return tmp;
}
void *wrealloc(void *ptr, size_t newsize)
{
void *nptr;
if (!ptr) {
nptr = wmalloc(newsize);
} else if (newsize == 0) {
wfree(ptr);
nptr = NULL;
} else {
#ifdef USE_BOEHM_GC
nptr = GC_REALLOC(ptr, newsize);
#else
nptr = realloc(ptr, newsize);
#endif
if (nptr == NULL) {
wwarning("realloc() failed. Retrying after 2s.");
sleep(2);
#ifdef USE_BOEHM_GC
nptr = GC_REALLOC(ptr, newsize);
#else
nptr = realloc(ptr, newsize);
#endif
if (nptr == NULL) {
if (Aborting) {
fputs("Really Bad Error: recursive realloc() failure.", stderr);
exit(-1);
} else {
wfatal("virtual memory exhausted");
Aborting = 1;
wAbort(False);
}
}
}
}
return nptr;
}
void *wretain(void *ptr)
{
int *refcount;
if (!table) {
table = WMCreateHashTable(WMIntHashCallbacks);
}
refcount = WMHashGet(table, ptr);
if (!refcount) {
refcount = wmalloc(sizeof(int));
*refcount = 1;
WMHashInsert(table, ptr, refcount);
#ifdef VERBOSE
printf("== %i (%p)\n", *refcount, ptr);
#endif
} else {
(*refcount)++;
#ifdef VERBOSE
printf("+ %i (%p)\n", *refcount, ptr);
#endif
}
return ptr;
}
void wfree(void *ptr)
{
if (ptr)
#ifdef USE_BOEHM_GC
/* This should eventually be removed, once the criss-cross
* of wmalloc()d memory being free()d, malloc()d memory being
* wfree()d, various misuses of calling wfree() on objects
* allocated by libc malloc() and calling libc free() on
* objects allocated by Boehm GC (think external libraries)
* is cleaned up.
*/
if (GC_base(ptr) != 0)
GC_FREE(ptr);
else
free(ptr);
#else
free(ptr);
#endif
ptr = NULL;
}
void wrelease(void *ptr)
{
int *refcount;
refcount = WMHashGet(table, ptr);
if (!refcount) {
wwarning("trying to release unexisting data %p", ptr);
} else {
(*refcount)--;
if (*refcount < 1) {
#ifdef VERBOSE
printf("RELEASING %p\n", ptr);
#endif
WMHashRemove(table, ptr);
wfree(refcount);
wfree(ptr);
}
#ifdef VERBOSE
else {
printf("- %i (%p)\n", *refcount, ptr);
}
#endif
}
}

View File

@@ -9,6 +9,7 @@ msgstr ""
"PO-Revision-Date: 2003-02-09 12:10+0200\n"
"Last-Translator: Anton Zinoviev <zinoviev@debian.org>\n"
"Language-Team: Bulgarian <dict@linux.zonebg.com>\n"
"Language: bg\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

View File

@@ -14,6 +14,7 @@ msgstr ""
"PO-Revision-Date: 2003-09-16 23:16+0200\n"
"Last-Translator: Ernest Adrogué <eadrogue@gmx.net>\n"
"Language-Team: Catalan <ca@dodds.net>\n"
"Language: ca\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

View File

@@ -12,6 +12,7 @@ msgstr ""
"PO-Revision-Date: 2001-10-11 22:00+0100\n"
"Last-Translator: Jiří Hnídek <jiri.hnidek@vslib.cz>\n"
"Language-Team: Czech <cz@li.org>\n"
"Language: cs\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: unknown\n"

View File

@@ -15,6 +15,7 @@ msgstr ""
"PO-Revision-Date: 2004-11-05 23:48+0100\n"
"Last-Translator: shlomme@gmx.net\n"
"Language-Team: German\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

View File

@@ -10,6 +10,7 @@ msgstr ""
"PO-Revision-Date: 2002-01-09 21:20+0100\n"
"Last-Translator: Emmanuel Benoit <tseeker@neptune.fr>\n"
"Language-Team: Français <fr@li.org>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: unknown\n"

View File

@@ -11,7 +11,7 @@ msgstr ""
"PO-Revision-Date: 2014-02-18 00:25+0100\n"
"Last-Translator: BALATON Zoltán <balaton@eik.bme.hu>\n"
"Language-Team: Hungarian\n"
"Language: \n"
"Language: hu\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

View File

@@ -843,9 +843,6 @@ msgstr "Kon invoerbestand \"%s\" niet openen"
msgid "Could not create target file \"%s\""
msgstr "Kon doelbestand \"%s\" niet aanmaken"
msgid "An error occured browsing '%s'."
msgstr "Er trad 'n fout op bij bladeren door '%s'."
msgid ""
"invalid characted '%c' in arg-list for macro \"%s\" while expecting "
"parameter name"
@@ -860,9 +857,6 @@ msgstr ""
"ongeldig letterteken '%c' in arg.-lijst voor macro \"%s\", verwachtte ',' "
"of ')'"
msgid "unknow directive '#%s'"
msgstr "onbekende aanwijzing '#%s'"
msgid "found #%s but have no matching #if"
msgstr "#%s gevonden, maar heeft geen bijbehorende #if"

View File

@@ -19,6 +19,7 @@ msgstr ""
"PO-Revision-Date: 2001-12-20 04:00+0100\n"
"Last-Translator: Jan \"judas\" Tomka <judas@linux.sk>\n"
"Language-Team: Slovak <sk@li.org>\n"
"Language: sk\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

View File

@@ -610,10 +610,9 @@ WMScreen *WMCreateScreenWithRContext(Display * display, int screen, RContext * c
assert(W_ApplicationInitialized());
}
scrPtr = malloc(sizeof(W_Screen));
scrPtr = wmalloc(sizeof(W_Screen));
if (!scrPtr)
return NULL;
memset(scrPtr, 0, sizeof(W_Screen));
scrPtr->aflags.hasAppIcon = 1;

View File

@@ -129,7 +129,7 @@ static void autoDelayChanged(void *observerData, WMNotification *notification)
}
char *value = WMGetTextFieldText(anAutoDelayT);
adjustButtonSelectionBasedOnValue(panel, row, value);
free(value);
wfree(value);
return;
}
}

View File

@@ -138,7 +138,7 @@ static void storeData(_Panel * panel)
if (sscanf(str, "%i", &i) != 1)
i = 0;
SetIntegerForKey(i, "RaiseDelay");
free(str);
wfree(str);
SetBoolForKey(WMGetButtonSelected(panel->ignB), "IgnoreFocusClick");
SetBoolForKey(WMGetButtonSelected(panel->newB), "AutoFocus");

View File

@@ -147,7 +147,7 @@ static void storeData(_Panel * panel)
if (sscanf(str, "%i", &i) != 1)
i = 0;
SetIntegerForKey(i, "HotCornerDelay");
free(str);
wfree(str);
SetIntegerForKey(WMGetSliderValue(panel->hceS), "HotCornerEdge");

View File

@@ -68,6 +68,7 @@ WPrefs_DEPENDENCIES = $(top_builddir)/WINGs/libWINGs.la
WPrefs_LDADD = \
$(top_builddir)/WINGs/libWINGs.la\
$(top_builddir)/WINGs/libWUtil.la\
$(top_builddir)/wmaker-rs/target/debug/libwmaker_rs.a\
$(top_builddir)/wrlib/libwraster.la \
@XLFLAGS@ @XLIBS@ \
@LIBM@ \

View File

@@ -5,7 +5,8 @@ CATALOGS = @WPREFSMOFILES@
CLEANFILES = $(DOMAIN).pot $(CATALOGS)
EXTRA_DIST = bg.po ca.po cs.po de.po es.po et.po fi.po fr.po fy.po hr.po hu.po \
it.po ja.po ko.po nl.po pt.po ru.po sk.po tr.po uk.po zh_CN.po zh_TW.po
it.po ja.po ko.po nl.po pt.po ru.po sk.po sr.po tr.po uk.po zh_CN.po \
zh_TW.po
POTFILES = \
$(top_srcdir)/WPrefs.app/Appearance.c \

View File

@@ -8,6 +8,7 @@ msgstr ""
"PO-Revision-Date: 2001-04-18 23:22+03:00\n"
"Last-Translator: Anton Zinoviev <zinoviev@debian.org>\n"
"Language-Team: Bulgarian <dict@linux.zonebg.com>\n"
"Language: bg\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

View File

@@ -14,6 +14,7 @@ msgstr ""
"PO-Revision-Date: 2003-09-16 23:15+0200\n"
"Last-Translator: Ernest Adrogué <eadrogue@gmx.net>\n"
"Language-Team: Catalan <ca@dodds.net>\n"
"Language: ca\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

View File

@@ -16,6 +16,7 @@ msgstr ""
"PO-Revision-Date: 2001-10-14 21:07+0000\n"
"Last-Translator: Jiří Hnídek <jiri.hnidek@vslib.cz>\n"
"Language-Team: czech <cs@li.org>\n"
"Language: cs\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: unknown\n"

View File

@@ -18,6 +18,7 @@ msgstr ""
"PO-Revision-Date: 2010-02-02 10:49+0100\n"
"Last-Translator: Carlos R. Mafra <crmafra@gmail.com>\n"
"Language-Team: German <>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

View File

@@ -8,6 +8,7 @@ msgstr ""
"PO-Revision-Date: 2003-09-19 03:05-0400\n"
"Last-Translator: Alberto Giménez <algibe@teleline.es>\n"
"Language-Team: Spanish \n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: unknown\n"

View File

@@ -8,6 +8,7 @@ msgstr ""
"PO-Revision-Date: 2001-09-05 09:40+0200\n"
"Last-Translator: Ivar Smolin <okul@linux.ee>\n"
"Language-Team: Estonian <linux-ee@eenet.ee>\n"
"Language: et\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -475,7 +476,7 @@ msgstr "Window Maker vőttis vastu signaali %i."
#: ../src/dialog.c:1707
msgid ""
" This fatal error occured probably due to a bug. Please fill the included "
" This fatal error occurred probably due to a bug. Please fill the included "
"BUGFORM and report it to bugs@windowmaker.info."
msgstr ""
" See fataalviga on arvatavasti pőhjustatud programmi veast. Palun täitke "
@@ -1437,7 +1438,7 @@ msgstr "ei őnnestu käivitada alternatiivset aknahaldurit. Annan alla."
#: ../src/startup.c:419
msgid ""
"a fatal error has occured, probably due to a bug. Please fill the included "
"a fatal error has occurred, probably due to a bug. Please fill the included "
"BUGFORM and report it."
msgstr ""
"aset on leidnud fataalne viga, arvatavasti programmi viga. Palun täida "

View File

@@ -11,6 +11,7 @@ msgstr ""
"PO-Revision-Date: 2001-09-03 22:18+03:00\n"
"Last-Translator: Tomi Kajala <tomi@iki.fi>\n"
"Language-Team: Finnish <fi@li.org>\n"
"Language: fi\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"

View File

@@ -12,6 +12,7 @@ msgstr ""
"PO-Revision-Date: 1999-07-28 16:31-0100\n"
"Last-Translator: Antoine Hulin <antoine.hulin@origan.fdn.org>\n"
"Language-Team: French <fr@li.org>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"

View File

@@ -9,6 +9,7 @@ msgstr ""
"PO-Revision-Date: 1998-08-24 14:36:41-0300\n"
"Last-Translator: Toni Bilić tbilic@oliver.efos.hr \n"
"Language-Team: Croatian \n"
"Language: hr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

View File

@@ -11,7 +11,7 @@ msgstr ""
"PO-Revision-Date: 2014-02-18 00:33+0100\n"
"Last-Translator: BALATON Zoltán <balaton@eik.bme.hu>\n"
"Language-Team: Hungarian\n"
"Language: \n"
"Language: hu\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

View File

@@ -11,6 +11,7 @@ msgstr ""
"PO-Revision-Date: 2001-05-21\n"
"Last-Translator: Michele Campeotto <micampe@f2s.com\n"
"Language-Team: Italian\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: unknown\n"

View File

@@ -12,6 +12,7 @@ msgstr ""
"PO-Revision-Date: 2013-08-13 19:26+0900\n"
"Last-Translator: \n"
"Language-Team: Korean\n"
"Language: ko\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

View File

@@ -12,6 +12,7 @@ msgstr ""
"PO-Revision-Date: 2000-01-04 18:25-0300\n"
"Last-Translator: Eliphas Levy Theodoro <eliphas@conectiva.com.br>\n"
"Language-Team: Portuguese \n"
"Language: pt\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"

View File

@@ -12,6 +12,7 @@ msgstr ""
"PO-Revision-Date: 2002-09-12 17:45+0300\n"
"Last-Translator: awn@bcs.zp.ua\n"
"Language-Team: Russian\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

View File

@@ -18,6 +18,7 @@ msgstr ""
"PO-Revision-Date: 2001-10-15 20:40+0100\n"
"Last-Translator: Jan \"judas\" Tomka <judas@linux.sk>\n"
"Language-Team: Slovak <sk@li.org>\n"
"Language: sk\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

View File

@@ -5,6 +5,7 @@ msgstr ""
"PO-Revision-Date: 2004-09-06 21:42+4000\n"
"Last-Translator: Victor Forsyuk <victor@ksi-linux.com>\n"
"Language-Team: KSI Linux Ukrainian <uk@ksi-linux.com>\n"
"Language: uk\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

View File

@@ -9,6 +9,7 @@ msgstr ""
"PO-Revision-Date: 1999-07-05 23:20+0800\n"
"Last-Translator: Wang Jian <larkw@263.net>\n"
"Language-Team: chinese <zh@li.org>\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"

View File

@@ -10,6 +10,7 @@ msgstr ""
"PO-Revision-Date: 2005-01-11 17:46+0800\n"
"Last-Translator: Li Wei Jih <lwj83@cs.ccu.edu.tw>\n"
"Language-Team: chinese <zh@li.org>\n"
"Language: zh_TW\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"

View File

@@ -1,26 +1,16 @@
#!/bin/sh
srcdir=$(dirname $0)
test -z "$srcdir" && srcdir=.
# Generate the documentation about compiling Window Maker
./script/generate-txt-from-texi.sh "doc/build/Compilation.texi" -o "INSTALL-WMAKER"
./script/generate-txt-from-texi.sh "doc/build/Translations.texi" -o "README.i18n"
$srcdir/script/generate-txt-from-texi.sh "$srcdir/doc/build/Compilation.texi" \
-o "$srcdir/INSTALL-WMAKER"
$srcdir/script/generate-txt-from-texi.sh "$srcdir/doc/build/Translations.texi" \
-o "$srcdir/README.i18n"
# Change date of the files to the past so they will be regenerated by 'make'
touch -d '2000-01-01' INSTALL-WMAKER README.i18n
touch -d '2000-01-01' $srcdir/INSTALL-WMAKER $srcdir/README.i18n
# Generate the configure script from the 'configure.ac'
autoreconf -vfi -I m4
exit 0
if [ -x config.status -a -z "$*" ]; then
./config.status --recheck
else
if test -z "$*"; then
echo "I am going to run ./configure with no arguments - if you wish "
echo "to pass any to it, please specify them on the $0 command line."
echo "If you do not wish to run ./configure, press Ctrl-C now."
trap 'echo "configure aborted" ; exit 0' 1 2 15
sleep 1
fi
./configure "$@"
fi
autoreconf -vfi -I m4 $srcdir

View File

@@ -1,6 +0,0 @@
###############################################################################
# Bazel now uses Bzlmod by default to manage external dependencies.
# Please consider migrating your external dependencies from WORKSPACE to MODULE.bazel.
#
# For more details, please check https://github.com/bazelbuild/bazel/issues/18958
###############################################################################

View File

@@ -1,3 +0,0 @@
- filepanel does not reread / . If you add new files in / they will not be
visible until the program is restarted. Closing and reopening the file
panel does not help.

View File

@@ -1,86 +0,0 @@
cc_library(
name = "WINGs",
copts = [
"-DRESOURCE_PATH=\\\"Resources\\\"",
"-D_GNU_SOURCE",
"-DHAVE_BSD_STRING_H",
],
data = glob(['Resources/*']),
srcs = [
"array.c",
"bagtree.c",
"configuration.c",
"data.c",
"dragcommon.c",
"dragdestination.c",
"dragsource.c",
"error.c",
"findfile.c",
"handlers.c",
"hashtable.c",
"memory.c",
"menuparser.c",
"menuparser_macros.c",
"misc.c",
"notification.c",
"proplist.c",
"selection.c",
"string.c",
"tree.c",
"userdefaults.c",
"usleep.c",
"wapplication.c",
"wappresource.c",
"wballoon.c",
"wbox.c",
"wbrowser.c",
"wbutton.c",
"wcolor.c",
"wcolorpanel.c",
"wcolorwell.c",
"wevent.c",
"wfilepanel.c",
"wfont.c",
"wfontpanel.c",
"wframe.c",
"widgets.c",
"winputmethod.c",
"wlabel.c",
"wlist.c",
"wmenuitem.c",
"wmisc.c",
"wpanel.c",
"wpixmap.c",
"wpopupbutton.c",
"wprogressindicator.c",
"wruler.c",
"wscroller.c",
"wscrollview.c",
"wslider.c",
"wsplitview.c",
"wtabview.c",
"wtext.c",
"wtextfield.c",
"wview.c",
"wwindow.c",
],
hdrs = [
"menuparser.h",
"userdefaults.h",
"rgb.h",
"wconfig.h",
"WINGs.h",
"WINGsP.h",
"WUtil.h",
],
deps = [
"//config",
"//wmaker:gnustep_compat",
"//wrlib",
"@freetype2//:lib",
"@libbsd//:lib",
"@pango//:lib",
"@pangoxft//:lib",
],
visibility = ["//visibility:public"],
)

View File

@@ -1,659 +0,0 @@
Changes since wmaker 0.96.0:
............................
- added W_KeycodeToKeysym to replace XKeycodeToKeysym/XkbKeycodeToKeysym calls
Changes since wmaker 0.92.0:
............................
- updated the XDND code in to work with GDK based applications.
WINGs based applications should now work with both KDE and GNOME
applications (Sylvain Reynal <sreynal@nerim.net>)
- better check for the XDND protocol version when interoperating with other
applications. As it seems xdnd version 3 (which WINGs supports) and newer
are not backward compatible with xdnd version 1 and 2. This is why WINGs
applications cannot interoperate with GNUstep applications (which uses
xdnd version 2). Xdnd version 4 and 5 are backwards compatible with
version 3 though. (Sylvain Reynal <sreynal@nerim.net>)
- removed dependency on rgb.txt from X11 and issues with locating it on the
filesystem for different systems/distributions.
- Removed dependency on rgb.txt (from X11) and issues with locating it on the
filesystem for different systems/distributions.
Changes since wmaker 0.80.1:
............................
- Added WMSetConnectionShutdownOnClose()
- Added an extra member to the ConnectionDelegate: canResumeSending
see NEWS for details.
- WMDrawString() and WMDrawImageString() now take WMColor instead of GC as
arguments. WMDrawImageString() receives 2 colors (text & background).
This is to allow easy extension for Xft/Xrender and hide X low level details
Read NEWS for details since this will break backward compatibility.
- Added alpha channel to WMColor. 2 new functions also:
WMCreateRGBAColor() and WMSetColorAlpha()
- Miscelaneous code cleanups in wtext.c
- Added Xft2 support in WINGs (for drawing antialiased fonts with transparency).
- New options in WMGLOBAL: AntialiasedText. Check NEWS for details.
- Fixed some improper calls to snprintf in wfont.c
- Added double buffering when drawing a WMFrame title with an antialiased font
to avoid flickering.
- Added double buffering when drawing WMList items to avoid flickering.
Double buffering for list also works for user drawn lists. Read NEWS for
details and incompatibilities introduced by this change.
- Added WMGetColorAlpha(WMColor *color)
- Better outline when drawing balloons.
- Added WMCreateFontWithAttributes()
- You can now pass "SystemFont", "BoldSystemFont", "SystemFont-##" or
"BoldSystemFont-##", with ## being the font size to any font creating
function to create a font with the (bold) system font font specification.
- Added WMCopyFontWithChanges(). This is a more generic and powerful function
meant to replaces the obsoleted WMEmphasizeFont(), WMNormalizeFont(),
WMStrenghtenFont() and the other similar functions. To get the same effect
you pass some predefined structs to it: WFANormal, WFABold, WFAEmphasized,
etc which are declared in WINGs.h).
- Fixed a bug with empty frame titles (Alexey Voinov <voins@voins.program.ru>)
- Added WMGetWidgetBackgroundColor()
- Code cleanup in wtext.c
- Fixed a memory leak in wfontpanel.c
- Fixed WMGetTextDefaultColor() not to retain the returned color. It returns
only a reference to the internal color, which you shouldn't release
- Added wstrndup()
- Added WMGetFontName()
- Added fontpanel callback
- Added WMSetTableViewHasHorizontalScroller()
- Fixed bug that could cause SIGSEGV by accessing beyond the end of text in
a WINGs textfield widget.
- Fixed small memory leak in the font panel code.
- Fixed call to qsort in WMSortArray.
- Fixed a memleak in the file panel.
- Double/triple-click selection in text widgets
(Vitaly Ovtchinnikov <ov@rbcmail.ru>)
- Fixed bug in tableview (clicked row callback got incorrect row)
(Carlos Torres <vlaadbrain@operamail.com>)
- Fixed bug in resizing a scrollview
- Fixed bug with wrong text wrapping (Alexey Voinov <voins@voins.program.ru>)
- Added wmkrect()
- Added xdnd v3 support (Sylvain Reynal <sreynal@nerim.net>)
- Fixed and enhanced text wrapping.
Changes since wmaker 0.80.0:
............................
- fixed a bug in wfindfile() (rewrote wfindfile() with better logic).
- separated the font caches for normal fonts and fontsets in WINGs (they can
have the same names and collide in the cache giving unwanted results)
- fixed labels not to display '\n' as a character if multiple '\n' are passed
but just skip to the next line.
- better warning when importing non-digit characters in PropList Data.
- rewrote WMBox to use a WMArray for subviews. with this change fixed a bug
about arranging subviews after removing one and a memleak occuring in the
same case.
- Fixed WMGetViewScreenPosition() to consider the window decorations.
- Added ability to enable/disable individual WMTableViewItems.
- Fixed textfields regarding interpretation of special keys with modifiers.
- Fixed some functions that accept a boolean flag as a paramater, to set only
1 or 0 for the flag value, not the flag passed by the user.
- Added 2 functions to retrieve the default system fonts:
WMDefaultSystemFont(WMScreen *scr) and WMDefaultBoldSystemFont(WMScreen *scr)
- Added WMSetButtonImageDimsWhenDisabled() and WMGetButtonEnabled()
- Cleaned-up the header files of functions/vars declared but not implemented
- Added WMGetTextFieldDelegate()
Changes since wmaker 0.70.0:
............................
- added an internal strcasecmp() (only on systems where is not present)
- removed some redundant includes of ../src/config.h when wconfig.h is
included too
- removed a wsyserror() message when reading a property list from file
(the programmer should decide if to give that message or just ignore).
- added a 'Bool recursive' flag to WMMergePLDictionaries()
- added WMSubtractPLDictionaries()
Changes since wmaker 0.65.0:
............................
- fixed problem with WINGs based apps exiting with a "X_RotateProperties"
related error when text was selected in a textfiled.
- moved wstrdup(), wstrconcat() and wstrappend() from memory.c to string.c
- added property list handling code making libPropList unnecessary and
obsolete. Backward compatibility is provided through the
WINGs/proplist-compat.h header file which has #defines from old libPropList
function names to new function names with minimal changes. Read this
header file and the NEWS file for more details about this subject.
- Renamed WMGetUDAllKeys() to WMGetUDKeys()
Changes since wmaker 0.64.0:
............................
- made programmatic scroller changes send notifications
- replaced WMSetBoxExpandsToParent with WMSetViewExpands...
- added WMGetLabelFont()
- added WMAddPersistentTimerHandler()
- Moved all internal handlers (timer, idle and input) to handlers.c
- simplified wevent.c and wutil.c.
- fixed handling of input with poll (was broken)
- fixed mem leak that occured when input handling was done with poll
- simpler and more straightforward event handling for timer, idle, input
and X events (also fixed some problems the old handling logic had)
- moved timer, idle and input handler definitions and prototypes from
WINGs.h to WUtil.h because they're not GUI related.
- better and more robust handling of events (timer, idle, input, X) in
WMMaskEvent(). Also fixed a bug where input and timer events were not
treated for undefined periods of time under some circumstances.
- fixed secure textfields not to allow text selection, to avoid compromising
sensitive information by pasting it to a terminal.
- replaced wmkrange(), wmkpoint() and wmksize() functions with macros.
- added WMRemoveFromArrayMatching(array, match, cdata), which will remove the
first element in the array that is matched by match(item, cdata)==True.
- added WMArrayFirst(), WMArrayLast(), WMArrayNext() and WMArrayPrevious()
functions and also WM_ITERATE_ARRAY() and WM_ETARETI_ARRAY() macros, to make
interfaces to WMBag and WMArray similar and to make life a little simpler
when iterating through all elements of an array.
- replaced bags with arrays wherever appropriate. This will improve
performance a bit.
- replaced some recursive code with iterative code in selection.c
- added WMCreateBlendedPixmapFromRImage()
- small API change:
1. Renamed WMSetApplicationIconImage(), WMGetApplicationIconImage() and
WMSetWindowMiniwindowImage() to respectively WMSetApplicationIconPixmap(),
WMGetApplicationIconPixmap() and WMSetWindowMiniwindowPixmap()
They operate on a WMPixmap which is practically an X Pixmap with no alpha
channel information and the new name is more suggestive and also leaves
room for the new functions added for operating on images with alpha info.
2. Added WMSetApplicationIconImage() and WMGetApplicationIconImage() which
operate on an RImage and store alpha information too.
3. Added WMCreateApplicationIconBlendedPixmap() which will take the image
set by WMSetApplicationIconImage() and will combine it with a color.
If color is NULL it will blend using the default panel color (#aeaaae)
All these changes will allow WINGs to handle images with alpha blending
correctly in panels and wherever else needed. More about in NEWS.
- updated panels to use the newly available RImages if present and fallback
to old WMPixmaps if not, to properly show alpha blended images.
- replaced some still left malloc's with wmalloc's.
- fixed a bug in WMReparentWidget()
- added WMReparentWidget() to WINGs.h
- fixed a bug that made the scroller knob jump backwards when dragged (this
bug had no relation with the behavior that #define STRICT_NEXT_BEHAVIOUR
attempts to accomplish).
- fixed scrolling direction with mouse wheel for horizontal scroller.
changes since wmaker 0.63.1:
............................
- added WMRunModalLoop() and WMBreakModalLoop()
- added WMSetBoxExpandsToParent()
- added WMRemoveBoxSubview()
- moved WINGs headers in a WINGs subdirectory when installed.
use #include <WINGs/header_file_name> in your application from now on.
Also updated get-{wings|wutil}-flags.
- Fixed a mem leak in WMList.
- Fixed a bug that caused sigsegv for a WMList with more than 32767 items.
- Added an example of how to create a server type program with WMConnection.
- added WMOpenScreen()
changes since wmaker 0.62.1:
............................
- added WRuler widget
- added WText widget (rtf multiline text widget)
Nwanua Elumeze <nwanua@colorado.edu>
- added a new AUTO option for the UseMultiByte option
- added WMRaiseWidget()/WMLowerWidget()
- added missing EscapeTextMovement to textfield delegate/notification
- added WMGetLabelText()
- added WMReparentWidget()
- added WMCreateTabViewItem()
- added W_CreateUnmanagedTopView()
- added wtokenjoin(), wtokensplit(), wtokenfree(), wtrimspace()
- added WMWidgetIsMapped()
- added WMSetApplicationIconWindow()
- restructured the directory tree. Added Documentation, Examples and Tests
subdirectories
- removed WMArrayBag and reorganized WMTreeBag to be WMBag.
- added WMArray class.
- added WMSetWindowUserPosition()
- added WMGetListSelectedItems()
- added WMSetListAllowMultipleSelection(), WMListAllowsMultipleSelection().
- added WMSetListAllowEmptySelection(), WMListAllowsEmptySelection().
- WMListSelectionDidChangeNotification passes NULL as the notification
client data (previously passed the selected item row).
- added WMUnselectListItem(), WMSelectAllListItems(), WMUnselectAllListItems()
- better behavior of wheel mices in WMList. Simple mouse wheel events
will scroll by 1/3 of the WMList height. Using Shift as a modifier will
scroll line by line, while using Control as a modifier will scroll page
by page.
- better behavior of WMScroller regarding mouse wheel events. 'Shift' modifier
will scroll line by line, while 'Control' modifier will scroll page by page.
- fixed some buffer overflow allowing bugs.
- added WSDecrementWheel and WSIncrementWheel for handling mouse wheel in
scrollers and scrolled widgets. This should be treated like the WSxxxPage
counterparts, except it should scroll by page_size/3 instead of one full page
- added WMSetBrowserAllowMultipleSelection(), WMSetBrowserAllowEmptySelection()
WMBrowserAllowsMultipleSelection() and WMBrowserAllowsEmptySelection()
- WMBrowser now allows multiple selections.
- Added WMGetBrowserPaths() to retrieve the paths for browsers that allow
multiple selections.
- WMDestroyWidget() now calls WMUnmapWidget() first
- added WMScrollerDidScrollNotification to scroller
- added WMGetScrollViewVisibleRect()
- fixed a mem leak in the browser code.
- renamed wstrappend() to wstrconcat(). wstrconcat(str1, str2) concatenates
str1 with str2 and returns that in a newly malloc'ed string.
Be sure to rename wstrappend with wstrconcat in your code too, else
hazardous things can happen!
- implemented a new wstrappend() function. wstrappend(dst, src) will append
src to dst modifing dst and returning a pointer to it. No new string is
generated, except if dst is NULL, in which case its the same as calling
wstrdup(src).
dst can ONLY be NULL or a dynamically allocated string (obtained from a
call to malloc, realloc, wmalloc, wrealloc, ...). dst CANNOT be a static
or a constant string!
- added wmessage() for printing a variable formatted string to stderr, with
the program name prepended to it. Similar to wwarning(), except that it
doesn't add "warning:" in the output message.
- added WMBox widget
- added WMAddTabViewItemWithView()
- added W_SetViewCursor()
- made Extra widgets library
- added table widget in Extras library
- added WMGetConnectionUnsentData() (WMGetConnectionQueuedData() too as an
alias).
- added WMSetConnectionCloseOnExec() to specify if the socket associated
with a connection survives an exec* call or not. When a new connection is
created using the WMCreate... or WMAcceptConnection() calls, it has the
close on exec flag set automatically to 'True' by the library. Unless
you want to let the socket of some connection to survive across an exec*
call, you need not to call this function.
- removed all the wsyserror() and wwarning() calls from host.c and
connection.c and replaced where appropriate with assertions. If a function
returns some invalid result, you can still get the system error message if
you need, by calling wsyserrorwithcode() and passing WCErrorCode, if
WCErrorCode > 0. If WCErrorCode==0, that is not a system error, and
wsyserrorwithcode() should not be called in this case.
- added WMNextHashEnumeratorKey() to retrieve all keys in some hash enumerator
one by one.
- fixed a bug with mouse wheels scrolling in scrollers even with the widget
fully visible.
- Fixed a memory leak (the destroy function for a view was never called and
as a result the shaded windows didn't go away when closed. The non-shaded
windows were unmapped on close but not destroyed either so they only
apparently went away, but continued to use memory).
- Fixed a bug in the hashtable code which free'd the whole item instead of
just the item key in WMResetHashTable() (possible source of SIGSEGVs)
changes since wmaker 0.62.0:
............................
- added WMSetWidgetDefaultFont(), WMSetWidgetDefaultBoldFont()
changes since wmaker 0.62.0:
............................
- added WM{S,G}etDataFormat()
- added drag and drop
- changed selection code
- added clientdata to WMFindInBag
- removed SetWindowInitialSize()
- added SetWindowAspectRatio()
- added initial timeout when establishing a connection.
- added WMSetConnectionDefaultTimeout() and WMSetConnectionOpenTimeout();
- added WMGetConnectionTimeoutState()
changes since wmaker 0.61.1:
............................
- WARNING: semantic of bags has changed!
An index assigned to an item will always keep that index unless
you insert an item before it.
For example:
bag = WMCreateBag();
WMSetInBag(bag, 10, "bla");
That code will put "bla" in index 10, instead of 0, as it used to be.
- fixed WMInsertInBag(). It ignored index, and always put the new item at end.
- added WMSaveUserDefaults().
- rewrote WMPopUpButton to use WMMenuItem
- added WMGetPopUpButtonMenuItem(WMPopUpButton *bPtr, int index)
- WMSortListItemsWithComparer(WMList *lPtr, (int)(f)(const void*, const void*))
- WMSortBrowserColumnWithComparer()
- fixed bug with sorting list items.
- fixed bug in handling keyboard input associated with selection and
notification sending.
- filepanel puts dirs on top of list (Wolff <wolff@cybercable.fr>)
- added WMReplaceInBag (Wolff <wolff@cybercable.fr>)
- added vertical views and multiple views in WMSplitView (Wolff <wolff@cybercable.fr>)
- changed values of parameter values of WMSplitViewConstrainProc()
- configurable default fontsize patch (Igor P. Roboul <igor@mordor.myip.org>)
- fixed a bug that crashed the programm when a popup button was scrolled.
- fixed a bug that caused incorrect drawing position of the popup indicator.
- fixed a bug that prevented selecting no item (-1) in a popup button.
- an assertion will be raised if the program tries to select a popup button
item that is beyond the total number of items present in the popup button.
- changed names of functions for SplitView to be consistent. Some contained
SubView while other Subview. Now all have Subview.
- fixed a bug in how input events were posted. Establishing 2 or more input
handlers for the same file descriptor, handling different (read/write/except)
events, caused wrong handlers to be called.
- Reimplemented the input and idle handlers with WMBag to avoid a functional
problem with them: inability to remove handlers next to the called one, from
the called handler itself. Trying to do this with the old version caused the
program to crash.
- changed wrealloc behaviour to be like this: new = wrealloc(old, new_size);
1. if old is NULL, return wmalloc(new_size).
2. if new_size is 0, call wfree(old), and return NULL.
3. if both old is a valid pointer and new_size>0, call realloc.
- added wstrerror(int errnum) to return the string associated with errnum.
- new wsyserrorwithcode(int error, const char* fmt, ...), similar to
wsyserror(), but printing the message for the specified error code.
- added 3 new classes: WMData, WMHost and WMConnection
- fixed a big memory leak in the color panel code (from Pascal Hofstee).
- added scrolling to tabview
changes since wmaker 0.61.0:
............................
- added WMGetTextFieldFont()
- escape key in panels (craig nellist <crn@ozemail.com.au>)
- applied patch with fixes and enhancements to textfield
(Franck Wolff <wolff@cybercable.fr>)
- changed WMList to use WMBag internally, instead of a linked list
- replaced WMAddSortedListItem() with WMSortListItems()
- replaced WMAddSortedBrowserItem() with WMSortBrowserColumn()
changes since wmaker 0.60.0:
............................
- added WMScreenWidth() and WMScreenHeight() functions.
- fixed some problems when compiling with non gcc compilers.
- added WMSetTextFieldFont()
- added WMSetButtonImageDefault() (craig nellist <crn@ozemail.com.au>)
- added WMBag (array/list)
- added libWUtil, a library that is a subset of libWINGs. It contains utils
that can be used in writing non-GUI programs. They include: hashes,
notifications, input/idle/timer handlers, user defaults database handling,
memory handling, application resource handling, etc.
All the non-GUI stuff from libWINGs is present.
Still linWINGs contain all this stuff so if you use libWINGs, you don't
need to link against libWUtil too.
One notable aspect of libWUtil is that it has a modified version of the
event handling function. It is named WHandleEvents() and will handle all
input/idle/timer events the app has.
If your app has a permanent input handler (as for example a socket a server
is listening on), then the main loop of the app can be:
while(1) {
WHandleEvents();
}
but if there is no permanent input handler, you need to add some delay to
avoid a too high cpu load by your program:
while(1) {
WHandleEvents();
wusleep(5000);
}
A permanent input handler is one that is established when the program starts
and is present until the program exits.
One that is deleted and later reinstalled, is not considered permanent.
This difference is because if there is some input handler, the function will
block until some event appears, while if there is no input handler the
function will return almost immediately (after handling the timer/idle
stuff).
Except the stuff declared in WUtil.h, the following functions declared in
WINGs.h are also present in libWUtil (you will need to #include <WINGs.h>
if you use one of these):
WMInitializeApplication(char *applicationName, int *argc, char **argv);
WMSetResourcePath(char *path);
WMGetApplicationName();
WMPathForResourceOfType(char *resource, char *ext);
WMAddTimerHandler(int milliseconds, WMCallback *callback, void *cdata);
WMDeleteTimerWithClientData(void *cdata);
WMDeleteTimerHandler(WMHandlerID handlerID);
WMAddIdleHandler(WMCallback *callback, void *cdata);
WMDeleteIdleHandler(WMHandlerID handlerID);
WMAddInputHandler(int fd, int condition, WMInputProc *proc,
void *clientData);
WMDeleteInputHandler(WMHandlerID handlerID);
- added progress indicator widget
- Changed WMSetWindowUPosition() and WMSetWindowUSize() to
WMSetWindowInitialPosition() and WMSetWindowInitialSize() respectively,
for better naming conventions.
changes since wmaker 0.53.0:
............................
- added balloon help
- fixed a bug with setting initial path in browsers.
- added WMSetButtonImageDimsWhenDisabled()
- changed simple callback/notifications to delegate-like stuff. Affected
widgets are:
WMBrowser
- WMSetBrowserFillProc() was replaced with WMSetBrowserDelegate
- WMBrowserDidScrollNotification was replaced with a delegate callback
WMTextField (not completed yet)
The notifications will still work, but using the delegate is preferable
How to convert old code to delegate callbacks:
1 - create a variable (static or dynamic) of the type of the
delegate for the widget type.
2 - Replace the notification observers with the equivalent
delegate callbacks.
3 - Put pointers to the callbacks in the delegate variable.
Take a look in wfilepanel.c to see how it is used there.
- changed W_ViewProcedureTable to delegates
This will only affect user created widgets. If you have a custom
widget, you will need to update the callbacks and the declaration
of the W_ViewProcedureTable variable to be a W_ViewDelegate,
which is declared in WINGsP.h To setup the delegate, assign
the delegate variable to view->delegate.
- WMTextField
Removed all the didChange notifications that were sent when the text
was changed programmatically. Only changes made by user interaction
will be notified now. If you need the old behaviour, send notifications
manually when you change the text.
- added WMTabView
- added WMGetColorPanelColor(WMColorPanel *panel)
- made WMGetUDStringForKey() to only return a reference to the string, not a
wstrdup()'ed copy. DO NOT FREE IT ANYMORE!
- added MultiByteText option to userdefaults file to control use of multibyte
string drawing functions
- renamed WMCreateFont() to WMCreateFontSet()
- renamed WMCreateFontInDefaultEncoding() to WMCreateNormalFont()
- added WMCreateFont() with different semantics
changes since wmaker 0.52.0:
............................
- added int WMGetBrowserMaxVisibleColumns(WMBrowser *bPtr);
changes since wmaker 0.51.2:
............................
- added WMColorWellDidChangeNotification
- added wfindfileinarray()
- fixed bug in window title setting
(MANOME Tomonori <manome@itlb.te.noda.sut.ac.jp>)
changes since wmaker 0.51.1:
............................
- wusergnusteppath() will return a statically allocated string now.
DO NOT FREE IT ANYMORE!!
changes since wmaker 0.51.0:
............................
- applied c++ compat header patch from Martynas Kunigelis <mkunigelis@alna.lt>
- added WMSetTextFieldBeveled()
- removed W_GC() : use WMColorGC() instead
- added WMCreatePixmap()
- changed WMSetTextFieldEnabled() to WMSetTextFieldEditable()
changes since wmaker 0.50.1:
............................
- fixed various bugs
- added patch from Franck Wolff <frawolff@club-internet.fr>, with
many fixes and enhancements
- added notification queues, asynchronous notifications etc.
- added WMSetBrowserDoubleAction()
- fixed list double click action
changes since wmaker 0.50.2:
............................
- added wsetabort() - look WUtil.h
- fixed bug in WMList resize
- added notification sending when changing textfield programatically
- removed WMHideWindow()
- fixed bug in WMCloseWindow()
- added textfield selection patch
- added color panel code
- added auto name completion for the file panel
- added function to select text range, and to set cursor position in text
fields programatically
changes since wmaker 0.20.3:
............................
- added WMSetSliderImage(), WMSetSliderKnobThickness()
- added WMGetListItemHeight()
- added WMListDidScrollNotification
- added WSetColorWellBordered()
- added hacky color dragging in colorwell
- added poll() support in WMNextEvent. WARNING: the stuff needed for
WMAddInputHandler() is not yet implemented for the poll stuff
- added WMSetFilePanelAccessoryView(), WMGetFilePanelAccessoryView()
- added WMSetPopUpButtonEnabled()
- added WMGetLabelImage()
- autoscroll for popup button menus
- added WMDrawPixmap()
- WARNING: changed parameter list for WMListDrawProc
changes since wmaker 0.20.2:
............................
- WMSetBrowserMaxVisibleColumns() - untested
changes since wmaker 0.20.0:
............................
- added generic object field for WMListItem. This is for hanging generic
clientdata
changes since wmaker 0.20.0:
............................
- changed WMGetFilePanelFile() with WMGetFilePanelFileName()
- made SavePanel
changes since wmaker 0.19.3:
............................
- added WMCreatePanelForWindow()
- added extra parent parameter for filepanel, alertpanel and inputpanel
- WMCloseWindow()
- WMChangePanelOwner()
- added WMAddInputHandler()
- change range related function arguments (WMTextField) to use WMRange
changes since wmaker 0.19.1:
............................
- added wstrappend()
- fixed bug when changing selected radio button by hand
changes since wmaker 0.18.1:
............................
- removed textHeight arg from W_PaintImageAndText
- added WMCreateWindowWithStyle()
- added WMSetWindowBaseSize() and ResizeIncrements()
- added WMSetWindowLeve()
- added WMSetWindowDocumentEdited()
- added WMSetScrollViewLineScroll(), WMSetScrollViewPageScroll()
- added WMSetWindowMiniwindowTitle()
- added WMSetWindowMiniwindowImage()
changes since wmaker 0.18.0:
............................
- added functions to get RGB components and "#rrggbb" string from WMColor.
- added function to create color from a name
- fixed bug that caused blocking until some new event arrives, even
when there already were events in the queue
(like having to move the pointer over window to force the window to be
painted)
changes since wmaker 0.17.5:
............................
I don't remember everything, but here it goes:
- fixed some bugs in text field
- added a incomplete implementation of split view (not yet usable)
- added a slider
- changed the filepanel stuff. Each application can have only 1 file panel.
The same panel will be reused every time you call for it, unless you free it.
- changed semantics of WMCreateFont() so that it returns NULL if the requested
font can't be loaded
- removed WMAddDestroyCallback()
- fixed bug in WMRemovePopUpButtonItem()
- added function for user specified item height in WMList
- added WMSetPopUpButtonText(). It will set the default text in the button
when no options are selected
- fixed bug in remove/add item in already mapped popupbuttons. Note: it is
not good practice to change the contents of a popup button when it's
already visible and the user has probably interacted with it.
- fixed behaviour of "radio buttons"
- WMInitializeApplication() must be the first function to be called in the
program
- removed applicationName, argc and argv arguments from the WMCreateScree...
functions
- WMReleaseColor(scr,color) changed to WMReleaseColor(color)
- WMPaintColorRectangle() changed to WMPaintColorSwatch()
- added various functions in font and color handling
- added WMSetButtonFont()
- changed WMCreateCommandButton() so that the buttons it creates will change
their label when pushed
- added WMGetSystemPixmap(WMScreen *scr, int image)
- added partial I18N support
- added libPropList requirement and some related utility functions
- added a interface to prooplist, so that it works as a user defaults db
- added WMWidthOfString() (removed WMFontWidthOfString())
- added WMDrawString()
- added WMSetTextFieldSecure(WMTextField *tPtr, Bool flag)
- WMGetListItem() will dup the returned string
- removed need for ProgName being defined
- rewrote hashtable stuff and made it available for outside use
- added notification functions, with view resize notification
- added WMSetWindowMinSize() and MaxSize()
- text editing notification
- added WMSetListPosition() etc.
- added WMInsertBrowserItem()
- the above 2 functions return WMListItem*, instead of Bool
- rewrote browser
- WMGetListItem() will return WMListItem*
- removed WMGetListItems() and WMSetListItems()
- fixed focus stuff for multi-window apps
- changed all WMList function names that contained index to row

View File

@@ -1,6 +0,0 @@
## automake input file for WINGs - Documentation
AUTOMAKE_OPTIONS =
EXTRA_DIST =

View File

@@ -1,21 +0,0 @@
## automake input file for WINGs - Examples
AUTOMAKE_OPTIONS =
noinst_PROGRAMS = fontl puzzle colorpick
LDADD= $(top_builddir)/WINGs/libWINGs.la $(top_builddir)/wrlib/libwraster.la \
$(top_builddir)/WINGs/libWUtil.la \
@XFT_LIBS@ @INTLIBS@ @XLIBS@
colorpick_DEPENDENCIES = $(top_builddir)/WINGs/libWINGs.la
fontl_DEPENDENCIES = $(top_builddir)/WINGs/libWINGs.la
puzzle_DEPENDENCIES = $(top_builddir)/WINGs/libWINGs.la
AM_CPPFLAGS = -I$(top_srcdir)/WINGs -I$(top_srcdir)/wrlib -I$(top_srcdir)/src \
-DRESOURCE_PATH=\"$(datadir)/WINGs\" @HEADER_SEARCH_PATH@

View File

@@ -1,12 +0,0 @@
Files:
-----
colorpick - a color picker
puzzle - a nice zuPzel =)
fontl - a map of all characters with their corresponding ascii,
hex, decimal and octal representations.

View File

@@ -1,40 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
#include <WINGs/WINGs.h>
void showSelectedColor(void *self, void *cdata)
{
WMColorPanel *panel = (WMColorPanel *) self;
(void) cdata;
printf("Selected Color: %s\n", WMGetColorRGBDescription(WMGetColorPanelColor(panel)));
}
int main(int argc, char **argv)
{
Display *dpy;
WMScreen *scr;
WMInitializeApplication("wmcolorpick", &argc, argv);
dpy = XOpenDisplay("");
if (!dpy) {
printf("could not open display\n");
exit(1);
}
scr = WMCreateScreen(dpy, DefaultScreen(dpy));
{
WMColorPanel *panel = WMGetColorPanel(scr);
WMSetColorPanelAction(panel, showSelectedColor, NULL);
WMShowColorPanel(panel);
}
WMScreenMainLoop(scr);
return 0;
}

View File

@@ -1,100 +0,0 @@
/*
* WINGs demo: font lister
*
* Copyright (c) 1998-2003 Alfredo K. Kojima
*
* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <WINGs/WINGs.h>
#include <WINGs/WUtil.h>
#include <inttypes.h>
void wAbort()
{
exit(0);
}
void show(WMWidget * self, void *data)
{
char buf[60];
void *d;
WMLabel *l = (WMLabel *) data;
d = WMGetHangedData(self);
sprintf(buf, "%"PRIiPTR" - 0x%"PRIxPTR" - 0%"PRIoPTR, (intptr_t) d, (intptr_t) d, (intptr_t) d);
WMSetLabelText(l, buf);
}
void quit(WMWidget * self, void *data)
{
(void) self;
(void) data;
exit(0);
}
int main(int argc, char **argv)
{
Display *dpy;
WMWindow *win;
WMScreen *scr;
WMButton *lab, *l0 = NULL;
WMLabel *pos;
int x, y, c;
char buf[20];
WMInitializeApplication("FontView", &argc, argv);
dpy = XOpenDisplay("");
if (!dpy) {
wfatal("cant open display");
exit(0);
}
scr = WMCreateSimpleApplicationScreen(dpy);
win = WMCreateWindow(scr, "main");
WMResizeWidget(win, 20 * 33, 20 + 20 * 9);
WMSetWindowTitle(win, "Font Chars");
WMSetWindowCloseAction(win, quit, NULL);
pos = WMCreateLabel(win);
WMResizeWidget(pos, 20 * 33, 20);
WMMoveWidget(pos, 10, 5);
c = 0;
for (y = 0; y < 8; y++) {
for (x = 0; x < 32; x++, c++) {
lab = WMCreateCustomButton(win, WBBStateLightMask);
WMResizeWidget(lab, 20, 20);
WMMoveWidget(lab, 10 + x * 20, 30 + y * 20);
sprintf(buf, "%c", c);
WMSetButtonText(lab, buf);
WMSetButtonAction(lab, show, pos);
WMHangData(lab, (void *)(uintptr_t) c);
if (c > 0) {
WMGroupButtons(l0, lab);
} else {
l0 = lab;
}
}
}
WMRealizeWidget(win);
WMMapSubwidgets(win);
WMMapWidget(win);
WMScreenMainLoop(scr);
return 0;
}

View File

@@ -1,236 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
#include <WINGs/WINGs.h>
#include <stdint.h>
#define MAX_SIZE 10*10
WMWindow *win;
WMButton *Button[MAX_SIZE];
signed char Map[MAX_SIZE];
int Size = 4;
int MoveCount;
#define MAP(x,y) Map[(x)+(y)*Size]
int WinSize = 120;
Bool CheckWin(void)
{
int i;
for (i = 0; i < Size * Size - 1; i++) {
if (Map[i] != i)
return False;
}
return True;
}
void MoveButton(int button, int x, int y)
{
WMMoveWidget(Button[button], x * (WinSize / Size), y * (WinSize / Size));
}
Bool SlideButton(int button)
{
int x = 0, y = 0, done = 0;
/* locate the button */
for (y = 0; y < Size; y++) {
for (x = 0; x < Size; x++) {
if (MAP(x, y) == button) {
done = 1;
break;
}
}
if (done)
break;
}
if (x > 0 && MAP(x - 1, y) < 0) {
MAP(x, y) = -1;
MoveButton(button, x - 1, y);
MAP(x - 1, y) = button;
} else if (x < Size - 1 && MAP(x + 1, y) < 0) {
MAP(x, y) = -1;
MoveButton(button, x + 1, y);
MAP(x + 1, y) = button;
} else if (y > 0 && MAP(x, y - 1) < 0) {
MAP(x, y) = -1;
MoveButton(button, x, y - 1);
MAP(x, y - 1) = button;
} else if (y < Size - 1 && MAP(x, y + 1) < 0) {
MAP(x, y) = -1;
MoveButton(button, x, y + 1);
MAP(x, y + 1) = button;
} else {
return False;
}
return True;
}
#define SWAP(a,b) {int tmp; tmp=a; a=b; b=tmp;}
void ResetGame(void)
{
int i, x, y, ox, oy;
MoveCount = 0;
for (i = 0; i < Size * Size - 1; i++) {
Map[i] = i;
}
Map[i] = -1;
ox = x = Size - 1;
oy = y = Size - 1;
for (i = 0; i < 1000; i++) {
int ok;
ok = 1;
switch (rand() % 4) {
case 0:
if (x > 0)
x--;
else
ok = 0;
break;
case 2:
if (x < Size - 1)
x++;
else
ok = 0;
break;
case 1:
if (y > 0)
y--;
else
ok = 0;
break;
case 3:
if (y < Size - 1)
y++;
else
ok = 0;
break;
}
if (ok) {
MoveButton(MAP(x, y), ox, oy);
SWAP(MAP(ox, oy), MAP(x, y));
while (XPending(WMScreenDisplay(WMWidgetScreen(win)))) {
XEvent ev;
WMNextEvent(WMScreenDisplay(WMWidgetScreen(win)), &ev);
WMHandleEvent(&ev);
}
ox = x;
oy = y;
}
}
}
void buttonClick(WMWidget * w, void *ptr)
{
char buffer[300];
if (SlideButton((uintptr_t)ptr)) {
MoveCount++;
if (CheckWin()) {
sprintf(buffer, "You finished the game in %i moves.", MoveCount);
if (WMRunAlertPanel(WMWidgetScreen(w), win, "You Won!", buffer,
"Wee!", "Gah! Lemme retry!", NULL) == WAPRDefault) {
exit(0);
}
ResetGame();
}
}
}
static void resizeObserver(void *self, WMNotification * notif)
{
WMSize size = WMGetViewSize(WMWidgetView(win));
int x, y;
(void) self;
(void) notif;
WinSize = size.width;
for (y = 0; y < Size; y++) {
for (x = 0; x < Size; x++) {
if (MAP(x, y) >= 0) {
WMResizeWidget(Button[(int)MAP(x, y)], WinSize / Size, WinSize / Size);
WMMoveWidget(Button[(int)MAP(x, y)], x * (WinSize / Size), y * (WinSize / Size));
}
}
}
}
int main(int argc, char **argv)
{
Display *dpy;
WMScreen *scr;
int x, y, i;
WMInitializeApplication("Puzzle", &argc, argv);
dpy = XOpenDisplay("");
if (!dpy) {
printf("could not open display\n");
exit(1);
}
scr = WMCreateScreen(dpy, DefaultScreen(dpy));
win = WMCreateWindow(scr, "puzzle");
WMResizeWidget(win, WinSize, WinSize);
WMSetWindowTitle(win, "zuPzel");
WMSetWindowMinSize(win, 80, 80);
WMSetWindowAspectRatio(win, 2, 2, 2, 2);
WMSetWindowResizeIncrements(win, Size, Size);
WMSetViewNotifySizeChanges(WMWidgetView(win), True);
WMAddNotificationObserver(resizeObserver, NULL, WMViewSizeDidChangeNotification, WMWidgetView(win));
for (i = y = 0; y < Size && i < Size * Size - 1; y++) {
for (x = 0; x < Size && i < Size * Size - 1; x++) {
char buf[32];
WMColor *color;
RColor col;
RHSVColor hsv;
hsv.hue = i * 360 / (Size * Size - 1);
hsv.saturation = 120;
hsv.value = 200;
RHSVtoRGB(&hsv, &col);
color = WMCreateRGBColor(scr, col.red << 8, col.green << 8, col.blue << 8, False);
MAP(x, y) = i;
Button[i] = WMCreateButton(win, WBTMomentaryLight);
WMSetWidgetBackgroundColor(Button[i], color);
WMReleaseColor(color);
WMSetButtonAction(Button[i], buttonClick, (void *)(uintptr_t) i);
WMResizeWidget(Button[i], WinSize / Size, WinSize / Size);
WMMoveWidget(Button[i], x * (WinSize / Size), y * (WinSize / Size));
sprintf(buf, "%i", i + 1);
WMSetButtonText(Button[i], buf);
WMSetButtonTextAlignment(Button[i], WACenter);
i++;
}
}
WMMapSubwidgets(win);
WMMapWidget(win);
WMRealizeWidget(win);
ResetGame();
WMScreenMainLoop(scr);
return 0;
}

View File

@@ -1,30 +0,0 @@
## automake input file for WINGs
AUTOMAKE_OPTIONS =
# is this a kluge? if so, how should i do it?
includedir = @includedir@/WINGs
include_HEADERS = wtableview.h wtabledelegates.h
lib_LTLIBRARIES = libExtraWINGs.la
noinst_PROGRAMS = tableview
EXTRA_DIST =
libExtraWINGs_la_SOURCES = \
wtableview.c \
wtabledelegates.c \
wtableview.h \
wtabledelegates.h
AM_CPPFLAGS = -I$(top_srcdir)/wrlib -I$(top_srcdir)/WINGs \
-DRESOURCE_PATH=\"$(datadir)/WINGs\" @HEADER_SEARCH_PATH@
LDADD= $(top_builddir)/WINGs/libWINGs.la $(top_builddir)/wrlib/libwraster.la \
$(top_builddir)/WINGs/libWUtil.la \
@XFT_LIBS@ @INTLIBS@ @XLIBS@
tableview_LDADD = wtableview.o wtabledelegates.o $(LDADD)

View File

@@ -1,132 +0,0 @@
#include <WINGs/WINGs.h>
#include <stdio.h>
#include <stdint.h>
#include "wtableview.h"
#include "wtabledelegates.h"
static char *col1[20] = { 0 };
static int col2[20];
static char *options[] = {
"Option1",
"Option2",
"Option3",
"Option4",
"Option5"
};
int numberOfRows(WMTableViewDelegate * self, WMTableView * table)
{
(void) self;
(void) table;
return 20;
}
void *valueForCell(WMTableViewDelegate * self, WMTableColumn * column, int row)
{
(void) self;
/*WMTableView *table = (WMTableView*)WMGetTableColumnTableView(column); */
int i;
if (col1[0] == 0) {
for (i = 0; i < 20; i++) {
char buf[128];
sprintf(buf, "Test row %i", i);
col1[i] = wstrdup(buf);
col2[i] = 0;
}
}
if ((uintptr_t)WMGetTableColumnId(column) == 1)
return col1[row];
else
return (void *)(uintptr_t) col2[row];
}
void setValueForCell(WMTableViewDelegate * self, WMTableColumn * column, int row, void *data)
{
(void) self;
if ((uintptr_t)WMGetTableColumnId(column) == 1)
col1[row] = data;
else
col2[row] = (uintptr_t) data;
}
static WMTableViewDelegate delegate = {
NULL,
numberOfRows,
valueForCell,
setValueForCell
};
void clickedTable(WMWidget * w, void *self)
{
(void) w;
int row = WMGetTableViewClickedRow((WMTableView *) self);
WMEditTableViewRow(self, row);
}
int main(int argc, char **argv)
{
WMScreen *scr;
WMWindow *win;
WMTableView *table;
WMTableColumn *col;
WMTableColumnDelegate *colDeleg;
WMInitializeApplication("test", &argc, argv);
scr = WMOpenScreen(NULL);
XSynchronize(WMScreenDisplay(scr), 1);
win = WMCreateWindow(scr, "eweq");
WMResizeWidget(win, 400, 200);
WMMapWidget(win);
table = WMCreateTableView(win);
WMSetTableViewHasHorizontalScroller(table, 0);
WMSetViewExpandsToParent(WMWidgetView(table), 10, 10, 10, 10);
WMSetTableViewBackgroundColor(table, WMWhiteColor(scr));
/*WMSetTableViewGridColor(table, WMGrayColor(scr)); */
WMSetTableViewHeaderHeight(table, 20);
WMSetTableViewDelegate(table, &delegate);
WMSetTableViewAction(table, clickedTable, table);
colDeleg = WTCreateStringEditorDelegate(table);
col = WMCreateTableColumn("Group");
WMSetTableColumnWidth(col, 180);
WMAddTableViewColumn(table, col);
WMSetTableColumnDelegate(col, colDeleg);
WMSetTableColumnId(col, (void *)1);
colDeleg = WTCreateEnumSelectorDelegate(table);
WTSetEnumSelectorOptions(colDeleg, options, 5);
col = WMCreateTableColumn("Package");
WMSetTableColumnWidth(col, 140);
WMAddTableViewColumn(table, col);
WMSetTableColumnDelegate(col, colDeleg);
WMSetTableColumnId(col, (void *)2);
colDeleg = WTCreateBooleanSwitchDelegate(table);
col = WMCreateTableColumn("Bool");
WMSetTableColumnWidth(col, 50);
WMAddTableViewColumn(table, col);
WMSetTableColumnDelegate(col, colDeleg);
WMSetTableColumnId(col, (void *)2);
WMMapWidget(table);
WMRealizeWidget(win);
WMScreenMainLoop(scr);
return 0;
}

View File

@@ -1,522 +0,0 @@
#include <stdint.h>
#include <WINGs/WINGsP.h>
#include "wtableview.h"
#include "wtabledelegates.h"
typedef struct {
WMTableView *table;
WMFont *font;
GC gc;
GC selGC;
WMColor *textColor;
} StringData;
typedef struct {
WMTableView *table;
GC selGc;
} PixmapData;
typedef struct {
WMTextField *widget;
WMTableView *table;
WMFont *font;
GC gc;
GC selGC;
WMColor *textColor;
} StringEditorData;
typedef struct {
WMPopUpButton *widget;
WMTableView *table;
WMFont *font;
char **options;
int count;
GC gc;
GC selGC;
WMColor *textColor;
} EnumSelectorData;
typedef struct {
WMButton *widget;
WMTableView *table;
Bool state;
GC gc;
GC selGC;
} BooleanSwitchData;
static char *SelectionColor = "#bbbbcc";
static void
stringDraw(WMScreen * scr, Drawable d, GC gc, GC sgc, WMColor * textColor,
WMFont * font, void *data, WMRect rect, Bool selected)
{
int x, y;
XRectangle rects[1];
Display *dpy = WMScreenDisplay(scr);
x = rect.pos.x + 5;
y = rect.pos.y + (rect.size.height - WMFontHeight(font)) / 2;
rects[0].x = rect.pos.x + 1;
rects[0].y = rect.pos.y + 1;
rects[0].width = rect.size.width - 1;
rects[0].height = rect.size.height - 1;
XSetClipRectangles(dpy, gc, 0, 0, rects, 1, YXSorted);
if (!selected) {
XFillRectangles(dpy, d, gc, rects, 1);
WMDrawString(scr, d, textColor, font, x, y, data, strlen(data));
} else {
XFillRectangles(dpy, d, sgc, rects, 1);
WMDrawString(scr, d, textColor, font, x, y, data, strlen(data));
}
XSetClipMask(dpy, gc, None);
}
static void pixmapDraw(WMScreen * scr, Drawable d, GC gc, GC sgc, WMPixmap * pixmap, WMRect rect, Bool selected)
{
int x, y;
XRectangle rects[1];
Display *dpy = WMScreenDisplay(scr);
WMSize size;
rects[0].x = rect.pos.x + 1;
rects[0].y = rect.pos.y + 1;
rects[0].width = rect.size.width - 1;
rects[0].height = rect.size.height - 1;
XSetClipRectangles(dpy, gc, 0, 0, rects, 1, YXSorted);
if (!selected) {
XFillRectangles(dpy, d, gc, rects, 1);
if (pixmap) {
size = WMGetPixmapSize(pixmap);
x = rect.pos.x + (rect.size.width - size.width) / 2;
y = rect.pos.y + (rect.size.height - size.height) / 2;
WMDrawPixmap(pixmap, d, x, y);
}
} else {
XFillRectangles(dpy, d, sgc, rects, 1);
if (pixmap) {
size = WMGetPixmapSize(pixmap);
x = rect.pos.x + (rect.size.width - size.width) / 2;
y = rect.pos.y + (rect.size.height - size.height) / 2;
WMDrawPixmap(pixmap, d, x, y);
}
}
XSetClipMask(dpy, gc, None);
}
/* ---------------------------------------------------------------------- */
static void SECellPainter(WMTableColumnDelegate * self, WMTableColumn * column, int row, Drawable d)
{
StringEditorData *strdata = (StringEditorData *) self->data;
WMTableView *table = WMGetTableColumnTableView(column);
stringDraw(WMWidgetScreen(table), d,
strdata->gc, strdata->selGC, strdata->textColor, strdata->font,
WMTableViewDataForCell(table, column, row), WMTableViewRectForCell(table, column, row), False);
}
static void selectedSECellPainter(WMTableColumnDelegate * self, WMTableColumn * column, int row, Drawable d)
{
StringEditorData *strdata = (StringEditorData *) self->data;
WMTableView *table = WMGetTableColumnTableView(column);
stringDraw(WMWidgetScreen(table), d,
strdata->gc, strdata->selGC, strdata->textColor, strdata->font,
WMTableViewDataForCell(table, column, row), WMTableViewRectForCell(table, column, row), True);
}
static void beginSECellEdit(WMTableColumnDelegate * self, WMTableColumn * column, int row)
{
StringEditorData *strdata = (StringEditorData *) self->data;
WMRect rect = WMTableViewRectForCell(strdata->table, column, row);
void *data = WMTableViewDataForCell(strdata->table, column, row);
WMSetTextFieldText(strdata->widget, (char *)data);
WMMoveWidget(strdata->widget, rect.pos.x, rect.pos.y);
WMResizeWidget(strdata->widget, rect.size.width + 1, rect.size.height + 1);
WMMapWidget(strdata->widget);
}
static void endSECellEdit(WMTableColumnDelegate * self, WMTableColumn * column, int row)
{
StringEditorData *strdata = (StringEditorData *) self->data;
char *text;
WMUnmapWidget(strdata->widget);
text = WMGetTextFieldText(strdata->widget);
WMSetTableViewDataForCell(strdata->table, column, row, (void *)text);
}
WMTableColumnDelegate *WTCreateStringEditorDelegate(WMTableView * parent)
{
WMTableColumnDelegate *delegate = wmalloc(sizeof(WMTableColumnDelegate));
WMScreen *scr = WMWidgetScreen(parent);
StringEditorData *data = wmalloc(sizeof(StringEditorData));
data->widget = WMCreateTextField(parent);
W_ReparentView(WMWidgetView(data->widget), WMGetTableViewDocumentView(parent), 0, 0);
data->table = parent;
data->font = WMSystemFontOfSize(scr, 12);
data->gc = WMColorGC(WMWhiteColor(scr));
data->selGC = WMColorGC(WMCreateNamedColor(scr, SelectionColor, False));
data->textColor = WMBlackColor(scr);
delegate->data = data;
delegate->drawCell = SECellPainter;
delegate->drawSelectedCell = selectedSECellPainter;
delegate->beginCellEdit = beginSECellEdit;
delegate->endCellEdit = endSECellEdit;
return delegate;
}
/* ---------------------------------------------------------------------- */
static void ESCellPainter(WMTableColumnDelegate * self, WMTableColumn * column, int row, Drawable d)
{
EnumSelectorData *strdata = (EnumSelectorData *) self->data;
WMTableView *table = WMGetTableColumnTableView(column);
uintptr_t i = (uintptr_t)WMTableViewDataForCell(table, column, row);
stringDraw(WMWidgetScreen(table), d,
strdata->gc, strdata->selGC, strdata->textColor, strdata->font,
strdata->options[i], WMTableViewRectForCell(table, column, row), False);
}
static void selectedESCellPainter(WMTableColumnDelegate * self, WMTableColumn * column, int row, Drawable d)
{
EnumSelectorData *strdata = (EnumSelectorData *) self->data;
WMTableView *table = WMGetTableColumnTableView(column);
uintptr_t i = (uintptr_t)WMTableViewDataForCell(table, column, row);
stringDraw(WMWidgetScreen(table), d,
strdata->gc, strdata->selGC, strdata->textColor, strdata->font,
strdata->options[i], WMTableViewRectForCell(table, column, row), True);
}
static void beginESCellEdit(WMTableColumnDelegate * self, WMTableColumn * column, int row)
{
EnumSelectorData *strdata = (EnumSelectorData *) self->data;
WMRect rect = WMTableViewRectForCell(strdata->table, column, row);
uintptr_t data = (uintptr_t)WMTableViewDataForCell(strdata->table, column, row);
wassertr(data < strdata->count);
WMSetPopUpButtonSelectedItem(strdata->widget, data);
WMMoveWidget(strdata->widget, rect.pos.x, rect.pos.y);
WMResizeWidget(strdata->widget, rect.size.width, rect.size.height + 1);
WMMapWidget(strdata->widget);
}
static void endESCellEdit(WMTableColumnDelegate * self, WMTableColumn * column, int row)
{
EnumSelectorData *strdata = (EnumSelectorData *) self->data;
int option;
WMUnmapWidget(strdata->widget);
option = WMGetPopUpButtonSelectedItem(strdata->widget);
WMSetTableViewDataForCell(strdata->table, column, row, (void *)(uintptr_t) option);
}
WMTableColumnDelegate *WTCreateEnumSelectorDelegate(WMTableView * parent)
{
WMTableColumnDelegate *delegate = wmalloc(sizeof(WMTableColumnDelegate));
WMScreen *scr = WMWidgetScreen(parent);
EnumSelectorData *data = wmalloc(sizeof(EnumSelectorData));
data->widget = WMCreatePopUpButton(parent);
W_ReparentView(WMWidgetView(data->widget), WMGetTableViewDocumentView(parent), 0, 0);
data->table = parent;
data->font = WMSystemFontOfSize(scr, 12);
data->gc = WMColorGC(WMWhiteColor(scr));
data->selGC = WMColorGC(WMCreateNamedColor(scr, SelectionColor, False));
data->textColor = WMBlackColor(scr);
data->count = 0;
data->options = NULL;
delegate->data = data;
delegate->drawCell = ESCellPainter;
delegate->drawSelectedCell = selectedESCellPainter;
delegate->beginCellEdit = beginESCellEdit;
delegate->endCellEdit = endESCellEdit;
return delegate;
}
void WTSetEnumSelectorOptions(WMTableColumnDelegate * delegate, char **options, int count)
{
EnumSelectorData *data = (EnumSelectorData *) delegate->data;
int i;
for (i = 0; i < WMGetPopUpButtonNumberOfItems(data->widget); i++) {
WMRemovePopUpButtonItem(data->widget, 0);
}
data->options = options;
data->count = count;
for (i = 0; i < count; i++) {
WMAddPopUpButtonItem(data->widget, options[i]);
}
}
/* ---------------------------------------------------------------------- */
static void BSCellPainter(WMTableColumnDelegate * self, WMTableColumn * column, int row, Drawable d)
{
BooleanSwitchData *strdata = (BooleanSwitchData *) self->data;
WMTableView *table = WMGetTableColumnTableView(column);
uintptr_t i = (uintptr_t)WMTableViewDataForCell(table, column, row);
WMScreen *scr = WMWidgetScreen(table);
if (i) {
pixmapDraw(scr, d,
strdata->gc, strdata->selGC, WMGetSystemPixmap(scr, WSICheckMark),
WMTableViewRectForCell(table, column, row), False);
} else {
pixmapDraw(scr, d,
strdata->gc, strdata->selGC, NULL, WMTableViewRectForCell(table, column, row), False);
}
}
static void selectedBSCellPainter(WMTableColumnDelegate * self, WMTableColumn * column, int row, Drawable d)
{
BooleanSwitchData *strdata = (BooleanSwitchData *) self->data;
WMTableView *table = WMGetTableColumnTableView(column);
uintptr_t i = (uintptr_t)WMTableViewDataForCell(table, column, row);
WMScreen *scr = WMWidgetScreen(table);
if (i) {
pixmapDraw(scr, d,
strdata->gc, strdata->selGC, WMGetSystemPixmap(scr, WSICheckMark),
WMTableViewRectForCell(table, column, row), True);
} else {
pixmapDraw(scr, d,
strdata->gc, strdata->selGC, NULL, WMTableViewRectForCell(table, column, row), True);
}
}
static void beginBSCellEdit(WMTableColumnDelegate * self, WMTableColumn * column, int row)
{
BooleanSwitchData *strdata = (BooleanSwitchData *) self->data;
WMRect rect = WMTableViewRectForCell(strdata->table, column, row);
uintptr_t data = (uintptr_t)WMTableViewDataForCell(strdata->table, column, row);
WMSetButtonSelected(strdata->widget, data);
WMMoveWidget(strdata->widget, rect.pos.x + 1, rect.pos.y + 1);
WMResizeWidget(strdata->widget, rect.size.width - 1, rect.size.height - 1);
WMMapWidget(strdata->widget);
}
static void endBSCellEdit(WMTableColumnDelegate * self, WMTableColumn * column, int row)
{
BooleanSwitchData *strdata = (BooleanSwitchData *) self->data;
int value;
value = WMGetButtonSelected(strdata->widget);
WMSetTableViewDataForCell(strdata->table, column, row, (void *)(uintptr_t) value);
WMUnmapWidget(strdata->widget);
}
WMTableColumnDelegate *WTCreateBooleanSwitchDelegate(WMTableView * parent)
{
WMTableColumnDelegate *delegate = wmalloc(sizeof(WMTableColumnDelegate));
WMScreen *scr = WMWidgetScreen(parent);
BooleanSwitchData *data = wmalloc(sizeof(BooleanSwitchData));
WMColor *color;
data->widget = WMCreateSwitchButton(parent);
W_ReparentView(WMWidgetView(data->widget), WMGetTableViewDocumentView(parent), 0, 0);
WMSetButtonText(data->widget, NULL);
WMSetButtonImagePosition(data->widget, WIPImageOnly);
WMSetButtonImage(data->widget, NULL);
WMSetButtonAltImage(data->widget, WMGetSystemPixmap(scr, WSICheckMark));
data->table = parent;
color = WMCreateNamedColor(scr, SelectionColor, False);
WMSetWidgetBackgroundColor(data->widget, color);
data->gc = WMColorGC(WMWhiteColor(scr));
data->selGC = WMColorGC(color);
delegate->data = data;
delegate->drawCell = BSCellPainter;
delegate->drawSelectedCell = selectedBSCellPainter;
delegate->beginCellEdit = beginBSCellEdit;
delegate->endCellEdit = endBSCellEdit;
return delegate;
}
/* ---------------------------------------------------------------------- */
static void SCellPainter(WMTableColumnDelegate * self, WMTableColumn * column, int row, Drawable d)
{
StringData *strdata = (StringData *) self->data;
WMTableView *table = WMGetTableColumnTableView(column);
stringDraw(WMWidgetScreen(table), d,
strdata->gc, strdata->selGC, strdata->textColor, strdata->font,
WMTableViewDataForCell(table, column, row), WMTableViewRectForCell(table, column, row), False);
}
static void selectedSCellPainter(WMTableColumnDelegate * self, WMTableColumn * column, int row, Drawable d)
{
StringData *strdata = (StringData *) self->data;
WMTableView *table = WMGetTableColumnTableView(column);
stringDraw(WMWidgetScreen(table), d,
strdata->gc, strdata->selGC, strdata->textColor, strdata->font,
WMTableViewDataForCell(table, column, row), WMTableViewRectForCell(table, column, row), True);
}
WMTableColumnDelegate *WTCreateStringDelegate(WMTableView * parent)
{
WMTableColumnDelegate *delegate = wmalloc(sizeof(WMTableColumnDelegate));
WMScreen *scr = WMWidgetScreen(parent);
StringData *data = wmalloc(sizeof(StringData));
data->table = parent;
data->font = WMSystemFontOfSize(scr, 12);
data->gc = WMColorGC(WMWhiteColor(scr));
data->selGC = WMColorGC(WMCreateNamedColor(scr, SelectionColor, False));
data->textColor = WMBlackColor(scr);
delegate->data = data;
delegate->drawCell = SCellPainter;
delegate->drawSelectedCell = selectedSCellPainter;
delegate->beginCellEdit = NULL;
delegate->endCellEdit = NULL;
return delegate;
}
/* ---------------------------------------------------------------------- */
static void PCellPainter(WMTableColumnDelegate * self, WMTableColumn * column, int row, Drawable d)
{
StringData *strdata = (StringData *) self->data;
WMTableView *table = WMGetTableColumnTableView(column);
pixmapDraw(WMWidgetScreen(table), d,
strdata->gc, strdata->selGC,
(WMPixmap *) WMTableViewDataForCell(table, column, row),
WMTableViewRectForCell(table, column, row), False);
}
static void selectedPCellPainter(WMTableColumnDelegate * self, WMTableColumn * column, int row, Drawable d)
{
StringData *strdata = (StringData *) self->data;
WMTableView *table = WMGetTableColumnTableView(column);
pixmapDraw(WMWidgetScreen(table), d,
strdata->gc, strdata->selGC,
(WMPixmap *) WMTableViewDataForCell(table, column, row),
WMTableViewRectForCell(table, column, row), True);
}
WMTableColumnDelegate *WTCreatePixmapDelegate(WMTableView * table)
{
WMTableColumnDelegate *delegate = wmalloc(sizeof(WMTableColumnDelegate));
WMScreen *scr = WMWidgetScreen(table);
StringData *data = wmalloc(sizeof(StringData));
data->table = table;
data->gc = WMColorGC(WMWhiteColor(scr));
data->selGC = WMColorGC(WMCreateNamedColor(scr, SelectionColor, False));
delegate->data = data;
delegate->drawCell = PCellPainter;
delegate->drawSelectedCell = selectedPCellPainter;
delegate->beginCellEdit = NULL;
delegate->endCellEdit = NULL;
return delegate;
}
/* ---------------------------------------------------------------------- */
static void drawPSCell(WMTableColumnDelegate * self, Drawable d, WMTableColumn * column, int row, Bool selected)
{
StringData *strdata = (StringData *) self->data;
WMTableView *table = WMGetTableColumnTableView(column);
void **data;
WMPixmap *pix;
char *str;
WMRect rect;
WMSize size;
data = WMTableViewDataForCell(table, column, row);
str = (char *)data[0];
pix = (WMPixmap *) data[1];
rect = WMTableViewRectForCell(table, column, row);
if (pix) {
int owidth = rect.size.width;
size = WMGetPixmapSize(pix);
rect.size.width = size.width;
pixmapDraw(WMWidgetScreen(table),
WMViewXID(WMGetTableViewDocumentView(table)),
strdata->gc, strdata->selGC, pix, rect, selected);
rect.pos.x += size.width - 1;
rect.size.width = owidth - size.width + 1;
}
stringDraw(WMWidgetScreen(table), d, strdata->gc, strdata->selGC,
strdata->textColor, strdata->font, str, rect, selected);
}
static void PSCellPainter(WMTableColumnDelegate * self, WMTableColumn * column, int row, Drawable d)
{
drawPSCell(self, d, column, row, False);
}
static void selectedPSCellPainter(WMTableColumnDelegate * self, WMTableColumn * column, int row, Drawable d)
{
drawPSCell(self, d, column, row, True);
}
WMTableColumnDelegate *WTCreatePixmapStringDelegate(WMTableView * parent)
{
WMTableColumnDelegate *delegate = wmalloc(sizeof(WMTableColumnDelegate));
WMScreen *scr = WMWidgetScreen(parent);
StringData *data = wmalloc(sizeof(StringData));
data->table = parent;
data->font = WMSystemFontOfSize(scr, 12);
data->gc = WMColorGC(WMWhiteColor(scr));
data->selGC = WMColorGC(WMCreateNamedColor(scr, SelectionColor, False));
data->textColor = WMBlackColor(scr);
delegate->data = data;
delegate->drawCell = PSCellPainter;
delegate->drawSelectedCell = selectedPSCellPainter;
delegate->beginCellEdit = NULL;
delegate->endCellEdit = NULL;
return delegate;
}

View File

@@ -1,25 +0,0 @@
#ifndef _TABLEDELEGATES_H_
#define _TABLEDELEGATES_H_
#ifdef __cplusplus
extern "C" {
#endif
WMTableColumnDelegate *WTCreatePixmapDelegate(WMTableView *table);
WMTableColumnDelegate *WTCreateStringDelegate(WMTableView *table);
WMTableColumnDelegate *WTCreatePixmapStringDelegate(WMTableView *parent);
WMTableColumnDelegate *WTCreateStringEditorDelegate(WMTableView *table);
WMTableColumnDelegate *WTCreateEnumSelectorDelegate(WMTableView *table);
void WTSetEnumSelectorOptions(WMTableColumnDelegate *delegate,
char **options, int count);
WMTableColumnDelegate *WTCreateBooleanSwitchDelegate(WMTableView *parent);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,121 +0,0 @@
#ifndef _WTABLEVIEW_H_
#define _WTABLEVIEW_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef struct W_TableColumn WMTableColumn;
typedef struct W_TableView WMTableView;
extern const char *WMTableViewSelectionDidChangeNotification;
typedef struct WMTableColumnDelegate {
void *data;
void (*drawCell)(struct WMTableColumnDelegate *self,
WMTableColumn *column, int row, Drawable d);
void (*drawSelectedCell)(struct WMTableColumnDelegate *self,
WMTableColumn *column, int row, Drawable d);
void (*beginCellEdit)(struct WMTableColumnDelegate *self, WMTableColumn *column,
int row);
void (*endCellEdit)(struct WMTableColumnDelegate *self, WMTableColumn *column,
int row);
} WMTableColumnDelegate;
typedef struct W_TableViewDelegate {
void *data;
int (*numberOfRows)(struct W_TableViewDelegate *self,
WMTableView *table);
void *(*valueForCell)(struct W_TableViewDelegate *self,
WMTableColumn *column, int row);
void (*setValueForCell)(struct W_TableViewDelegate *self,
WMTableColumn *column, int row, void *value);
} WMTableViewDelegate;
WMTableColumn *WMCreateTableColumn(char *title);
void WMSetTableColumnWidth(WMTableColumn *column, unsigned width);
void WMSetTableColumnConstraints(WMTableColumn *column,
unsigned minWidth, unsigned maxWidth);
void WMSetTableColumnDelegate(WMTableColumn *column,
WMTableColumnDelegate *delegate);
WMTableView *WMGetTableColumnTableView(WMTableColumn *column);
void WMSetTableColumnId(WMTableColumn *column, void *id);
void *WMGetTableColumnId(WMTableColumn *column);
WMTableView *WMCreateTableView(WMWidget *parent);
void WMSetTableViewDataSource(WMTableView *table, void *source);
void *WMGetTableViewDataSource(WMTableView *table);
void WMSetTableViewHeaderHeight(WMTableView *table, unsigned height);
void WMAddTableViewColumn(WMTableView *table, WMTableColumn *column);
void WMSetTableViewDelegate(WMTableView *table, WMTableViewDelegate *delegate);
void WMSetTableViewAction(WMTableView *table, WMAction *action,
void *clientData);
void *WMGetTableViewClickedColumn(WMTableView *table);
int WMGetTableViewClickedRow(WMTableView *table);
WMArray *WMGetTableViewSelectedRows(WMTableView *table);
WMView *WMGetTableViewDocumentView(WMTableView *table);
void WMEditTableViewRow(WMTableView *table, int row);
void WMSelectTableViewRow(WMTableView *table, int row);
void *WMTableViewDataForCell(WMTableView *table, WMTableColumn *column,
int row);
void WMSetTableViewDataForCell(WMTableView *table, WMTableColumn *column,
int row, void *data);
WMRect WMTableViewRectForCell(WMTableView *table, WMTableColumn *column,
int row);
void WMSetTableViewBackgroundColor(WMTableView *table, WMColor *color);
void WMSetTableViewGridColor(WMTableView *table, WMColor *color);
void WMSetTableViewRowHeight(WMTableView *table, int height);
void WMReloadTableView(WMTableView *table);
void WMNoteTableViewNumberOfRowsChanged(WMTableView *table);
void WMScrollTableViewRowToVisible(WMTableView *table, int row);
void WMSetTableViewHasHorizontalScroller(WMTableView *tPtr, Bool flag);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,119 +0,0 @@
## automake input file for WINGs
AUTOMAKE_OPTIONS =
SUBDIRS = WINGs . po Documentation Resources
DIST_SUBDIRS = $(SUBDIRS) Tests Examples Extras
libWINGs_la_LDFLAGS = -version-info @WINGS_VERSION@
libWUtil_la_LDFLAGS = -version-info @WUTIL_VERSION@
lib_LTLIBRARIES = libWUtil.la libWINGs.la
LDADD= libWUtil.la libWINGs.la $(top_builddir)/wrlib/libwraster.la @INTLIBS@
libWINGs_la_LIBADD = libWUtil.la $(top_builddir)/wrlib/libwraster.la @XLIBS@ @XFT_LIBS@ @FCLIBS@ @LIBM@ @PANGO_LIBS@
libWUtil_la_LIBADD = @LIBBSD@
EXTRA_DIST = BUGS make-rgb Examples Extras Tests
# wbutton.c
libWINGs_la_SOURCES = \
configuration.c \
dragcommon.c \
dragdestination.c \
dragsource.c \
rgb.h \
selection.c \
wappresource.c \
wballoon.c \
wbox.c \
wbrowser.c \
wbutton.c \
wcolor.c \
wcolorpanel.c \
wcolorwell.c \
wconfig.h \
wevent.c \
wfilepanel.c \
wframe.c \
wfont.c \
wfontpanel.c \
widgets.c \
winputmethod.c \
wlabel.c \
wlist.c \
wmenuitem.c \
wmisc.c \
wpanel.c \
wpixmap.c \
wpopupbutton.c \
wprogressindicator.c \
wruler.c \
wscroller.c \
wscrollview.c \
wslider.c \
wsplitview.c \
wtabview.c \
wtext.c \
wtextfield.c \
wview.c \
wwindow.c
libWUtil_la_SOURCES = \
array.c \
bagtree.c \
data.c \
error.c \
error.h \
findfile.c \
handlers.c \
hashtable.c \
memory.c \
menuparser.c \
menuparser.h \
menuparser_macros.c \
misc.c \
notification.c \
proplist.c \
string.c \
tree.c \
userdefaults.c \
userdefaults.h \
usleep.c \
wapplication.c \
wconfig.h \
wutil.c
AM_CFLAGS = @PANGO_CFLAGS@
AM_CPPFLAGS = -DRESOURCE_PATH=\"$(datadir)/WINGs\" \
-I$(top_srcdir)/WINGs/WINGs -I$(top_builddir)/WINGs/WINGs \
-I$(top_builddir)/wrlib -I$(top_srcdir)/src \
@XFT_CFLAGS@ @HEADER_SEARCH_PATH@
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = WINGs.pc WUtil.pc
DISTCLEANFILES = $(pkgconfig_DATA)
WINGs.pc: Makefile
@echo "Generating $@"
@echo 'Name: WINGs' > $@
@echo 'Description: Small widget set with the NeXTStep(TM) look and feel' >> $@
@echo 'Version: $(VERSION)' >> $@
@echo 'Requires: wrlib WUtil' >> $@
@echo 'Libs: $(lib_search_path) -lWINGs' >> $@
@echo 'Libs.private: $(XFT_LIBS) $(PANGOLIBS) $(XLIBS) -lm $(INTLIBS)' >> $@
@echo 'Cflags: $(inc_search_path) @PANGO_CFLAGS@' >> $@
WUtil.pc: Makefile
@echo "Generating $@"
@echo 'Name: WUtil' > $@
@echo 'Description: Utility library for WINGs' >> $@
@echo 'Version: $(VERSION)' >> $@
@echo 'Libs: -L$(libdir) -lWUtil' >> $@
@echo 'Libs.private: $(INTLIBS)' >> $@
@echo 'Cflags: -I$(includedir)' >> $@

View File

@@ -1,514 +0,0 @@
** API and ABI modifications since wmaker 0.96.0
----------------------------------------------------
** libWINGs **
<WINGsP.h>
W_KeycodeToKeysym ADDED
struct W_DragDestinationInfo: new members added SIZE CHANGE
<WINGs.h>
WMGetTextFieldCursorPosition ADDED
WC_Matrix REMOVED from enum.
WMCreateProgressIndicator REMOVED
WMSetProgressIndicatorMinValue REMOVED
WMSetProgressIndicatorMaxValue REMOVED
WMSetProgressIndicatorValue REMOVED
WMGetProgressIndicatorMinValue REMOVED
WMGetProgressIndicatorMaxValue REMOVED
WMGetProgressIndicatorValue REMOVED
typedef struct W_Ruler WMRuler REMOVED
typedef struct WMRulerMargins REMOVED
WMAppendTextBlock REMOVED
WMAppendTextStream REMOVED
WMCreateRuler REMOVED
WMCreateTextBlockWithObject REMOVED
WMCreateTextBlockWithPixmap REMOVED
WMCreateTextBlockWithText REMOVED
WMCreateTextForDocumentType REMOVED
WMDestroyTextBlock REMOVED
WMFindInTextStream REMOVED
WMFreezeText REMOVED
WMGetGrabbedRulerMargin REMOVED
WMGetReleasedRulerMargin REMOVED
WMGetRulerMargins REMOVED
WMGetRulerOffset REMOVED
WMGetTextBlockProperties REMOVED
WMGetTextDefaultColor REMOVED
WMGetTextDefaultFont REMOVED
WMGetTextEditable REMOVED
WMGetTextIgnoresNewline REMOVED
WMGetTextInsertType REMOVED
WMGetTextObjects REMOVED
WMGetTextRulerShown REMOVED
WMGetTextSelectedObjects REMOVED
WMGetTextSelectedStream REMOVED
WMGetTextSelectionColor REMOVED
WMGetTextSelectionFont REMOVED
WMGetTextSelectionUnderlined REMOVED
WMGetTextStream REMOVED
WMGetTextUsesMonoFont REMOVED
WMIsMarginEqualToMargin REMOVED
WMPageText REMOVED
WMPrependTextBlock REMOVED
WMPrependTextStream REMOVED
WMRemoveTextBlock REMOVED
WMReplaceTextSelection REMOVED
WMScrollText REMOVED
WMSetRulerMargins REMOVED
WMSetRulerMoveAction REMOVED
WMSetRulerOffset REMOVED
WMSetRulerReleaseAction REMOVED
WMSetTextAlignment REMOVED
WMSetTextBackgroundColor REMOVED
WMSetTextBackgroundPixmap REMOVED
WMSetTextBlockProperties REMOVED
WMSetTextDefaultColor REMOVED
WMSetTextDefaultFont REMOVED
WMSetTextDelegate REMOVED
WMSetTextEditable REMOVED
WMSetTextForegroundColor REMOVED
WMSetTextHasHorizontalScroller REMOVED
WMSetTextHasRuler REMOVED
WMSetTextHasVerticalScroller REMOVED
WMSetTextIgnoresNewline REMOVED
WMSetTextIndentNewLines REMOVED
WMSetTextRelief REMOVED
WMSetTextSelectionColor REMOVED
WMSetTextSelectionFont REMOVED
WMSetTextSelectionUnderlined REMOVED
WMSetTextUsesMonoFont REMOVED
WMShowTextRuler REMOVED
WMThawText REMOVED
WMRefreshText REMOVED
WMCreateText REMOVED
WMClearText REMOVED
** libWutil **
enum WMConnectionState REMOVED
enum WMConnectionTimeoutState REMOVED
struct ConnectionDelegate REMOVED
__wmessage ADDED
wstrerror REMOVED
wmessage converted from function to wrapper macro
wwarning converted from function to wrapper macro
wfatal converted from function to wrapper macro
wsyserror converted from function to wrapper macro
wsyserror REMOVED (use werror instead)
werror macro ADDED (replaces wsyserror)
wsyserrorwithcode removed
wmkdirhier ADDED
wrmdirhier ADDED
wmalloc0 REMOVED
wnew REMOVED
wnew0 REMOVED
wstrlcpy ADDED
wstrlcat ADDED
WMPushInArray REMOVED
WMWritePropListToFile NUMBER OF FUNCTION ARGUMENTS CHANGED
WMGetCurrentHost
WMGetHostWithName
WMGetHostWithAddress
WMRetainHost
WMReleaseHost
WMSetHostCacheEnabled
WMIsHostCacheEnabled
WMFlushHostCache
WMIsHostEqualToHost
WMGetHostName
WMGetHostNames
WMGetHostAddress
WMCreateConnectionAsServerAtAddress REMOVED
WMCreateConnectionToAddress REMOVED
WMCreateConnectionToAddressAndNotify REMOVED
WMCloseConnection REMOVED
WMDestroyConnection REMOVED
WMConnection* WMAcceptConnection REMOVED
WMGetConnectionAvailableData REMOVED
WMSendConnectionData REMOVED
WMEnqueueConnectionData REMOVED
WMFlushConnection REMOVED
WMSetConnectionDelegate REMOVED
WMGetConnectionService REMOVED
WMGetConnectionProtocol REMOVED
WMSetConnectionNonBlocking REMOVED
WMSetConnectionCloseOnExec REMOVED
WMSetConnectionShutdownOnClose REMOVED
WMGetConnectionClientData REMOVED
WMSetConnectionClientData REMOVED
WMGetConnectionFlags REMOVED
WMSetConnectionFlags REMOVED
WMGetConnectionSocket REMOVED
WMGetConnectionState REMOVED
WMGetConnectionTimeoutState REMOVED
WMGetConnectionUnsentData REMOVED
WMGetConnectionQueuedData REMOVED
WMSetConnectionDefaultTimeout REMOVED
WMSetConnectionOpenTimeout REMOVED
WMSetConnectionSendTimeout REMOVED
WMTreeWalkProc ADDED
WMTreeWalk ADDED
wshellquote ADDED
----------------------------------------------------
*** Fri May 15 18:44:50 CEST 2015 - Christophe
New Tri-state type for WMButton
-------------------------------
A new check-box type button is available with state On/Off/Tri, the later being
generally used to express "leave as-is". The states are cycled through as user
click on the button. It is created with:
btn = WMCreateButton(parent_widget, WBTTriState);
There are is this case 3 possible values for WMSetButtonSelected/WMGetButtonSelected:
- 0 and 1, the legacy checked/unchecked states
- the new -1, when in the 3rd state
*** Sun Dec 7 10:52:21 CET 2014 - David
Support for pixmap in the background of Widget
----------------------------------------------
The new function WMSetWidgetBackgroundPixmap was introduced to specify a pixmap
that will be displayed as the background of a widget instead of the usual plain
color. The dual WMGetWidgetBackgroundPixmap is provided too.
*** Sun Nov 2 13:04:14 CET 2014 - David
Get the text of a button
------------------------
It was assumed that there was no need to retrieve the text from a button because
it is generally a static constant text, but there are some cases where this can
be useful, so the new function WMGetButtonText was added to the API.
*** Thu May 9 18:24:03 CEST 2013 - Christophe
Const-correctness API changes for WRaster, WUtils and WINGs
-----------------------------------------------------------
The 3 libraries have been modified to include appropriate 'const' qualifier
to the function parameters that are treated as such. This should provide
some hints to the compiler for better optimisation.
This change should have no impact on the binary interface, and will not
impact existing source code.
There is one exception however:
WUtil: wusergnusteppath()
This function now returns 'const char *' because its result must *not* be
modified, so it may generate a const related warning in old code.
*** Fri Mar 7 00:39:28 CET 2014 - David
New function WMCreateScaledBlendedPixmapFromFile
------------------------------------------------
This function can load an image from a file and if it is bigger than the
specified width/height then it will be scaled down to fit the size while
keeping the aspect ratio of the original image.
*** Mon Oct 14 19:42:42 EEST 2002 - Dan
Double buffering
----------------
To avoid flickering caused by redrawing the widgets on Expose events, a
double buffering technique was implemented for most of the widgets.
This flickering effect has gotten more visible with the introduction
of antialiased fonts. If with normal text one can redraw the text over the
old one over and over again without any degradation of the text (new pixels
simply overwrite old pixels), with antialiased text the situation is
different and text gets quickly corrupted. To avoid this corruption, one
needs to first erase the area where the text will go, which can cause the
before mentioned flickering.
The double buffer is implemented to solve this issue.
This is a change that that will be automatically available for any WINGs
applications and will require no change in the existing code.
However there is an exception from this in case of WMList if you delegate
the drawing of items to userspace (read below for the complete details).
*** Mon Oct 14 22:07:42 EEST 2002 - Dan
WMList change
-------------
In case of WMList there is the possibility to delegate the drawing of the
list items to the application that is linked with WINGs, and this code will
not be inside the WINGs library, but in userland. Since we use the double
buffering technique in this case too (to allow all widgets based on WMList
and the ones that draw their list items by themselves to benefit from the
double buffering advantage automatically), we no longer pass the window to
the user code doing item drawing, but instead pass this pixmap in which we
draw before copying to the real window.
Since one cannot use XClearWindow() or XClearArea() on pixmaps, but only on
windows, if the code drawing list items used to call these functions to clear
the item area before drawing it needs to change to using XFillRectangle()
instead.
With this change it also means that there is no longer any need to do any
double buffering in the user code, since it's already done by WINGs.
*** Mon Oct 14 19:28:35 EEST 2002 - Dan
API change
----------
WMDrawString() and WMDrawImageString() no longer take a GC as argument.
Instead WMDrawString() takes a WMColor* as the color for the string to be
drawn, while WMDrawImageString() takes 2 WMColor* arguments in place of the
old GC: first for text color and second for background color.
This change is required to support extending WMFont to allow it to handle
antialiased fonts through the XFree86 Xft2 extension.
This also has the advantage of hiding low level X11 details and use WINGs
internal objects instead.
To fix your old code to work with the new WINGs API you need to replace the
GC passed to WMDraw***String() in your code with a WMColor*.
Most of the old code used to be like this:
WMDrawString(screen, window, WMColorGC(color), font, x, y, txt, len);
for the new API it should be replaced by:
WMDrawString(screen, window, color, font, x, y, txt, len);
However if you used a particular GC created by yourself to suit your special
needs, you need to pass a color which is the same as the foreground color of
that gc.
For WMDrawImageString(), from:
WMDrawImageString(screen, window, gc, font, x, y, txt, len);
becomes
WMDrawImageString(screen, window, textColor, backColor, font, x, y, txt, len);
where textColor and backColor are declared like:
WMColor *textColor, *backColor;
and have the color of the foreground respective the background of the old gc.
*** Wed Oct 9 07:10:04 EEST 2002 - Dan
Antialiased font support
------------------------
With the addition of Xft2 support in the WINGs library, now WINGs can display
antialiased text with TrueType or any scalable fonts.
Antialiased text is enabled by default, but can be disabled by adding
AntialiasedText = NO; in ~/GNUstep/Defaults/WMGLOBAL
This will disable antialiased text for any WINGs based application. If you
only want to disable them for a specific application only, like WindowMaker
for example, then add the same option in the applications configuration file,
in this case ~/GNUstep/Defaults/WindowMaker
Note that bitmapped fonts look much better than TrueType when antialiasing is
disabled.
*** Mon Sep 09 06:58:30 EEST 2002 - Dan
New delegate for the WMConnection class
---------------------------------------
ConnectionDelegate structure has a new member: canResumeSending.
The purpose of this callback is to notify you that you can resume sending
data over a WMConnection.
It works in the following manner:
WMSendConnectionData() can return 3 values: -1, 0, 1
-1 - means that the connection has died. you should stop sending data and
close the connection ASAP.
1 - means that the data was successfully sent
0 - means that the data (or part of it) was not sent. however, it was saved
in a queue and the library will try to send it later when possible.
if the return value is 1, you can continue to send the next message, and so
on, until the return value of such a send call will be 0.
After it returns 0 you can continue sending, however, the data will not be
sent over the connection because the operating system cannot accept any more
data for the moment. Instead it will be queued inside the library, making your
program's memory footprint increase. If the amount of data you need to
send is limited and not too big, this shouldn't be a problem, because your
data will be queued and sent when the operating system will notify the
library that sending is possible again.
If this is the case you can just ignore the output of WMSendConnectionData()
and not set a callback for canResumeSending.
However, if the amount of data you have to send is undetermined and you
also want to keep a small memory footprint for your program (so that it
won't grow until it uses all your available memory ;) ), you will have to
stop sending data over the connection as soon as WMSendConnectionData()
returns with 0. Then you should somehow mark this situation in your program
to avoid it trying to send anymore data until notified that it can resume.
(You should have also set a canResumeSending callback when you initialized
your WMConnection object because else you cannot be notified when to resume.)
Now, when you receive such a 0 from the send operation, your last sent data
is put in a queue inside the library. At a later time when the operating
system notifies the library that sending is possible again, the library will
resume to send the data that is saved in the queue. After it will be able to
send all the data in the queue, the canResumeSending callback will be
called, letting you know that not only you can resume sending because the
operating system is again able to send data, but also that the queue was
completely flushed.
From the canResumeSending callback, you should again update the status of
your program marking that it can send again, and then resume sending the
data from where you were left.
*** Thu Oct 04 06:00:09 EEST 2001 -Dan
Property lists handling code
----------------------------
Code to handle property lists was added to WINGs. It is more robust
than the libPropList code, mostly because some conflicting concepts
borrowed from UserDefaults (which libPropList use) are no longer used in
the WINGs property lists code. These borrowed concepts conflicted with the
retain/release mechanism of property lists and could lead in certain cases
to segmentation faults when executing libPropList based code. But the worse
part was that these libPropList problems were practically unsolvable without
removing one of those conflicting concepts and without a complete redesign.
The new WINGs property lists code is also better integrated with the other
data types from WINGs and is actively maintained.
Practically the things that were removed from the WINGs property list
implementation compared to the old libPropList implementation, are exactly
the UserDefaults borrowed concepts that conflict with the retain/release
mechanism:
- The container of a proplist object and the associated functions are gone.
- The filename associated with a proplist object and the corresponding
functions are gone. Now the saving function needs the filename as a
parameter.
- The synchronization functions are no longer supported. They are part of
the UserDefaults and are implemented there.
- No functions related to domains/registering were implemented in the WINGs
property lists code, because they are also not part of property lists.
They are more in connection with UserDefaults and a central point of access
for domains.
The above 2 concepts: container and filename were added to libPropList just
to let it support synchronization which was borrowed from UserDefaults.
Property lists as defined in the openstep specification are just complex
data structures composed of strings, data, arrays, dictionaries and a mix of
them and are not associated with any file in particular. UserDefaults on the
other hand are property lists read from a specific file and they associate
that property list with that file and allow them to be synchronized.
Old libPropList based code can still be used by linking against the WINGs
library containing the new proplist code with minimal changes which are
described in detail in the comments at the top of the WINGs/proplist-compat.h
header file (the same file carries the #defines for mapping old libPropList
functions to the new WINGs proplist functions).
Our recommendation is to move to the new functions WINGs provide because
they better integrate with other function naming conventions in WINGs.
The proplist-compat.h header file is just a way to have old code up and
running with minimal changes so that we can remove the old and unmaintained
libPropList from systems while keeping to use old libPropList based code
without rewriting it and it should not be used for other purposes.
*** Sat Apr 21 09:12:09 EEST 2001 -Dan
API change
----------
To allow a correct display of icon images with alpha blending in panels and
other places where a WINGs based application may use them the following
changes took place:
1. The following functions were renamed:
- WMSetApplicationIconImage() --> WMSetApplicationIconPixmap()
- WMGetApplicationIconImage() --> WMGetApplicationIconPixmap()
- WMSetWindowMiniwindowImage() --> WMSetWindowMiniwindowPixmap()
2. The following functions were added:
- WMSetApplicationIconImage(WMScreen *scr, RImage *image)
- RImage* WMGetApplicationIconImage(WMScreen *scr)
- WMPixmap* WMCreateApplicationIconBlendedPixmap(WMScreen *scr, RColor *col)
As you can see the old functions that operated on WMPixmap images (which are
basically X Pixmaps that lack alpha information) were renamed to ...Pixmap()
to make them more suggestive about what they do and to make room for the
new functions that operate on RImages (that hold alpha information).
Since the corresponding WMGet... functions only retrieve the stored
image/pixmap from the application, I'll outline how the WMSet...
functions operate:
All WM...IconPixmap() functions operate on WMPixmaps
All WM...IconImage() functions operate on RImages
- WMSetApplicationIconImage() will set the RImage to be used in panels
and will also convert the RImage to a WMPixmap with a threshold of 128
and will use that pixmap for the appicon image. If that doesn't satisfy
you, you can make a call to WMSetApplicationIconPixmap() on your own to
set whatever WMPixmap you see fit for the appicon.
- WMSetApplicationIconPixmap() will set the WMPixmap to be used for the
appicon and for the panels
If you use only one of the above functions, the corresponding image/pixmap
will be used everywhere where needed (panels and appicon), but the pixmap
version will not be able to handle alpha blending correctly.
If you use both WMSetApplicationIconImage() and WMSetApplicationIconPixmap()
then the RImage will have priority in panels, and the WMPixmap will only be
used for the appicon. This allows you to better control what icon is
displayed in the appicon, in case the default conversion of the RImage to a
pixmap with a threshold of 128 is not good enough, or in case you want a
different icon to be shown in the appicon than in panels.
Also this new function was added:
- WMCreateApplicationIconBlendedPixmap() will use the RImage set with
WMSetApplicationIconImage() if available and will blend it with the color
you passed. This will make the image show well on a background of that
color. If the RImage was not set it will return NULL. You need to call
WMReleasePixmap() on it after you finish with it. Passing a NULL pointer
instead of a color will make the RImage be blended with the default color
of the WINGs widgets: '#aeaaae' making it suitable to be assigned to any
WINGs widget.
To make your existing code work as before all you need to do is to rename
the following functions:
- WMSetApplicationIconImage() --> WMSetApplicationIconPixmap()
- WMGetApplicationIconImage() --> WMGetApplicationIconPixmap()
- WMSetWindowMiniwindowImage() --> WMSetWindowMiniwindowPixmap()
But if you want to take advantage of the new abilities to show alpha
blended images you need to start using the new functions.

View File

@@ -1,97 +0,0 @@
WINGs - WINGs Is Not GNUstep
by
Alfredo Kengi Kojima
kojima@windowmaker.info
WINGs is a small widget set with the N*XTSTEP look and feel. Its API
is inspired in OpenStep and its implementation borrows some ideas
from Tk. It has a reasonable set of widgets, sufficient for building
small applications (like a CDPlayer or hacking something like rxvt). It
also has other functions that are usefull for applications, like a
User Defaults alike configuration manager and a notification system.
The library is limited and its design is a little sloppy,
so it's not intended to build large or complex applications, like
anything more complex than a CDPlayer. GNUstep should be used for such
applications.
Since WINGs is written in C and is sort of low-level it is small
and faster than say, Motif or even Athena. Knowing Xlib will help you to
workaround some of its limitations, although you'll probably be able to
write something like a trivial tic-tac-toe game without knowing much Xlib.
Some of its functions are designed to support the Window Maker window
manager (see http://windowmaker.info) In fact, its primary role is to
support Window Maker. All other uses of it are just an added bonus.
It will help you to understand the API if you read the ApplicationKit
reference manual, distributed as a PDF by Apple. The function names,
structs and most of the intrinsics are very close to OpenStep classes.
Internationalization:
---------------------
Change ~/GNUstep/Defaults/WMGLOBAL to set the desired font set and
set MultiByteText = YES; to enable support for multibyte text.
Widgets provided by WINGs:
--------------------------
- button (command button, radio, switch etc. - all buttons defined in OpenStep)
- label
- textfield
- frame
- window
- popup menu button
- scroller
- selection list
- browser
- slider
- scrollable view
- color well
- split view
- tabbed view
- progress indicator
- selection (make pasteboard like?)
- drag&drop
- input box
- file panel
- color panel
- alert panel
- font panel
If you think you can code the following, please do. They are needed by
WPrefs.app, but the number of other things I have to do is huge.
- input method support (XIM). I have no idea of how to code it. People who use
different characters than ASCII will have trouble editing menus without it...
Wish list: (I don't have the know-how or time to do them)
---------------------------------------------------------
- text (with support for RTF)
- matrix (like NSMatrix)
- font manager (like NSFontManager)
- finish other wigets
- optimize list scrolling (XCopyArea() the area that's already drawn)
- InterfaceMaker?
- use XSetWMName and XSetWMIconName for the window/icon title setting.
This requires transforming the received text to a text property with
the proper encoding.
Copyright
---------
WINGs is copyright (c) Alfredo K. Kojima and is licensed through the GNU
Library General Public License (LGPL).

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +0,0 @@
resdatadir = $(datadir)/WINGs
resdata_DATA = Images.tiff Images.xpm defaultIcon.tiff defaultIcon.xpm
EXTRA_DIST = $(resdata_DATA) Images.xcf

View File

@@ -1,54 +0,0 @@
/* XPM */
static char * defaultIcon_xpm[] = {
"48 48 3 1",
" c #000000000000",
". c None",
"X c #FFFFFFFFFFFF",
" ..",
" ..",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ..",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ..",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
" ",
" ",
".... ",
".... "};

View File

@@ -1,14 +0,0 @@
- move paint to idle handlers
- check if its useful to add some WMBrowserSelectionDidChangeNotification
(actually a pass-through for WMListSelectionDidChangeNotification).
Or a delegate to be called when the list selection change.
- add some way to modify speed when scrolling WMList, depending on how
far the mouse is moved outside of the list.
- clean up header files of declared but not implemented anywhere functions
- implement a generic WMChangeFontAttribute(WMFont *font, enum attributes)
function
- optimize color allocation for repeated colors
- make it work in 8bpp
- optimize SystemFont allocation for repeated font sizes

View File

@@ -1,21 +0,0 @@
## automake input file for WINGs - Tests
AUTOMAKE_OPTIONS =
noinst_PROGRAMS = wtest wmquery wmfile testmywidget
LDADD= $(top_builddir)/WINGs/libWINGs.la $(top_builddir)/wrlib/libwraster.la \
$(top_builddir)/WINGs/libWUtil.la \
@XFT_LIBS@ @INTLIBS@ @XLIBS@
testmywidget_SOURCES = testmywidget.c mywidget.c mywidget.h
wtest_DEPENDENCIES = $(top_builddir)/WINGs/libWINGs.la
EXTRA_DIST = logo.xpm upbtn.xpm wm.html wm.png
AM_CPPFLAGS = -I$(top_srcdir)/WINGs -I$(top_srcdir)/wrlib -I$(top_srcdir)/src \
-DRESOURCE_PATH=\"$(datadir)/WINGs\" @XFT_CFLAGS@ @HEADER_SEARCH_PATH@ \
@PANGO_CFLAGS@

View File

@@ -1,56 +0,0 @@
/* XPM */
static char * GNUSTEP_XPM[] = {
"45 45 8 1",
" c None",
". c #666666666666",
"X c #777777777777",
"o c #596559656185",
"O c #000000000000",
"+ c #3CF33CF33CF3",
"@ c #CF3CCF3CCF3C",
"# c #FFFFFFFFFFFF",
" ",
" .Xooooooooo. ",
" ..ooOOOOOOOOOOOOOo. ",
" .XoOOOOOOOOOOOOOOOOOO+ ",
" .oOOOOOOOOOOOOOOOOOOOOOO+ ",
" XOOOOOOOOOOOOOOOOOOOOOOOOOOo ",
" oOOOOOOOOOOOOOOOOOOOOOOOOOOOO+ ",
" oOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO+ooooooo",
" +OOOOOOOOOOOOOOOOOOOOOOOOoXXXXX.XOOOOOOO",
" XOOOOOOOOOOOOOOOOOOOOOOOOOX#######.OOOOOO",
" XOOOOOOOOOOOOOOOOOOOOOOOOOOX########oOOOOO",
" OOOOOOOOOOOOOOOOOOOOOOOOOOOX#########oOOOO",
" oOOOOOOOOOOOOOOOOOOOOOOOOOOOX#########@OOOO",
" OOOOOOOOOOOOOOOOOOOOOOOOOOOOX##########oOOO",
" oOOOOOOOOOOOOOOOOOOOOOOOOOOOOX##########@OOO",
" OOOOOOOOOOOOOOOOOOOOOOOOOOOOOX###########+OO",
" OOOOOOOOOOOOOOOOOOOOOOOOOOOOOX###########oOO",
"oOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX###########@OO",
"+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOX###########@OO",
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX############XO",
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX############XO",
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX############XO",
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX############XO",
"OOOOOOOOOOOOOOOoX.X.X.X.XX.XXX@############XO",
"OOOOOOOOOOOOOOOX###########################XO",
"OOOOOOOOOOOOOOOX###########################XO",
"OOOOOOOOOOOOOOOX###########################XO",
"+OOOOOOOOOOOOOOX###########################OO",
"oOOOOOOOOOOOOOOX###########################OO",
" OOOOOOOOOOOOOOX##########################XOO",
" OOOOOOOOOOOOOOX##########################oOO",
" oOOOOOOOOOOOOOX#########################@OOO",
" OOOOOOOOOOOOOX#########################+OOO",
" oOOOOOOOOOOOOX########################@OOOO",
" OOOOOOOOOOOOX########################oOOOO",
" OOOOOOOOOOOX#######################oOOOOO",
" OOOOOOOOOOX######################XOOOOOO",
"OOOOOOOXXXXXXXX@#####################@OOOOOOO",
"OOOOOOOo############################@OOOOOOOO",
"OOOOOOOOO@#########################oOOOOOOOOO",
"OOOOOOOOOOX######################@oOOOOOOOOOO",
"OOOOOOOOOOOOX###################XOOOOOOOOOOOO",
"OOOOOOOOOOOOOOX@#############@XOOOOOOOOOOOOOO",
"OOOOOOOOOOOOOOOOOXXX#####XXXOOOOOOOOOOOOOOOOO",
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO"};

View File

@@ -1,198 +0,0 @@
/*
* Demo user widget for WINGs
*
* Author: Alfredo K. Kojima
*
* This file is in the public domain.
*
*/
/*
*
* Include the WINGs private data header.
*
*
*/
#include <WINGs/WINGsP.h>
/*
* Our public header.
*/
#include "mywidget.h"
/*
* Define the widget "class"
*/
typedef struct W_MyWidget {
/* these two fields must be present in all your widgets in this
* exact position */
W_Class widgetClass;
WMView *view;
/* put your stuff here */
char *text;
} _MyWidget;
/* some forward declarations */
static void destroyMyWidget(_MyWidget * mPtr);
static void paintMyWidget(_MyWidget * mPtr);
static void handleEvents(XEvent * event, void *data);
static void handleActionEvents(XEvent * event, void *data);
/*
* Delegates
* See the source for the other widgets to see how to use.
* You won't need to use this most of the time.
*/
static W_ViewDelegate _MyWidgetDelegate = {
NULL,
NULL,
NULL,
NULL,
NULL
};
/* our widget class ID */
static W_Class myWidgetClass = 0;
/*
* Initializer for our widget. Must be called before creating any
* instances of the widget.
*/
W_Class InitMyWidget(WMScreen * scr)
{
(void)scr;
/* register our widget with WINGs and get our widget class ID */
if (!myWidgetClass) {
myWidgetClass = W_RegisterUserWidget();
}
return myWidgetClass;
}
/*
* Our widget fabrication plant.
*/
MyWidget *CreateMyWidget(WMWidget * parent)
{
MyWidget *mPtr;
/* allocate some storage for our new widget instance */
mPtr = wmalloc(sizeof(MyWidget));
/* initialize it */
memset(mPtr, 0, sizeof(MyWidget));
/* set the class ID */
mPtr->widgetClass = myWidgetClass;
/*
* Create the view for our widget.
* Note: the Window for the view is only created after the view is
* realized with W_RealizeView()
*
* Consider the returned view as read-only.
*/
mPtr->view = W_CreateView(W_VIEW(parent));
if (!mPtr->view) {
wfree(mPtr);
return NULL;
}
/* always do this */
mPtr->view->self = mPtr;
/* setup the delegates for the view */
mPtr->view->delegate = &_MyWidgetDelegate;
/*
* Intercept some events for our widget, so that we can handle them.
*/
WMCreateEventHandler(mPtr->view, ExposureMask /* this allows us to know when we should paint */
| StructureNotifyMask, /* this allows us to know things like when we are destroyed */
handleEvents, mPtr);
/*
* Intercept some other events. This could be merged with the above
* call, but we separate for more organization.
*/
WMCreateEventHandler(mPtr->view, ButtonPressMask, handleActionEvents, mPtr);
return mPtr;
}
/*
* Paint our widget contents.
*/
static void paintMyWidget(_MyWidget * mPtr)
{
W_Screen *scr = mPtr->view->screen;
WMColor *color;
if (mPtr->text) {
color = WMWhiteColor(scr);
W_PaintText(mPtr->view, mPtr->view->window, scr->normalFont, 0, 0,
mPtr->view->size.width, WACenter, color, False, mPtr->text, strlen(mPtr->text));
WMReleaseColor(color);
}
}
static void handleEvents(XEvent * event, void *data)
{
_MyWidget *mPtr = (_MyWidget *) data;
switch (event->type) {
case Expose:
if (event->xexpose.count != 0)
break;
paintMyWidget(mPtr);
break;
case DestroyNotify:
destroyMyWidget(mPtr);
break;
}
}
static void handleActionEvents(XEvent * event, void *data)
{
_MyWidget *mPtr = (_MyWidget *) data;
switch (event->type) {
case ButtonPress:
XBell(mPtr->view->screen->display, 100);
XBell(mPtr->view->screen->display, 100);
break;
}
}
void SetMyWidgetText(MyWidget * mPtr, char *text)
{
CHECK_CLASS(mPtr, myWidgetClass);
if (mPtr->text)
wfree(mPtr->text);
mPtr->text = wstrdup(text);
if (W_VIEW_MAPPED(mPtr->view)) {
paintMyWidget(mPtr);
}
}
static void destroyMyWidget(_MyWidget * mPtr)
{
/*
* Free all data we allocated for our widget.
*/
if (mPtr->text)
wfree(mPtr->text);
wfree(mPtr);
}

View File

@@ -1,15 +0,0 @@
/*
* Header for demo widget.
*
*/
typedef struct W_MyWidget MyWidget;
MyWidget *CreateMyWidget(WMWidget *parent);
void SetMyWidgetText(MyWidget *mPtr, char *text);
W_Class InitMyWidget(WMScreen *scr);

View File

@@ -1,46 +0,0 @@
#include <WINGs/WINGs.h>
#include <stdlib.h>
#include "mywidget.h"
_Noreturn void wAbort(void)
{
exit(1);
}
int main(int argc, char **argv)
{
Display *dpy = XOpenDisplay("");
WMScreen *scr;
WMWindow *win;
MyWidget *thing;
WMInitializeApplication("Test", &argc, argv);
if (!dpy) {
wfatal("could not open display");
exit(1);
}
scr = WMCreateSimpleApplicationScreen(dpy);
/* init our widget */
InitMyWidget(scr);
win = WMCreateWindow(scr, "test");
WMResizeWidget(win, 150, 50);
thing = CreateMyWidget(win);
SetMyWidgetText(thing, "The Test");
WMResizeWidget(thing, 100, 20);
WMMoveWidget(thing, 10, 10);
WMRealizeWidget(win);
WMMapSubwidgets(win);
WMMapWidget(win);
WMScreenMainLoop(scr);
return 0;
}

View File

@@ -1,57 +0,0 @@
/* XPM */
static char * upbtn_xpm[] = {
"20 22 32 1",
" c None",
". c #000000",
"+ c #FFFFFF",
"@ c #4A485A",
"# c #524052",
"$ c #4A595A",
"% c #5A596A",
"& c #4A486A",
"* c #5A595A",
"= c #52556A",
"- c #52406A",
"; c #6A556A",
"> c #5A6D6A",
", c #5A597B",
"' c #5A6D7B",
") c #6A557B",
"! c #6A6D7B",
"~ c #6A697B",
"{ c #6A698B",
"] c #7B797B",
"^ c #C5C2C5",
"/ c #6A818B",
"( c #6A7D7B",
"_ c #7B698B",
": c #6A798B",
"< c #7B799C",
"[ c #7B798B",
"} c #7B8D94",
"| c #7B81A4",
"1 c #8B85A4",
"2 c #73899C",
"3 c #7B89A4",
" ",
" .+ ",
" .@#+ ",
" .$%$&+ ",
" .*=*-*-+ ",
" .%%%%%%$%+ ",
" .%=%;%=*=*-+ ",
" .>%>,''>,>%=%+ ",
" .%)>)!~>)>)>=*#+ ",
" .>~'~'{'{'~',>%$@+ ",
" ]+++^{!{!~!)>+++++ ",
" ./{/{({'~+ ",
" ._:_:_!~>+ ",
" ./</</{'~+ ",
" .<<<[_({!+ ",
" .}|}</{(~+ ",
" .12<[_:{'+ ",
" .31}</{'~+ ",
" .12<[_!~>+ ",
" .2</</{''+ ",
" ]+++++++++ ",
" "};

View File

@@ -1,37 +0,0 @@
<HTML><font size=-1>
<center>
<Img src=wm.png></b><p>
<b>GNU Window Maker</B><br>
<i>X11 Window Manager</i><p>
<u>http://windowmaker.info<br>
ftp.windowmaker.info</u></font><Br>
</center>
<b><i>Window Maker</b>
<Img src=upbtn.xpm></i>is the GNU window manager
for the X Window System. It was
designed to emulate the look and feel of part of the NEXTSTEP(tm) GUI. Its
supposed to be relatively fast and small, feature rich, easy to configure and
easy to use, with a simple and elegant appearance borrowed from NEXTSTEP(tm).
<p>
<b>Window Maker</b> was designed keeping integration with GNUstep in
mind and is the
"official" window manager for it. It is also part of the GNU project
(<u>www.gnu.org</u>)
<p>
<b>What is <i>GNUstep?</i></b><p>
<i><b>G</i>NU</b>step is a complete object-oriented development system, based on the
OpenStep specification released by NeXT(tm) (now Apple(tm)) and Sun(tm). It will provide everything one needs to produce cross-platform, object-oriented, graphical (and non-graphical) applications; providing among other things, base system libraries, a high-level GUI application framework that uses a Display PostScript(tm)-like imaging model (DGS), objects for accessing relational databases, distributed objects and a graphical development environment, with tools like interface modeller, a project management system
(project center) and other tools.
<p>
The GNUstep development system will be used to create a user environment,
with everything needed for a complete graphical user interface, such as a
file viewer, text editors and other applications. Note that the user
environment (or "desktop environment") is only a small part of the whole
GNUstep project and therefore it does not "compete" with other projects like
KDE or GNOME, simply because they are completely different things.
<p>
For more information on the GNUstep project, visit:
<u>http://www.gnustep.org</u> and <u>http://gnustep.current.nu</u>
</HTML>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

View File

@@ -1,109 +0,0 @@
/*
* Author: Len Trigg <trigg@cs.waikato.ac.nz>
*/
/*
Update: Franck Wolff <frawolff@club-internet.fr>
-----------------------------------------------------------------------
List of updated functions :
- main :
add -s option for a save panel...
-----------------------------------------------------------------------
*/
#include <WINGs/WINGs.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include "logo.xpm"
_Noreturn void wAbort(void)
{
exit(1);
}
char *ProgName;
_Noreturn void usage(void)
{
fprintf(stderr,
"usage:\n"
"\t%s [-options]\n"
"\n"
"options:\n"
" -s\t\tSave panel (default open panel)\n"
" -i <str>\tInitial directory (default /)\n"
" -t <str>\tQuery window title (default none)\n"
"\n"
"information:\n"
"\t%s pops up a WindowMaker style file selection panel.\n"
"\n" "version:\n" "\t%s\n", ProgName, ProgName, __DATE__);
exit(0);
}
#define OPEN_PANEL_TYPE 0
#define SAVE_PANEL_TYPE 1
int main(int argc, char **argv)
{
Display *dpy = XOpenDisplay("");
WMScreen *scr;
WMPixmap *pixmap;
WMOpenPanel *oPanel;
WMSavePanel *sPanel;
char *title = NULL;
char *initial = "/";
int ch;
int panelType = OPEN_PANEL_TYPE;
if (!dpy) {
puts("could not open display");
exit(1);
}
WMInitializeApplication("WMFile", &argc, argv);
ProgName = argv[0];
while ((ch = getopt(argc, argv, "si:ht:")) != -1)
switch (ch) {
case 's':
panelType = SAVE_PANEL_TYPE;
break;
case 'i':
initial = optarg;
break;
case 't':
title = optarg;
break;
default:
usage();
}
for (; optind < argc; optind++)
usage();
scr = WMCreateSimpleApplicationScreen(dpy);
pixmap = WMCreatePixmapFromXPMData(scr, GNUSTEP_XPM);
WMSetApplicationIconPixmap(scr, pixmap);
WMReleasePixmap(pixmap);
if (panelType == SAVE_PANEL_TYPE) {
sPanel = WMGetSavePanel(scr);
if (WMRunModalFilePanelForDirectory(sPanel, NULL, initial,
title, NULL) == True)
printf("%s\n", WMGetFilePanelFileName(sPanel));
else
printf("\n");
} else {
oPanel = WMGetOpenPanel(scr);
if (WMRunModalFilePanelForDirectory(oPanel, NULL, initial,
title, NULL) == True)
printf("%s\n", WMGetFilePanelFileName(oPanel));
else
printf("\n");
}
return 0;
}

View File

@@ -1,88 +0,0 @@
/*
* Author: Len Trigg <trigg@cs.waikato.ac.nz>
*/
#include <WINGs/WINGs.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include "logo.xpm"
_Noreturn void wAbort(void)
{
exit(1);
}
char *ProgName;
_Noreturn void usage(void)
{
fprintf(stderr,
"usage:\n"
"\t%s [-options]\n"
"\n"
"options:\n"
" -i <str>\tInitial entry contents (default none)\n"
" -p <str>\tPrompt message (default none)\n"
" -t <str>\tQuery window title (default none)\n"
"\n"
"information:\n"
"\t%s pops up a WindowMaker style input panel.\n"
"\n" "version:\n" "\t%s\n", ProgName, ProgName, __DATE__);
exit(0);
}
int main(int argc, char **argv)
{
Display *dpy = XOpenDisplay("");
WMScreen *scr;
WMPixmap *pixmap;
char *title = NULL;
char *prompt = NULL;
char *initial = NULL;
char *result = NULL;
int ch;
WMInitializeApplication("WMQuery", &argc, argv);
ProgName = argv[0];
if (!dpy) {
puts("could not open display");
exit(1);
}
while ((ch = getopt(argc, argv, "i:hp:t:")) != -1)
switch (ch) {
case 'i':
initial = optarg;
break;
case 'p':
prompt = optarg;
break;
case 't':
title = optarg;
break;
default:
usage();
}
for (; optind < argc; optind++)
usage();
scr = WMCreateSimpleApplicationScreen(dpy);
pixmap = WMCreatePixmapFromXPMData(scr, GNUSTEP_XPM);
WMSetApplicationIconPixmap(scr, pixmap);
WMReleasePixmap(pixmap);
if ((result = WMRunInputPanel(scr, NULL, title, prompt, initial, "OK", "Cancel")) != NULL)
printf("%s\n", result);
else
printf("\n");
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,698 +0,0 @@
#ifndef _WINGSP_H_
#define _WINGSP_H_
#include <X11/Xlib.h>
#include <X11/Xutil.h>
// TODO: Pango support was originally optional.
#include "pango/pango.h"
#include "WINGs/WINGs.h"
#if WINGS_H_VERSION < 20041030
#error There_is_an_old_WINGs.h_file_somewhere_in_your_system._Please_remove_it.
#endif
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* ---[ global settigns ]------------------------------------------------- */
#define DOUBLE_BUFFER 1
#define SCROLLER_WIDTH 20
typedef struct _WINGsConfiguration {
char *systemFont;
char *boldSystemFont;
int defaultFontSize;
Bool antialiasedText;
char *floppyPath;
unsigned doubleClickDelay;
unsigned mouseWheelUp;
unsigned mouseWheelDown;
} _WINGsConfiguration;
extern const char *_WINGS_progname;
extern _WINGsConfiguration WINGsConfiguration;
extern struct W_Application WMApplication;
/* ---[ drag*.c ]--------------------------------------------------------- */
/*
* We need to define these structure first because they are used in W_Screen
* below. The rest of drag-related stuff if after because it needs W_Screen
*/
#define XDND_VERSION 3
typedef struct W_DraggingInfo {
unsigned char protocolVersion; /* version supported on the other side */
Time timestamp;
Atom sourceAction;
Atom destinationAction;
struct W_DragSourceInfo* sourceInfo; /* infos needed by source */
struct W_DragDestinationInfo* destInfo; /* infos needed by destination */
} W_DraggingInfo;
/* ---[ Structures from WINGs.h ]----------------------------------------- */
/* Pre-definition of internal structs */
typedef struct W_Color W_Color;
typedef struct W_Pixmap W_Pixmap;
typedef struct W_View W_View;
typedef struct W_FocusInfo {
W_View *toplevel;
W_View *focused; /* view that has the focus in this toplevel */
struct W_FocusInfo *next;
} W_FocusInfo;
typedef struct W_Screen {
Display *display;
int screen;
int depth;
Colormap colormap;
Visual *visual;
Time lastEventTime;
Window rootWin;
W_View *rootView;
RContext *rcontext;
struct W_IMContext *imctx;
struct _XftDraw *xftdraw; /* shared XftDraw */
/* application related */
W_FocusInfo *focusInfo;
RImage *applicationIconImage; /* image (can have alpha channel) */
W_Pixmap *applicationIconPixmap; /* pixmap - no alpha channel */
Window applicationIconWindow;
struct W_Window *windowList; /* list of windows in the app */
Window groupLeader; /* the leader of the application */
/* also used for other things */
struct W_SelectionHandlers *selectionHandlerList;
struct {
unsigned int hasAppIcon:1;
unsigned int simpleApplication:1;
} aflags;
WMOpenPanel *sharedOpenPanel;
WMSavePanel *sharedSavePanel;
struct W_FontPanel *sharedFontPanel;
struct W_ColorPanel *sharedColorPanel;
Pixmap stipple;
W_View *dragSourceView;
W_DraggingInfo dragInfo;
/* colors */
W_Color *white;
W_Color *black;
W_Color *gray;
W_Color *darkGray;
GC stippleGC;
GC copyGC;
GC clipGC;
GC monoGC; /* GC for 1bpp visuals */
GC xorGC;
GC ixorGC; /* IncludeInferiors XOR */
GC drawStringGC; /* for WMDrawString() */
GC drawImStringGC; /* for WMDrawImageString() */
struct W_Font *normalFont;
struct W_Font *boldFont;
WMHashTable *fontCache;
Bool antialiasedText;
unsigned int ignoredModifierMask; /* modifiers to ignore when typing txt */
struct W_Balloon *balloon;
W_Pixmap *checkButtonImageOn;
W_Pixmap *checkButtonImageOff;
W_Pixmap *radioButtonImageOn;
W_Pixmap *radioButtonImageOff;
W_Pixmap *buttonArrow;
W_Pixmap *pushedButtonArrow;
W_Pixmap *scrollerDimple;
W_Pixmap *upArrow;
W_Pixmap *downArrow;
W_Pixmap *leftArrow;
W_Pixmap *rightArrow;
W_Pixmap *hiUpArrow;
W_Pixmap *hiDownArrow;
W_Pixmap *hiLeftArrow;
W_Pixmap *hiRightArrow;
W_Pixmap *pullDownIndicator;
W_Pixmap *popUpIndicator;
W_Pixmap *checkMark;
W_Pixmap *homeIcon;
W_Pixmap *altHomeIcon;
W_Pixmap *trashcanIcon;
W_Pixmap *altTrashcanIcon;
W_Pixmap *createDirIcon;
W_Pixmap *altCreateDirIcon;
W_Pixmap *disketteIcon;
W_Pixmap *altDisketteIcon;
W_Pixmap *unmountIcon;
W_Pixmap *altUnmountIcon;
W_Pixmap *magnifyIcon;
/*W_Pixmap *altMagnifyIcon;*/
W_Pixmap *wheelIcon;
W_Pixmap *grayIcon;
W_Pixmap *rgbIcon;
W_Pixmap *cmykIcon;
W_Pixmap *hsbIcon;
W_Pixmap *customPaletteIcon;
W_Pixmap *colorListIcon;
W_Pixmap *defaultObjectIcon;
Cursor defaultCursor;
Cursor textCursor;
Cursor invisibleCursor;
Atom attribsAtom; /* GNUstepWindowAttributes */
Atom deleteWindowAtom; /* WM_DELETE_WINDOW */
Atom protocolsAtom; /* _XA_WM_PROTOCOLS */
Atom clipboardAtom; /* CLIPBOARD */
Atom xdndAwareAtom; /* XdndAware */
Atom xdndSelectionAtom;
Atom xdndEnterAtom;
Atom xdndLeaveAtom;
Atom xdndPositionAtom;
Atom xdndDropAtom;
Atom xdndFinishedAtom;
Atom xdndTypeListAtom;
Atom xdndActionListAtom;
Atom xdndActionDescriptionAtom;
Atom xdndStatusAtom;
Atom xdndActionCopy;
Atom xdndActionMove;
Atom xdndActionLink;
Atom xdndActionAsk;
Atom xdndActionPrivate;
Atom wmIconDragOffsetAtom;
Atom wmStateAtom; /* WM_STATE */
Atom utf8String;
Atom netwmName;
Atom netwmIconName;
Atom netwmIcon;
/* stuff for detecting double-clicks */
Time lastClickTime; /* time of last mousedown event */
Window lastClickWindow; /* window of the last mousedown */
struct W_View *modalView;
unsigned modalLoop:1;
unsigned ignoreNextDoubleClick:1;
/*
* New stuff in Window Maker 0.95.7
* Added at the end of the structure to avoid breaking binary compatibility
* with previous versions of the toolkit
*/
W_Pixmap *tristateButtonImageOn;
W_Pixmap *tristateButtonImageOff;
W_Pixmap *tristateButtonImageTri;
} W_Screen;
#define W_DRAWABLE(scr) (scr)->rcontext->drawable
/* ---[ configuration.c ]------------------------------------------------- */
void W_ReadConfigurations(void);
/* ---[ drag*.c ]--------------------------------------------------------- */
typedef struct W_DragOperationItem {
WMDragOperationType type;
char* text;
} W_DragOperationItem;
typedef void* W_DndState(WMView *destView, XClientMessageEvent *event,
WMDraggingInfo *info);
typedef struct W_DragSourceInfo {
WMView *sourceView;
Window destinationWindow;
W_DndState *state;
WMSelectionProcs *selectionProcs;
Window icon;
WMPoint imageLocation;
WMPoint mouseOffset; /* mouse pos in icon */
Cursor dragCursor;
WMRect noPositionMessageZone;
Atom firstThreeTypes[3];
} W_DragSourceInfo;
typedef struct W_DragDestinationInfo {
WMView *destView;
WMView *xdndAwareView;
Window sourceWindow;
W_DndState *state;
Bool sourceActionChanged;
WMArray *sourceTypes;
WMArray *requiredTypes;
Bool typeListAvailable;
WMArray *dropDatas;
} W_DragDestinationInfo;
/* -- Functions -- */
void W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event);
Atom W_OperationToAction(WMScreen *scr, WMDragOperationType operation);
WMDragOperationType W_ActionToOperation(WMScreen *scr, Atom action);
void W_FreeDragOperationItem(void* item);
Bool W_SendDnDClientMessage(Display *dpy, Window win, Atom message,
unsigned long data1, unsigned long data2,
unsigned long data3, unsigned long data4,
unsigned long data5);
void W_DragSourceStartTimer(WMDraggingInfo *info);
void W_DragSourceStopTimer(void);
void W_DragSourceStateHandler(WMDraggingInfo *info, XClientMessageEvent *event);
void W_DragDestinationStartTimer(WMDraggingInfo *info);
void W_DragDestinationStopTimer(void);
void W_DragDestinationStoreEnterMsgInfo(WMDraggingInfo *info, WMView *toplevel,
XClientMessageEvent *event);
void W_DragDestinationStorePositionMsgInfo(WMDraggingInfo *info,
WMView *toplevel,
XClientMessageEvent *event);
void W_DragDestinationCancelDropOnEnter(WMView *toplevel, WMDraggingInfo *info);
void W_DragDestinationStateHandler(WMDraggingInfo *info,
XClientMessageEvent *event);
void W_DragDestinationInfoClear(WMDraggingInfo *info);
void W_FreeViewXdndPart(WMView *view);
/* ---[ handlers.c ]------------------------------------------------------ */
Bool W_CheckIdleHandlers(void);
void W_CheckTimerHandlers(void);
Bool W_HandleInputEvents(Bool waitForInput, int inputfd);
/* ---[ notification.c ]-------------------------------------------------- */
void W_InitNotificationCenter(void);
void W_ReleaseNotificationCenter(void);
void W_FlushASAPNotificationQueue(void);
void W_FlushIdleNotificationQueue(void);
/* ---[ selection.c ]----------------------------------------------------- */
void W_HandleSelectionEvent(XEvent *event);
/* ---[ wapplication.c ]-------------------------------------------------- */
typedef struct W_Application {
char *applicationName;
int argc;
char **argv;
char *resourcePath;
} W_Application;
/* -- Functions -- */
void W_InitApplication(WMScreen *scr);
Bool W_ApplicationInitialized(void);
/* ---[ wballoon.c ]------------------------------------------------------ */
struct W_Balloon *W_CreateBalloon(WMScreen *scr);
void W_BalloonHandleEnterView(WMView *view);
void W_BalloonHandleLeaveView(WMView *view);
/* ---[ wcolor.c ]-------------------------------------------------------- */
struct W_Color {
struct W_Screen *screen;
XColor color;
unsigned short alpha;
short refCount;
GC gc;
struct {
unsigned int exact:1;
} flags;
};
#define W_PIXEL(c) (c)->color.pixel
/* ---[ wevent.c ]-------------------------------------------------------- */
typedef struct W_EventHandler {
unsigned long eventMask;
WMEventProc *proc;
void *clientData;
} W_EventHandler;
/* -- Functions -- */
void W_CallDestroyHandlers(W_View *view);
/* ---[ wfont.c ]--------------------------------------------------------- */
typedef struct W_Font {
struct W_Screen *screen;
struct _XftFont *font;
short height;
short y;
short refCount;
char *name;
// TODO: Pango support was originally optional.
PangoLayout *layout;
} W_Font;
#define W_FONTID(f) (f)->font->fid
/* ---[ widgets.c ]------------------------------------------------------- */
#define WC_UserWidget 128
#define CHECK_CLASS(widget, class) assert(W_CLASS(widget)==(class))
#define W_CLASS(widget) (((W_WidgetType*)(widget))->widgetClass)
#define W_VIEW(widget) (((W_WidgetType*)(widget))->view)
/* -- Functions -- */
W_Class W_RegisterUserWidget(void);
/* ---[ winputmethod.c ]-------------------------------------------------- */
void W_InitIM(WMScreen *scr);
void W_CreateIC(WMView *view);
void W_DestroyIC(WMView *view);
void W_FocusIC(WMView *view);
void W_UnFocusIC(WMView *view);
void W_SetPreeditPositon(W_View *view, int x, int y);
int W_LookupString(W_View *view, XKeyPressedEvent *event, char *buffer,
int buflen, KeySym *keysym, Status *status);
KeySym W_KeycodeToKeysym(Display *display, KeyCode keycode, int index);
/* ---[ wmisc.c ]--------------------------------------------------------- */
void W_DrawRelief(W_Screen *scr, Drawable d, int x, int y, unsigned int width,
unsigned int height, WMReliefType relief);
void W_DrawReliefWithGC(W_Screen *scr, Drawable d, int x, int y,
unsigned int width, unsigned int height,
WMReliefType relief,
GC black, GC dark, GC light, GC white);
void W_PaintTextAndImage(W_View *view, int wrap, WMColor *textColor,
W_Font *font, WMReliefType relief, const char *text,
WMAlignment alignment, W_Pixmap *image,
WMImagePosition position, WMColor *backColor, int ofs);
void W_PaintText(W_View *view, Drawable d, WMFont *font, int x, int y,
int width, WMAlignment alignment, WMColor *color,
int wrap, const char *text, int length);
int W_GetTextHeight(WMFont *font, const char *text, int width, int wrap);
/* ---[ wpixmap.c ]------------------------------------------------------- */
struct W_Pixmap {
struct W_Screen *screen;
Pixmap pixmap;
Pixmap mask;
unsigned short width;
unsigned short height;
short depth;
short refCount;
};
/* ---[ wview.c ]--------------------------------------------------------- */
typedef struct W_ViewDelegate {
void *data;
void (*didMove)(struct W_ViewDelegate*, WMView*);
void (*didResize)(struct W_ViewDelegate*, WMView*);
void (*willMove)(struct W_ViewDelegate*, WMView*, int*, int*);
void (*willResize)(struct W_ViewDelegate*, WMView*,
unsigned int*, unsigned int*);
} W_ViewDelegate;
struct W_View {
struct W_Screen *screen;
WMWidget *self; /* must point to the widget the view belongs to */
W_ViewDelegate *delegate;
Window window;
WMSize size;
short topOffs;
short leftOffs;
short bottomOffs;
short rightOffs;
WMPoint pos;
struct W_View *nextFocusChain; /* next/prev in focus chain */
struct W_View *prevFocusChain;
struct W_View *nextResponder; /* next to receive keyboard events */
struct W_View *parent; /* parent WMView */
struct W_View *childrenList; /* first in list of child windows */
struct W_View *nextSister; /* next on parent's children list */
WMArray *eventHandlers; /* event handlers for this window */
unsigned long attribFlags;
XSetWindowAttributes attribs;
void *hangedData; /* data holder for user program */
WMColor *backColor;
WMPixmap *backImage;
Cursor cursor;
Atom *droppableTypes;
struct W_DragSourceProcs *dragSourceProcs;
struct W_DragDestinationProcs *dragDestinationProcs;
WMPixmap *dragImage;
int helpContext;
XIC xic;
struct {
unsigned int realized:1;
unsigned int mapped:1;
unsigned int parentDying:1;
unsigned int dying:1; /* the view is being destroyed */
unsigned int topLevel:1; /* is a top level window */
unsigned int root:1; /* is the root window */
unsigned int mapWhenRealized:1; /* map the view when it's realized */
unsigned int alreadyDead:1; /* view was freed */
unsigned int dontCompressMotion:1; /* motion notify event compress */
unsigned int notifySizeChanged:1;
unsigned int dontCompressExpose:1; /* expose event compress */
/* toplevel only */
unsigned int worksWhenModal:1;
unsigned int pendingRelease1:1;
unsigned int pendingRelease2:1;
unsigned int pendingRelease3:1;
unsigned int pendingRelease4:1;
unsigned int pendingRelease5:1;
unsigned int xdndHintSet:1;
} flags;
int refCount;
};
#define W_VIEW_REALIZED(view) (view)->flags.realized
#define W_VIEW_MAPPED(view) (view)->flags.mapped
#define W_VIEW_DISPLAY(view) (view)->screen->display
#define W_VIEW_SCREEN(view) (view)->screen
#define W_VIEW_DRAWABLE(view) (view)->window
#define W_VIEW_WIDTH(view) (view)->size.width
#define W_VIEW_HEIGHT(view) (view)->size.height
/* -- Functions -- */
W_View *W_GetViewForXWindow(Display *display, Window window);
W_View *W_CreateView(W_View *parent);
W_View *W_CreateTopView(W_Screen *screen);
W_View *W_CreateUnmanagedTopView(W_Screen *screen);
W_View *W_CreateRootView(W_Screen *screen);
void W_DestroyView(W_View *view);
void W_RealizeView(W_View *view);
void W_RedisplayView(WMView *view);
void W_ReparentView(W_View *view, W_View *newParent, int x, int y);
void W_RaiseView(W_View *view);
void W_LowerView(W_View *view);
void W_MapView(W_View *view);
void W_MapSubviews(W_View *view);
void W_UnmapSubviews(W_View *view);
W_View *W_TopLevelOfView(W_View *view);
void W_UnmapView(W_View *view);
WMView *W_RetainView(WMView *view);
void W_ReleaseView(WMView *view);
void W_MoveView(W_View *view, int x, int y);
void W_ResizeView(W_View *view, unsigned int width, unsigned int height);
void W_SetViewBackgroundColor(W_View *view, WMColor *color);
void W_SetViewBackgroundPixmap(W_View *view, WMPixmap *pix);
void W_SetViewCursor(W_View *view, Cursor cursor);
void W_SetFocusOfTopLevel(W_View *toplevel, W_View *view);
W_View *W_FocusedViewOfToplevel(W_View *view);
void W_BroadcastMessage(W_View *targetParent, XEvent *event);
void W_DispatchMessage(W_View *target, XEvent *event);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _WINGSP_H_ */

View File

@@ -1,959 +0,0 @@
/* WUtil.h
*
* Copyright (c) 1998 scottc
* Copyright (c) 1999-2004 Dan Pascu
* Copyright (c) 1999-2000 Alfredo K. Kojima
*
* 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.
*/
#ifndef _WUTIL_H_
#define _WUTIL_H_
#include <X11/Xlib.h>
#include <limits.h>
#include <sys/types.h>
/* SunOS 4.x Blargh.... */
#ifndef NULL
#define NULL ((void*)0)
#endif
#ifndef WMAX
# define WMAX(a,b) ((a)>(b) ? (a) : (b))
#endif
#ifndef WMIN
# define WMIN(a,b) ((a)<(b) ? (a) : (b))
#endif
#ifndef __GNUC__
#define __attribute__(x) /*NOTHING*/
#endif
#ifdef NDEBUG
#define wassertr(expr) \
if (!(expr)) { return; }
#define wassertrv(expr, val) \
if (!(expr)) { return (val); }
#else /* !NDEBUG */
#define wassertr(expr) \
if (!(expr)) { \
wwarning("wassertr: assertion %s failed", #expr); \
return;\
}
#define wassertrv(expr, val) \
if (!(expr)) { \
wwarning("wassertrv: assertion %s failed", #expr); \
return (val);\
}
#endif /* !NDEBUG */
#ifdef static_assert
# define _wutil_static_assert(check, message) static_assert(check, message)
#else
# ifdef __STDC_VERSION__
# if __STDC_VERSION__ >= 201112L
/*
* Ideally, we would like to include <assert.h> to have 'static_assert'
* properly defined, but as we have to be sure about portability and
* because we're a public header we can't count on 'configure' to tell
* us about availability, so we use the raw C11 keyword
*/
# define _wutil_static_assert(check, message) _Static_assert(check, message)
# else
# define _wutil_static_assert(check, message) /**/
# endif
# else
# define _wutil_static_assert(check, message) /**/
# endif
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef enum {
WMPostWhenIdle = 1,
WMPostASAP = 2,
WMPostNow = 3
} WMPostingStyle;
typedef enum {
WNCNone = 0,
WNCOnName = 1,
WNCOnSender = 2
} WMNotificationCoalescing;
enum {
WBNotFound = INT_MIN, /* element was not found in WMBag */
WANotFound = -1 /* element was not found in WMArray */
};
typedef struct W_Array WMArray;
typedef struct W_Bag WMBag;
typedef struct W_Data WMData;
typedef struct W_TreeNode WMTreeNode;
typedef struct W_HashTable WMHashTable;
typedef struct W_UserDefaults WMUserDefaults;
typedef struct W_Notification WMNotification;
typedef struct W_NotificationQueue WMNotificationQueue;
typedef struct W_Host WMHost;
typedef struct W_Connection WMConnection;
typedef struct W_PropList WMPropList;
/* Some typedefs for the handler stuff */
typedef void *WMHandlerID;
typedef void WMCallback(void *data);
typedef void WMInputProc(int fd, int mask, void *clientData);
typedef int WMCompareDataProc(const void *item1, const void *item2);
typedef void WMTreeWalkProc(WMTreeNode *aNode, void *data);
typedef void WMFreeDataProc(void *data);
/* Used by WMBag or WMArray for matching data */
typedef int WMMatchDataProc(const void *item, const void *cdata);
typedef struct {
int position;
int count;
} WMRange;
/* DO NOT ACCESS THE CONTENTS OF THIS STRUCT */
typedef struct {
void *table;
void *nextItem;
int index;
} WMHashEnumerator;
typedef struct {
/* NULL is pointer hash */
unsigned (*hash)(const void *);
/* NULL is pointer compare */
Bool (*keyIsEqual)(const void *, const void *);
/* NULL does nothing */
void* (*retainKey)(const void *);
/* NULL does nothing */
void (*releaseKey)(const void *);
} WMHashTableCallbacks;
typedef int WMArrayIterator;
typedef void *WMBagIterator;
typedef void WMNotificationObserverAction(void *observerData,
WMNotification *notification);
/* ---[ Macros ]---------------------------------------------------------- */
#define wlengthof(array) \
({ \
_wutil_static_assert(sizeof(array) > sizeof(array[0]), \
"the macro 'wlengthof' cannot be used on pointers, only on known size arrays"); \
sizeof(array) / sizeof(array[0]); \
})
/* These macros can be used to adjust the location and size pixel values in
* the panel layouts so that they match the configured size of the system
* font (useful with high DPI screens, where you have to increase this size).
* The macros require two local variables to be set:
* wmScaleWidth: the width of the alphabet in the current system font
* wmScaleHeight: the height of the current system font
* Use the WMGetScaleBaseFromSystemFont function to set these values.
*/
#define WMScaleX(value) ((int)((double)value / 177.0 * (double)wmScaleWidth + 0.5))
#define WMScaleY(value) ((int)((double)value / 15.0 * (double)wmScaleHeight + 0.5))
/* ---[ WINGs/memory.c ]-------------------------------------------------- */
void* wmalloc(size_t size);
void* wrealloc(void *ptr, size_t newsize);
void wfree(void *ptr);
void wrelease(void *ptr);
void* wretain(void *ptr);
typedef void waborthandler(int);
waborthandler* wsetabort(waborthandler* handler);
/* ---[ WINGs/error.c ]--------------------------------------------------- */
enum {
WMESSAGE_TYPE_MESSAGE,
WMESSAGE_TYPE_WARNING,
WMESSAGE_TYPE_ERROR,
WMESSAGE_TYPE_FATAL
};
#define wmessage(fmt, args...) __wmessage( __func__, __FILE__, __LINE__, WMESSAGE_TYPE_MESSAGE, fmt, ## args)
#define wwarning(fmt, args...) __wmessage( __func__, __FILE__, __LINE__, WMESSAGE_TYPE_WARNING, fmt, ## args)
#define werror(fmt, args...) __wmessage( __func__, __FILE__, __LINE__, WMESSAGE_TYPE_ERROR, fmt, ## args)
#define wfatal(fmt, args...) __wmessage( __func__, __FILE__, __LINE__, WMESSAGE_TYPE_FATAL, fmt, ## args)
void __wmessage(const char *func, const char *file, int line, int type, const char *msg, ...)
__attribute__((__format__(printf,5,6)));
/* ---[ WINGs/findfile.c ]------------------------------------------------ */
/* For the 4 function below, you have to free the returned string when you no longer need it */
char* wfindfile(const char *paths, const char *file);
char* wfindfileinlist(char *const *path_list, const char *file);
char* wfindfileinarray(WMPropList* array, const char *file);
char* wexpandpath(const char *path);
int wcopy_file(const char *toPath, const char *srcFile, const char *destFile);
/* don't free the returned string */
const char* wgethomedir(void);
/* ---[ WINGs/proplist.c ]------------------------------------------------ */
int wmkdirhier(const char *path);
int wrmdirhier(const char *path);
/* ---[ WINGs/string.c ]-------------------------------------------------- */
char *wstrdup(const char *str);
char* wstrndup(const char *str, size_t len);
/* Concatenate str1 with str2 and return that in a newly malloc'ed string.
* str1 and str2 can be any strings including static and constant strings.
* str1 and str2 will not be modified.
* Free the returned string when you're done with it. */
char* wstrconcat(const char *str1, const char *str2);
/* This will append src to dst, and return dst. dst MUST be either NULL
* or a string that was a result of a dynamic allocation (malloc, realloc
* wmalloc, wrealloc, ...). dst CANNOT be a static or a constant string!
* Modifies dst (no new string is created except if dst==NULL in which case
* it is equivalent to calling wstrdup(src) ).
* The returned address may be different from the original address of dst,
* so always assign the returned address to avoid dangling pointers. */
char* wstrappend(char *dst, const char *src);
size_t wstrlcpy(char *, const char *, size_t);
size_t wstrlcat(char *, const char *, size_t);
void wtokensplit(char *command, char ***argv, int *argc);
char* wtokennext(char *word, char **next);
char* wtokenjoin(char **list, int count);
void wtokenfree(char **tokens, int count);
char* wtrimspace(const char *s);
/* transform `s' so that the result is safe to pass to the shell as an argument.
* returns a newly allocated string.
* with very heavy inspirations from NetBSD's shquote(3).
*/
char *wshellquote(const char *s);
/* ---[ WINGs/misc.c ]--------------------------------------------------- */
WMRange wmkrange(int start, int count);
/* An application must call this function before exiting, to let WUtil do some internal cleanup */
void wutil_shutdown(void);
/* ---[ WINGs/usleep.c ]-------------------------------------------------- */
void wusleep(unsigned int usec);
/* ---[ WINGs/handlers.c ]------------------------------------------------ */
/* Event handlers: timer, idle, input */
WMHandlerID WMAddTimerHandler(int milliseconds, WMCallback *callback,
void *cdata);
WMHandlerID WMAddPersistentTimerHandler(int milliseconds, WMCallback *callback,
void *cdata);
void WMDeleteTimerWithClientData(void *cdata);
void WMDeleteTimerHandler(WMHandlerID handlerID);
WMHandlerID WMAddIdleHandler(WMCallback *callback, void *cdata);
void WMDeleteIdleHandler(WMHandlerID handlerID);
WMHandlerID WMAddInputHandler(int fd, int condition, WMInputProc *proc,
void *clientData);
void WMDeleteInputHandler(WMHandlerID handlerID);
/* This function is used _only_ if you create a non-GUI program.
* For GUI based programs use WMNextEvent()/WMHandleEvent() instead.
* This function will handle all input/timer/idle events, then return.
*/
void WHandleEvents(void);
/* ---[ WINGs/hashtable.c ]----------------------------------------------- */
WMHashTable* WMCreateHashTable(const WMHashTableCallbacks callbacks);
void WMFreeHashTable(WMHashTable *table);
void WMResetHashTable(WMHashTable *table);
unsigned WMCountHashTable(WMHashTable *table);
void* WMHashGet(WMHashTable *table, const void *key);
/* Returns True if there is a value associated with <key> in the table, in
* which case <retKey> and <retItem> will contain the item's internal key
* address and the item's value respectively.
* If there is no value associated with <key> it will return False and in
* this case <retKey> and <retItem> will be undefined.
* Use this when you need to perform your own custom retain/release mechanism
* which requires access to the keys too.
*/
Bool WMHashGetItemAndKey(WMHashTable *table, const void *key,
void **retItem, void **retKey);
/* put data in table, replacing already existing data and returning
* the old value */
void* WMHashInsert(WMHashTable *table, const void *key, const void *data);
void WMHashRemove(WMHashTable *table, const void *key);
/* warning: do not manipulate the table while using the enumerator functions */
WMHashEnumerator WMEnumerateHashTable(WMHashTable *table);
void* WMNextHashEnumeratorItem(WMHashEnumerator *enumerator);
void* WMNextHashEnumeratorKey(WMHashEnumerator *enumerator);
/* Returns True if there is a next element, in which case key and item
* will contain the next element's key and value respectively.
* If there is no next element available it will return False and in this
* case key and item will be undefined.
*/
Bool WMNextHashEnumeratorItemAndKey(WMHashEnumerator *enumerator,
void **item, void **key);
/* some predefined callback sets */
extern const WMHashTableCallbacks WMIntHashCallbacks;
/* sizeof(keys) are <= sizeof(void*) */
extern const WMHashTableCallbacks WMStringHashCallbacks;
/* keys are strings. Strings will be copied with wstrdup()
* and freed with wfree() */
extern const WMHashTableCallbacks WMStringPointerHashCallbacks;
/* keys are strings, but they are not copied */
/* ---[ WINGs/array.c ]--------------------------------------------------- */
/*
* WMArray use an array to store the elements.
* Item indexes may be only positive integer numbers.
* The array cannot contain holes in it.
*
* Pros:
* Fast [O(1)] access to elements
* Fast [O(1)] push/pop
*
* Cons:
* A little slower [O(n)] for insertion/deletion of elements that
* aren't in the end
*/
WMArray* WMCreateArray(int initialSize);
WMArray* WMCreateArrayWithDestructor(int initialSize, WMFreeDataProc *destructor);
WMArray* WMCreateArrayWithArray(WMArray *array);
#define WMDuplicateArray(array) WMCreateArrayWithArray(array)
void WMEmptyArray(WMArray *array);
void WMFreeArray(WMArray *array);
int WMGetArrayItemCount(WMArray *array);
/* appends other to array. other remains unchanged */
void WMAppendArray(WMArray *array, WMArray *other);
/* add will place the element at the end of the array */
void WMAddToArray(WMArray *array, void *item);
/* insert will increment the index of elements after it by 1 */
void WMInsertInArray(WMArray *array, int index, void *item);
/* replace and set will return the old item WITHOUT calling the
* destructor on it even if its available. Free the returned item yourself.
*/
void* WMReplaceInArray(WMArray *array, int index, void *item);
#define WMSetInArray(array, index, item) WMReplaceInArray(array, index, item)
/* delete and remove will remove the elements and cause the elements
* after them to decrement their indexes by 1. Also will call the
* destructor on the deleted element if there's one available.
*/
int WMDeleteFromArray(WMArray *array, int index);
#define WMRemoveFromArray(array, item) WMRemoveFromArrayMatching(array, NULL, item)
int WMRemoveFromArrayMatching(WMArray *array, WMMatchDataProc *match, void *cdata);
void* WMGetFromArray(WMArray *array, int index);
#define WMGetFirstInArray(array, item) WMFindInArray(array, NULL, item)
/* pop will return the last element from the array, also removing it
* from the array. The destructor is NOT called, even if available.
* Free the returned element if needed by yourself
*/
void* WMPopFromArray(WMArray *array);
int WMFindInArray(WMArray *array, WMMatchDataProc *match, void *cdata);
int WMCountInArray(WMArray *array, void *item);
/* comparer must return:
* < 0 if a < b
* > 0 if a > b
* = 0 if a = b
*/
void WMSortArray(WMArray *array, WMCompareDataProc *comparer);
void WMMapArray(WMArray *array, void (*function)(void*, void*), void *data);
WMArray* WMGetSubarrayWithRange(WMArray* array, WMRange aRange);
void* WMArrayFirst(WMArray *array, WMArrayIterator *iter);
void* WMArrayLast(WMArray *array, WMArrayIterator *iter);
/* The following 2 functions assume that the array doesn't change between calls */
void* WMArrayNext(WMArray *array, WMArrayIterator *iter);
void* WMArrayPrevious(WMArray *array, WMArrayIterator *iter);
/* The following 2 macros assume that the array doesn't change in the for loop */
#define WM_ITERATE_ARRAY(array, var, i) \
for (var = WMArrayFirst(array, &(i)); (i) != WANotFound; \
var = WMArrayNext(array, &(i)))
#define WM_ETARETI_ARRAY(array, var, i) \
for (var = WMArrayLast(array, &(i)); (i) != WANotFound; \
var = WMArrayPrevious(array, &(i)))
/* ---[ WINGs/bagtree.c ]------------------------------------------------- */
/*
* Tree bags use a red-black tree for storage.
* Item indexes may be any integer number.
*
* Pros:
* O(lg n) insertion/deletion/search
* Good for large numbers of elements with sparse indexes
*
* Cons:
* O(lg n) insertion/deletion/search
* Slow for storing small numbers of elements
*/
#define WMCreateBag(size) WMCreateTreeBag()
#define WMCreateBagWithDestructor(size, d) WMCreateTreeBagWithDestructor(d)
WMBag* WMCreateTreeBag(void);
WMBag* WMCreateTreeBagWithDestructor(WMFreeDataProc *destructor);
int WMGetBagItemCount(WMBag *bag);
void WMAppendBag(WMBag *bag, WMBag *other);
void WMPutInBag(WMBag *bag, void *item);
/* insert will increment the index of elements after it by 1 */
void WMInsertInBag(WMBag *bag, int index, void *item);
/* erase will remove the element from the bag,
* but will keep the index of the other elements unchanged */
int WMEraseFromBag(WMBag *bag, int index);
/* delete and remove will remove the elements and cause the elements
* after them to decrement their indexes by 1 */
int WMDeleteFromBag(WMBag *bag, int index);
int WMRemoveFromBag(WMBag *bag, void *item);
void* WMGetFromBag(WMBag *bag, int index);
void* WMReplaceInBag(WMBag *bag, int index, void *item);
#define WMSetInBag(bag, index, item) WMReplaceInBag(bag, index, item)
/* comparer must return:
* < 0 if a < b
* > 0 if a > b
* = 0 if a = b
*/
void WMSortBag(WMBag *bag, WMCompareDataProc *comparer);
void WMEmptyBag(WMBag *bag);
void WMFreeBag(WMBag *bag);
void WMMapBag(WMBag *bag, void (*function)(void*, void*), void *data);
int WMGetFirstInBag(WMBag *bag, void *item);
int WMCountInBag(WMBag *bag, void *item);
int WMFindInBag(WMBag *bag, WMMatchDataProc *match, void *cdata);
void* WMBagFirst(WMBag *bag, WMBagIterator *ptr);
void* WMBagLast(WMBag *bag, WMBagIterator *ptr);
/* The following 4 functions assume that the bag doesn't change between calls */
void* WMBagNext(WMBag *bag, WMBagIterator *ptr);
void* WMBagPrevious(WMBag *bag, WMBagIterator *ptr);
void* WMBagIteratorAtIndex(WMBag *bag, int index, WMBagIterator *ptr);
int WMBagIndexForIterator(WMBag *bag, WMBagIterator ptr);
/* The following 2 macros assume that the bag doesn't change in the for loop */
#define WM_ITERATE_BAG(bag, var, i) \
for (var = WMBagFirst(bag, &(i)); (i) != NULL; \
var = WMBagNext(bag, &(i)))
#define WM_ETARETI_BAG(bag, var, i) \
for (var = WMBagLast(bag, &(i)); (i) != NULL; \
var = WMBagPrevious(bag, &(i)))
/* ---[ WINGs/data.c ]---------------------------------------------------- */
/* WMData handling */
/* Creating/destroying data */
WMData* WMCreateDataWithCapacity(unsigned capacity);
WMData* WMCreateDataWithLength(unsigned length);
WMData* WMCreateDataWithBytes(const void *bytes, unsigned length);
/* destructor is a function called to free the data when releasing the data
* object, or NULL if no freeing of data is necesary. */
WMData* WMCreateDataWithBytesNoCopy(void *bytes, unsigned length,
WMFreeDataProc *destructor);
WMData* WMCreateDataWithData(WMData *aData);
WMData* WMRetainData(WMData *aData);
void WMReleaseData(WMData *aData);
/* Adjusting capacity */
void WMSetDataCapacity(WMData *aData, unsigned capacity);
void WMSetDataLength(WMData *aData, unsigned length);
void WMIncreaseDataLengthBy(WMData *aData, unsigned extraLength);
/* Accessing data */
const void* WMDataBytes(WMData *aData);
void WMGetDataBytes(WMData *aData, void *buffer);
void WMGetDataBytesWithLength(WMData *aData, void *buffer, unsigned length);
void WMGetDataBytesWithRange(WMData *aData, void *buffer, WMRange aRange);
WMData* WMGetSubdataWithRange(WMData *aData, WMRange aRange);
/* Testing data */
Bool WMIsDataEqualToData(WMData *aData, WMData *anotherData);
unsigned WMGetDataLength(WMData *aData);
/* Adding data */
void WMAppendDataBytes(WMData *aData, const void *bytes, unsigned length);
void WMAppendData(WMData *aData, WMData *anotherData);
/* Modifying data */
void WMReplaceDataBytesInRange(WMData *aData, WMRange aRange, const void *bytes);
void WMResetDataBytesInRange(WMData *aData, WMRange aRange);
void WMSetData(WMData *aData, WMData *anotherData);
void WMSetDataFormat(WMData *aData, unsigned format);
unsigned WMGetDataFormat(WMData *aData);
/* Storing data */
/* ---[ WINGs/tree.c ]---------------------------------------------------- */
/* Generic Tree and TreeNode */
WMTreeNode* WMCreateTreeNode(void *data);
WMTreeNode* WMCreateTreeNodeWithDestructor(void *data, WMFreeDataProc *destructor);
WMTreeNode* WMInsertItemInTree(WMTreeNode *parent, int index, void *item);
#define WMAddItemToTree(parent, item) WMInsertItemInTree(parent, -1, item)
WMTreeNode* WMInsertNodeInTree(WMTreeNode *parent, int index, WMTreeNode *aNode);
#define WMAddNodeToTree(parent, aNode) WMInsertNodeInTree(parent, -1, aNode)
void WMDestroyTreeNode(WMTreeNode *aNode);
void WMDeleteLeafForTreeNode(WMTreeNode *aNode, int index);
void WMRemoveLeafForTreeNode(WMTreeNode *aNode, void *leaf);
void* WMReplaceDataForTreeNode(WMTreeNode *aNode, void *newData);
void* WMGetDataForTreeNode(WMTreeNode *aNode);
int WMGetTreeNodeDepth(WMTreeNode *aNode);
WMTreeNode* WMGetParentForTreeNode(WMTreeNode *aNode);
/* Sort only the leaves of the passed node */
void WMSortLeavesForTreeNode(WMTreeNode *aNode, WMCompareDataProc *comparer);
/* Sort all tree recursively starting from the passed node */
void WMSortTree(WMTreeNode *aNode, WMCompareDataProc *comparer);
/* Returns the first node which matches node's data with cdata by 'match' */
WMTreeNode* WMFindInTree(WMTreeNode *aTree, WMMatchDataProc *match, void *cdata);
/* Returns the first node where node's data matches cdata by 'match' and node is
* at most `limit' depths down from `aTree'. */
WMTreeNode *WMFindInTreeWithDepthLimit(WMTreeNode * aTree, WMMatchDataProc * match, void *cdata, int limit);
/* Returns first tree node that has data == cdata */
#define WMGetFirstInTree(aTree, cdata) WMFindInTree(aTree, NULL, cdata)
/* Walk every node of aNode with `walk' */
void WMTreeWalk(WMTreeNode *aNode, WMTreeWalkProc * walk, void *data, Bool DepthFirst);
/* ---[ WINGs/data.c ]---------------------------------------------------- */
WMNotification* WMCreateNotification(const char *name, void *object, void *clientData);
void WMReleaseNotification(WMNotification *notification);
WMNotification* WMRetainNotification(WMNotification *notification);
void* WMGetNotificationClientData(WMNotification *notification);
void* WMGetNotificationObject(WMNotification *notification);
const char* WMGetNotificationName(WMNotification *notification);
void WMAddNotificationObserver(WMNotificationObserverAction *observerAction,
void *observer, const char *name, void *object);
void WMPostNotification(WMNotification *notification);
void WMRemoveNotificationObserver(void *observer);
void WMRemoveNotificationObserverWithName(void *observer, const char *name,
void *object);
void WMPostNotificationName(const char *name, void *object, void *clientData);
WMNotificationQueue* WMGetDefaultNotificationQueue(void);
WMNotificationQueue* WMCreateNotificationQueue(void);
void WMDequeueNotificationMatching(WMNotificationQueue *queue,
WMNotification *notification,
unsigned mask);
void WMEnqueueNotification(WMNotificationQueue *queue,
WMNotification *notification,
WMPostingStyle postingStyle);
void WMEnqueueCoalesceNotification(WMNotificationQueue *queue,
WMNotification *notification,
WMPostingStyle postingStyle,
unsigned coalesceMask);
/* ---[ WINGs/proplist.c ]------------------------------------------------ */
/* Property Lists handling */
void WMPLSetCaseSensitive(Bool caseSensitive);
WMPropList* WMCreatePLString(const char *str);
WMPropList* WMCreatePLData(WMData *data);
WMPropList* WMCreatePLDataWithBytes(const unsigned char *bytes, unsigned int length);
WMPropList* WMCreatePLDataWithBytesNoCopy(unsigned char *bytes,
unsigned int length,
WMFreeDataProc *destructor);
WMPropList* WMCreatePLArray(WMPropList *elem, ...);
WMPropList* WMCreatePLDictionary(WMPropList *key, WMPropList *value, ...);
WMPropList* WMRetainPropList(WMPropList *plist);
void WMReleasePropList(WMPropList *plist);
/* Objects inserted in arrays and dictionaries will be retained,
* so you can safely release them after insertion.
* For dictionaries both the key and value are retained.
* Objects removed from arrays or dictionaries are released */
void WMInsertInPLArray(WMPropList *plist, int index, WMPropList *item);
void WMAddToPLArray(WMPropList *plist, WMPropList *item);
void WMDeleteFromPLArray(WMPropList *plist, int index);
void WMRemoveFromPLArray(WMPropList *plist, WMPropList *item);
void WMPutInPLDictionary(WMPropList *plist, WMPropList *key, WMPropList *value);
void WMRemoveFromPLDictionary(WMPropList *plist, WMPropList *key);
/* It will insert all key/value pairs from source into dest, overwriting
* the values with the same keys from dest, keeping all values with keys
* only present in dest unchanged */
WMPropList* WMMergePLDictionaries(WMPropList *dest, WMPropList *source,
Bool recursive);
/* It will remove all key/value pairs from dest for which there is an
* identical key/value present in source. Entires only present in dest, or
* which have different values in dest than in source will be preserved. */
WMPropList* WMSubtractPLDictionaries(WMPropList *dest, WMPropList *source,
Bool recursive);
int WMGetPropListItemCount(WMPropList *plist);
Bool WMIsPLString(WMPropList *plist);
Bool WMIsPLData(WMPropList *plist);
Bool WMIsPLArray(WMPropList *plist);
Bool WMIsPLDictionary(WMPropList *plist);
Bool WMIsPropListEqualTo(WMPropList *plist, WMPropList *other);
/* Returns a reference. Do not free it! */
char* WMGetFromPLString(WMPropList *plist);
/* Returns a reference. Do not free it! */
WMData* WMGetFromPLData(WMPropList *plist);
/* Returns a reference. Do not free it! */
const unsigned char* WMGetPLDataBytes(WMPropList *plist);
int WMGetPLDataLength(WMPropList *plist);
/* Returns a reference. */
WMPropList* WMGetFromPLArray(WMPropList *plist, int index);
/* Returns a reference. */
WMPropList* WMGetFromPLDictionary(WMPropList *plist, WMPropList *key);
/* Returns a PropList array with all the dictionary keys. Release it when
* you're done. Keys in array are retained from the original dictionary
* not copied and need NOT to be released individually. */
WMPropList* WMGetPLDictionaryKeys(WMPropList *plist);
/* Creates only the first level deep object. All the elements inside are
* retained from the original */
WMPropList* WMShallowCopyPropList(WMPropList *plist);
/* Makes a completely separate replica of the original proplist */
WMPropList* WMDeepCopyPropList(WMPropList *plist);
WMPropList* WMCreatePropListFromDescription(const char *desc);
/* Free the returned string when you no longer need it */
char* WMGetPropListDescription(WMPropList *plist, Bool indented);
WMPropList* WMReadPropListFromFile(const char *file);
WMPropList* WMReadPropListFromPipe(const char *command);
Bool WMWritePropListToFile(WMPropList *plist, const char *path);
/* ---[ WINGs/userdefaults.c ]-------------------------------------------- */
/* don't free the returned string */
const char* wusergnusteppath(void);
const char* wuserdatapath(void);
/* Free the returned string when you no longer need it */
char* wdefaultspathfordomain(const char *domain);
/* Free the returned string when you no longer need it */
char* wglobaldefaultspathfordomain(const char *domain);
WMUserDefaults* WMGetStandardUserDefaults(void);
WMUserDefaults* WMGetDefaultsFromPath(const char *path);
void WMSynchronizeUserDefaults(WMUserDefaults *database);
void WMSaveUserDefaults(WMUserDefaults *database);
void WMEnableUDPeriodicSynchronization(WMUserDefaults *database, Bool enable);
/* Returns a WMPropList array with all the keys in the user defaults database.
* Free the array with WMReleasePropList() when no longer needed.
* Keys in array are just retained references to the original keys */
WMPropList* WMGetUDKeys(WMUserDefaults *database);
WMPropList* WMGetUDObjectForKey(WMUserDefaults *database, const char *defaultName);
void WMSetUDObjectForKey(WMUserDefaults *database, WMPropList *object,
const char *defaultName);
void WMRemoveUDObjectForKey(WMUserDefaults *database, const char *defaultName);
/* Returns a reference. Do not free it! */
char* WMGetUDStringForKey(WMUserDefaults *database, const char *defaultName);
int WMGetUDIntegerForKey(WMUserDefaults *database, const char *defaultName);
float WMGetUDFloatForKey(WMUserDefaults *database, const char *defaultName);
Bool WMGetUDBoolForKey(WMUserDefaults *database, const char *defaultName);
void WMSetUDStringForKey(WMUserDefaults *database, const char *value,
const char *defaultName);
void WMSetUDIntegerForKey(WMUserDefaults *database, int value,
const char *defaultName);
void WMSetUDFloatForKey(WMUserDefaults *database, float value,
const char *defaultName);
void WMSetUDBoolForKey(WMUserDefaults *database, Bool value,
const char *defaultName);
WMPropList* WMGetUDSearchList(WMUserDefaults *database);
void WMSetUDSearchList(WMUserDefaults *database, WMPropList *list);
extern char *WMUserDefaultsDidChangeNotification;
/* ---[ WINGs/menuparser.c ]---------------------------------------------- */
typedef struct w_menu_parser *WMenuParser;
WMenuParser WMenuParserCreate(const char *file_name, void *file, const char *include_default_paths);
void WMenuParserRegisterSimpleMacro(WMenuParser parser, const char *name, const char *value);
void WMenuParserError(WMenuParser parser, const char *msg, ...)
__attribute__ ((format (printf, 2, 3)));
const char *WMenuParserGetFilename(WMenuParser parser);
Bool WMenuParserGetLine(WMenuParser parser, char **title, char **command, char **parameter, char **shortcut);
void WMenuParserDelete(WMenuParser parser);
/*-------------------------------------------------------------------------*/
/* Global variables */
extern int WCErrorCode;
/*-------------------------------------------------------------------------*/
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif

View File

@@ -1,363 +0,0 @@
/*
* Dynamically Resized Array
*
* Authors: Alfredo K. Kojima <kojima@windowmaker.info>
* Dan Pascu <dan@windowmaker.info>
*
* This code is released to the Public Domain, but
* proper credit is always appreciated :)
*/
#include <stdlib.h>
#include <string.h>
#include "WINGs/WUtil.h"
#define INITIAL_SIZE 8
#define RESIZE_INCREMENT 8
typedef struct W_Array {
void **items; /* the array data */
int itemCount; /* # of items in array */
int allocSize; /* allocated size of array */
WMFreeDataProc *destructor; /* the destructor to free elements */
} W_Array;
WMArray *WMCreateArray(int initialSize)
{
return WMCreateArrayWithDestructor(initialSize, NULL);
}
WMArray *WMCreateArrayWithDestructor(int initialSize, WMFreeDataProc * destructor)
{
WMArray *array;
array = wmalloc(sizeof(WMArray));
if (initialSize <= 0) {
initialSize = INITIAL_SIZE;
}
array->items = wmalloc(sizeof(void *) * initialSize);
array->itemCount = 0;
array->allocSize = initialSize;
array->destructor = destructor;
return array;
}
WMArray *WMCreateArrayWithArray(WMArray * array)
{
WMArray *newArray;
newArray = wmalloc(sizeof(WMArray));
newArray->items = wmalloc(sizeof(void *) * array->allocSize);
memcpy(newArray->items, array->items, sizeof(void *) * array->itemCount);
newArray->itemCount = array->itemCount;
newArray->allocSize = array->allocSize;
newArray->destructor = NULL;
return newArray;
}
void WMEmptyArray(WMArray * array)
{
if (array->destructor) {
while (array->itemCount > 0) {
array->itemCount--;
array->destructor(array->items[array->itemCount]);
}
}
/*memset(array->items, 0, array->itemCount * sizeof(void*)); */
array->itemCount = 0;
}
void WMFreeArray(WMArray * array)
{
if (array == NULL)
return;
WMEmptyArray(array);
wfree(array->items);
wfree(array);
}
int WMGetArrayItemCount(WMArray * array)
{
if (array == NULL)
return 0;
return array->itemCount;
}
void WMAppendArray(WMArray * array, WMArray * other)
{
if (array == NULL || other == NULL)
return;
if (other->itemCount == 0)
return;
if (array->itemCount + other->itemCount > array->allocSize) {
array->allocSize += other->allocSize;
array->items = wrealloc(array->items, sizeof(void *) * array->allocSize);
}
memcpy(array->items + array->itemCount, other->items, sizeof(void *) * other->itemCount);
array->itemCount += other->itemCount;
}
void WMAddToArray(WMArray * array, void *item)
{
if (array == NULL)
return;
if (array->itemCount >= array->allocSize) {
array->allocSize += RESIZE_INCREMENT;
array->items = wrealloc(array->items, sizeof(void *) * array->allocSize);
}
array->items[array->itemCount] = item;
array->itemCount++;
}
void WMInsertInArray(WMArray * array, int index, void *item)
{
if (array == NULL)
return;
wassertr(index >= 0 && index <= array->itemCount);
if (array->itemCount >= array->allocSize) {
array->allocSize += RESIZE_INCREMENT;
array->items = wrealloc(array->items, sizeof(void *) * array->allocSize);
}
if (index < array->itemCount) {
memmove(array->items + index + 1, array->items + index,
sizeof(void *) * (array->itemCount - index));
}
array->items[index] = item;
array->itemCount++;
}
void *WMReplaceInArray(WMArray * array, int index, void *item)
{
void *old;
if (array == NULL)
return NULL;
wassertrv(index >= 0 && index <= array->itemCount, NULL);
/* is it really useful to perform append if index == array->itemCount ? -Dan */
if (index == array->itemCount) {
WMAddToArray(array, item);
return NULL;
}
old = array->items[index];
array->items[index] = item;
return old;
}
int WMDeleteFromArray(WMArray * array, int index)
{
if (array == NULL)
return 0;
wassertrv(index >= 0 && index < array->itemCount, 0);
if (array->destructor) {
array->destructor(array->items[index]);
}
if (index < array->itemCount - 1) {
memmove(array->items + index, array->items + index + 1,
sizeof(void *) * (array->itemCount - index - 1));
}
array->itemCount--;
return 1;
}
int WMRemoveFromArrayMatching(WMArray * array, WMMatchDataProc * match, void *cdata)
{
int i;
if (array == NULL)
return 1;
if (match != NULL) {
for (i = 0; i < array->itemCount; i++) {
if ((*match) (array->items[i], cdata)) {
WMDeleteFromArray(array, i);
return 1;
}
}
} else {
for (i = 0; i < array->itemCount; i++) {
if (array->items[i] == cdata) {
WMDeleteFromArray(array, i);
return 1;
}
}
}
return 0;
}
void *WMGetFromArray(WMArray * array, int index)
{
if (index < 0 || array == NULL || index >= array->itemCount)
return NULL;
return array->items[index];
}
void *WMPopFromArray(WMArray * array)
{
if (array == NULL || array->itemCount <= 0)
return NULL;
array->itemCount--;
return array->items[array->itemCount];
}
int WMFindInArray(WMArray * array, WMMatchDataProc * match, void *cdata)
{
int i;
if (array == NULL)
return WANotFound;
if (match != NULL) {
for (i = 0; i < array->itemCount; i++) {
if ((*match) (array->items[i], cdata))
return i;
}
} else {
for (i = 0; i < array->itemCount; i++) {
if (array->items[i] == cdata)
return i;
}
}
return WANotFound;
}
int WMCountInArray(WMArray * array, void *item)
{
int i, count;
if (array == NULL)
return 0;
for (i = 0, count = 0; i < array->itemCount; i++) {
if (array->items[i] == item)
count++;
}
return count;
}
void WMSortArray(WMArray * array, WMCompareDataProc * comparer)
{
if (array == NULL)
return;
if (array->itemCount > 1) { /* Don't sort empty or single element arrays */
qsort(array->items, array->itemCount, sizeof(void *), comparer);
}
}
void WMMapArray(WMArray * array, void (*function) (void *, void *), void *data)
{
int i;
if (array == NULL)
return;
for (i = 0; i < array->itemCount; i++) {
(*function) (array->items[i], data);
}
}
WMArray *WMGetSubarrayWithRange(WMArray * array, WMRange aRange)
{
WMArray *newArray;
if (aRange.count <= 0 || array == NULL)
return WMCreateArray(0);
if (aRange.position < 0)
aRange.position = 0;
if (aRange.position >= array->itemCount)
aRange.position = array->itemCount - 1;
if (aRange.position + aRange.count > array->itemCount)
aRange.count = array->itemCount - aRange.position;
newArray = WMCreateArray(aRange.count);
memcpy(newArray->items, array->items + aRange.position, sizeof(void *) * aRange.count);
newArray->itemCount = aRange.count;
return newArray;
}
void *WMArrayFirst(WMArray * array, WMArrayIterator * iter)
{
if (array == NULL || array->itemCount == 0) {
*iter = WANotFound;
return NULL;
} else {
*iter = 0;
return array->items[0];
}
}
void *WMArrayLast(WMArray * array, WMArrayIterator * iter)
{
if (array == NULL || array->itemCount == 0) {
*iter = WANotFound;
return NULL;
} else {
*iter = array->itemCount - 1;
return array->items[*iter];
}
}
void *WMArrayNext(WMArray * array, WMArrayIterator * iter)
{
if (array == NULL) {
*iter = WANotFound;
return NULL;
}
if (*iter >= 0 && *iter < array->itemCount - 1) {
return array->items[++(*iter)];
} else {
*iter = WANotFound;
return NULL;
}
}
void *WMArrayPrevious(WMArray * array, WMArrayIterator * iter)
{
if (array == NULL) {
*iter = WANotFound;
return NULL;
}
if (*iter > 0 && *iter < array->itemCount) {
return array->items[--(*iter)];
} else {
*iter = WANotFound;
return NULL;
}
}

View File

@@ -1,745 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include "WUtil.h"
typedef struct W_Node {
struct W_Node *parent;
struct W_Node *left;
struct W_Node *right;
int color;
void *data;
int index;
} W_Node;
typedef struct W_Bag {
W_Node *root;
W_Node *nil; /* sentinel */
int count;
void (*destructor) (void *item);
} W_Bag;
#define IS_LEFT(node) (node == node->parent->left)
#define IS_RIGHT(node) (node == node->parent->right)
static void leftRotate(W_Bag * tree, W_Node * node)
{
W_Node *node2;
node2 = node->right;
node->right = node2->left;
node2->left->parent = node;
node2->parent = node->parent;
if (node->parent == tree->nil) {
tree->root = node2;
} else {
if (IS_LEFT(node)) {
node->parent->left = node2;
} else {
node->parent->right = node2;
}
}
node2->left = node;
node->parent = node2;
}
static void rightRotate(W_Bag * tree, W_Node * node)
{
W_Node *node2;
node2 = node->left;
node->left = node2->right;
node2->right->parent = node;
node2->parent = node->parent;
if (node->parent == tree->nil) {
tree->root = node2;
} else {
if (IS_LEFT(node)) {
node->parent->left = node2;
} else {
node->parent->right = node2;
}
}
node2->right = node;
node->parent = node2;
}
static void treeInsert(W_Bag * tree, W_Node * node)
{
W_Node *y = tree->nil;
W_Node *x = tree->root;
while (x != tree->nil) {
y = x;
if (node->index <= x->index)
x = x->left;
else
x = x->right;
}
node->parent = y;
if (y == tree->nil)
tree->root = node;
else if (node->index <= y->index)
y->left = node;
else
y->right = node;
}
static void rbTreeInsert(W_Bag * tree, W_Node * node)
{
W_Node *y;
treeInsert(tree, node);
node->color = 'R';
while (node != tree->root && node->parent->color == 'R') {
if (IS_LEFT(node->parent)) {
y = node->parent->parent->right;
if (y->color == 'R') {
node->parent->color = 'B';
y->color = 'B';
node->parent->parent->color = 'R';
node = node->parent->parent;
} else {
if (IS_RIGHT(node)) {
node = node->parent;
leftRotate(tree, node);
}
node->parent->color = 'B';
node->parent->parent->color = 'R';
rightRotate(tree, node->parent->parent);
}
} else {
y = node->parent->parent->left;
if (y->color == 'R') {
node->parent->color = 'B';
y->color = 'B';
node->parent->parent->color = 'R';
node = node->parent->parent;
} else {
if (IS_LEFT(node)) {
node = node->parent;
rightRotate(tree, node);
}
node->parent->color = 'B';
node->parent->parent->color = 'R';
leftRotate(tree, node->parent->parent);
}
}
}
tree->root->color = 'B';
}
static void rbDeleteFixup(W_Bag * tree, W_Node * node)
{
W_Node *w;
while (node != tree->root && node->color == 'B') {
if (IS_LEFT(node)) {
w = node->parent->right;
if (w->color == 'R') {
w->color = 'B';
node->parent->color = 'R';
leftRotate(tree, node->parent);
w = node->parent->right;
}
if (w->left->color == 'B' && w->right->color == 'B') {
w->color = 'R';
node = node->parent;
} else {
if (w->right->color == 'B') {
w->left->color = 'B';
w->color = 'R';
rightRotate(tree, w);
w = node->parent->right;
}
w->color = node->parent->color;
node->parent->color = 'B';
w->right->color = 'B';
leftRotate(tree, node->parent);
node = tree->root;
}
} else {
w = node->parent->left;
if (w->color == 'R') {
w->color = 'B';
node->parent->color = 'R';
rightRotate(tree, node->parent);
w = node->parent->left;
}
if (w->left->color == 'B' && w->right->color == 'B') {
w->color = 'R';
node = node->parent;
} else {
if (w->left->color == 'B') {
w->right->color = 'B';
w->color = 'R';
leftRotate(tree, w);
w = node->parent->left;
}
w->color = node->parent->color;
node->parent->color = 'B';
w->left->color = 'B';
rightRotate(tree, node->parent);
node = tree->root;
}
}
}
node->color = 'B';
}
static W_Node *treeMinimum(W_Node * node, W_Node * nil)
{
while (node->left != nil)
node = node->left;
return node;
}
static W_Node *treeMaximum(W_Node * node, W_Node * nil)
{
while (node->right != nil)
node = node->right;
return node;
}
static W_Node *treeSuccessor(W_Node * node, W_Node * nil)
{
W_Node *y;
if (node->right != nil) {
return treeMinimum(node->right, nil);
}
y = node->parent;
while (y != nil && node == y->right) {
node = y;
y = y->parent;
}
return y;
}
static W_Node *treePredecessor(W_Node * node, W_Node * nil)
{
W_Node *y;
if (node->left != nil) {
return treeMaximum(node->left, nil);
}
y = node->parent;
while (y != nil && node == y->left) {
node = y;
y = y->parent;
}
return y;
}
static W_Node *rbTreeDelete(W_Bag * tree, W_Node * node)
{
W_Node *nil = tree->nil;
W_Node *x, *y;
if (node->left == nil || node->right == nil) {
y = node;
} else {
y = treeSuccessor(node, nil);
}
if (y->left != nil) {
x = y->left;
} else {
x = y->right;
}
x->parent = y->parent;
if (y->parent == nil) {
tree->root = x;
} else {
if (IS_LEFT(y)) {
y->parent->left = x;
} else {
y->parent->right = x;
}
}
if (y != node) {
node->index = y->index;
node->data = y->data;
}
if (y->color == 'B') {
rbDeleteFixup(tree, x);
}
return y;
}
static W_Node *treeSearch(W_Node * root, W_Node * nil, int index)
{
if (root == nil || root->index == index) {
return root;
}
if (index < root->index) {
return treeSearch(root->left, nil, index);
} else {
return treeSearch(root->right, nil, index);
}
}
static W_Node *treeFind(W_Node * root, W_Node * nil, void *data)
{
W_Node *tmp;
if (root == nil || root->data == data)
return root;
tmp = treeFind(root->left, nil, data);
if (tmp != nil)
return tmp;
tmp = treeFind(root->right, nil, data);
return tmp;
}
#if 0
static char buf[512];
static void printNodes(W_Node * node, W_Node * nil, int depth)
{
if (node == nil) {
return;
}
printNodes(node->left, nil, depth + 1);
memset(buf, ' ', depth * 2);
buf[depth * 2] = 0;
if (IS_LEFT(node))
printf("%s/(%2i\n", buf, node->index);
else
printf("%s\\(%2i\n", buf, node->index);
printNodes(node->right, nil, depth + 1);
}
void PrintTree(WMBag * bag)
{
W_TreeBag *tree = (W_TreeBag *) bag->data;
printNodes(tree->root, tree->nil, 0);
}
#endif
WMBag *WMCreateTreeBag(void)
{
return WMCreateTreeBagWithDestructor(NULL);
}
WMBag *WMCreateTreeBagWithDestructor(WMFreeDataProc * destructor)
{
WMBag *bag;
bag = wmalloc(sizeof(WMBag));
bag->nil = wmalloc(sizeof(W_Node));
bag->nil->left = bag->nil->right = bag->nil->parent = bag->nil;
bag->nil->index = WBNotFound;
bag->root = bag->nil;
bag->destructor = destructor;
return bag;
}
int WMGetBagItemCount(WMBag * self)
{
return self->count;
}
void WMAppendBag(WMBag * self, WMBag * bag)
{
WMBagIterator ptr;
void *data;
for (data = WMBagFirst(bag, &ptr); data != NULL; data = WMBagNext(bag, &ptr)) {
WMPutInBag(self, data);
}
}
void WMPutInBag(WMBag * self, void *item)
{
W_Node *ptr;
ptr = wmalloc(sizeof(W_Node));
ptr->data = item;
ptr->index = self->count;
ptr->left = self->nil;
ptr->right = self->nil;
ptr->parent = self->nil;
rbTreeInsert(self, ptr);
self->count++;
}
void WMInsertInBag(WMBag * self, int index, void *item)
{
W_Node *ptr;
ptr = wmalloc(sizeof(W_Node));
ptr->data = item;
ptr->index = index;
ptr->left = self->nil;
ptr->right = self->nil;
ptr->parent = self->nil;
rbTreeInsert(self, ptr);
while ((ptr = treeSuccessor(ptr, self->nil)) != self->nil) {
ptr->index++;
}
self->count++;
}
static int treeDeleteNode(WMBag * self, W_Node *ptr)
{
if (ptr != self->nil) {
W_Node *tmp;
self->count--;
tmp = treeSuccessor(ptr, self->nil);
while (tmp != self->nil) {
tmp->index--;
tmp = treeSuccessor(tmp, self->nil);
}
ptr = rbTreeDelete(self, ptr);
if (self->destructor)
self->destructor(ptr->data);
wfree(ptr);
return 1;
}
return 0;
}
int WMRemoveFromBag(WMBag * self, void *item)
{
W_Node *ptr = treeFind(self->root, self->nil, item);
return treeDeleteNode(self, ptr);
}
int WMEraseFromBag(WMBag * self, int index)
{
W_Node *ptr = treeSearch(self->root, self->nil, index);
if (ptr != self->nil) {
self->count--;
ptr = rbTreeDelete(self, ptr);
if (self->destructor)
self->destructor(ptr->data);
wfree(ptr);
wassertrv(self->count == 0 || self->root->index >= 0, 1);
return 1;
} else {
return 0;
}
}
int WMDeleteFromBag(WMBag * self, int index)
{
W_Node *ptr = treeSearch(self->root, self->nil, index);
return treeDeleteNode(self, ptr);
}
void *WMGetFromBag(WMBag * self, int index)
{
W_Node *node;
node = treeSearch(self->root, self->nil, index);
if (node != self->nil)
return node->data;
else
return NULL;
}
int WMGetFirstInBag(WMBag * self, void *item)
{
W_Node *node;
node = treeFind(self->root, self->nil, item);
if (node != self->nil)
return node->index;
else
return WBNotFound;
}
static int treeCount(W_Node * root, W_Node * nil, void *item)
{
int count = 0;
if (root == nil)
return 0;
if (root->data == item)
count++;
if (root->left != nil)
count += treeCount(root->left, nil, item);
if (root->right != nil)
count += treeCount(root->right, nil, item);
return count;
}
int WMCountInBag(WMBag * self, void *item)
{
return treeCount(self->root, self->nil, item);
}
void *WMReplaceInBag(WMBag * self, int index, void *item)
{
W_Node *ptr = treeSearch(self->root, self->nil, index);
void *old = NULL;
if (item == NULL) {
self->count--;
ptr = rbTreeDelete(self, ptr);
if (self->destructor)
self->destructor(ptr->data);
wfree(ptr);
} else if (ptr != self->nil) {
old = ptr->data;
ptr->data = item;
} else {
W_Node *ptr;
ptr = wmalloc(sizeof(W_Node));
ptr->data = item;
ptr->index = index;
ptr->left = self->nil;
ptr->right = self->nil;
ptr->parent = self->nil;
rbTreeInsert(self, ptr);
self->count++;
}
return old;
}
void WMSortBag(WMBag * self, WMCompareDataProc * comparer)
{
void **items;
W_Node *tmp;
int i;
if (self->count == 0)
return;
items = wmalloc(sizeof(void *) * self->count);
i = 0;
tmp = treeMinimum(self->root, self->nil);
while (tmp != self->nil) {
items[i++] = tmp->data;
tmp = treeSuccessor(tmp, self->nil);
}
qsort(&items[0], self->count, sizeof(void *), comparer);
i = 0;
tmp = treeMinimum(self->root, self->nil);
while (tmp != self->nil) {
tmp->index = i;
tmp->data = items[i++];
tmp = treeSuccessor(tmp, self->nil);
}
wfree(items);
}
static void deleteTree(WMBag * self, W_Node * node)
{
if (node == self->nil)
return;
deleteTree(self, node->left);
if (self->destructor)
self->destructor(node->data);
deleteTree(self, node->right);
wfree(node);
}
void WMEmptyBag(WMBag * self)
{
deleteTree(self, self->root);
self->root = self->nil;
self->count = 0;
}
void WMFreeBag(WMBag * self)
{
WMEmptyBag(self);
wfree(self->nil);
wfree(self);
}
static void mapTree(W_Bag * tree, W_Node * node, void (*function) (void *, void *), void *data)
{
if (node == tree->nil)
return;
mapTree(tree, node->left, function, data);
(*function) (node->data, data);
mapTree(tree, node->right, function, data);
}
void WMMapBag(WMBag * self, void (*function) (void *, void *), void *data)
{
mapTree(self, self->root, function, data);
}
static int findInTree(W_Bag * tree, W_Node * node, WMMatchDataProc * function, void *cdata)
{
int index;
if (node == tree->nil)
return WBNotFound;
index = findInTree(tree, node->left, function, cdata);
if (index != WBNotFound)
return index;
if ((*function) (node->data, cdata)) {
return node->index;
}
return findInTree(tree, node->right, function, cdata);
}
int WMFindInBag(WMBag * self, WMMatchDataProc * match, void *cdata)
{
return findInTree(self, self->root, match, cdata);
}
void *WMBagFirst(WMBag * self, WMBagIterator * ptr)
{
W_Node *node;
node = treeMinimum(self->root, self->nil);
if (node == self->nil) {
*ptr = NULL;
return NULL;
} else {
*ptr = node;
return node->data;
}
}
void *WMBagLast(WMBag * self, WMBagIterator * ptr)
{
W_Node *node;
node = treeMaximum(self->root, self->nil);
if (node == self->nil) {
*ptr = NULL;
return NULL;
} else {
*ptr = node;
return node->data;
}
}
void *WMBagNext(WMBag * self, WMBagIterator * ptr)
{
W_Node *node;
if (*ptr == NULL)
return NULL;
node = treeSuccessor(*ptr, self->nil);
if (node == self->nil) {
*ptr = NULL;
return NULL;
} else {
*ptr = node;
return node->data;
}
}
void *WMBagPrevious(WMBag * self, WMBagIterator * ptr)
{
W_Node *node;
if (*ptr == NULL)
return NULL;
node = treePredecessor(*ptr, self->nil);
if (node == self->nil) {
*ptr = NULL;
return NULL;
} else {
*ptr = node;
return node->data;
}
}
void *WMBagIteratorAtIndex(WMBag * self, int index, WMBagIterator * ptr)
{
W_Node *node;
node = treeSearch(self->root, self->nil, index);
if (node == self->nil) {
*ptr = NULL;
return NULL;
} else {
*ptr = node;
return node->data;
}
}
int WMBagIndexForIterator(WMBag * bag, WMBagIterator ptr)
{
/* Parameter not used, but tell the compiler that it is ok */
(void) bag;
return ((W_Node *) ptr)->index;
}

View File

@@ -1,132 +0,0 @@
#include "WINGs/WINGsP.h"
#include "WINGs/wconfig.h"
#include <X11/Xlocale.h>
_WINGsConfiguration WINGsConfiguration;
#define SYSTEM_FONT "sans serif"
#define BOLD_SYSTEM_FONT "sans serif:bold"
#define DEFAULT_FONT_SIZE 12
#define FLOPPY_PATH "/floppy"
static unsigned getButtonWithName(const char *name, unsigned defaultButton)
{
if (strncmp(name, "Button", 6) == 0 && strlen(name) == 7) {
switch (name[6]) {
case '1':
return Button1;
case '2':
return Button2;
case '3':
return Button3;
case '4':
return Button4;
case '5':
return Button5;
default:
break;
}
}
return defaultButton;
}
void W_ReadConfigurations(void)
{
WMUserDefaults *defaults;
Bool aaIsSet = False;
memset(&WINGsConfiguration, 0, sizeof(_WINGsConfiguration));
defaults = WMGetStandardUserDefaults();
if (defaults) {
char *buttonName;
WMPropList *val;
unsigned button;
WINGsConfiguration.systemFont = WMGetUDStringForKey(defaults, "SystemFont");
WINGsConfiguration.boldSystemFont = WMGetUDStringForKey(defaults, "BoldSystemFont");
val = WMGetUDObjectForKey(defaults, "AntialiasedText");
if (val && WMIsPLString(val) && WMGetFromPLString(val)) {
aaIsSet = True;
WINGsConfiguration.antialiasedText =
WMGetUDBoolForKey(defaults, "AntialiasedText");
}
WINGsConfiguration.doubleClickDelay = WMGetUDIntegerForKey(defaults, "DoubleClickTime");
WINGsConfiguration.floppyPath = WMGetUDStringForKey(defaults, "FloppyPath");
buttonName = WMGetUDStringForKey(defaults, "MouseWheelUp");
if (buttonName) {
button = getButtonWithName(buttonName, Button4);
wfree(buttonName);
} else {
button = Button4;
}
WINGsConfiguration.mouseWheelUp = button;
buttonName = WMGetUDStringForKey(defaults, "MouseWheelDown");
if (buttonName) {
button = getButtonWithName(buttonName, Button5);
wfree(buttonName);
} else {
button = Button5;
}
WINGsConfiguration.mouseWheelDown = button;
if (WINGsConfiguration.mouseWheelDown == WINGsConfiguration.mouseWheelUp) {
WINGsConfiguration.mouseWheelUp = Button4;
WINGsConfiguration.mouseWheelDown = Button5;
}
WINGsConfiguration.defaultFontSize = WMGetUDIntegerForKey(defaults, "DefaultFontSize");
}
if (!WINGsConfiguration.systemFont) {
WINGsConfiguration.systemFont = SYSTEM_FONT;
}
if (!WINGsConfiguration.boldSystemFont) {
WINGsConfiguration.boldSystemFont = BOLD_SYSTEM_FONT;
}
if (WINGsConfiguration.defaultFontSize == 0) {
WINGsConfiguration.defaultFontSize = DEFAULT_FONT_SIZE;
}
if (!aaIsSet) {
WINGsConfiguration.antialiasedText = True;
}
if (!WINGsConfiguration.floppyPath) {
WINGsConfiguration.floppyPath = FLOPPY_PATH;
}
if (WINGsConfiguration.doubleClickDelay == 0) {
WINGsConfiguration.doubleClickDelay = 250;
}
if (WINGsConfiguration.mouseWheelUp == 0) {
WINGsConfiguration.mouseWheelUp = Button4;
}
if (WINGsConfiguration.mouseWheelDown == 0) {
WINGsConfiguration.mouseWheelDown = Button5;
}
}
unsigned W_getconf_mouseWheelUp(void)
{
return WINGsConfiguration.mouseWheelUp;
}
unsigned W_getconf_mouseWheelDown(void)
{
return WINGsConfiguration.mouseWheelDown;
}
void W_setconf_doubleClickDelay(int value)
{
WINGsConfiguration.doubleClickDelay = value;
}

View File

@@ -1,289 +0,0 @@
/*
* WINGs WMData function library
*
* Copyright (c) 1999-2003 Dan Pascu
*
* 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 St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <string.h>
#include "WUtil.h"
typedef struct W_Data {
unsigned length; /* How many bytes we have */
unsigned capacity; /* How many bytes it can hold */
unsigned growth; /* How much to grow */
void *bytes; /* Actual data */
unsigned retainCount;
WMFreeDataProc *destructor;
int format; /* 0, 8, 16 or 32 */
} W_Data;
/* Creating and destroying data objects */
WMData *WMCreateDataWithCapacity(unsigned capacity)
{
WMData *aData;
aData = (WMData *) wmalloc(sizeof(WMData));
if (capacity > 0)
aData->bytes = wmalloc(capacity);
else
aData->bytes = NULL;
aData->capacity = capacity;
aData->growth = capacity / 2 > 0 ? capacity / 2 : 1;
aData->length = 0;
aData->retainCount = 1;
aData->format = 0;
aData->destructor = wfree;
return aData;
}
WMData *WMCreateDataWithLength(unsigned length)
{
WMData *aData;
aData = WMCreateDataWithCapacity(length);
if (length > 0) {
aData->length = length;
}
return aData;
}
WMData *WMCreateDataWithBytes(const void *bytes, unsigned length)
{
WMData *aData;
aData = WMCreateDataWithCapacity(length);
aData->length = length;
memcpy(aData->bytes, bytes, length);
return aData;
}
WMData *WMCreateDataWithBytesNoCopy(void *bytes, unsigned length, WMFreeDataProc * destructor)
{
WMData *aData;
aData = (WMData *) wmalloc(sizeof(WMData));
aData->length = length;
aData->capacity = length;
aData->growth = length / 2 > 0 ? length / 2 : 1;
aData->bytes = bytes;
aData->retainCount = 1;
aData->format = 0;
aData->destructor = destructor;
return aData;
}
WMData *WMCreateDataWithData(WMData * aData)
{
WMData *newData;
if (aData->length > 0) {
newData = WMCreateDataWithBytes(aData->bytes, aData->length);
} else {
newData = WMCreateDataWithCapacity(0);
}
newData->format = aData->format;
return newData;
}
WMData *WMRetainData(WMData * aData)
{
aData->retainCount++;
return aData;
}
void WMReleaseData(WMData * aData)
{
aData->retainCount--;
if (aData->retainCount > 0)
return;
if (aData->bytes != NULL && aData->destructor != NULL) {
aData->destructor(aData->bytes);
}
wfree(aData);
}
/* Adjusting capacity */
void WMSetDataCapacity(WMData * aData, unsigned capacity)
{
if (aData->capacity != capacity) {
aData->bytes = wrealloc(aData->bytes, capacity);
aData->capacity = capacity;
aData->growth = capacity / 2 > 0 ? capacity / 2 : 1;
}
if (aData->length > capacity) {
aData->length = capacity;
}
}
void WMSetDataLength(WMData * aData, unsigned length)
{
if (length > aData->capacity) {
WMSetDataCapacity(aData, length);
}
if (length > aData->length) {
memset((unsigned char *)aData->bytes + aData->length, 0, length - aData->length);
}
aData->length = length;
}
void WMSetDataFormat(WMData * aData, unsigned format)
{
aData->format = format;
}
void WMIncreaseDataLengthBy(WMData * aData, unsigned extraLength)
{
WMSetDataLength(aData, aData->length + extraLength);
}
/* Accessing data */
const void *WMDataBytes(WMData * aData)
{
return aData->bytes;
}
void WMGetDataBytes(WMData * aData, void *buffer)
{
wassertr(aData->length > 0);
memcpy(buffer, aData->bytes, aData->length);
}
unsigned WMGetDataFormat(WMData * aData)
{
return aData->format;
}
void WMGetDataBytesWithLength(WMData * aData, void *buffer, unsigned length)
{
wassertr(aData->length > 0);
wassertr(length <= aData->length);
memcpy(buffer, aData->bytes, length);
}
void WMGetDataBytesWithRange(WMData * aData, void *buffer, WMRange aRange)
{
wassertr(aRange.position < aData->length);
wassertr(aRange.count <= aData->length - aRange.position);
memcpy(buffer, (unsigned char *)aData->bytes + aRange.position, aRange.count);
}
WMData *WMGetSubdataWithRange(WMData * aData, WMRange aRange)
{
void *buffer;
WMData *newData;
if (aRange.count <= 0)
return WMCreateDataWithCapacity(0);
buffer = wmalloc(aRange.count);
WMGetDataBytesWithRange(aData, buffer, aRange);
newData = WMCreateDataWithBytesNoCopy(buffer, aRange.count, wfree);
newData->format = aData->format;
return newData;
}
/* Testing data */
Bool WMIsDataEqualToData(WMData * aData, WMData * anotherData)
{
if (aData->length != anotherData->length)
return False;
else if (!aData->bytes && !anotherData->bytes) /* both are empty */
return True;
else if (!aData->bytes || !anotherData->bytes) /* one of them is empty */
return False;
return (memcmp(aData->bytes, anotherData->bytes, aData->length) == 0);
}
unsigned WMGetDataLength(WMData * aData)
{
return aData->length;
}
/* Adding data */
void WMAppendDataBytes(WMData * aData, const void *bytes, unsigned length)
{
unsigned oldLength = aData->length;
unsigned newLength = oldLength + length;
if (newLength > aData->capacity) {
unsigned nextCapacity = aData->capacity + aData->growth;
unsigned nextGrowth = aData->capacity ? aData->capacity : 1;
while (nextCapacity < newLength) {
unsigned tmp = nextCapacity + nextGrowth;
nextGrowth = nextCapacity;
nextCapacity = tmp;
}
WMSetDataCapacity(aData, nextCapacity);
aData->growth = nextGrowth;
}
memcpy((unsigned char *)aData->bytes + oldLength, bytes, length);
aData->length = newLength;
}
void WMAppendData(WMData * aData, WMData * anotherData)
{
if (anotherData->length > 0)
WMAppendDataBytes(aData, anotherData->bytes, anotherData->length);
}
/* Modifying data */
void WMReplaceDataBytesInRange(WMData * aData, WMRange aRange, const void *bytes)
{
wassertr(aRange.position < aData->length);
wassertr(aRange.count <= aData->length - aRange.position);
memcpy((unsigned char *)aData->bytes + aRange.position, bytes, aRange.count);
}
void WMResetDataBytesInRange(WMData * aData, WMRange aRange)
{
wassertr(aRange.position < aData->length);
wassertr(aRange.count <= aData->length - aRange.position);
memset((unsigned char *)aData->bytes + aRange.position, 0, aRange.count);
}
void WMSetData(WMData * aData, WMData * anotherData)
{
unsigned length = anotherData->length;
WMSetDataCapacity(aData, length);
if (length > 0)
memcpy(aData->bytes, anotherData->bytes, length);
aData->length = length;
}
/* Storing data */

View File

@@ -1,259 +0,0 @@
#include "wconfig.h"
#include "WINGs/WINGsP.h"
#define XDND_SOURCE_VERSION(dragInfo) dragInfo->protocolVersion
#define XDND_DEST_INFO(dragInfo) dragInfo->destInfo
#define XDND_DEST_VIEW(dragInfo) dragInfo->destInfo->destView
static Bool _WindowExists;
Atom W_OperationToAction(WMScreen * scr, WMDragOperationType operation)
{
switch (operation) {
case WDOperationNone:
return None;
case WDOperationCopy:
return scr->xdndActionCopy;
case WDOperationMove:
return scr->xdndActionMove;
case WDOperationLink:
return scr->xdndActionLink;
case WDOperationAsk:
return scr->xdndActionAsk;
case WDOperationPrivate:
return scr->xdndActionPrivate;
default:
return None;
}
}
WMDragOperationType W_ActionToOperation(WMScreen * scr, Atom action)
{
if (action == scr->xdndActionCopy) {
return WDOperationCopy;
} else if (action == scr->xdndActionMove) {
return WDOperationMove;
} else if (action == scr->xdndActionLink) {
return WDOperationLink;
} else if (action == scr->xdndActionAsk) {
return WDOperationAsk;
} else if (action == scr->xdndActionPrivate) {
return WDOperationPrivate;
} else if (action == None) {
return WDOperationNone;
} else {
char *tmp = XGetAtomName(scr->display, action);
wwarning(_("unknown XDND action %s"), tmp);
XFree(tmp);
return WDOperationCopy;
}
}
static void freeDragOperationItem(void *item)
{
wfree(item);
}
WMArray *WMCreateDragOperationArray(int initialSize)
{
return WMCreateArrayWithDestructor(initialSize, freeDragOperationItem);
}
WMDragOperationItem *WMCreateDragOperationItem(WMDragOperationType type, char *text)
{
W_DragOperationItem *result = wmalloc(sizeof(W_DragOperationItem));
result->type = type;
result->text = text;
return (WMDragOperationItem *) result;
}
WMDragOperationType WMGetDragOperationItemType(WMDragOperationItem * item)
{
return ((W_DragOperationItem *) item)->type;
}
char *WMGetDragOperationItemText(WMDragOperationItem * item)
{
return ((W_DragOperationItem *) item)->text;
}
static int handleNoWindowXError(Display * dpy, XErrorEvent * errEvt)
{
/* Parameter not used, but tell the compiler that it is ok */
(void) dpy;
if (errEvt->error_code == BadWindow || errEvt->error_code == BadDrawable) {
_WindowExists = False;
return Success;
}
return errEvt->error_code;
}
static Bool windowExists(Display * dpy, Window win)
{
void *previousErrorHandler;
XWindowAttributes attr;
XSynchronize(dpy, True);
previousErrorHandler = XSetErrorHandler(handleNoWindowXError);
_WindowExists = True;
/* can generate BadDrawable or BadWindow */
XGetWindowAttributes(dpy, win, &attr);
XSetErrorHandler(previousErrorHandler);
XSynchronize(dpy, False);
return _WindowExists;
}
Bool
W_SendDnDClientMessage(Display * dpy, Window win, Atom message,
unsigned long data0,
unsigned long data1, unsigned long data2, unsigned long data3, unsigned long data4)
{
XEvent ev;
#ifdef XDND_DEBUG
char *msgName = XGetAtomName(dpy, message);
printf("sending message %s ... ", msgName);
XFree(msgName);
#endif
if (!windowExists(dpy, win)) {
wwarning(_("target %lu for XDND message no longer exists"), win);
return False; /* message not sent */
}
ev.type = ClientMessage;
ev.xclient.message_type = message;
ev.xclient.format = 32;
ev.xclient.window = win;
ev.xclient.data.l[0] = data0;
ev.xclient.data.l[1] = data1;
ev.xclient.data.l[2] = data2;
ev.xclient.data.l[3] = data3;
ev.xclient.data.l[4] = data4;
XSendEvent(dpy, win, False, 0, &ev);
XFlush(dpy);
#ifdef XDND_DEBUG
printf("sent\n");
#endif
return True; /* message sent */
}
static void handleLeaveMessage(WMDraggingInfo * info)
{
if (XDND_DEST_INFO(info) != NULL) {
/* XDND_DEST_VIEW is never NULL (it's the xdnd aware view) */
wassertr(XDND_DEST_VIEW(info) != NULL);
if (XDND_DEST_VIEW(info)->dragDestinationProcs != NULL) {
XDND_DEST_VIEW(info)->dragDestinationProcs->concludeDragOperation(XDND_DEST_VIEW(info));
}
W_DragDestinationInfoClear(info);
}
}
void W_HandleDNDClientMessage(WMView * toplevel, XClientMessageEvent * event)
{
WMScreen *scr = W_VIEW_SCREEN(toplevel);
WMDraggingInfo *info = &scr->dragInfo;
Atom messageType = event->message_type;
#ifdef XDND_DEBUG
{
char *msgTypeName = XGetAtomName(scr->display, messageType);
if (msgTypeName != NULL)
printf("event type = %s\n", msgTypeName);
else
printf("pb with event type !\n");
}
#endif
/* Messages from destination to source */
if (messageType == scr->xdndStatusAtom || messageType == scr->xdndFinishedAtom) {
W_DragSourceStopTimer();
W_DragSourceStateHandler(info, event);
return;
}
/* Messages from source to destination */
if (messageType == scr->xdndEnterAtom) {
Bool positionSent = (XDND_DEST_INFO(info) != NULL);
W_DragDestinationStopTimer();
W_DragDestinationStoreEnterMsgInfo(info, toplevel, event);
/* Xdnd version 3 and up are not compatible with version 1 or 2 */
if (XDND_SOURCE_VERSION(info) > 2) {
if (positionSent) {
/* xdndPosition previously received on xdnd aware view */
W_DragDestinationStateHandler(info, event);
return;
} else {
W_DragDestinationStartTimer(info);
return;
}
} else {
wwarning(_("unsupported version %i for XDND enter message"), XDND_SOURCE_VERSION(info));
W_DragDestinationCancelDropOnEnter(toplevel, info);
return;
}
}
if (messageType == scr->xdndPositionAtom) {
W_DragDestinationStopTimer();
W_DragDestinationStorePositionMsgInfo(info, toplevel, event);
W_DragDestinationStateHandler(info, event);
return;
}
if (messageType == scr->xdndSelectionAtom || messageType == scr->xdndDropAtom) {
W_DragDestinationStopTimer();
W_DragDestinationStateHandler(info, event);
return;
}
if (messageType == scr->xdndLeaveAtom) {
/* conclude drop operation, and clear dragging info */
W_DragDestinationStopTimer();
handleLeaveMessage(info);
}
}
/* called in destroyView (wview.c) */
void W_FreeViewXdndPart(WMView * view)
{
WMUnregisterViewDraggedTypes(view);
if (view->dragSourceProcs)
wfree(view->dragSourceProcs);
if (view->dragDestinationProcs)
wfree(view->dragDestinationProcs);
if (view->dragImage)
WMReleasePixmap(view->dragImage);
}

View File

@@ -1,999 +0,0 @@
#include "WINGs/WINGsP.h"
#include <X11/Xatom.h>
#define XDND_SOURCE_RESPONSE_MAX_DELAY 3000
#define XDND_PROPERTY_FORMAT 32
#define XDND_ACTION_DESCRIPTION_FORMAT 8
#define XDND_SOURCE_VERSION(dragInfo) dragInfo->protocolVersion
#define XDND_DEST_INFO(dragInfo) dragInfo->destInfo
#define XDND_AWARE_VIEW(dragInfo) dragInfo->destInfo->xdndAwareView
#define XDND_SOURCE_WIN(dragInfo) dragInfo->destInfo->sourceWindow
#define XDND_DEST_VIEW(dragInfo) dragInfo->destInfo->destView
#define XDND_DEST_STATE(dragInfo) dragInfo->destInfo->state
#define XDND_SOURCE_ACTION_CHANGED(dragInfo) dragInfo->destInfo->sourceActionChanged
#define XDND_SOURCE_TYPES(dragInfo) dragInfo->destInfo->sourceTypes
#define XDND_TYPE_LIST_AVAILABLE(dragInfo) dragInfo->destInfo->typeListAvailable
#define XDND_REQUIRED_TYPES(dragInfo) dragInfo->destInfo->requiredTypes
#define XDND_SOURCE_ACTION(dragInfo) dragInfo->sourceAction
#define XDND_DEST_ACTION(dragInfo) dragInfo->destinationAction
#define XDND_DROP_DATAS(dragInfo) dragInfo->destInfo->dropDatas
#define XDND_DEST_VIEW_IS_REGISTERED(dragInfo) ((dragInfo->destInfo) != NULL)\
&& ((dragInfo->destInfo->destView->dragDestinationProcs) != NULL)
static const unsigned char XDNDversion = XDND_VERSION;
static WMHandlerID dndDestinationTimer = NULL;
static void *idleState(WMView * destView, XClientMessageEvent * event, WMDraggingInfo * info);
static void *waitEnterState(WMView * destView, XClientMessageEvent * event, WMDraggingInfo * info);
static void *inspectDropDataState(WMView * destView, XClientMessageEvent * event, WMDraggingInfo * info);
static void *dropAllowedState(WMView * destView, XClientMessageEvent * event, WMDraggingInfo * info);
static void *dropNotAllowedState(WMView * destView, XClientMessageEvent * event, WMDraggingInfo * info);
static void *waitForDropDataState(WMView * destView, XClientMessageEvent * event, WMDraggingInfo * info);
/* ----- Types & datas list ----- */
static void freeSourceTypeArrayItem(void *type)
{
XFree(type);
}
static WMArray *createSourceTypeArray(int initialSize)
{
return WMCreateArrayWithDestructor(initialSize, freeSourceTypeArrayItem);
}
static void freeDropDataArrayItem(void *data)
{
if (data != NULL)
WMReleaseData((WMData *) data);
}
static WMArray *createDropDataArray(WMArray * requiredTypes)
{
if (requiredTypes != NULL)
return WMCreateArrayWithDestructor(WMGetArrayItemCount(requiredTypes), freeDropDataArrayItem);
else
return WMCreateArray(0);
}
static WMArray *getTypesFromTypeList(WMScreen * scr, Window sourceWin)
{
Atom dataType;
Atom *typeAtomList;
WMArray *typeList;
int i, format;
unsigned long count, remaining;
unsigned char *data = NULL;
XGetWindowProperty(scr->display, sourceWin, scr->xdndTypeListAtom,
0, 0x8000000L, False, XA_ATOM, &dataType, &format, &count, &remaining, &data);
if (dataType != XA_ATOM || format != XDND_PROPERTY_FORMAT || count == 0 || !data) {
if (data) {
XFree(data);
}
return createSourceTypeArray(0);
}
typeList = createSourceTypeArray(count);
typeAtomList = (Atom *) data;
for (i = 0; i < count; i++) {
WMAddToArray(typeList, XGetAtomName(scr->display, typeAtomList[i]));
}
XFree(data);
return typeList;
}
static WMArray *getTypesFromThreeTypes(WMScreen * scr, XClientMessageEvent * event)
{
WMArray *typeList;
Atom atom;
int i;
typeList = createSourceTypeArray(3);
for (i = 2; i < 5; i++) {
if (event->data.l[i] != None) {
atom = (Atom) event->data.l[i];
WMAddToArray(typeList, XGetAtomName(scr->display, atom));
}
}
return typeList;
}
static void storeRequiredTypeList(WMDraggingInfo * info)
{
WMView *destView = XDND_DEST_VIEW(info);
WMScreen *scr = W_VIEW_SCREEN(destView);
WMArray *requiredTypes;
/* First, see if the stored source types are enough for dest requirements */
requiredTypes = destView->dragDestinationProcs->requiredDataTypes(destView,
W_ActionToOperation(scr,
XDND_SOURCE_ACTION
(info)),
XDND_SOURCE_TYPES(info));
if (requiredTypes == NULL && XDND_TYPE_LIST_AVAILABLE(info)) {
/* None of the stored source types fits, but the whole type list
hasn't been retrieved yet. */
WMFreeArray(XDND_SOURCE_TYPES(info));
XDND_SOURCE_TYPES(info) = getTypesFromTypeList(scr, XDND_SOURCE_WIN(info));
/* Don't retrieve the type list again */
XDND_TYPE_LIST_AVAILABLE(info) = False;
requiredTypes =
destView->dragDestinationProcs->requiredDataTypes(destView,
W_ActionToOperation(scr,
XDND_SOURCE_ACTION
(info)),
XDND_SOURCE_TYPES(info));
}
XDND_REQUIRED_TYPES(info) = requiredTypes;
}
static char *getNextRequestedDataType(WMDraggingInfo * info)
{
/* get the type of the first data not yet retrieved from selection */
int nextTypeIndex;
if (XDND_REQUIRED_TYPES(info) != NULL) {
nextTypeIndex = WMGetArrayItemCount(XDND_DROP_DATAS(info));
return WMGetFromArray(XDND_REQUIRED_TYPES(info), nextTypeIndex);
/* NULL if no more type */
} else
return NULL;
}
/* ----- Action list ----- */
static WMArray *sourceOperationList(WMScreen * scr, Window sourceWin)
{
Atom dataType, *actionList;
int i, size;
unsigned long count, remaining;
unsigned char *actionDatas = NULL;
unsigned char *descriptionList = NULL;
WMArray *operationArray;
WMDragOperationItem *operationItem;
char *description;
remaining = 0;
XGetWindowProperty(scr->display, sourceWin, scr->xdndActionListAtom,
0, 0x8000000L, False, XA_ATOM, &dataType, &size, &count, &remaining, &actionDatas);
if (dataType != XA_ATOM || size != XDND_PROPERTY_FORMAT || count == 0 || !actionDatas) {
wwarning("Cannot read action list");
if (actionDatas) {
XFree(actionDatas);
}
return NULL;
}
actionList = (Atom *) actionDatas;
XGetWindowProperty(scr->display, sourceWin, scr->xdndActionDescriptionAtom,
0, 0x8000000L, False, XA_STRING, &dataType, &size,
&count, &remaining, &descriptionList);
if (dataType != XA_STRING || size != XDND_ACTION_DESCRIPTION_FORMAT || count == 0 || !descriptionList) {
wwarning("Cannot read action description list");
if (actionList) {
XFree(actionList);
}
if (descriptionList) {
XFree(descriptionList);
}
return NULL;
}
operationArray = WMCreateDragOperationArray(count);
description = (char *)descriptionList;
for (i = 0; count > 0; i++) {
size = strlen(description);
operationItem = WMCreateDragOperationItem(W_ActionToOperation(scr, actionList[i]),
wstrdup(description));
WMAddToArray(operationArray, operationItem);
count -= (size + 1); /* -1 : -NULL char */
/* next description */
description = &(description[size + 1]);
}
XFree(actionList);
XFree(descriptionList);
return operationArray;
}
/* ----- Dragging Info ----- */
static void updateSourceWindow(WMDraggingInfo * info, XClientMessageEvent * event)
{
XDND_SOURCE_WIN(info) = (Window) event->data.l[0];
}
static WMView *findChildInView(WMView * parent, int x, int y)
{
if (parent->childrenList == NULL)
return parent;
else {
WMView *child = parent->childrenList;
while (child != NULL
&& (!child->flags.mapped
|| x < WMGetViewPosition(child).x
|| x > WMGetViewPosition(child).x + WMGetViewSize(child).width
|| y < WMGetViewPosition(child).y
|| y > WMGetViewPosition(child).y + WMGetViewSize(child).height))
child = child->nextSister;
if (child == NULL)
return parent;
else
return findChildInView(child,
x - WMGetViewPosition(child).x, y - WMGetViewPosition(child).y);
}
}
static WMView *findDestinationViewInToplevel(WMView * toplevel, int x, int y)
{
WMScreen *scr = W_VIEW_SCREEN(toplevel);
Window toplevelWin = WMViewXID(toplevel);
int xInToplevel, yInToplevel;
Window foo;
XTranslateCoordinates(scr->display, scr->rootWin, toplevelWin, x, y, &xInToplevel, &yInToplevel, &foo);
return findChildInView(toplevel, xInToplevel, yInToplevel);
}
/* Clear datas only used by current destination view */
static void freeDestinationViewInfos(WMDraggingInfo * info)
{
if (XDND_SOURCE_TYPES(info) != NULL) {
WMFreeArray(XDND_SOURCE_TYPES(info));
XDND_SOURCE_TYPES(info) = NULL;
}
if (XDND_DROP_DATAS(info) != NULL) {
WMFreeArray(XDND_DROP_DATAS(info));
XDND_DROP_DATAS(info) = NULL;
}
XDND_REQUIRED_TYPES(info) = NULL;
}
void W_DragDestinationInfoClear(WMDraggingInfo * info)
{
W_DragDestinationStopTimer();
if (XDND_DEST_INFO(info) != NULL) {
freeDestinationViewInfos(info);
wfree(XDND_DEST_INFO(info));
XDND_DEST_INFO(info) = NULL;
}
}
static void initDestinationDragInfo(WMDraggingInfo * info, WMView * destView)
{
wassertr(destView != NULL);
XDND_DEST_INFO(info) = (W_DragDestinationInfo *) wmalloc(sizeof(W_DragDestinationInfo));
XDND_DEST_STATE(info) = idleState;
XDND_DEST_VIEW(info) = destView;
XDND_SOURCE_ACTION_CHANGED(info) = False;
XDND_SOURCE_TYPES(info) = NULL;
XDND_REQUIRED_TYPES(info) = NULL;
XDND_DROP_DATAS(info) = NULL;
}
void W_DragDestinationStoreEnterMsgInfo(WMDraggingInfo * info, WMView * toplevel, XClientMessageEvent * event)
{
WMScreen *scr = W_VIEW_SCREEN(toplevel);
if (XDND_DEST_INFO(info) == NULL)
initDestinationDragInfo(info, toplevel);
XDND_SOURCE_VERSION(info) = (event->data.l[1] >> 24);
XDND_AWARE_VIEW(info) = toplevel;
updateSourceWindow(info, event);
#if 0
if (event->data.l[1] & 1)
/* XdndTypeList property is available */
XDND_SOURCE_TYPES(info) = getTypesFromTypeList(scr, XDND_SOURCE_WIN(info));
else
XDND_SOURCE_TYPES(info) = getTypesFromThreeTypes(scr, event);
#endif
XDND_SOURCE_TYPES(info) = getTypesFromThreeTypes(scr, event);
/* to use if the 3 types are not enough */
XDND_TYPE_LIST_AVAILABLE(info) = (event->data.l[1] & 1);
}
void W_DragDestinationStorePositionMsgInfo(WMDraggingInfo * info, WMView * toplevel, XClientMessageEvent * event)
{
int x = event->data.l[2] >> 16;
int y = event->data.l[2] & 0xffff;
WMView *newDestView;
newDestView = findDestinationViewInToplevel(toplevel, x, y);
if (XDND_DEST_INFO(info) == NULL) {
initDestinationDragInfo(info, newDestView);
XDND_AWARE_VIEW(info) = toplevel;
updateSourceWindow(info, event);
} else {
if (newDestView != XDND_DEST_VIEW(info)) {
updateSourceWindow(info, event);
XDND_DEST_VIEW(info) = newDestView;
XDND_SOURCE_ACTION_CHANGED(info) = False;
if (XDND_DEST_STATE(info) != waitEnterState)
XDND_DEST_STATE(info) = idleState;
} else {
XDND_SOURCE_ACTION_CHANGED(info) = (XDND_SOURCE_ACTION(info) != event->data.l[4]);
}
}
XDND_SOURCE_ACTION(info) = event->data.l[4];
/* note: source position is not stored */
}
/* ----- End of Dragging Info ----- */
/* ----- Messages ----- */
/* send a DnD message to the source window */
static void
sendDnDClientMessage(WMDraggingInfo * info, Atom message,
unsigned long data1, unsigned long data2, unsigned long data3, unsigned long data4)
{
if (!W_SendDnDClientMessage(W_VIEW_SCREEN(XDND_AWARE_VIEW(info))->display,
XDND_SOURCE_WIN(info),
message, WMViewXID(XDND_AWARE_VIEW(info)), data1, data2, data3, data4)) {
/* drop failed */
W_DragDestinationInfoClear(info);
}
}
/* send a xdndStatus message to the source, with position and size
of the destination if it has no subwidget (requesting a position message
on every move otherwise) */
static void sendStatusMessage(WMView * destView, WMDraggingInfo * info, Atom action)
{
unsigned long data1;
data1 = (action == None) ? 0 : 1;
if (destView->childrenList == NULL) {
WMScreen *scr = W_VIEW_SCREEN(destView);
int destX, destY;
WMSize destSize = WMGetViewSize(destView);
Window foo;
XTranslateCoordinates(scr->display, WMViewXID(destView), scr->rootWin, 0, 0, &destX, &destY, &foo);
sendDnDClientMessage(info,
W_VIEW_SCREEN(destView)->xdndStatusAtom,
data1,
(destX << 16) | destY, (destSize.width << 16) | destSize.height, action);
} else {
/* set bit 1 to request explicitly position message on every move */
data1 = data1 | 2;
sendDnDClientMessage(info, W_VIEW_SCREEN(destView)->xdndStatusAtom, data1, 0, 0, action);
}
}
static void
storeDropData(WMView * destView, Atom selection, Atom target, Time timestamp, void *cdata, WMData * data)
{
WMScreen *scr = W_VIEW_SCREEN(destView);
WMDraggingInfo *info = &(scr->dragInfo);
WMData *dataToStore = NULL;
/* Parameter not used, but tell the compiler that it is ok */
(void) selection;
(void) target;
(void) timestamp;
(void) cdata;
if (data != NULL)
dataToStore = WMRetainData(data);
if (XDND_DEST_INFO(info) != NULL && XDND_DROP_DATAS(info) != NULL) {
WMAddToArray(XDND_DROP_DATAS(info), dataToStore);
W_SendDnDClientMessage(scr->display, WMViewXID(destView),
scr->xdndSelectionAtom, WMViewXID(destView), 0, 0, 0, 0);
}
}
static Bool requestDropDataInSelection(WMView * destView, const char *type)
{
WMScreen *scr = W_VIEW_SCREEN(destView);
if (type != NULL) {
if (!WMRequestSelection(destView,
scr->xdndSelectionAtom,
XInternAtom(scr->display, type, False),
CurrentTime, storeDropData, NULL)) {
wwarning("could not request data for dropped data");
return False;
}
return True;
}
return False;
}
static Bool requestDropData(WMDraggingInfo * info)
{
WMView *destView = XDND_DEST_VIEW(info);
char *nextType = getNextRequestedDataType(info);
while ((nextType != NULL)
&& (!requestDropDataInSelection(destView, nextType))) {
/* store NULL if request failed, and try with next type */
WMAddToArray(XDND_DROP_DATAS(info), NULL);
nextType = getNextRequestedDataType(info);
}
/* remains types to retrieve ? */
return (nextType != NULL);
}
static void concludeDrop(WMView * destView)
{
destView->dragDestinationProcs->concludeDragOperation(destView);
}
/* send cancel message to the source */
static void cancelDrop(WMView * destView, WMDraggingInfo * info)
{
sendStatusMessage(destView, info, None);
concludeDrop(destView);
freeDestinationViewInfos(info);
}
/* suspend drop, when dragged icon enter an unregistered view
or a register view that doesn't accept the drop */
static void suspendDropAuthorization(WMView * destView, WMDraggingInfo * info)
{
sendStatusMessage(destView, info, None);
/* Free datas that depend on destination behaviour */
if (XDND_DROP_DATAS(info) != NULL) {
WMFreeArray(XDND_DROP_DATAS(info));
XDND_DROP_DATAS(info) = NULL;
}
XDND_REQUIRED_TYPES(info) = NULL;
}
/* cancel drop on Enter message, if protocol version is nok */
void W_DragDestinationCancelDropOnEnter(WMView * toplevel, WMDraggingInfo * info)
{
if (XDND_DEST_VIEW_IS_REGISTERED(info))
cancelDrop(XDND_DEST_VIEW(info), info);
else
sendStatusMessage(toplevel, info, None);
W_DragDestinationInfoClear(info);
}
static void finishDrop(WMView * destView, WMDraggingInfo * info)
{
sendDnDClientMessage(info, W_VIEW_SCREEN(destView)->xdndFinishedAtom, 0, 0, 0, 0);
concludeDrop(destView);
W_DragDestinationInfoClear(info);
}
static Atom getAllowedAction(WMView * destView, WMDraggingInfo * info)
{
WMScreen *scr = W_VIEW_SCREEN(destView);
return W_OperationToAction(scr,
destView->dragDestinationProcs->allowedOperation(destView,
W_ActionToOperation(scr,
XDND_SOURCE_ACTION
(info)),
XDND_SOURCE_TYPES(info)));
}
static void *checkActionAllowed(WMView * destView, WMDraggingInfo * info)
{
XDND_DEST_ACTION(info) = getAllowedAction(destView, info);
if (XDND_DEST_ACTION(info) == None) {
suspendDropAuthorization(destView, info);
return dropNotAllowedState;
}
sendStatusMessage(destView, info, XDND_DEST_ACTION(info));
return dropAllowedState;
}
static void *checkDropAllowed(WMView *destView, WMDraggingInfo *info)
{
storeRequiredTypeList(info);
if (destView->dragDestinationProcs->inspectDropData != NULL) {
XDND_DROP_DATAS(info) = createDropDataArray(XDND_REQUIRED_TYPES(info));
/* store first available data */
if (requestDropData(info))
return inspectDropDataState;
/* no data retrieved, but inspect can allow it */
if (destView->dragDestinationProcs->inspectDropData(destView, XDND_DROP_DATAS(info)))
return checkActionAllowed(destView, info);
suspendDropAuthorization(destView, info);
return dropNotAllowedState;
}
return checkActionAllowed(destView, info);
}
static WMPoint *getDropLocationInView(WMView * view)
{
Window rootWin, childWin;
int rootX, rootY;
unsigned int mask;
WMPoint *location;
location = (WMPoint *) wmalloc(sizeof(WMPoint));
XQueryPointer(W_VIEW_SCREEN(view)->display,
WMViewXID(view), &rootWin, &childWin, &rootX, &rootY, &(location->x), &(location->y), &mask);
return location;
}
static void callPerformDragOperation(WMView * destView, WMDraggingInfo * info)
{
WMArray *operationList = NULL;
WMScreen *scr = W_VIEW_SCREEN(destView);
WMPoint *dropLocation;
if (XDND_SOURCE_ACTION(info) == scr->xdndActionAsk)
operationList = sourceOperationList(scr, XDND_SOURCE_WIN(info));
dropLocation = getDropLocationInView(destView);
destView->dragDestinationProcs->performDragOperation(destView,
XDND_DROP_DATAS(info), operationList, dropLocation);
wfree(dropLocation);
if (operationList != NULL)
WMFreeArray(operationList);
}
/* ----- Destination timer ----- */
static void dragSourceResponseTimeOut(void *destView)
{
WMView *view = (WMView *) destView;
WMDraggingInfo *info;
wwarning("delay for drag source response expired");
info = &(W_VIEW_SCREEN(view)->dragInfo);
if (XDND_DEST_VIEW_IS_REGISTERED(info))
cancelDrop(view, info);
else {
sendStatusMessage(view, info, None);
}
W_DragDestinationInfoClear(info);
}
void W_DragDestinationStopTimer(void)
{
if (dndDestinationTimer != NULL) {
WMDeleteTimerHandler(dndDestinationTimer);
dndDestinationTimer = NULL;
}
}
void W_DragDestinationStartTimer(WMDraggingInfo * info)
{
W_DragDestinationStopTimer();
if (XDND_DEST_STATE(info) != idleState)
dndDestinationTimer = WMAddTimerHandler(XDND_SOURCE_RESPONSE_MAX_DELAY,
dragSourceResponseTimeOut, XDND_DEST_VIEW(info));
}
/* ----- End of Destination timer ----- */
/* ----- Destination states ----- */
#ifdef XDND_DEBUG
static const char *stateName(W_DndState * state)
{
if (state == NULL)
return "no state defined";
if (state == idleState)
return "idleState";
if (state == waitEnterState)
return "waitEnterState";
if (state == inspectDropDataState)
return "inspectDropDataState";
if (state == dropAllowedState)
return "dropAllowedState";
if (state == dropNotAllowedState)
return "dropNotAllowedState";
if (state == waitForDropDataState)
return "waitForDropDataState";
return "unknown state";
}
#endif
static void *idleState(WMView * destView, XClientMessageEvent * event, WMDraggingInfo * info)
{
WMScreen *scr;
Atom sourceMsg;
if (destView->dragDestinationProcs != NULL) {
scr = W_VIEW_SCREEN(destView);
sourceMsg = event->message_type;
if (sourceMsg == scr->xdndPositionAtom) {
destView->dragDestinationProcs->prepareForDragOperation(destView);
if (XDND_SOURCE_TYPES(info) != NULL) {
/* enter message infos are available */
return checkDropAllowed(destView, info);
}
/* waiting for enter message */
return waitEnterState;
}
}
suspendDropAuthorization(destView, info);
return idleState;
}
/* Source position and action are stored,
waiting for xdnd protocol version and source type */
static void *waitEnterState(WMView * destView, XClientMessageEvent * event, WMDraggingInfo * info)
{
WMScreen *scr = W_VIEW_SCREEN(destView);
Atom sourceMsg = event->message_type;
if (sourceMsg == scr->xdndEnterAtom) {
W_DragDestinationStoreEnterMsgInfo(info, destView, event);
return checkDropAllowed(destView, info);
}
return waitEnterState;
}
/* We have requested a data, and have received it */
static void *inspectDropDataState(WMView * destView, XClientMessageEvent * event, WMDraggingInfo * info)
{
WMScreen *scr;
Atom sourceMsg;
scr = W_VIEW_SCREEN(destView);
sourceMsg = event->message_type;
if (sourceMsg == scr->xdndSelectionAtom) {
/* a data has been retrieved, store next available */
if (requestDropData(info))
return inspectDropDataState;
/* all required (and available) datas are stored */
if (destView->dragDestinationProcs->inspectDropData(destView, XDND_DROP_DATAS(info)))
return checkActionAllowed(destView, info);
suspendDropAuthorization(destView, info);
return dropNotAllowedState;
}
return inspectDropDataState;
}
static void *dropNotAllowedState(WMView * destView, XClientMessageEvent * event, WMDraggingInfo * info)
{
WMScreen *scr = W_VIEW_SCREEN(destView);
Atom sourceMsg = event->message_type;
if (sourceMsg == scr->xdndDropAtom) {
finishDrop(destView, info);
return idleState;
}
if (sourceMsg == scr->xdndPositionAtom) {
if (XDND_SOURCE_ACTION_CHANGED(info)) {
return checkDropAllowed(destView, info);
} else {
sendStatusMessage(destView, info, None);
return dropNotAllowedState;
}
}
return dropNotAllowedState;
}
static void *dropAllowedState(WMView * destView, XClientMessageEvent * event, WMDraggingInfo * info)
{
WMScreen *scr = W_VIEW_SCREEN(destView);
Atom sourceMsg = event->message_type;
if (sourceMsg == scr->xdndDropAtom) {
if (XDND_DROP_DATAS(info) != NULL) {
/* drop datas were cached with inspectDropData call */
callPerformDragOperation(destView, info);
} else {
XDND_DROP_DATAS(info) = createDropDataArray(XDND_REQUIRED_TYPES(info));
/* store first available data */
if (requestDropData(info))
return waitForDropDataState;
/* no data retrieved */
callPerformDragOperation(destView, info);
}
finishDrop(destView, info);
return idleState;
}
if (sourceMsg == scr->xdndPositionAtom) {
if (XDND_SOURCE_ACTION_CHANGED(info)) {
return checkDropAllowed(destView, info);
} else {
sendStatusMessage(destView, info, XDND_DEST_ACTION(info));
return dropAllowedState;
}
}
return dropAllowedState;
}
static void *waitForDropDataState(WMView * destView, XClientMessageEvent * event, WMDraggingInfo * info)
{
WMScreen *scr = W_VIEW_SCREEN(destView);
Atom sourceMsg = event->message_type;
if (sourceMsg == scr->xdndSelectionAtom) {
/* store next data */
if (requestDropData(info))
return waitForDropDataState;
/* all required (and available) datas are stored */
callPerformDragOperation(destView, info);
finishDrop(destView, info);
return idleState;
}
return waitForDropDataState;
}
/* ----- End of Destination states ----- */
void W_DragDestinationStateHandler(WMDraggingInfo * info, XClientMessageEvent * event)
{
WMView *destView;
W_DndState *newState;
wassertr(XDND_DEST_INFO(info) != NULL);
wassertr(XDND_DEST_VIEW(info) != NULL);
destView = XDND_DEST_VIEW(info);
if (XDND_DEST_STATE(info) == NULL)
XDND_DEST_STATE(info) = idleState;
#ifdef XDND_DEBUG
printf("current dest state: %s\n", stateName(XDND_DEST_STATE(info)));
#endif
newState = (W_DndState *) XDND_DEST_STATE(info) (destView, event, info);
#ifdef XDND_DEBUG
printf("new dest state: %s\n", stateName(newState));
#endif
if (XDND_DEST_INFO(info) != NULL) {
XDND_DEST_STATE(info) = newState;
if (XDND_DEST_STATE(info) != idleState)
W_DragDestinationStartTimer(info);
}
}
static void realizedObserver(void *self, WMNotification * notif)
{
WMView *view = (WMView *) WMGetNotificationObject(notif);
WMScreen *scr = W_VIEW_SCREEN(view);
XChangeProperty(scr->display, W_VIEW_DRAWABLE(view),
scr->xdndAwareAtom, XA_ATOM, XDND_PROPERTY_FORMAT, PropModeReplace, &XDNDversion, 1);
WMRemoveNotificationObserver(self);
}
static void W_SetXdndAwareProperty(WMScreen *scr, WMView *view)
{
WMView *toplevel = W_TopLevelOfView(view);
if (!toplevel->flags.xdndHintSet) {
toplevel->flags.xdndHintSet = 1;
if (toplevel->flags.realized) {
XChangeProperty(scr->display, W_VIEW_DRAWABLE(toplevel),
scr->xdndAwareAtom, XA_ATOM, XDND_PROPERTY_FORMAT,
PropModeReplace, &XDNDversion, 1);
} else {
WMAddNotificationObserver(realizedObserver,
/* just use as an id */
&view->dragDestinationProcs,
WMViewRealizedNotification, toplevel);
}
}
}
void WMRegisterViewForDraggedTypes(WMView * view, WMArray * acceptedTypes)
{
Atom *types;
int typeCount;
int i;
typeCount = WMGetArrayItemCount(acceptedTypes);
types = wmalloc(sizeof(Atom) * (typeCount + 1));
for (i = 0; i < typeCount; i++) {
types[i] = XInternAtom(W_VIEW_SCREEN(view)->display, WMGetFromArray(acceptedTypes, i), False);
}
types[i] = 0;
view->droppableTypes = types;
/* WMFreeArray(acceptedTypes); */
W_SetXdndAwareProperty(W_VIEW_SCREEN(view), view);
}
void WMUnregisterViewDraggedTypes(WMView * view)
{
if (view->droppableTypes != NULL)
wfree(view->droppableTypes);
view->droppableTypes = NULL;
}
/*
requestedOperation: operation requested by the source
sourceDataTypes: data types (mime-types strings) supported by the source
(never NULL, destroyed when drop ends)
return operation allowed by destination (self)
*/
static WMDragOperationType
defAllowedOperation(WMView * self, WMDragOperationType requestedOperation, WMArray * sourceDataTypes)
{
/* Parameter not used, but tell the compiler that it is ok */
(void) self;
(void) requestedOperation;
(void) sourceDataTypes;
/* no operation allowed */
return WDOperationNone;
}
/*
requestedOperation: operation requested by the source
sourceDataTypes: data types (mime-types strings) supported by the source
(never NULL, destroyed when drop ends)
return data types (mime-types strings) required by destination (self)
or NULL if no suitable data type is available (force
to 2nd pass with full source type list).
*/
static WMArray *defRequiredDataTypes(WMView * self,
WMDragOperationType requestedOperation, WMArray * sourceDataTypes)
{
/* Parameter not used, but tell the compiler that it is ok */
(void) self;
(void) requestedOperation;
(void) sourceDataTypes;
/* no data type allowed (NULL even at 2nd pass) */
return NULL;
}
/*
Executed when the drag enters destination (self)
*/
static void defPrepareForDragOperation(WMView * self)
{
/* Parameter not used, but tell the compiler that it is ok */
(void) self;
}
/*
Checks datas to be dropped (optional).
dropDatas: datas (WMData*) required by destination (self)
(given in same order as returned by requiredDataTypes).
A NULL data means it couldn't be retreived.
Destroyed when drop ends.
return true if data array is ok
*/
/* Bool (*inspectDropData)(WMView *self, WMArray *dropDatas); */
/*
Process drop
dropDatas: datas (WMData*) required by destination (self)
(given in same order as returned by requiredDataTypes).
A NULL data means it couldn't be retrieved.
Destroyed when drop ends.
operationList: if source operation is WDOperationAsk, contains
operations (and associated texts) that can be asked
to source. (destroyed after performDragOperation call)
Otherwise this parameter is NULL.
*/
static void
defPerformDragOperation(WMView * self, WMArray * dropDatas, WMArray * operationList, WMPoint * dropLocation)
{
/* Parameter not used, but tell the compiler that it is ok */
(void) self;
(void) dropDatas;
(void) operationList;
(void) dropLocation;
}
/* Executed after drop */
static void defConcludeDragOperation(WMView * self)
{
/* Parameter not used, but tell the compiler that it is ok */
(void) self;
}
void WMSetViewDragDestinationProcs(WMView * view, WMDragDestinationProcs * procs)
{
if (view->dragDestinationProcs == NULL) {
view->dragDestinationProcs = wmalloc(sizeof(WMDragDestinationProcs));
}
*view->dragDestinationProcs = *procs;
/*XXX fill in non-implemented stuffs */
if (procs->allowedOperation == NULL) {
view->dragDestinationProcs->allowedOperation = defAllowedOperation;
}
if (procs->allowedOperation == NULL) {
view->dragDestinationProcs->requiredDataTypes = defRequiredDataTypes;
}
/* note: inspectDropData can be NULL, if data consultation is not needed
to give drop permission */
if (procs->prepareForDragOperation == NULL) {
view->dragDestinationProcs->prepareForDragOperation = defPrepareForDragOperation;
}
if (procs->performDragOperation == NULL) {
view->dragDestinationProcs->performDragOperation = defPerformDragOperation;
}
if (procs->concludeDragOperation == NULL) {
view->dragDestinationProcs->concludeDragOperation = defConcludeDragOperation;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,147 +0,0 @@
/*
* Window Maker miscelaneous function library
*
* Copyright (c) 1997-2003 Alfredo K. Kojima
*
* 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 St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include "wconfig.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "WINGs/WUtil.h"
#include "WINGs/WINGsP.h"
#ifdef HAVE_SYSLOG_H
#include <syslog.h>
static Bool syslog_initialized = False;
static void syslog_open(const char *prog_name)
{
int options;
if (!prog_name)
prog_name = "WINGs";
options = LOG_PID;
openlog(prog_name, options, LOG_DAEMON);
syslog_initialized = True;
}
static void syslog_message(int prio, const char *prog_name, const char *msg)
{
if (!syslog_initialized)
syslog_open(prog_name);
//jump over the program name cause syslog is already displaying it
syslog(prio, "%s", msg + strlen(prog_name));
}
void w_syslog_close(void)
{
if (syslog_initialized) {
closelog();
syslog_initialized = False;
}
}
#endif
void __wmessage(const char *func, const char *file, int line, int type, const char *msg, ...)
{
va_list args;
char *buf;
static int linemax = 0;
int truncated = 0;
#ifdef HAVE_SYSLOG
int syslog_priority = LOG_INFO;
#endif
if (linemax == 0) {
#ifdef HAVE_SYSCONF
linemax = sysconf(_SC_LINE_MAX);
if (linemax == -1) {
/* I'd like to know of this ever fires */
fprintf(stderr, "%s %d: sysconf(_SC_LINE_MAX) returned error\n",
__FILE__, __LINE__);
linemax = 512;
}
#else /* !HAVE_SYSCONF */
fprintf(stderr, "%s %d: Your system does not have sysconf(3); "
"let wmaker-dev@windowmaker.org know.\n", __FILE__, __LINE__);
linemax = 512;
#endif /* HAVE_SYSCONF */
}
buf = wmalloc(linemax);
fflush(stdout);
/* message format: <wings_progname>(function(file:line): <type?>: <message>"\n" */
strncat(buf, _WINGS_progname ? _WINGS_progname : "WINGs", linemax - 1);
snprintf(buf + strlen(buf), linemax - strlen(buf), "(%s(%s:%d))", func, file, line);
strncat(buf, ": ", linemax - 1 - strlen(buf));
switch (type) {
case WMESSAGE_TYPE_FATAL:
strncat(buf, _("fatal: "), linemax - 1 - strlen(buf));
#ifdef HAVE_SYSLOG
syslog_priority = LOG_CRIT;
#endif
break;
case WMESSAGE_TYPE_ERROR:
strncat(buf, _("error: "), linemax - 1 - strlen(buf));
#ifdef HAVE_SYSLOG
syslog_priority = LOG_ERR;
#endif
break;
case WMESSAGE_TYPE_WARNING:
strncat(buf, _("warning: "), linemax - 1 - strlen(buf));
#ifdef HAVE_SYSLOG
syslog_priority = LOG_WARNING;
#endif
break;
case WMESSAGE_TYPE_MESSAGE:
/* FALLTHROUGH */
default: /* should not happen, but doesn't hurt either */
break;
}
va_start(args, msg);
if (vsnprintf(buf + strlen(buf), linemax - strlen(buf), msg, args) >= linemax - strlen(buf))
truncated = 1;
va_end(args);
fputs(buf, stderr);
#ifdef HAVE_SYSLOG
syslog_message(syslog_priority, _WINGS_progname ? _WINGS_progname : "WINGs", buf);
#endif
if (truncated)
fputs("*** message truncated ***", stderr);
fputs("\n", stderr);
wfree(buf);
}

View File

@@ -1,36 +0,0 @@
/* WUtil / error.h
*
* Copyright (c) 2014 Window Maker Team
*
* 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.
*/
#ifndef WUTIL_ERROR_H
#define WUTIL_ERROR_H
/*
* This file is not part of WUtil public API
*
* It defines internal things for the error message display functions
*/
#ifdef HAVE_SYSLOG_H
/* Function to cleanly close the syslog stuff, called by wutil_shutdown from user side */
void w_syslog_close(void);
#endif
#endif /* WUTIL_ERROR_H */

View File

@@ -1,523 +0,0 @@
/*
* Window Maker miscelaneous function library
*
* Copyright (c) 1997-2003 Alfredo K. Kojima
*
* 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 St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include "wconfig.h"
#include "WUtil.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pwd.h>
#include <limits.h>
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
const char *wgethomedir(void)
{
static char *home = NULL;
char *tmp;
struct passwd *user;
if (home)
return home;
tmp = GETENV("HOME");
if (tmp) {
home = wstrdup(tmp);
return home;
}
user = getpwuid(getuid());
if (!user) {
werror(_("could not get password entry for UID %i"), getuid());
home = "/";
return home;
}
if (!user->pw_dir)
home = "/";
else
home = wstrdup(user->pw_dir);
return home;
}
/*
* Return the home directory for the specified used
*
* If user not found, returns NULL, otherwise always returns a path that is
* statically stored.
*
* Please note you must use the path before any other call to 'getpw*' or it
* may be erased. This is a design choice to avoid duplication considering
* the use case for this function.
*/
static const char *getuserhomedir(const char *username)
{
static const char default_home[] = "/";
struct passwd *user;
user = getpwnam(username);
if (!user) {
werror(_("could not get password entry for user %s"), username);
return NULL;
}
if (!user->pw_dir)
return default_home;
else
return user->pw_dir;
}
char *wexpandpath(const char *path)
{
const char *origpath = path;
char buffer2[PATH_MAX + 2];
char buffer[PATH_MAX + 2];
int i;
memset(buffer, 0, PATH_MAX + 2);
if (*path == '~') {
const char *home;
path++;
if (*path == '/' || *path == 0) {
home = wgethomedir();
if (strlen(home) > PATH_MAX ||
wstrlcpy(buffer, home, sizeof(buffer)) >= sizeof(buffer))
goto error;
} else {
int j;
j = 0;
while (*path != 0 && *path != '/') {
if (j > PATH_MAX)
goto error;
buffer2[j++] = *path;
buffer2[j] = 0;
path++;
}
home = getuserhomedir(buffer2);
if (!home || wstrlcat(buffer, home, sizeof(buffer)) >= sizeof(buffer))
goto error;
}
}
i = strlen(buffer);
while (*path != 0 && i <= PATH_MAX) {
char *tmp;
if (*path == '$') {
int j;
path++;
/* expand $(HOME) or $HOME style environment variables */
if (*path == '(') {
path++;
j = 0;
while (*path != 0 && *path != ')') {
if (j > PATH_MAX)
goto error;
buffer2[j++] = *(path++);
}
buffer2[j] = 0;
if (*path == ')') {
path++;
tmp = getenv(buffer2);
} else {
tmp = NULL;
}
if (!tmp) {
if ((i += strlen(buffer2) + 2) > PATH_MAX)
goto error;
buffer[i] = 0;
if (wstrlcat(buffer, "$(", sizeof(buffer)) >= sizeof(buffer) ||
wstrlcat(buffer, buffer2, sizeof(buffer)) >= sizeof(buffer))
goto error;
if (*(path-1)==')') {
if (++i > PATH_MAX ||
wstrlcat(buffer, ")", sizeof(buffer)) >= sizeof(buffer))
goto error;
}
} else {
if ((i += strlen(tmp)) > PATH_MAX ||
wstrlcat(buffer, tmp, sizeof(buffer)) >= sizeof(buffer))
goto error;
}
} else {
j = 0;
while (*path != 0 && *path != '/') {
if (j > PATH_MAX)
goto error;
buffer2[j++] = *(path++);
}
buffer2[j] = 0;
tmp = getenv(buffer2);
if (!tmp) {
if ((i += strlen(buffer2) + 1) > PATH_MAX ||
wstrlcat(buffer, "$", sizeof(buffer)) >= sizeof(buffer) ||
wstrlcat(buffer, buffer2, sizeof(buffer)) >= sizeof(buffer))
goto error;
} else {
if ((i += strlen(tmp)) > PATH_MAX ||
wstrlcat(buffer, tmp, sizeof(buffer)) >= sizeof(buffer))
goto error;
}
}
} else {
buffer[i++] = *path;
path++;
}
}
if (*path!=0)
goto error;
return wstrdup(buffer);
error:
errno = ENAMETOOLONG;
werror(_("could not expand %s"), origpath);
return NULL;
}
/* return address of next char != tok or end of string whichever comes first */
static const char *skipchar(const char *string, char tok)
{
while (*string != 0 && *string == tok)
string++;
return string;
}
/* return address of next char == tok or end of string whichever comes first */
static const char *nextchar(const char *string, char tok)
{
while (*string != 0 && *string != tok)
string++;
return string;
}
/*
*----------------------------------------------------------------------
* findfile--
* Finds a file in a : separated list of paths. ~ expansion is also
* done.
*
* Returns:
* The complete path for the file (in a newly allocated string) or
* NULL if the file was not found.
*
* Side effects:
* A new string is allocated. It must be freed later.
*
*----------------------------------------------------------------------
*/
char *wfindfile(const char *paths, const char *file)
{
char *path;
const char *tmp, *tmp2;
int len, flen;
char *fullpath;
if (!file)
return NULL;
if (*file == '/' || *file == '~' || *file == '$' || !paths || *paths == 0) {
if (access(file, F_OK) < 0) {
fullpath = wexpandpath(file);
if (!fullpath)
return NULL;
if (access(fullpath, F_OK) < 0) {
wfree(fullpath);
return NULL;
} else {
return fullpath;
}
} else {
return wstrdup(file);
}
}
flen = strlen(file);
tmp = paths;
while (*tmp) {
tmp = skipchar(tmp, ':');
if (*tmp == 0)
break;
tmp2 = nextchar(tmp, ':');
len = tmp2 - tmp;
path = wmalloc(len + flen + 2);
path = memcpy(path, tmp, len);
path[len] = 0;
if (path[len - 1] != '/' &&
wstrlcat(path, "/", len + flen + 2) >= len + flen + 2) {
wfree(path);
return NULL;
}
if (wstrlcat(path, file, len + flen + 2) >= len + flen + 2) {
wfree(path);
return NULL;
}
fullpath = wexpandpath(path);
wfree(path);
if (fullpath) {
if (access(fullpath, F_OK) == 0) {
return fullpath;
}
wfree(fullpath);
}
tmp = tmp2;
}
return NULL;
}
char *wfindfileinlist(char *const *path_list, const char *file)
{
int i;
char *path;
int len, flen;
char *fullpath;
if (!file)
return NULL;
if (*file == '/' || *file == '~' || !path_list) {
if (access(file, F_OK) < 0) {
fullpath = wexpandpath(file);
if (!fullpath)
return NULL;
if (access(fullpath, F_OK) < 0) {
wfree(fullpath);
return NULL;
} else {
return fullpath;
}
} else {
return wstrdup(file);
}
}
flen = strlen(file);
for (i = 0; path_list[i] != NULL; i++) {
len = strlen(path_list[i]);
path = wmalloc(len + flen + 2);
path = memcpy(path, path_list[i], len);
path[len] = 0;
if (wstrlcat(path, "/", len + flen + 2) >= len + flen + 2 ||
wstrlcat(path, file, len + flen + 2) >= len + flen + 2) {
wfree(path);
return NULL;
}
/* expand tilde */
fullpath = wexpandpath(path);
wfree(path);
if (fullpath) {
/* check if file exists */
if (access(fullpath, F_OK) == 0) {
return fullpath;
}
wfree(fullpath);
}
}
return NULL;
}
char *wfindfileinarray(WMPropList *array, const char *file)
{
int i;
char *path;
int len, flen;
char *fullpath;
if (!file)
return NULL;
if (*file == '/' || *file == '~' || !array) {
if (access(file, F_OK) < 0) {
fullpath = wexpandpath(file);
if (!fullpath)
return NULL;
if (access(fullpath, F_OK) < 0) {
wfree(fullpath);
return NULL;
} else {
return fullpath;
}
} else {
return wstrdup(file);
}
}
flen = strlen(file);
for (i = 0; i < WMGetPropListItemCount(array); i++) {
WMPropList *prop;
char *p;
prop = WMGetFromPLArray(array, i);
if (!prop)
continue;
p = WMGetFromPLString(prop);
len = strlen(p);
path = wmalloc(len + flen + 2);
path = memcpy(path, p, len);
path[len] = 0;
if (wstrlcat(path, "/", len + flen + 2) >= len + flen + 2 ||
wstrlcat(path, file, len + flen + 2) >= len + flen + 2) {
wfree(path);
return NULL;
}
/* expand tilde */
fullpath = wexpandpath(path);
wfree(path);
if (fullpath) {
/* check if file exists */
if (access(fullpath, F_OK) == 0) {
return fullpath;
}
wfree(fullpath);
}
}
return NULL;
}
int wcopy_file(const char *dest_dir, const char *src_file, const char *dest_file)
{
char *path_dst;
int fd_src, fd_dst;
struct stat stat_src;
mode_t permission_dst;
const size_t buffer_size = 2 * 1024 * 1024; /* 4MB is a decent start choice to allow the OS to take advantage of modern disk's performance */
char *buffer; /* The buffer is not created on the stack to avoid possible stack overflow as our buffer is big */
try_again_src:
fd_src = open(src_file, O_RDONLY | O_NOFOLLOW);
if (fd_src == -1) {
if (errno == EINTR)
goto try_again_src;
werror(_("Could not open input file \"%s\": %s"), src_file, strerror(errno));
return -1;
}
/* Only accept to copy regular files */
if (fstat(fd_src, &stat_src) != 0 || !S_ISREG(stat_src.st_mode)) {
close(fd_src);
return -1;
}
path_dst = wstrconcat(dest_dir, dest_file);
try_again_dst:
fd_dst = open(path_dst, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (fd_dst == -1) {
if (errno == EINTR)
goto try_again_dst;
werror(_("Could not create target file \"%s\": %s"), path_dst, strerror(errno));
wfree(path_dst);
close(fd_src);
return -1;
}
buffer = malloc(buffer_size); /* Don't use wmalloc to avoid the memset(0) we don't need */
if (buffer == NULL) {
werror(_("could not allocate memory for the copy buffer"));
close(fd_dst);
goto cleanup_and_return_failure;
}
for (;;) {
ssize_t size_data;
const char *write_ptr;
size_t write_remain;
try_again_read:
size_data = read(fd_src, buffer, buffer_size);
if (size_data == 0)
break; /* End of File have been reached */
if (size_data < 0) {
if (errno == EINTR)
goto try_again_read;
werror(_("could not read from file \"%s\": %s"), src_file, strerror(errno));
close(fd_dst);
goto cleanup_and_return_failure;
}
write_ptr = buffer;
write_remain = size_data;
while (write_remain > 0) {
ssize_t write_done;
try_again_write:
write_done = write(fd_dst, write_ptr, write_remain);
if (write_done < 0) {
if (errno == EINTR)
goto try_again_write;
werror(_("could not write data to file \"%s\": %s"), path_dst, strerror(errno));
close(fd_dst);
goto cleanup_and_return_failure;
}
write_ptr += write_done;
write_remain -= write_done;
}
}
/* Keep only the permission-related part of the field: */
permission_dst = stat_src.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX);
if (fchmod(fd_dst, permission_dst) != 0)
wwarning(_("could not set permission 0%03o on file \"%s\": %s"),
permission_dst, path_dst, strerror(errno));
if (close(fd_dst) != 0) {
werror(_("could not close the file \"%s\": %s"), path_dst, strerror(errno));
cleanup_and_return_failure:
free(buffer);
close(fd_src);
unlink(path_dst);
wfree(path_dst);
return -1;
}
free(buffer);
wfree(path_dst);
close(fd_src);
return 0;
}

View File

@@ -1,566 +0,0 @@
/*
* WINGs internal handlers: timer, idle and input handlers
*/
#include "wconfig.h"
#include "WINGs/WINGsP.h"
#include <sys/types.h>
#include <unistd.h>
#include <X11/Xos.h>
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif
#include <time.h>
#ifndef X_GETTIMEOFDAY
#define X_GETTIMEOFDAY(t) gettimeofday(t, (struct timezone*)0)
#endif
typedef struct TimerHandler {
WMCallback *callback; /* procedure to call */
struct timeval when; /* when to call the callback */
void *clientData;
struct TimerHandler *next;
int nextDelay; /* 0 if it's one-shot */
} TimerHandler;
typedef struct IdleHandler {
WMCallback *callback;
void *clientData;
} IdleHandler;
typedef struct InputHandler {
WMInputProc *callback;
void *clientData;
int fd;
int mask;
} InputHandler;
/* queue of timer event handlers */
static TimerHandler *timerHandler = NULL;
static WMArray *idleHandler = NULL;
static WMArray *inputHandler = NULL;
#define timerPending() (timerHandler)
static void rightNow(struct timeval *tv)
{
X_GETTIMEOFDAY(tv);
}
/* is t1 after t2 ? */
#define IS_AFTER(t1, t2) (((t1).tv_sec > (t2).tv_sec) || \
(((t1).tv_sec == (t2).tv_sec) \
&& ((t1).tv_usec > (t2).tv_usec)))
#define IS_ZERO(tv) (tv.tv_sec == 0 && tv.tv_usec == 0)
#define SET_ZERO(tv) tv.tv_sec = 0, tv.tv_usec = 0
static void addmillisecs(struct timeval *tv, int milliseconds)
{
tv->tv_usec += milliseconds * 1000;
tv->tv_sec += tv->tv_usec / 1000000;
tv->tv_usec = tv->tv_usec % 1000000;
}
static void enqueueTimerHandler(TimerHandler * handler)
{
TimerHandler *tmp;
/* insert callback in queue, sorted by time left */
if (!timerHandler || !IS_AFTER(handler->when, timerHandler->when)) {
/* first in the queue */
handler->next = timerHandler;
timerHandler = handler;
} else {
tmp = timerHandler;
while (tmp->next && IS_AFTER(handler->when, tmp->next->when)) {
tmp = tmp->next;
}
handler->next = tmp->next;
tmp->next = handler;
}
}
static void delayUntilNextTimerEvent(struct timeval *delay)
{
struct timeval now;
TimerHandler *handler;
handler = timerHandler;
while (handler && IS_ZERO(handler->when))
handler = handler->next;
if (!handler) {
/* The return value of this function is only valid if there _are_
timers active. */
delay->tv_sec = 0;
delay->tv_usec = 0;
return;
}
rightNow(&now);
if (IS_AFTER(now, handler->when)) {
delay->tv_sec = 0;
delay->tv_usec = 0;
} else {
delay->tv_sec = handler->when.tv_sec - now.tv_sec;
delay->tv_usec = handler->when.tv_usec - now.tv_usec;
if (delay->tv_usec < 0) {
delay->tv_usec += 1000000;
delay->tv_sec--;
}
}
}
WMHandlerID WMAddTimerHandler(int milliseconds, WMCallback * callback, void *cdata)
{
TimerHandler *handler;
handler = malloc(sizeof(TimerHandler));
if (!handler)
return NULL;
rightNow(&handler->when);
addmillisecs(&handler->when, milliseconds);
handler->callback = callback;
handler->clientData = cdata;
handler->nextDelay = 0;
enqueueTimerHandler(handler);
return handler;
}
WMHandlerID WMAddPersistentTimerHandler(int milliseconds, WMCallback * callback, void *cdata)
{
TimerHandler *handler = WMAddTimerHandler(milliseconds, callback, cdata);
if (handler != NULL)
handler->nextDelay = milliseconds;
return handler;
}
void WMDeleteTimerWithClientData(void *cdata)
{
TimerHandler *handler, *tmp;
if (!cdata || !timerHandler)
return;
tmp = timerHandler;
if (tmp->clientData == cdata) {
tmp->nextDelay = 0;
if (!IS_ZERO(tmp->when)) {
timerHandler = tmp->next;
wfree(tmp);
}
} else {
while (tmp->next) {
if (tmp->next->clientData == cdata) {
handler = tmp->next;
handler->nextDelay = 0;
if (IS_ZERO(handler->when))
break;
tmp->next = handler->next;
wfree(handler);
break;
}
tmp = tmp->next;
}
}
}
void WMDeleteTimerHandler(WMHandlerID handlerID)
{
TimerHandler *tmp, *handler = (TimerHandler *) handlerID;
if (!handler || !timerHandler)
return;
tmp = timerHandler;
handler->nextDelay = 0;
if (IS_ZERO(handler->when))
return;
if (tmp == handler) {
timerHandler = handler->next;
wfree(handler);
} else {
while (tmp->next) {
if (tmp->next == handler) {
tmp->next = handler->next;
wfree(handler);
break;
}
tmp = tmp->next;
}
}
}
WMHandlerID WMAddIdleHandler(WMCallback * callback, void *cdata)
{
IdleHandler *handler;
handler = malloc(sizeof(IdleHandler));
if (!handler)
return NULL;
handler->callback = callback;
handler->clientData = cdata;
/* add handler at end of queue */
if (!idleHandler) {
idleHandler = WMCreateArrayWithDestructor(16, wfree);
}
WMAddToArray(idleHandler, handler);
return handler;
}
void WMDeleteIdleHandler(WMHandlerID handlerID)
{
IdleHandler *handler = (IdleHandler *) handlerID;
if (!handler || !idleHandler)
return;
WMRemoveFromArray(idleHandler, handler);
}
WMHandlerID WMAddInputHandler(int fd, int condition, WMInputProc * proc, void *clientData)
{
InputHandler *handler;
handler = wmalloc(sizeof(InputHandler));
handler->fd = fd;
handler->mask = condition;
handler->callback = proc;
handler->clientData = clientData;
if (!inputHandler)
inputHandler = WMCreateArrayWithDestructor(16, wfree);
WMAddToArray(inputHandler, handler);
return handler;
}
void WMDeleteInputHandler(WMHandlerID handlerID)
{
InputHandler *handler = (InputHandler *) handlerID;
if (!handler || !inputHandler)
return;
WMRemoveFromArray(inputHandler, handler);
}
Bool W_CheckIdleHandlers(void)
{
IdleHandler *handler;
WMArray *handlerCopy;
WMArrayIterator iter;
if (!idleHandler || WMGetArrayItemCount(idleHandler) == 0) {
W_FlushIdleNotificationQueue();
/* make sure an observer in queue didn't added an idle handler */
return (idleHandler != NULL && WMGetArrayItemCount(idleHandler) > 0);
}
handlerCopy = WMDuplicateArray(idleHandler);
WM_ITERATE_ARRAY(handlerCopy, handler, iter) {
/* check if the handler still exist or was removed by a callback */
if (WMGetFirstInArray(idleHandler, handler) == WANotFound)
continue;
(*handler->callback) (handler->clientData);
WMDeleteIdleHandler(handler);
}
WMFreeArray(handlerCopy);
W_FlushIdleNotificationQueue();
/* this is not necesarrily False, because one handler can re-add itself */
return (WMGetArrayItemCount(idleHandler) > 0);
}
void W_CheckTimerHandlers(void)
{
TimerHandler *handler;
struct timeval now;
if (!timerHandler) {
W_FlushASAPNotificationQueue();
return;
}
rightNow(&now);
handler = timerHandler;
while (handler && IS_AFTER(now, handler->when)) {
if (!IS_ZERO(handler->when)) {
SET_ZERO(handler->when);
(*handler->callback) (handler->clientData);
}
handler = handler->next;
}
while (timerHandler && IS_ZERO(timerHandler->when)) {
handler = timerHandler;
timerHandler = timerHandler->next;
if (handler->nextDelay > 0) {
handler->when = now;
addmillisecs(&handler->when, handler->nextDelay);
enqueueTimerHandler(handler);
} else {
wfree(handler);
}
}
W_FlushASAPNotificationQueue();
}
/*
* This functions will handle input events on all registered file descriptors.
* Input:
* - waitForInput - True if we want the function to wait until an event
* appears on a file descriptor we watch, False if we
* want the function to immediately return if there is
* no data available on the file descriptors we watch.
* - inputfd - Extra input file descriptor to watch for input.
* This is only used when called from wevent.c to watch
* on ConnectionNumber(dpy) to avoid blocking of X events
* if we wait for input from other file handlers.
* Output:
* if waitForInput is False, the function will return False if there are no
* input handlers registered, or if there is no data
* available on the registered ones, and will return True
* if there is at least one input handler that has data
* available.
* if waitForInput is True, the function will return False if there are no
* input handlers registered, else it will block until an
* event appears on one of the file descriptors it watches
* and then it will return True.
*
* If the retured value is True, the input handlers for the corresponding file
* descriptors are also called.
*
* Parametersshould be passed like this:
* - from wevent.c:
* waitForInput - apropriate value passed by the function who called us
* inputfd = ConnectionNumber(dpy)
* - from wutil.c:
* waitForInput - apropriate value passed by the function who called us
* inputfd = -1
*
*/
Bool W_HandleInputEvents(Bool waitForInput, int inputfd)
{
#if defined(HAVE_POLL) && defined(HAVE_POLL_H) && !defined(HAVE_SELECT)
struct poll fd *fds;
InputHandler *handler;
int count, timeout, nfds, i, extrafd;
extrafd = (inputfd < 0) ? 0 : 1;
if (inputHandler)
nfds = WMGetArrayItemCount(inputHandler);
else
nfds = 0;
if (!extrafd && nfds == 0) {
W_FlushASAPNotificationQueue();
return False;
}
fds = wmalloc((nfds + extrafd) * sizeof(struct pollfd));
if (extrafd) {
/* put this to the end of array to avoid using ranges from 1 to nfds+1 */
fds[nfds].fd = inputfd;
fds[nfds].events = POLLIN;
}
/* use WM_ITERATE_ARRAY() here */
for (i = 0; i < nfds; i++) {
handler = WMGetFromArray(inputHandler, i);
fds[i].fd = handler->fd;
fds[i].events = 0;
if (handler->mask & WIReadMask)
fds[i].events |= POLLIN;
if (handler->mask & WIWriteMask)
fds[i].events |= POLLOUT;
#if 0 /* FIXME */
if (handler->mask & WIExceptMask)
FD_SET(handler->fd, &eset);
#endif
}
/*
* Setup the timeout to the estimated time until the
* next timer expires.
*/
if (!waitForInput) {
timeout = 0;
} else if (timerPending()) {
struct timeval tv;
delayUntilNextTimerEvent(&tv);
timeout = tv.tv_sec * 1000 + tv.tv_usec / 1000;
} else {
timeout = -1;
}
count = poll(fds, nfds + extrafd, timeout);
if (count > 0 && nfds > 0) {
WMArray *handlerCopy = WMDuplicateArray(inputHandler);
int mask;
/* use WM_ITERATE_ARRAY() here */
for (i = 0; i < nfds; i++) {
handler = WMGetFromArray(handlerCopy, i);
/* check if the handler still exist or was removed by a callback */
if (WMGetFirstInArray(inputHandler, handler) == WANotFound)
continue;
mask = 0;
if ((handler->mask & WIReadMask) &&
(fds[i].revents & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)))
mask |= WIReadMask;
if ((handler->mask & WIWriteMask) && (fds[i].revents & (POLLOUT | POLLWRBAND)))
mask |= WIWriteMask;
if ((handler->mask & WIExceptMask) && (fds[i].revents & (POLLHUP | POLLNVAL | POLLERR)))
mask |= WIExceptMask;
if (mask != 0 && handler->callback) {
(*handler->callback) (handler->fd, mask, handler->clientData);
}
}
WMFreeArray(handlerCopy);
}
wfree(fds);
W_FlushASAPNotificationQueue();
return (count > 0);
#else
#ifdef HAVE_SELECT
struct timeval timeout;
struct timeval *timeoutPtr;
fd_set rset, wset, eset;
int maxfd, nfds, i;
int count;
InputHandler *handler;
if (inputHandler)
nfds = WMGetArrayItemCount(inputHandler);
else
nfds = 0;
if (inputfd < 0 && nfds == 0) {
W_FlushASAPNotificationQueue();
return False;
}
FD_ZERO(&rset);
FD_ZERO(&wset);
FD_ZERO(&eset);
if (inputfd < 0) {
maxfd = 0;
} else {
FD_SET(inputfd, &rset);
maxfd = inputfd;
}
/* use WM_ITERATE_ARRAY() here */
for (i = 0; i < nfds; i++) {
handler = WMGetFromArray(inputHandler, i);
if (handler->mask & WIReadMask)
FD_SET(handler->fd, &rset);
if (handler->mask & WIWriteMask)
FD_SET(handler->fd, &wset);
if (handler->mask & WIExceptMask)
FD_SET(handler->fd, &eset);
if (maxfd < handler->fd)
maxfd = handler->fd;
}
/*
* Setup the timeout to the estimated time until the
* next timer expires.
*/
if (!waitForInput) {
SET_ZERO(timeout);
timeoutPtr = &timeout;
} else if (timerPending()) {
delayUntilNextTimerEvent(&timeout);
timeoutPtr = &timeout;
} else {
timeoutPtr = (struct timeval *)0;
}
count = select(1 + maxfd, &rset, &wset, &eset, timeoutPtr);
if (count > 0 && nfds > 0) {
WMArray *handlerCopy = WMDuplicateArray(inputHandler);
int mask;
/* use WM_ITERATE_ARRAY() here */
for (i = 0; i < nfds; i++) {
handler = WMGetFromArray(handlerCopy, i);
/* check if the handler still exist or was removed by a callback */
if (WMGetFirstInArray(inputHandler, handler) == WANotFound)
continue;
mask = 0;
if ((handler->mask & WIReadMask) && FD_ISSET(handler->fd, &rset))
mask |= WIReadMask;
if ((handler->mask & WIWriteMask) && FD_ISSET(handler->fd, &wset))
mask |= WIWriteMask;
if ((handler->mask & WIExceptMask) && FD_ISSET(handler->fd, &eset))
mask |= WIExceptMask;
if (mask != 0 && handler->callback) {
(*handler->callback) (handler->fd, mask, handler->clientData);
}
}
WMFreeArray(handlerCopy);
}
W_FlushASAPNotificationQueue();
return (count > 0);
#else /* not HAVE_SELECT, not HAVE_POLL */
# error Neither select nor poll. You lose.
#endif /* HAVE_SELECT */
#endif /* HAVE_POLL */
}

View File

@@ -1,422 +0,0 @@
#include "config/config.h"
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "WINGs/WUtil.h"
#define INITIAL_CAPACITY 23
typedef struct HashItem {
const void *key;
const void *data;
struct HashItem *next; /* collided item list */
} HashItem;
typedef struct W_HashTable {
WMHashTableCallbacks callbacks;
unsigned itemCount;
unsigned size; /* table size */
HashItem **table;
} HashTable;
#define HASH(table, key) (((table)->callbacks.hash ? \
(*(table)->callbacks.hash)(key) : hashPtr(key)) % (table)->size)
#define DUPKEY(table, key) ((table)->callbacks.retainKey ? \
(*(table)->callbacks.retainKey)(key) : (key))
#define RELKEY(table, key) if ((table)->callbacks.releaseKey) \
(*(table)->callbacks.releaseKey)(key)
static inline unsigned hashString(const void *param)
{
const char *key = param;
unsigned ret = 0;
unsigned ctr = 0;
while (*key) {
ret ^= *key++ << ctr;
ctr = (ctr + 1) % sizeof(char *);
}
return ret;
}
static inline unsigned hashPtr(const void *key)
{
return ((size_t) key / sizeof(char *));
}
static void rellocateItem(WMHashTable * table, HashItem * item)
{
unsigned h;
h = HASH(table, item->key);
item->next = table->table[h];
table->table[h] = item;
}
static void rebuildTable(WMHashTable * table)
{
HashItem *next;
HashItem **oldArray;
int i;
int oldSize;
int newSize;
oldArray = table->table;
oldSize = table->size;
newSize = table->size * 2;
table->table = wmalloc(sizeof(char *) * newSize);
table->size = newSize;
for (i = 0; i < oldSize; i++) {
while (oldArray[i] != NULL) {
next = oldArray[i]->next;
rellocateItem(table, oldArray[i]);
oldArray[i] = next;
}
}
wfree(oldArray);
}
WMHashTable *WMCreateHashTable(const WMHashTableCallbacks callbacks)
{
HashTable *table;
table = wmalloc(sizeof(HashTable));
table->callbacks = callbacks;
table->size = INITIAL_CAPACITY;
table->table = wmalloc(sizeof(HashItem *) * table->size);
return table;
}
void WMResetHashTable(WMHashTable * table)
{
HashItem *item, *tmp;
int i;
for (i = 0; i < table->size; i++) {
item = table->table[i];
while (item) {
tmp = item->next;
RELKEY(table, item->key);
wfree(item);
item = tmp;
}
}
table->itemCount = 0;
if (table->size > INITIAL_CAPACITY) {
wfree(table->table);
table->size = INITIAL_CAPACITY;
table->table = wmalloc(sizeof(HashItem *) * table->size);
} else {
memset(table->table, 0, sizeof(HashItem *) * table->size);
}
}
void WMFreeHashTable(WMHashTable * table)
{
HashItem *item, *tmp;
int i;
for (i = 0; i < table->size; i++) {
item = table->table[i];
while (item) {
tmp = item->next;
RELKEY(table, item->key);
wfree(item);
item = tmp;
}
}
wfree(table->table);
wfree(table);
}
unsigned WMCountHashTable(WMHashTable * table)
{
return table->itemCount;
}
static HashItem *hashGetItem(WMHashTable *table, const void *key)
{
unsigned h;
HashItem *item;
h = HASH(table, key);
item = table->table[h];
if (table->callbacks.keyIsEqual) {
while (item) {
if ((*table->callbacks.keyIsEqual) (key, item->key)) {
break;
}
item = item->next;
}
} else {
while (item) {
if (key == item->key) {
break;
}
item = item->next;
}
}
return item;
}
void *WMHashGet(WMHashTable * table, const void *key)
{
HashItem *item;
item = hashGetItem(table, key);
if (!item)
return NULL;
return (void *)item->data;
}
Bool WMHashGetItemAndKey(WMHashTable * table, const void *key, void **retItem, void **retKey)
{
HashItem *item;
item = hashGetItem(table, key);
if (!item)
return False;
if (retKey)
*retKey = (void *)item->key;
if (retItem)
*retItem = (void *)item->data;
return True;
}
void *WMHashInsert(WMHashTable * table, const void *key, const void *data)
{
unsigned h;
HashItem *item;
int replacing = 0;
h = HASH(table, key);
/* look for the entry */
item = table->table[h];
if (table->callbacks.keyIsEqual) {
while (item) {
if ((*table->callbacks.keyIsEqual) (key, item->key)) {
replacing = 1;
break;
}
item = item->next;
}
} else {
while (item) {
if (key == item->key) {
replacing = 1;
break;
}
item = item->next;
}
}
if (replacing) {
const void *old;
old = item->data;
item->data = data;
RELKEY(table, item->key);
item->key = DUPKEY(table, key);
return (void *)old;
} else {
HashItem *nitem;
nitem = wmalloc(sizeof(HashItem));
nitem->key = DUPKEY(table, key);
nitem->data = data;
nitem->next = table->table[h];
table->table[h] = nitem;
table->itemCount++;
}
/* OPTIMIZE: put this in an idle handler. */
if (table->itemCount > table->size) {
#ifdef DEBUG0
printf("rebuilding hash table...\n");
#endif
rebuildTable(table);
#ifdef DEBUG0
printf("finished rebuild.\n");
#endif
}
return NULL;
}
static HashItem *deleteFromList(HashTable * table, HashItem * item, const void *key)
{
HashItem *next;
if (item == NULL)
return NULL;
if ((table->callbacks.keyIsEqual && (*table->callbacks.keyIsEqual) (key, item->key))
|| (!table->callbacks.keyIsEqual && key == item->key)) {
next = item->next;
RELKEY(table, item->key);
wfree(item);
table->itemCount--;
return next;
}
item->next = deleteFromList(table, item->next, key);
return item;
}
void WMHashRemove(WMHashTable * table, const void *key)
{
unsigned h;
h = HASH(table, key);
table->table[h] = deleteFromList(table, table->table[h], key);
}
WMHashEnumerator WMEnumerateHashTable(WMHashTable * table)
{
WMHashEnumerator enumerator;
enumerator.table = table;
enumerator.index = 0;
enumerator.nextItem = table->table[0];
return enumerator;
}
void *WMNextHashEnumeratorItem(WMHashEnumerator * enumerator)
{
const void *data = NULL;
/* this assumes the table doesn't change between
* WMEnumerateHashTable() and WMNextHashEnumeratorItem() calls */
if (enumerator->nextItem == NULL) {
HashTable *table = enumerator->table;
while (++enumerator->index < table->size) {
if (table->table[enumerator->index] != NULL) {
enumerator->nextItem = table->table[enumerator->index];
break;
}
}
}
if (enumerator->nextItem) {
data = ((HashItem *) enumerator->nextItem)->data;
enumerator->nextItem = ((HashItem *) enumerator->nextItem)->next;
}
return (void *)data;
}
void *WMNextHashEnumeratorKey(WMHashEnumerator * enumerator)
{
const void *key = NULL;
/* this assumes the table doesn't change between
* WMEnumerateHashTable() and WMNextHashEnumeratorKey() calls */
if (enumerator->nextItem == NULL) {
HashTable *table = enumerator->table;
while (++enumerator->index < table->size) {
if (table->table[enumerator->index] != NULL) {
enumerator->nextItem = table->table[enumerator->index];
break;
}
}
}
if (enumerator->nextItem) {
key = ((HashItem *) enumerator->nextItem)->key;
enumerator->nextItem = ((HashItem *) enumerator->nextItem)->next;
}
return (void *)key;
}
Bool WMNextHashEnumeratorItemAndKey(WMHashEnumerator * enumerator, void **item, void **key)
{
/* this assumes the table doesn't change between
* WMEnumerateHashTable() and WMNextHashEnumeratorItemAndKey() calls */
if (enumerator->nextItem == NULL) {
HashTable *table = enumerator->table;
while (++enumerator->index < table->size) {
if (table->table[enumerator->index] != NULL) {
enumerator->nextItem = table->table[enumerator->index];
break;
}
}
}
if (enumerator->nextItem) {
if (item)
*item = (void *)((HashItem *) enumerator->nextItem)->data;
if (key)
*key = (void *)((HashItem *) enumerator->nextItem)->key;
enumerator->nextItem = ((HashItem *) enumerator->nextItem)->next;
return True;
}
return False;
}
static Bool compareStrings(const void *param1, const void *param2)
{
const char *key1 = param1;
const char *key2 = param2;
return strcmp(key1, key2) == 0;
}
typedef void *(*retainFunc) (const void *);
typedef void (*releaseFunc) (const void *);
const WMHashTableCallbacks WMIntHashCallbacks = {
NULL,
NULL,
NULL,
NULL
};
const WMHashTableCallbacks WMStringHashCallbacks = {
hashString,
compareStrings,
(retainFunc) wstrdup,
(releaseFunc) wfree
};
const WMHashTableCallbacks WMStringPointerHashCallbacks = {
hashString,
compareStrings,
NULL,
NULL
};

View File

@@ -1,53 +0,0 @@
#!/usr/bin/python
import sys
import re
from optparse import OptionParser
parser = OptionParser(version="%prog 1.0")
parser.add_option("-f", "--file", dest="rgbtxtFile", default='/etc/X11/rgb.txt',
help="rgb.txt file containing X11 colors (/etc/X11/rgb.txt)",
metavar="File")
(options, args) = parser.parse_args()
f = open(options.rgbtxtFile)
lines = f.readlines()
f.close()
colorLine = re.compile(r'''\s*
(?P<red>\d+) # red
\s+
(?P<green>\d+) # green
\s+
(?P<blue>\d+) # blue
\s+
(?P<name>[^\s]+) # name
''', re.VERBOSE)
print '''
/* Automatically generated file. Do NOT edit. Regenerate it using make-rgb */
#ifndef RGB_H_
#define RGB_H_
#include <wraster.h>
typedef struct RGBColor {
RColor color;
char *name;
} RGBColor;
RGBColor rgbColors[] = {'''
for line in lines:
m = colorLine.match(line)
if m:
print ''' {{%(red)3s, %(green)3s, %(blue)3s, 0}, "%(name)s"},''' % m.groupdict()
print ''' {{ 0, 0, 0, 0}, NULL}
};
#endif
'''

View File

@@ -1,223 +0,0 @@
/*
* Window Maker miscelaneous function library
*
* Copyright (c) 1997-2003 Alfredo K. Kojima
*
* 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 St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include "wconfig.h"
#include "WUtil.h"
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <signal.h>
#ifdef HAVE_STDNORETURN
#include <stdnoreturn.h>
#endif
#ifdef USE_BOEHM_GC
#ifndef GC_DEBUG
#define GC_DEBUG
#endif /* !GC_DEBUG */
#include <gc/gc.h>
#endif /* USE_BOEHM_GC */
#ifndef False
# define False 0
#endif
#ifndef True
# define True 1
#endif
static void defaultHandler(int bla)
{
if (bla)
kill(getpid(), SIGABRT);
else
exit(1);
}
static waborthandler *aborthandler = defaultHandler;
static inline noreturn void wAbort(int bla)
{
(*aborthandler)(bla);
exit(-1);
}
waborthandler *wsetabort(waborthandler * handler)
{
waborthandler *old = aborthandler;
aborthandler = handler;
return old;
}
static int Aborting = 0; /* if we're in the middle of an emergency exit */
static WMHashTable *table = NULL;
void *wmalloc(size_t size)
{
void *tmp;
assert(size > 0);
#ifdef USE_BOEHM_GC
tmp = GC_MALLOC(size);
#else
tmp = malloc(size);
#endif
if (tmp == NULL) {
wwarning("malloc() failed. Retrying after 2s.");
sleep(2);
#ifdef USE_BOEHM_GC
tmp = GC_MALLOC(size);
#else
tmp = malloc(size);
#endif
if (tmp == NULL) {
if (Aborting) {
fputs("Really Bad Error: recursive malloc() failure.", stderr);
exit(-1);
} else {
wfatal("virtual memory exhausted");
Aborting = 1;
wAbort(False);
}
}
}
if (tmp != NULL)
memset(tmp, 0, size);
return tmp;
}
void *wrealloc(void *ptr, size_t newsize)
{
void *nptr;
if (!ptr) {
nptr = wmalloc(newsize);
} else if (newsize == 0) {
wfree(ptr);
nptr = NULL;
} else {
#ifdef USE_BOEHM_GC
nptr = GC_REALLOC(ptr, newsize);
#else
nptr = realloc(ptr, newsize);
#endif
if (nptr == NULL) {
wwarning("realloc() failed. Retrying after 2s.");
sleep(2);
#ifdef USE_BOEHM_GC
nptr = GC_REALLOC(ptr, newsize);
#else
nptr = realloc(ptr, newsize);
#endif
if (nptr == NULL) {
if (Aborting) {
fputs("Really Bad Error: recursive realloc() failure.", stderr);
exit(-1);
} else {
wfatal("virtual memory exhausted");
Aborting = 1;
wAbort(False);
}
}
}
}
return nptr;
}
void *wretain(void *ptr)
{
int *refcount;
if (!table) {
table = WMCreateHashTable(WMIntHashCallbacks);
}
refcount = WMHashGet(table, ptr);
if (!refcount) {
refcount = wmalloc(sizeof(int));
*refcount = 1;
WMHashInsert(table, ptr, refcount);
#ifdef VERBOSE
printf("== %i (%p)\n", *refcount, ptr);
#endif
} else {
(*refcount)++;
#ifdef VERBOSE
printf("+ %i (%p)\n", *refcount, ptr);
#endif
}
return ptr;
}
void wfree(void *ptr)
{
if (ptr)
#ifdef USE_BOEHM_GC
/* This should eventually be removed, once the criss-cross
* of wmalloc()d memory being free()d, malloc()d memory being
* wfree()d, various misuses of calling wfree() on objects
* allocated by libc malloc() and calling libc free() on
* objects allocated by Boehm GC (think external libraries)
* is cleaned up.
*/
if (GC_base(ptr) != 0)
GC_FREE(ptr);
else
free(ptr);
#else
free(ptr);
#endif
ptr = NULL;
}
void wrelease(void *ptr)
{
int *refcount;
refcount = WMHashGet(table, ptr);
if (!refcount) {
wwarning("trying to release unexisting data %p", ptr);
} else {
(*refcount)--;
if (*refcount < 1) {
#ifdef VERBOSE
printf("RELEASING %p\n", ptr);
#endif
WMHashRemove(table, ptr);
wfree(refcount);
wfree(ptr);
}
#ifdef VERBOSE
else {
printf("- %i (%p)\n", *refcount, ptr);
}
#endif
}
}

View File

@@ -1,652 +0,0 @@
/*
* Window Maker window manager
*
* Copyright (c) 2012 Christophe Curis
*
* 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.
*/
#include "wconfig.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include "WINGs/WUtil.h"
#include "WINGs/menuparser.h"
static WMenuParser menu_parser_create_new(const char *file_name, void *file,
const char *include_default_paths);
static char *menu_parser_isolate_token(WMenuParser parser);
static void menu_parser_get_directive(WMenuParser parser);
static Bool menu_parser_include_file(WMenuParser parser);
static void menu_parser_condition_ifmacro(WMenuParser parser, Bool check_exists);
static void menu_parser_condition_else(WMenuParser parser);
static void menu_parser_condition_end(WMenuParser parser);
/* Constructor and Destructor for the Menu Parser object */
WMenuParser WMenuParserCreate(const char *file_name, void *file,
const char *include_default_paths)
{
WMenuParser parser;
parser = menu_parser_create_new(file_name, file, include_default_paths);
menu_parser_register_preset_macros(parser);
return parser;
}
void WMenuParserDelete(WMenuParser parser)
{
if (parser->include_file) {
/* Trick: the top parser's data are not wmalloc'd, we point on the
* provided data so we do not wfree it; however for include files
* we did wmalloc them.
* This code should not be used as the wfree is done when we reach
* the end of an include file; however this may not happen when an
* early exit occurs (typically when 'readMenuFile' does not find
* its expected command). */
fclose(parser->include_file->file_handle);
wfree((char *) parser->include_file->file_name);
WMenuParserDelete(parser->include_file);
}
if (parser->macros)
menu_parser_free_macros(parser);
wfree(parser);
}
static WMenuParser menu_parser_create_new(const char *file_name, void *file,
const char *include_default_paths)
{
WMenuParser parser;
parser = wmalloc(sizeof(*parser));
parser->include_default_paths = include_default_paths;
parser->file_name = file_name;
parser->file_handle = file;
parser->rd = parser->line_buffer;
return parser;
}
/* To report helpfull messages to user */
const char *WMenuParserGetFilename(WMenuParser parser)
{
return parser->file_name;
}
void WMenuParserError(WMenuParser parser, const char *msg, ...)
{
char buf[MAXLINE];
va_list args;
WMenuParser parent;
while (parser->include_file)
parser = parser->include_file;
va_start(args, msg);
vsnprintf(buf, sizeof(buf), msg, args);
va_end(args);
__wmessage("WMenuParser", parser->file_name, parser->line_number,
WMESSAGE_TYPE_WARNING, "%s", buf);
for (parent = parser->parent_file; parent != NULL; parent = parent->parent_file)
__wmessage("WMenuParser", parser->file_name, parser->line_number,
WMESSAGE_TYPE_WARNING, _(" included from file \"%s\" at line %d"),
parent->file_name, parent->line_number);
}
/* Read one line from file and split content
* The function returns False when the end of file is reached */
Bool WMenuParserGetLine(WMenuParser top_parser, char **title, char **command,
char **parameter, char **shortcut)
{
WMenuParser cur_parser;
enum { GET_TITLE, GET_COMMAND, GET_PARAMETERS, GET_SHORTCUT } scanmode;
char *token, *params = NULL;
char lineparam[MAXLINE];
lineparam[0] = '\0';
*title = NULL;
*command = NULL;
*parameter = NULL;
*shortcut = NULL;
scanmode = GET_TITLE;
read_next_line_with_filechange:
cur_parser = top_parser;
while (cur_parser->include_file)
cur_parser = cur_parser->include_file;
read_next_line:
if (fgets(cur_parser->line_buffer, sizeof(cur_parser->line_buffer), cur_parser->file_handle) == NULL) {
if (cur_parser->cond.depth > 0) {
int i;
for (i = 0; i < cur_parser->cond.depth; i++)
WMenuParserError(cur_parser, _("missing #endif to match #%s at line %d"),
cur_parser->cond.stack[i].name, cur_parser->cond.stack[i].line);
}
if (cur_parser->parent_file == NULL)
/* Not inside an included file -> we have reached the end */
return False;
/* We have only reached the end of an included file -> go back to calling file */
fclose(cur_parser->file_handle);
wfree((char *) cur_parser->file_name);
cur_parser = cur_parser->parent_file;
wfree(cur_parser->include_file);
cur_parser->include_file = NULL;
goto read_next_line_with_filechange;
}
cur_parser->line_number++;
cur_parser->rd = cur_parser->line_buffer;
for (;;) {
if (!menu_parser_skip_spaces_and_comments(cur_parser)) {
/* We reached the end of line */
if (scanmode == GET_TITLE)
goto read_next_line; /* Empty line -> skip */
else
break; /* Finished reading current line -> return it to caller */
}
if ((scanmode == GET_TITLE) && (*cur_parser->rd == '#')) {
cur_parser->rd++;
menu_parser_get_directive(cur_parser);
goto read_next_line_with_filechange;
}
if (cur_parser->cond.stack[0].skip)
goto read_next_line;
/* Found a word */
token = menu_parser_isolate_token(cur_parser);
switch (scanmode) {
case GET_TITLE:
*title = token;
scanmode = GET_COMMAND;
break;
case GET_COMMAND:
if (strcmp(token, "SHORTCUT") == 0) {
scanmode = GET_SHORTCUT;
wfree(token);
} else {
*command = token;
scanmode = GET_PARAMETERS;
}
break;
case GET_SHORTCUT:
if (*shortcut != NULL) {
WMenuParserError(top_parser, _("multiple SHORTCUT definition not valid") );
wfree(*shortcut);
}
*shortcut = token;
scanmode = GET_COMMAND;
break;
case GET_PARAMETERS:
{
char *src;
if (params == NULL) {
params = lineparam;
} else {
if ((params - lineparam) < sizeof(lineparam) - 1)
*params++ = ' ';
}
src = token;
while ((params - lineparam) < sizeof(lineparam) - 1)
if ( (*params = *src++) == '\0')
break;
else
params++;
wfree(token);
}
break;
}
}
if (params != NULL) {
lineparam[sizeof(lineparam) - 1] = '\0';
*parameter = wstrdup(lineparam);
}
return True;
}
/* Return False when there's nothing left on the line,
otherwise increment parser's pointer to next token */
Bool menu_parser_skip_spaces_and_comments(WMenuParser parser)
{
for (;;) {
while (isspace(*parser->rd))
parser->rd++;
if (*parser->rd == '\0') {
return False; /* Found the end of current line */
} else if ((parser->rd[0] == '\\') &&
(parser->rd[1] == '\n') &&
(parser->rd[2] == '\0')) {
/* Means that the current line is expected to be continued on next line */
if (fgets(parser->line_buffer, sizeof(parser->line_buffer), parser->file_handle) == NULL) {
WMenuParserError(parser, _("premature end of file while expecting a new line after '\\'") );
return False;
}
parser->line_number++;
parser->rd = parser->line_buffer;
} else if (parser->rd[0] == '/') {
if (parser->rd[1] == '/') /* Single line C comment */
return False; /* Won't find anything more on this line */
if (parser->rd[1] == '*') {
int start_line;
start_line = parser->line_number;
parser->rd += 2;
for (;;) {
/* Search end-of-comment marker */
while (*parser->rd != '\0') {
if ((parser->rd[0] == '*') && (parser->rd[1] == '/'))
goto found_end_of_comment;
parser->rd++;
}
/* Marker not found -> load next line */
if (fgets(parser->line_buffer, sizeof(parser->line_buffer), parser->file_handle) == NULL) {
WMenuParserError(parser, _("reached end of file while searching '*/' for comment started at line %d"), start_line);
return False;
}
parser->line_number++;
parser->rd = parser->line_buffer;
}
found_end_of_comment:
parser->rd += 2; /* Skip closing mark */
continue; /* Because there may be spaces after the comment */
}
return True; /* the '/' was not a comment, treat it as user data */
} else {
return True; /* Found some data */
}
}
}
/* read a token (non-spaces suite of characters)
* the result is wmalloc's, so it needs to be free'd */
static char *menu_parser_isolate_token(WMenuParser parser)
{
char buffer_token[sizeof(parser->line_buffer)];
char *token;
int limit = MAX_NESTED_MACROS;
token = buffer_token;
restart_token_split:
while (*parser->rd != '\0')
if (isspace(*parser->rd)) {
break;
} else if ((parser->rd[0] == '/') &&
((parser->rd[1] == '*') || (parser->rd[1] == '/'))) {
break;
} else if (parser->rd[0] == '\\') {
if ((parser->rd[1] == '\n') || (parser->rd[1] == '\0'))
break;
parser->rd++;
*token++ = *parser->rd++;
} else if (*parser->rd == '"' ) {
char ch;
/* Double-quoted string deserve special processing because macros are not expanded
inside. We also remove the double quotes. */
parser->rd++;
while ((*parser->rd != '\0') && (*parser->rd != '\n')) {
ch = *parser->rd++;
if (ch == '\\') {
if ((*parser->rd == '\0') || (*parser->rd == '\n'))
break;
*token++ = *parser->rd++;
} else if (ch == '"')
goto found_end_dquote;
else
*token++ = ch;
}
WMenuParserError(parser, _("missing closing double-quote before end-of-line") );
found_end_dquote:
;
} else if (*parser->rd == '\'') {
char ch;
/* Simple-quoted string deserve special processing because we keep their content
as-is, including the quotes and the \-escaped text */
*token++ = *parser->rd++;
while ((*parser->rd != '\0') && (*parser->rd != '\n')) {
ch = *parser->rd++;
*token++ = ch;
if (ch == '\'')
goto found_end_squote;
}
WMenuParserError(parser, _("missing closing simple-quote before end-of-line") );
found_end_squote:
;
} else if (isnamechr(*parser->rd)) {
WParserMacro *macro;
macro = menu_parser_find_macro(parser, parser->rd);
if (macro != NULL) {
/* The expansion is done inside the parser's buffer
this is needed to allow sub macro calls */
menu_parser_expand_macro(parser, macro);
/* Restart parsing to allow expansion of sub macro calls */
if (limit-- > 0)
goto restart_token_split;
WMenuParserError(parser, _("too many nested macro expansions, breaking loop"));
while (isnamechr(*parser->rd))
parser->rd++;
break;
} else {
while (isnamechr(*parser->rd))
*token++ = *parser->rd++;
}
} else {
*token++ = *parser->rd++;
}
*token++ = '\0';
token = wmalloc(token - buffer_token);
strcpy(token, buffer_token);
return token;
}
/* Processing of special # directives */
static void menu_parser_get_directive(WMenuParser parser)
{
char *command;
/* Isolate the command */
while (isspace(*parser->rd))
parser->rd++;
command = parser->rd;
while (*parser->rd)
if (isspace(*parser->rd)) {
*parser->rd++ = '\0';
break;
} else {
parser->rd++;
}
if (strcmp(command, "include") == 0) {
if (!menu_parser_include_file(parser))
return;
} else if (strcmp(command, "define") == 0) {
menu_parser_define_macro(parser);
} else if (strcmp(command, "ifdef") == 0) {
menu_parser_condition_ifmacro(parser, 1);
} else if (strcmp(command, "ifndef") == 0) {
menu_parser_condition_ifmacro(parser, 0);
} else if (strcmp(command, "else") == 0) {
menu_parser_condition_else(parser);
} else if (strcmp(command, "endif") == 0) {
menu_parser_condition_end(parser);
} else {
WMenuParserError(parser, _("unknown directive '#%s'"), command);
return;
}
if (menu_parser_skip_spaces_and_comments(parser))
WMenuParserError(parser, _("extra text after '#' command is ignored: \"%.16s...\""),
parser->rd);
}
/* Extract the file name, search for it in known directories
* and create a sub-parser to handle it.
* Returns False if the file could not be found */
static Bool menu_parser_include_file(WMenuParser parser)
{
char buffer[MAXLINE];
char *req_filename, *fullfilename, *p;
char eot;
FILE *fh;
if (!menu_parser_skip_spaces_and_comments(parser)) {
WMenuParserError(parser, _("no file name found for #include") );
return False;
}
switch (*parser->rd++) {
case '<':
eot = '>';
break;
case '"':
eot = '"';
break;
default:
WMenuParserError(parser, _("file name must be enclosed in brackets or double-quotes for #define") );
return False;
}
req_filename = parser->rd;
while (*parser->rd) {
if (*parser->rd == eot) {
*parser->rd++ = '\0';
goto found_end_define_fname;
} else {
parser->rd++;
}
}
WMenuParserError(parser, _("missing closing '%c' in filename specification"), eot);
return False;
found_end_define_fname:
/* If we're inside a #if sequence, we abort now, but not sooner in
* order to keep the syntax check */
if (parser->cond.stack[0].skip)
return False;
{ /* Check we are not nesting too many includes */
WMenuParser p;
int count;
count = 0;
for (p = parser; p->parent_file; p = p->parent_file)
count++;
if (count > MAX_NESTED_INCLUDES) {
WMenuParserError(parser, _("too many nested #include's"));
return False;
}
}
/* Absolute paths */
fullfilename = req_filename;
if (req_filename[0] != '/') {
/* Search first in the same directory as the current file */
p = strrchr(parser->file_name, '/');
if (p != NULL) {
int len;
len = p - parser->file_name + 1;
if (len > sizeof(buffer) - 1)
len = sizeof(buffer) - 1;
strncpy(buffer, parser->file_name, len);
strncpy(buffer+len, req_filename, sizeof(buffer) - len - 1);
buffer[sizeof(buffer) - 1] = '\0';
fullfilename = buffer;
}
}
fh = fopen(fullfilename, "rb");
/* Not found? Search in wmaker's known places */
if (fh == NULL) {
if (req_filename[0] != '/') {
const char *src;
int idx;
fullfilename = buffer;
src = parser->include_default_paths;
while (*src != '\0') {
idx = 0;
if (*src == '~') {
const char *home = wgethomedir();
while (*home != '\0') {
if (idx < sizeof(buffer) - 2)
buffer[idx++] = *home;
home++;
}
src++;
}
while ((*src != '\0') && (*src != ':')) {
if (idx < sizeof(buffer) - 2)
buffer[idx++] = *src;
src++;
}
buffer[idx++] = '/';
for (p = req_filename; *p != '\0'; p++)
if (idx < sizeof(buffer) - 1)
buffer[idx++] = *p;
buffer[idx] = '\0';
fh = fopen(fullfilename, "rb");
if (fh != NULL)
goto found_valid_file;
if (*src == ':')
src++;
}
}
WMenuParserError(parser, _("could not find file \"%s\" for #include"), req_filename);
return False;
}
/* Found the file, make it our new source */
found_valid_file:
parser->include_file = menu_parser_create_new(wstrdup(req_filename), fh, parser->include_default_paths);
parser->include_file->parent_file = parser;
return True;
}
/* Check wether a macro exists or not, and marks the parser to ignore the
* following data accordingly */
static void menu_parser_condition_ifmacro(WMenuParser parser, Bool check_exists)
{
WParserMacro *macro;
int idx;
const char *cmd_name, *macro_name;
cmd_name = check_exists?"ifdef":"ifndef";
if (!menu_parser_skip_spaces_and_comments(parser)) {
WMenuParserError(parser, _("missing macro name argument to #%s"), cmd_name);
return;
}
/* jump to end of provided name for later checks that no extra stuff is following */
macro_name = parser->rd;
while (isnamechr(*parser->rd))
parser->rd++;
/* Add this condition to the stack of conditions */
if (parser->cond.depth >= wlengthof(parser->cond.stack)) {
WMenuParserError(parser, _("too many nested #if sequences") );
return;
}
for (idx = parser->cond.depth - 1; idx >= 0; idx--)
parser->cond.stack[idx + 1] = parser->cond.stack[idx];
parser->cond.depth++;
if (parser->cond.stack[1].skip) {
parser->cond.stack[0].skip = True;
} else {
macro = menu_parser_find_macro(parser, macro_name);
parser->cond.stack[0].skip =
((check_exists) && (macro == NULL)) ||
((!check_exists) && (macro != NULL));
}
strncpy(parser->cond.stack[0].name, cmd_name, sizeof(parser->cond.stack[0].name) - 1);
parser->cond.stack[0].line = parser->line_number;
}
/* Swap the 'data ignore' flag because a #else condition was found */
static void menu_parser_condition_else(WMenuParser parser)
{
if (parser->cond.depth <= 0) {
WMenuParserError(parser, _("found #%s but has no matching #if"), "else");
return;
}
if ((parser->cond.depth > 1) && (parser->cond.stack[1].skip))
/* The containing #if is false, so we continue skipping anyway */
parser->cond.stack[0].skip = True;
else
parser->cond.stack[0].skip = !parser->cond.stack[0].skip;
}
/* Closes the current conditional, removing it from the stack */
static void menu_parser_condition_end(WMenuParser parser)
{
int idx;
if (parser->cond.depth <= 0) {
WMenuParserError(parser, _("found #%s but has no matching #if"), "endif");
return;
}
if (--parser->cond.depth > 0)
for (idx = 0; idx < parser->cond.depth; idx++)
parser->cond.stack[idx] = parser->cond.stack[idx + 1];
else
parser->cond.stack[0].skip = False;
}

View File

@@ -1,86 +0,0 @@
/* menuparser.h
*
* Copyright (c) 2012 Christophe Curis
*
* 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.
*/
#ifndef _MENUPARSER_H_INCLUDED
#define _MENUPARSER_H_INCLUDED
/*
* This file is not part of WINGs public API
*
* It defines internal things for the Menu Parser, the public API is
* located in WINGs/WUtil.h as usual
*/
#define MAXLINE 1024
#define MAX_NESTED_INCLUDES 16 // To avoid infinite includes case
#define MAX_NESTED_MACROS 24 // To avoid infinite loop inside macro expansions
#define MAX_MACRO_ARG_COUNT 32 // Limited by design
typedef struct w_parser_macro WParserMacro;
typedef void WParserMacroFunction(WParserMacro *this, WMenuParser parser);
struct w_menu_parser {
WMenuParser include_file;
WMenuParser parent_file;
const char *include_default_paths;
const char *file_name;
FILE *file_handle;
int line_number;
WParserMacro *macros;
struct {
/* Conditional text parsing is implemented using a stack of the
skip states for each nested #if */
int depth;
struct {
Bool skip;
char name[8];
int line;
} stack[32];
} cond;
char *rd;
char line_buffer[MAXLINE];
};
struct w_parser_macro {
WParserMacro *next;
char name[64];
WParserMacroFunction *function;
int arg_count;
#ifdef DEBUG
int usage_count;
#endif
unsigned char value[MAXLINE * 4];
};
Bool menu_parser_skip_spaces_and_comments(WMenuParser parser);
void menu_parser_register_preset_macros(WMenuParser parser);
void menu_parser_define_macro(WMenuParser parser);
void menu_parser_free_macros(WMenuParser parser);
WParserMacro *menu_parser_find_macro(WMenuParser parser, const char *name);
void menu_parser_expand_macro(WMenuParser parser, WParserMacro *macro);
int isnamechr(char ch); // Check if char is valid character for a macro name
#endif /* _MENUPARSER_H_INCLUDED */

View File

@@ -1,723 +0,0 @@
/*
* Window Maker window manager
*
* Copyright (c) 2012 Christophe Curis
*
* 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.
*/
#include "wconfig.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <pwd.h>
#include "WINGs/WUtil.h"
#include "menuparser.h"
/*
This file contains the functions related to macros:
- parse a macro being defined
- handle single macro expansion
- pre-defined parser's macros
Some design notes for macro internal storage:
arg_count is -1 when the macro does not take arguments
but 0 when no args but still using parenthesis. The
difference is explained in GNU cpp's documentation:
http://gcc.gnu.org/onlinedocs/cpp/Function_002dlike-Macros.html
the value is stored for fast expansion; here is an
example of the storage format used:
#define EXAMPLE(a, b) "text:" a and b!
will be stored in macro->value[] as:
0x0000: 0x00 0x07 (strlen(part 1))
0x0002: '"', 't', 'e', 'x', 't', ':', '"' (first part)
0x0009: 0x00 (part 2, id=0 for replacement by 1st parameter 'a')
0x000A: 0x00 0x03 (strlen(part 3))
0x000C: 'a', 'n', 'd' (part 3)
0x000F: 0x01 (part 4, id=1 for replacement by 2nd parameter 'b')
0x0010: 0x00 0x01 (strlen(part 5))
0x0012: '!' (part 5)
0x0013: 0xFF (end of macro)
This structure allows to store any number and combination
of text/parameter and still provide very fast generation
at macro replacement time.
Predefined macros are using a call-back function mechanism
to generate the value on-demand. This value is generated
in the 'value' buffer of the structure.
Most of these call-backs will actually cache the value:
they generate it on the first use (inside a parser,
not globally) and reuse that value on next call(s).
Because none of these macros take parameters, the call-back
mechanism does not include passing of user arguments; the
complex storage mechanism for argument replacement being
not necessary the macro->value parameter is used as a
plain C string to be copied, this fact being recognised
by macro->function being non-null. It was chosen that the
call-back function would not have the possibility to fail.
*/
static Bool menu_parser_read_macro_def(WMenuParser parser, WParserMacro *macro, char **argname);
static Bool menu_parser_read_macro_args(WMenuParser parser, WParserMacro *macro,
char *array[], char *buffer, ssize_t buffer_size);
/* Free all used memory associated with parser's macros */
void menu_parser_free_macros(WMenuParser parser)
{
WParserMacro *macro, *mnext;
#ifdef DEBUG
unsigned char *rd;
unsigned int size;
unsigned int count;
/* if we were compiled with debugging, we take the opportunity that we
parse the list of macros, for memory release, to print all the
definitions */
printf(__FILE__ ": Macros defined while parsing \"%s\"\n", parser->file_name);
count = 0;
#endif
for (macro = parser->macros; macro != NULL; macro = mnext) {
#ifdef DEBUG
printf(" %s", macro->name);
if (macro->arg_count >= 0)
printf("(args=%d)", macro->arg_count);
printf(" = ");
if (macro->function != NULL) {
macro->function(macro, parser);
printf("function:\"%s\"", macro->value);
} else {
rd = macro->value;
for (;;) {
putchar('"');
size = (*rd++) << 8;
size |= *rd++;
while (size-- > 0) putchar(*rd++);
putchar('"');
if (*rd == 0xFF) break;
printf(" #%d ", (*rd++) + 1);
}
}
printf(", used %d times\n", macro->usage_count);
count++;
#endif
mnext = macro->next;
wfree(macro);
}
#ifdef DEBUG
printf(__FILE__ ": %d macros\n", count);
#endif
parser->macros = NULL; // Security
}
/* Check wether the specified character is valid for a name (macro, parameter) or not */
int isnamechr(char ch)
{
static const int table[256] = {
[0] = 0, // In case we'd fall on buggy compiler, to avoid crash
// C99: 6.7.8.21 -> non specified values are initialised to 0
['0'] = 1, ['1'] = 1, ['2'] = 1, ['3'] = 1, ['4'] = 1,
['5'] = 1, ['6'] = 1, ['7'] = 1, ['8'] = 1, ['9'] = 1,
['A'] = 1, ['B'] = 1, ['C'] = 1, ['D'] = 1, ['E'] = 1, ['F'] = 1,
['G'] = 1, ['H'] = 1, ['I'] = 1, ['J'] = 1, ['K'] = 1, ['L'] = 1,
['M'] = 1, ['N'] = 1, ['O'] = 1, ['P'] = 1, ['Q'] = 1, ['R'] = 1,
['S'] = 1, ['T'] = 1, ['U'] = 1, ['V'] = 1, ['W'] = 1, ['X'] = 1,
['Y'] = 1, ['Z'] = 1,
['a'] = 1, ['b'] = 1, ['c'] = 1, ['d'] = 1, ['e'] = 1, ['f'] = 1,
['g'] = 1, ['h'] = 1, ['i'] = 1, ['j'] = 1, ['k'] = 1, ['l'] = 1,
['m'] = 1, ['n'] = 1, ['o'] = 1, ['p'] = 1, ['q'] = 1, ['r'] = 1,
['s'] = 1, ['t'] = 1, ['u'] = 1, ['v'] = 1, ['w'] = 1, ['x'] = 1,
['y'] = 1, ['z'] = 1,
['_'] = 1
// We refuse any UTF-8 coded character, or accents in ISO-xxx codepages
};
return table[0x00FF & (unsigned)ch ];
}
/* Parse the definition of the macro and add it to the top-most parser's list */
void menu_parser_define_macro(WMenuParser parser)
{
WParserMacro *macro;
int idx;
char arg_names_buf[MAXLINE];
char *arg_name[MAX_MACRO_ARG_COUNT];
if (!menu_parser_skip_spaces_and_comments(parser)) {
WMenuParserError(parser, _("no macro name found for #define") );
return;
}
macro = wmalloc(sizeof(*macro));
memset(arg_name, 0, MAX_MACRO_ARG_COUNT * sizeof(char *));
/* Isolate name of macro */
idx = 0;
while (isnamechr(*parser->rd)) {
if (idx < sizeof(macro->name) - 1)
macro->name[idx++] = *parser->rd;
parser->rd++;
}
// macro->name[idx] = '\0'; -> Already present because wmalloc filled struct with 0s
/* Build list of expected arguments */
if (*parser->rd == '(') {
parser->rd++;
idx = 0;
for (;;) {
if (!menu_parser_skip_spaces_and_comments(parser)) {
arglist_error_premature_eol:
WMenuParserError(parser, _("premature end of file while reading arg-list for macro \"%s\""), macro->name);
wfree(macro);
return;
}
if (*parser->rd == ')') break;
if (macro->arg_count >= wlengthof(arg_name)) {
WMenuParserError(parser, _("too many parameters for macro \"%s\" definition"), macro->name);
wfree(macro);
*parser->rd = '\0'; // fake end-of-line to avoid warnings from remaining line content
return;
}
if (isnamechr(*parser->rd)) {
arg_name[macro->arg_count++] = arg_names_buf + idx;
do {
if (idx < sizeof(arg_names_buf) - 1)
arg_names_buf[idx++] = *parser->rd;
parser->rd++;
} while (isnamechr(*parser->rd));
arg_names_buf[idx] = '\0';
if (idx < sizeof(arg_names_buf) - 1) idx++;
} else {
WMenuParserError(parser, _("invalid character '%c' in arg-list for macro \"%s\" while expecting parameter name"),
*parser->rd, macro->name);
wfree(macro);
*parser->rd = '\0'; // fake end-of-line to avoid warnings from remaining line content
return;
}
if (!menu_parser_skip_spaces_and_comments(parser))
goto arglist_error_premature_eol;
if (*parser->rd == ')') break;
if (*parser->rd != ',') {
WMenuParserError(parser, _("invalid character '%c' in arg-list for macro \"%s\" while expecting ',' or ')'"),
*parser->rd, macro->name);
wfree(macro);
*parser->rd = '\0'; // fake end-of-line to avoid warnings from remaining line content
return;
}
parser->rd++;
}
parser->rd++; // skip the closing ')'
} else
macro->arg_count = -1; // Means no parenthesis at all to expect
/* If we're inside a #if sequence, we abort now, but not sooner in
order to keep the syntax check */
if (parser->cond.stack[0].skip) {
wfree(macro);
*parser->rd = '\0'; // Ignore macro content
return;
}
/* Get the macro's definition */
menu_parser_skip_spaces_and_comments(parser);
if (!menu_parser_read_macro_def(parser, macro, arg_name)) {
wfree(macro);
return;
}
/* Create the macro in the Root parser */
while (parser->parent_file != NULL)
parser = parser->parent_file;
/* Check that the macro was not already defined */
if (menu_parser_find_macro(parser, macro->name) != NULL) {
WMenuParserError(parser, _("macro \"%s\" already defined, ignoring redefinition"),
macro->name);
wfree(macro);
return;
}
/* Append at beginning of list */
macro->next = parser->macros;
parser->macros = macro;
}
/* Check if the current word in the parser matches a macro */
WParserMacro *menu_parser_find_macro(WMenuParser parser, const char *name)
{
const char *ref, *cmp;
WParserMacro *macro;
while (parser->parent_file != NULL)
parser = parser->parent_file;
for (macro = parser->macros; macro != NULL; macro = macro->next) {
ref = macro->name;
cmp = name;
while (*ref != '\0')
if (*ref++ != *cmp++)
goto check_next_macro;
if (isnamechr(*cmp))
continue;
return macro;
check_next_macro:
;
}
return NULL;
}
/* look to see if the next word matches the name of one of the parameter
names for a macro definition
This function is internal to the macro definition function as this is
where the analysis is done */
static inline char *mp_is_parameter(char *parse, const char *param) {
while (*param)
if (*parse++ != *param++)
return NULL;
if (isnamechr(*parse))
return NULL;
return parse;
}
/* Read the content definition part of a #define construct (the part after the optional
argument list) and store it in the prepared format for quick expansion
There is no need to keep track of the names of the parameters, so they are stored in
a temporary storage for the time of the macro parsing. */
static Bool menu_parser_read_macro_def(WMenuParser parser, WParserMacro *macro, char **arg)
{
unsigned char *wr_size;
unsigned char *wr;
unsigned int size_data;
unsigned int size_max;
int i;
wr_size = macro->value;
size_data = 0;
wr = wr_size + 2;
size_max = sizeof(macro->value) - (wr - macro->value) - 3;
while (menu_parser_skip_spaces_and_comments(parser)) {
if (isnamechr(*parser->rd)) {
char *next_rd;
/* Is the current word a parameter to replace? */
for (i = 0; i < macro->arg_count; i++) {
next_rd = mp_is_parameter(parser->rd, arg[i]);
if (next_rd != NULL) {
if (wr + 4 >= macro->value + sizeof(macro->value))
goto error_too_much_data;
wr_size[0] = (size_data >> 8) & 0xFF;
wr_size[1] = size_data & 0xFF;
*wr++ = i;
wr_size = wr;
wr += 2;
parser->rd = next_rd;
*wr++ = ' ';
size_data = 1;
size_max = sizeof(macro->value) - (wr - macro->value) - 3;
goto next_loop; // Because we can't 'break' this loop and 'continue'
// the outer one in a clean and easy way
}
}
/* Not parameter name -> copy as-is */
do {
*wr++ = *parser->rd++;
if (++size_data >= size_max) {
error_too_much_data:
WMenuParserError(parser, _("more content than supported for the macro \"%s\""),
macro->name);
return False;
}
} while (isnamechr(*parser->rd));
if (isspace(*parser->rd)) {
*wr++ = ' ';
if (++size_data >= size_max)
goto error_too_much_data;
}
} else {
/* Some uninterresting characters, copy as-is */
while (*parser->rd != '\0') {
if (isnamechr(*parser->rd)) break; // handle in next loop
if (parser->rd[0] == '/')
if ((parser->rd[1] == '*') || (parser->rd[1] == '/'))
break; // Comments are handled by std function
if ((parser->rd[0] == '\\') &&
(parser->rd[1] == '\n') &&
(parser->rd[2] == '\0'))
break; // Long-lines are handled by std function
*wr++ = *parser->rd++;
if (++size_data >= size_max)
goto error_too_much_data;
}
}
next_loop:
;
}
wr_size[0] = (size_data >> 8) & 0xFF;
wr_size[1] = size_data & 0xFF;
*wr = 0xFF;
return True;
}
/* When a macro is being used in the file, this function will generate the
expanded value for the macro in the parser's work line.
It blindly supposes that the data generated in macro->value is valid */
void menu_parser_expand_macro(WMenuParser parser, WParserMacro *macro)
{
char save_buf[sizeof(parser->line_buffer)];
char arg_values_buf[MAXLINE];
char *arg_value[MAX_MACRO_ARG_COUNT];
char *src, *dst;
unsigned char *rd;
unsigned int size;
int i, space_left;
memset(arg_value, 0, MAX_MACRO_ARG_COUNT * sizeof(char *));
/* Skip the name of the macro, this was not done by caller */
for (i = 0; macro->name[i] != '\0'; i++)
parser->rd++;
if (macro->arg_count >= 0) {
menu_parser_skip_spaces_and_comments(parser);
if (!menu_parser_read_macro_args(parser, macro, arg_value, arg_values_buf, sizeof(arg_values_buf)))
return;
}
#ifdef DEBUG
macro->usage_count++;
#endif
/* Save the remaining data from current line as we will overwrite the
current line's workspace with the expanded macro, so we can re-append
it afterwards */
dst = save_buf;
while ((*dst++ = *parser->rd++) != '\0') ;
/* Generate expanded macro */
dst = parser->line_buffer;
parser->rd = dst;
space_left = sizeof(parser->line_buffer) - 1;
if (macro->function != NULL) {
/* Parser's pre-defined macros actually proposes a function call to
generate dynamic value for the expansion of the macro. In this case
it is generated as a C string in the macro->value and used directly */
macro->function(macro, parser);
rd = macro->value;
while (--space_left > 0)
if ((*dst = *rd++) == '\0')
break;
else
dst++;
} else {
rd = macro->value;
for (;;) {
size = (*rd++) << 8;
size |= *rd++;
while (size-- > 0) {
*dst = *rd++;
if (--space_left > 0) dst++;
}
if (*rd == 0xFF) break;
src = arg_value[*rd++];
while (*src) {
*dst = *src++;
if (--space_left > 0) dst++;
}
}
}
/* Copy finished -> Re-append the text that was following the macro */
src = save_buf;
while (--space_left > 0)
if ((*dst++ = *src++) == '\0')
break;
*dst = '\0';
if (space_left <= 0)
WMenuParserError(parser, _("expansion for macro \"%s\" too big, line truncated"),
macro->name);
}
/* When reading a macro to be expanded (not being defined), that takes arguments,
this function parses the arguments being provided */
static Bool menu_parser_read_macro_args(WMenuParser parser, WParserMacro *macro,
char *array[], char *buffer, ssize_t buffer_size)
{
int arg;
if (*parser->rd != '(') {
WMenuParserError(parser, _("macro \"%s\" needs parenthesis for arguments"),
macro->name);
return False;
}
parser->rd++;
buffer_size--; // Room for final '\0'
menu_parser_skip_spaces_and_comments(parser);
arg = 0;
for (;;) {
int paren_count;
array[arg] = buffer;
paren_count = 0;
while (*parser->rd != '\0') {
if (*parser->rd == '(')
paren_count++;
if (paren_count <= 0)
if ((*parser->rd == ',') ||
(*parser->rd == ')') ) break;
if ((*parser->rd == '"') || (*parser->rd == '\'')) {
char eot = *parser->rd++;
if (buffer_size-- > 0) *buffer++ = eot;
while (*parser->rd) {
if ((*buffer = *parser->rd++) == eot)
goto found_end_of_string;
if (buffer_size-- > 0) buffer++;
}
WMenuParserError(parser, _("missing closing quote or double-quote before end-of-line") );
return False;
found_end_of_string:
continue;
}
if (isspace(*parser->rd)) {
if (buffer_size-- > 0) *buffer++ = ' ';
menu_parser_skip_spaces_and_comments(parser);
continue;
}
*buffer = *parser->rd++;
if (buffer_size-- > 0) buffer++;
}
*buffer = '\0';
if (buffer_size-- > 0) buffer++;
arg++;
if (*parser->rd == ',') {
parser->rd++;
if (arg >= macro->arg_count) {
WMenuParserError(parser, _("too many arguments for macro \"%s\", expected only %d"),
macro->name, macro->arg_count);
return False;
}
continue;
}
break;
}
if (*parser->rd != ')') {
WMenuParserError(parser, _("premature end of line while searching for arguments to macro \"%s\""),
macro->name);
return False;
}
parser->rd++;
if (arg < macro->arg_count) {
WMenuParserError(parser, _("not enough arguments for macro \"%s\", expected %d but got only %d"),
macro->name, macro->arg_count, arg);
return False;
}
if (buffer_size < 0)
WMenuParserError(parser, _("too much data in parameter list of macro \"%s\", truncated"),
macro->name);
return True;
}
/******************************************************************************/
/* Definition of pre-defined macros */
/******************************************************************************/
void WMenuParserRegisterSimpleMacro(WMenuParser parser, const char *name, const char *value)
{
WParserMacro *macro;
size_t len;
unsigned char *wr;
macro = wmalloc(sizeof(*macro));
strncpy(macro->name, name, sizeof(macro->name)-1);
macro->arg_count = -1;
len = strlen(value);
if (len > sizeof(macro->value) - 3) {
wwarning(_("size of value for macro '%s' is too big, truncated"), name);
len = sizeof(macro->value) - 3;
}
macro->value[0] = (len >> 8) & 0xFF;
macro->value[1] = len & 0xFF;
wr = &macro->value[2];
while (len-- > 0)
*wr++ = *value++;
*wr = 0xFF;
macro->next = parser->macros;
parser->macros = macro;
}
/* Name of the originally loaded file (before #includes) */
static void mpm_base_file(WParserMacro *this, WMenuParser parser)
{
unsigned char *src, *dst;
if (this->value[0] != '\0') return; // Value already evaluated, re-use previous
while (parser->parent_file != NULL)
parser = parser->parent_file;
dst = this->value;
src = (unsigned char *) parser->file_name;
*dst++ = '\"';
while (*src != '\0')
if (dst < this->value + sizeof(this->value) - 2)
*dst++ = *src++;
else
break;
*dst++ = '\"';
*dst = '\0';
}
/* Number of #include currently nested */
static void mpm_include_level(WParserMacro *this, WMenuParser parser)
{
int level = 0;
while (parser->parent_file != NULL) {
parser = parser->parent_file;
level++;
}
snprintf((char *) this->value, sizeof(this->value), "%d", level);
}
/* Name of current file */
static void mpm_current_file(WParserMacro *this, WMenuParser parser)
{
unsigned char *src, *dst;
dst = this->value;
src = (unsigned char *) parser->file_name;
*dst++ = '\"';
while (*src != '\0')
if (dst < this->value + sizeof(this->value) - 2)
*dst++ = *src++;
else
break;
*dst++ = '\"';
*dst = '\0';
}
/* Number of current line */
static void mpm_current_line(WParserMacro *this, WMenuParser parser)
{
snprintf((char *) this->value, sizeof(this->value), "%d", parser->line_number);
}
/* Name of host on which we are running, not necessarily displaying */
static void mpm_get_hostname(WParserMacro *this, WMenuParser parser)
{
char *h;
if (this->value[0] != '\0') return; // Value already evaluated, re-use previous
h = getenv("HOSTNAME");
if (h == NULL) {
h = getenv("HOST");
if (h == NULL) {
if (gethostname((char *) this->value, sizeof(this->value) ) != 0) {
WMenuParserError(parser, _("could not determine %s"), "HOSTNAME");
this->value[0] = '?';
this->value[1] = '?';
this->value[2] = '?';
this->value[3] = '\0';
}
return;
}
}
wstrlcpy((char *) this->value, h, sizeof(this->value) );
}
/* Name of the current user */
static void mpm_get_user_name(WParserMacro *this, WMenuParser parser)
{
char *user;
if (this->value[0] != '\0') return; // Value already evaluated, re-use previous
user = getlogin();
if (user == NULL) {
struct passwd *pw_user;
pw_user = getpwuid(getuid());
if (pw_user == NULL) {
error_no_username:
WMenuParserError(parser, _("could not determine %s"), "USER" );
/* Fall back on numeric id - better than nothing */
snprintf((char *) this->value, sizeof(this->value), "%d", getuid() );
return;
}
user = pw_user->pw_name;
if (user == NULL) goto error_no_username;
}
wstrlcpy((char *) this->value, user, sizeof(this->value) );
}
/* Number id of the user under which we are running */
static void mpm_get_user_id(WParserMacro *this, WMenuParser parser)
{
/* Parameter not used, but tell the compiler that it is ok */
(void) parser;
if (this->value[0] != '\0') return; // Already evaluated, re-use previous
snprintf((char *) this->value, sizeof(this->value), "%d", getuid() );
}
/* Small helper to automate creation of one pre-defined macro in the parser */
static void w_create_macro(WMenuParser parser, const char *name, WParserMacroFunction *handler)
{
WParserMacro *macro;
macro = wmalloc(sizeof(*macro));
strncpy(macro->name, name, sizeof(macro->name) - 1);
macro->function = handler;
macro->arg_count = -1;
macro->next = parser->macros;
parser->macros = macro;
}
/***** Register all the pre-defined macros in the parser *****/
void menu_parser_register_preset_macros(WMenuParser parser)
{
/* Defined by CPP: common predefined macros (GNU C extension) */
w_create_macro(parser, "__BASE_FILE__", mpm_base_file);
w_create_macro(parser, "__INCLUDE_LEVEL__", mpm_include_level);
/* Defined by CPP: standard predefined macros */
w_create_macro(parser, "__FILE__", mpm_current_file);
w_create_macro(parser, "__LINE__", mpm_current_line);
// w_create_macro(parser, "__DATE__", NULL); [will be implemented only per user request]
// w_create_macro(parser, "__TIME__", NULL); [will be implemented only per user request]
/* Historically defined by WindowMaker */
w_create_macro(parser, "HOST", mpm_get_hostname);
w_create_macro(parser, "UID", mpm_get_user_id);
w_create_macro(parser, "USER", mpm_get_user_name);
}

View File

@@ -1,45 +0,0 @@
/* WUtil / misc.c
*
* Copyright (c) 2001 Dan Pascu
* Copyright (c) 2014 Window Maker Team
*
* 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.
*/
/* Miscelaneous helper functions */
#include "WINGs/WUtil.h"
#include "error.h"
WMRange wmkrange(int start, int count)
{
WMRange range;
range.position = start;
range.count = count;
return range;
}
/*
* wutil_shutdown - cleanup in WUtil when user program wants to exit
*/
void wutil_shutdown(void)
{
#ifdef HAVE_SYSLOG
w_syslog_close();
#endif
}

View File

@@ -1,482 +0,0 @@
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "WINGs/WUtil.h"
#include "WINGs/WINGsP.h"
typedef struct W_Notification {
const char *name;
void *object;
void *clientData;
int refCount;
} Notification;
const char *WMGetNotificationName(WMNotification * notification)
{
return notification->name;
}
void *WMGetNotificationObject(WMNotification * notification)
{
return notification->object;
}
void *WMGetNotificationClientData(WMNotification * notification)
{
return notification->clientData;
}
WMNotification *WMCreateNotification(const char *name, void *object, void *clientData)
{
Notification *nPtr;
nPtr = wmalloc(sizeof(Notification));
nPtr->name = name;
nPtr->object = object;
nPtr->clientData = clientData;
nPtr->refCount = 1;
return nPtr;
}
void WMReleaseNotification(WMNotification * notification)
{
notification->refCount--;
if (notification->refCount < 1) {
wfree(notification);
}
}
WMNotification *WMRetainNotification(WMNotification * notification)
{
notification->refCount++;
return notification;
}
/***************** Notification Center *****************/
typedef struct NotificationObserver {
WMNotificationObserverAction *observerAction;
void *observer;
const char *name;
void *object;
struct NotificationObserver *prev; /* for tables */
struct NotificationObserver *next;
struct NotificationObserver *nextAction; /* for observerTable */
} NotificationObserver;
typedef struct W_NotificationCenter {
WMHashTable *nameTable; /* names -> observer lists */
WMHashTable *objectTable; /* object -> observer lists */
NotificationObserver *nilList; /* obervers that catch everything */
WMHashTable *observerTable; /* observer -> NotificationObserver */
} NotificationCenter;
/* default (and only) center */
static NotificationCenter *notificationCenter = NULL;
void W_InitNotificationCenter(void)
{
notificationCenter = wmalloc(sizeof(NotificationCenter));
notificationCenter->nameTable = WMCreateHashTable(WMStringPointerHashCallbacks);
notificationCenter->objectTable = WMCreateHashTable(WMIntHashCallbacks);
notificationCenter->nilList = NULL;
notificationCenter->observerTable = WMCreateHashTable(WMIntHashCallbacks);
}
void W_ReleaseNotificationCenter(void)
{
if (notificationCenter) {
if (notificationCenter->nameTable)
WMFreeHashTable(notificationCenter->nameTable);
if (notificationCenter->objectTable)
WMFreeHashTable(notificationCenter->objectTable);
if (notificationCenter->observerTable)
WMFreeHashTable(notificationCenter->observerTable);
wfree(notificationCenter);
notificationCenter = NULL;
}
}
void
WMAddNotificationObserver(WMNotificationObserverAction * observerAction,
void *observer, const char *name, void *object)
{
NotificationObserver *oRec, *rec;
oRec = wmalloc(sizeof(NotificationObserver));
oRec->observerAction = observerAction;
oRec->observer = observer;
oRec->name = name;
oRec->object = object;
oRec->next = NULL;
oRec->prev = NULL;
/* put this action in the list of actions for this observer */
rec = (NotificationObserver *) WMHashInsert(notificationCenter->observerTable, observer, oRec);
if (rec) {
/* if this is not the first action for the observer */
oRec->nextAction = rec;
} else {
oRec->nextAction = NULL;
}
if (!name && !object) {
/* catch-all */
oRec->next = notificationCenter->nilList;
if (notificationCenter->nilList) {
notificationCenter->nilList->prev = oRec;
}
notificationCenter->nilList = oRec;
} else if (!name) {
/* any message coming from object */
rec = (NotificationObserver *) WMHashInsert(notificationCenter->objectTable, object, oRec);
oRec->next = rec;
if (rec) {
rec->prev = oRec;
}
} else {
/* name && (object || !object) */
rec = (NotificationObserver *) WMHashInsert(notificationCenter->nameTable, name, oRec);
oRec->next = rec;
if (rec) {
rec->prev = oRec;
}
}
}
void WMPostNotification(WMNotification * notification)
{
NotificationObserver *orec, *tmp;
WMRetainNotification(notification);
/* tell the observers that want to know about a particular message */
orec = (NotificationObserver *) WMHashGet(notificationCenter->nameTable, notification->name);
while (orec) {
tmp = orec->next;
if (!orec->object || !notification->object || orec->object == notification->object) {
/* tell the observer */
if (orec->observerAction) {
(*orec->observerAction) (orec->observer, notification);
}
}
orec = tmp;
}
/* tell the observers that want to know about an object */
orec = (NotificationObserver *) WMHashGet(notificationCenter->objectTable, notification->object);
while (orec) {
tmp = orec->next;
/* tell the observer */
if (orec->observerAction) {
(*orec->observerAction) (orec->observer, notification);
}
orec = tmp;
}
/* tell the catch all observers */
orec = notificationCenter->nilList;
while (orec) {
tmp = orec->next;
/* tell the observer */
if (orec->observerAction) {
(*orec->observerAction) (orec->observer, notification);
}
orec = tmp;
}
WMReleaseNotification(notification);
}
void WMRemoveNotificationObserver(void *observer)
{
NotificationObserver *orec, *tmp, *rec;
/* get the list of actions the observer is doing */
orec = (NotificationObserver *) WMHashGet(notificationCenter->observerTable, observer);
/*
* FOREACH orec IN actionlist for observer
* DO
* remove from respective lists/tables
* free
* END
*/
while (orec) {
tmp = orec->nextAction;
if (!orec->name && !orec->object) {
/* catch-all */
if (notificationCenter->nilList == orec)
notificationCenter->nilList = orec->next;
} else if (!orec->name) {
/* any message coming from object */
rec = (NotificationObserver *) WMHashGet(notificationCenter->objectTable, orec->object);
if (rec == orec) {
/* replace table entry */
if (orec->next) {
WMHashInsert(notificationCenter->objectTable, orec->object, orec->next);
} else {
WMHashRemove(notificationCenter->objectTable, orec->object);
}
}
} else {
/* name && (object || !object) */
rec = (NotificationObserver *) WMHashGet(notificationCenter->nameTable, orec->name);
if (rec == orec) {
/* replace table entry */
if (orec->next) {
WMHashInsert(notificationCenter->nameTable, orec->name, orec->next);
} else {
WMHashRemove(notificationCenter->nameTable, orec->name);
}
}
}
if (orec->prev)
orec->prev->next = orec->next;
if (orec->next)
orec->next->prev = orec->prev;
wfree(orec);
orec = tmp;
}
WMHashRemove(notificationCenter->observerTable, observer);
}
void WMRemoveNotificationObserverWithName(void *observer, const char *name, void *object)
{
NotificationObserver *orec, *tmp, *rec;
NotificationObserver *newList = NULL;
/* get the list of actions the observer is doing */
orec = (NotificationObserver *) WMHashGet(notificationCenter->observerTable, observer);
WMHashRemove(notificationCenter->observerTable, observer);
/* rebuild the list of actions for the observer */
while (orec) {
tmp = orec->nextAction;
if (orec->name == name && orec->object == object) {
if (!name && !object) {
if (notificationCenter->nilList == orec)
notificationCenter->nilList = orec->next;
} else if (!name) {
rec =
(NotificationObserver *) WMHashGet(notificationCenter->objectTable,
orec->object);
if (rec == orec) {
assert(rec->prev == NULL);
/* replace table entry */
if (orec->next) {
WMHashInsert(notificationCenter->objectTable,
orec->object, orec->next);
} else {
WMHashRemove(notificationCenter->objectTable, orec->object);
}
}
} else {
rec = (NotificationObserver *) WMHashGet(notificationCenter->nameTable,
orec->name);
if (rec == orec) {
assert(rec->prev == NULL);
/* replace table entry */
if (orec->next) {
WMHashInsert(notificationCenter->nameTable,
orec->name, orec->next);
} else {
WMHashRemove(notificationCenter->nameTable, orec->name);
}
}
}
if (orec->prev)
orec->prev->next = orec->next;
if (orec->next)
orec->next->prev = orec->prev;
wfree(orec);
} else {
/* append this action in the new action list */
orec->nextAction = NULL;
if (!newList) {
newList = orec;
} else {
NotificationObserver *p;
p = newList;
while (p->nextAction) {
p = p->nextAction;
}
p->nextAction = orec;
}
}
orec = tmp;
}
/* reinsert the list to the table */
if (newList) {
WMHashInsert(notificationCenter->observerTable, observer, newList);
}
}
void WMPostNotificationName(const char *name, void *object, void *clientData)
{
WMNotification *notification;
notification = WMCreateNotification(name, object, clientData);
WMPostNotification(notification);
WMReleaseNotification(notification);
}
/**************** Notification Queues ****************/
typedef struct W_NotificationQueue {
WMArray *asapQueue;
WMArray *idleQueue;
struct W_NotificationQueue *next;
} NotificationQueue;
static WMNotificationQueue *notificationQueueList = NULL;
/* default queue */
static WMNotificationQueue *notificationQueue = NULL;
WMNotificationQueue *WMGetDefaultNotificationQueue(void)
{
if (!notificationQueue)
notificationQueue = WMCreateNotificationQueue();
return notificationQueue;
}
WMNotificationQueue *WMCreateNotificationQueue(void)
{
NotificationQueue *queue;
queue = wmalloc(sizeof(NotificationQueue));
queue->asapQueue = WMCreateArrayWithDestructor(8, (WMFreeDataProc *) WMReleaseNotification);
queue->idleQueue = WMCreateArrayWithDestructor(8, (WMFreeDataProc *) WMReleaseNotification);
queue->next = notificationQueueList;
notificationQueueList = queue;
return queue;
}
void WMEnqueueNotification(WMNotificationQueue * queue, WMNotification * notification, WMPostingStyle postingStyle)
{
WMEnqueueCoalesceNotification(queue, notification, postingStyle, WNCOnName | WNCOnSender);
}
#define NOTIF ((WMNotification*)cdata)
#define ITEM ((WMNotification*)item)
static int matchSenderAndName(const void *item, const void *cdata)
{
return (NOTIF->object == ITEM->object && strcmp(NOTIF->name, ITEM->name) == 0);
}
static int matchSender(const void *item, const void *cdata)
{
return (NOTIF->object == ITEM->object);
}
static int matchName(const void *item, const void *cdata)
{
return (strcmp(NOTIF->name, ITEM->name) == 0);
}
#undef NOTIF
#undef ITEM
void WMDequeueNotificationMatching(WMNotificationQueue * queue, WMNotification * notification, unsigned mask)
{
WMMatchDataProc *matchFunc;
if ((mask & WNCOnName) && (mask & WNCOnSender))
matchFunc = matchSenderAndName;
else if (mask & WNCOnName)
matchFunc = matchName;
else if (mask & WNCOnSender)
matchFunc = matchSender;
else
return;
WMRemoveFromArrayMatching(queue->asapQueue, matchFunc, notification);
WMRemoveFromArrayMatching(queue->idleQueue, matchFunc, notification);
}
void
WMEnqueueCoalesceNotification(WMNotificationQueue * queue,
WMNotification * notification, WMPostingStyle postingStyle, unsigned coalesceMask)
{
if (coalesceMask != WNCNone)
WMDequeueNotificationMatching(queue, notification, coalesceMask);
switch (postingStyle) {
case WMPostNow:
WMPostNotification(notification);
WMReleaseNotification(notification);
break;
case WMPostASAP:
WMAddToArray(queue->asapQueue, notification);
break;
case WMPostWhenIdle:
WMAddToArray(queue->idleQueue, notification);
break;
}
}
void W_FlushASAPNotificationQueue(void)
{
WMNotificationQueue *queue = notificationQueueList;
while (queue) {
while (WMGetArrayItemCount(queue->asapQueue)) {
WMPostNotification(WMGetFromArray(queue->asapQueue, 0));
WMDeleteFromArray(queue->asapQueue, 0);
}
queue = queue->next;
}
}
void W_FlushIdleNotificationQueue(void)
{
WMNotificationQueue *queue = notificationQueueList;
while (queue) {
while (WMGetArrayItemCount(queue->idleQueue)) {
WMPostNotification(WMGetFromArray(queue->idleQueue, 0));
WMDeleteFromArray(queue->idleQueue, 0);
}
queue = queue->next;
}
}

View File

@@ -1,125 +0,0 @@
DOMAIN = WINGs
CATALOGS = @WINGSMOFILES@
CLEANFILES = $(CATALOGS) $(DOMAIN).pot
EXTRA_DIST = bg.po ca.po cs.po de.po fr.po fy.po hu.po nl.po sk.po sr.po
# WUtil files:
POTFILES = \
$(top_srcdir)/WINGs/array.c \
$(top_srcdir)/WINGs/bagtree.c \
$(top_srcdir)/WINGs/data.c \
$(top_srcdir)/WINGs/error.c \
$(top_srcdir)/WINGs/findfile.c \
$(top_srcdir)/WINGs/handlers.c \
$(top_srcdir)/WINGs/hashtable.c \
$(top_srcdir)/WINGs/memory.c \
$(top_srcdir)/WINGs/menuparser.c \
$(top_srcdir)/WINGs/menuparser_macros.c \
$(top_srcdir)/WINGs/misc.c \
$(top_srcdir)/WINGs/notification.c \
$(top_srcdir)/WINGs/proplist.c \
$(top_srcdir)/WINGs/string.c \
$(top_srcdir)/WINGs/tree.c \
$(top_srcdir)/WINGs/userdefaults.c \
$(top_srcdir)/WINGs/usleep.c \
$(top_srcdir)/WINGs/wapplication.c \
$(top_srcdir)/WINGs/wutil.c
# WINGs files:
POTFILES += \
$(top_srcdir)/WINGs/configuration.c \
$(top_srcdir)/WINGs/dragcommon.c \
$(top_srcdir)/WINGs/dragdestination.c \
$(top_srcdir)/WINGs/dragsource.c \
$(top_srcdir)/WINGs/selection.c \
$(top_srcdir)/WINGs/wappresource.c \
$(top_srcdir)/WINGs/wballoon.c \
$(top_srcdir)/WINGs/wbox.c \
$(top_srcdir)/WINGs/wbrowser.c \
$(top_srcdir)/WINGs/wbutton.c \
$(top_srcdir)/WINGs/wcolor.c \
$(top_srcdir)/WINGs/wcolorpanel.c \
$(top_srcdir)/WINGs/wcolorwell.c \
$(top_srcdir)/WINGs/wevent.c \
$(top_srcdir)/WINGs/wfilepanel.c \
$(top_srcdir)/WINGs/wframe.c \
$(top_srcdir)/WINGs/wfont.c \
$(top_srcdir)/WINGs/wfontpanel.c \
$(top_srcdir)/WINGs/widgets.c \
$(top_srcdir)/WINGs/winputmethod.c \
$(top_srcdir)/WINGs/wlabel.c \
$(top_srcdir)/WINGs/wlist.c \
$(top_srcdir)/WINGs/wmenuitem.c \
$(top_srcdir)/WINGs/wmisc.c \
$(top_srcdir)/WINGs/wpanel.c \
$(top_srcdir)/WINGs/wpixmap.c \
$(top_srcdir)/WINGs/wpopupbutton.c \
$(top_srcdir)/WINGs/wprogressindicator.c \
$(top_srcdir)/WINGs/wruler.c \
$(top_srcdir)/WINGs/wscroller.c \
$(top_srcdir)/WINGs/wscrollview.c \
$(top_srcdir)/WINGs/wslider.c \
$(top_srcdir)/WINGs/wsplitview.c \
$(top_srcdir)/WINGs/wtabview.c \
$(top_srcdir)/WINGs/wtext.c \
$(top_srcdir)/WINGs/wtextfield.c \
$(top_srcdir)/WINGs/wview.c \
$(top_srcdir)/WINGs/wwindow.c
SUFFIXES = .po .mo
.po.mo:
$(AM_V_GEN)$(MSGFMT) -c -o $@ $<
all-local: $(CATALOGS)
.PHONY: update-lang
if HAVE_XGETTEXT
update-lang: $(DOMAIN).pot
$(AM_V_GEN)$(top_srcdir)/script/generate-po-from-template.sh \
-n "$(PACKAGE_NAME)" -v "$(PACKAGE_VERSION)" -b "$(PACKAGE_BUGREPORT)" \
-t "$(DOMAIN).pot" "$(srcdir)/$(PO).po"
$(DOMAIN).pot: $(POTFILES)
$(AM_V_GEN)$(XGETTEXT) --default-domain=$(DOMAIN) \
--add-comments --keyword=_ --keyword=N_ $(POTFILES)
@if cmp -s $(DOMAIN).po $(DOMAIN).pot; then \
rm -f $(DOMAIN).po; \
else \
mv -f $(DOMAIN).po $(DOMAIN).pot; \
fi
endif
install-data-local: $(CATALOGS)
$(mkinstalldirs) $(DESTDIR)$(localedir)
for n in $(CATALOGS) __DuMmY ; do \
if test "$$n" -a "$$n" != "__DuMmY" ; then \
l=`basename $$n .mo`; \
$(mkinstalldirs) $(DESTDIR)$(localedir)/$$l/LC_MESSAGES; \
$(INSTALL_DATA) -m 644 $$n $(DESTDIR)$(localedir)/$$l/LC_MESSAGES/$(DOMAIN).mo; \
fi; \
done
uninstall-local:
for n in $(CATALOGS) ; do \
l=`basename $$n .mo`; \
rm -f $(DESTDIR)$(localedir)/$$l/LC_MESSAGES/$(DOMAIN).mo; \
done
# Create a 'silent rule' for our make check the same way automake does
AM_V_CHKTRANS = $(am__v_CHKTRANS_$(V))
am__v_CHKTRANS_ = $(am__v_CHKTRANS_$(AM_DEFAULT_VERBOSITY))
am__v_CHKTRANS_0 = @echo " CHK translations" ;
am__v_CHKTRANS_1 =
# 'make check' will make sure the tranlation sources are in line with the compiled source
check-local:
$(AM_V_CHKTRANS)$(top_srcdir)/script/check-translation-sources.sh \
"$(srcdir)" -s "$(top_srcdir)/WINGs/Makefile.am"

Some files were not shown because too many files have changed in this diff Show More