diff --git a/configure.ac b/configure.ac index 6b9bca23..684a6064 100644 --- a/configure.ac +++ b/configure.ac @@ -158,6 +158,10 @@ AS_IF([test "x$debug" = "xyes"], AX_CFLAGS_GCC_OPTION([-Wno-deprecated-declarations]) ]) +dnl Posix thread +dnl ================= +AX_PTHREAD + dnl Tracking on what is detected for final status dnl ============================================= diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4 new file mode 100644 index 00000000..d383ad5c --- /dev/null +++ b/m4/ax_pthread.m4 @@ -0,0 +1,332 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_pthread.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +# +# DESCRIPTION +# +# This macro figures out how to build C programs using POSIX threads. It +# sets the PTHREAD_LIBS output variable to the threads library and linker +# flags, and the PTHREAD_CFLAGS output variable to any special C compiler +# flags that are needed. (The user can also force certain compiler +# flags/libs to be tested by setting these environment variables.) +# +# Also sets PTHREAD_CC to any special C compiler that is needed for +# multi-threaded programs (defaults to the value of CC otherwise). (This +# is necessary on AIX to use the special cc_r compiler alias.) +# +# NOTE: You are assumed to not only compile your program with these flags, +# but also link it with them as well. e.g. you should link with +# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS +# +# If you are only building threads programs, you may wish to use these +# variables in your default LIBS, CFLAGS, and CC: +# +# LIBS="$PTHREAD_LIBS $LIBS" +# CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +# CC="$PTHREAD_CC" +# +# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant +# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name +# (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +# +# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the +# PTHREAD_PRIO_INHERIT symbol is defined when compiling with +# PTHREAD_CFLAGS. +# +# ACTION-IF-FOUND is a list of shell commands to run if a threads library +# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it +# is not found. If ACTION-IF-FOUND is not specified, the default action +# will define HAVE_PTHREAD. +# +# Please let the authors know if this macro fails on any platform, or if +# you have any other suggestions or comments. This macro was based on work +# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help +# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by +# Alejandro Forero Cuervo to the autoconf macro repository. We are also +# grateful for the helpful feedback of numerous users. +# +# Updated for Autoconf 2.68 by Daniel Richard G. +# +# LICENSE +# +# Copyright (c) 2008 Steven G. Johnson +# Copyright (c) 2011 Daniel Richard G. +# +# 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 3 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, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 21 + +AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) +AC_DEFUN([AX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_LANG_PUSH([C]) +ax_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on True64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) + AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes]) + AC_MSG_RESULT([$ax_pthread_ok]) + if test x"$ax_pthread_ok" = xno; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) +# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) +# -pthreads: Solaris/gcc +# -mthreads: Mingw32/gcc, Lynx/gcc +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads too; +# also defines -D_REENTRANT) +# ... -mt is also the pthreads flag for HP/aCC +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case ${host_os} in + solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthreads/-mt/ + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + + ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" + ;; + + darwin*) + ax_pthread_flags="-pthread $ax_pthread_flags" + ;; +esac + +# Clang doesn't consider unrecognized options an error unless we specify +# -Werror. We throw in some extra Clang-specific options to ensure that +# this doesn't happen for GCC, which also accepts -Werror. + +AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags]) +save_CFLAGS="$CFLAGS" +ax_pthread_extra_flags="-Werror" +CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument" +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])], + [AC_MSG_RESULT([yes])], + [ax_pthread_extra_flags= + AC_MSG_RESULT([no])]) +CFLAGS="$save_CFLAGS" + +if test x"$ax_pthread_ok" = xno; then +for flag in $ax_pthread_flags; do + + case $flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $flag]) + PTHREAD_CFLAGS="$flag" + ;; + + pthread-config) + AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) + if test x"$ax_pthread_config" = xno; then continue; fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$flag]) + PTHREAD_LIBS="-l$flag" + ;; + esac + + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include + static void routine(void *a) { a = 0; } + static void *start_routine(void *a) { return a; }], + [pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */])], + [ax_pthread_ok=yes], + []) + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + AC_MSG_RESULT([$ax_pthread_ok]) + if test "x$ax_pthread_ok" = xyes; then + break; + fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$ax_pthread_ok" = xyes; then + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + AC_MSG_CHECKING([for joinable pthread attribute]) + attr_name=unknown + for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], + [int attr = $attr; return attr /* ; */])], + [attr_name=$attr; break], + []) + done + AC_MSG_RESULT([$attr_name]) + if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then + AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name], + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + fi + + AC_MSG_CHECKING([if more special flags are required for pthreads]) + flag=no + case ${host_os} in + aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";; + osf* | hpux*) flag="-D_REENTRANT";; + solaris*) + if test "$GCC" = "yes"; then + flag="-D_REENTRANT" + else + # TODO: What about Clang on Solaris? + flag="-mt -D_REENTRANT" + fi + ;; + esac + AC_MSG_RESULT([$flag]) + if test "x$flag" != xno; then + PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" + fi + + AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], + [ax_cv_PTHREAD_PRIO_INHERIT], [ + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[int i = PTHREAD_PRIO_INHERIT;]])], + [ax_cv_PTHREAD_PRIO_INHERIT=yes], + [ax_cv_PTHREAD_PRIO_INHERIT=no]) + ]) + AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"], + [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])]) + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + # More AIX lossage: compile with *_r variant + if test "x$GCC" != xyes; then + case $host_os in + aix*) + AS_CASE(["x/$CC"], + [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], + [#handle absolute path differently from PATH based program lookup + AS_CASE(["x$CC"], + [x/*], + [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], + [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) + ;; + esac + fi +fi + +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + +AC_SUBST([PTHREAD_LIBS]) +AC_SUBST([PTHREAD_CFLAGS]) +AC_SUBST([PTHREAD_CC]) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test x"$ax_pthread_ok" = xyes; then + ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) + : +else + ax_pthread_ok=no + $2 +fi +AC_LANG_POP +])dnl AX_PTHREAD diff --git a/util/Makefile.am b/util/Makefile.am index dbdd1fdf..5cde3eef 100644 --- a/util/Makefile.am +++ b/util/Makefile.am @@ -5,7 +5,7 @@ AUTOMAKE_OPTIONS = pkgdatadir = $(datadir)/@PACKAGE@ bin_PROGRAMS = wxcopy wxpaste wdwrite wdread getstyle setstyle convertfonts \ - seticons geticonset wmsetbg wmagnify wmgenmenu wmmenugen + seticons geticonset wmsetbg wmagnify wmgenmenu wmmenugen wmiv bin_SCRIPTS = wmaker.inst wm-oldmenu2new wkdemenu.pl @@ -70,6 +70,13 @@ wmmenugen_SOURCES = wmmenugen.c wmmenugen.h wmmenugen_misc.c \ wmmenugen_parse_wmconfig.c \ wmmenugen_parse_xdg.c +wmiv_LDADD = \ + $(top_builddir)/wrlib/libwraster.la \ + @XLFLAGS@ @XLIBS@ \ + @GFXLIBS@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) + +wmiv_SOURCES = wmiv.c wmiv.h + CLEANFILES = wmaker.inst wmaker.inst: $(srcdir)/wmaker.inst.in ./Makefile diff --git a/util/wmiv.c b/util/wmiv.c new file mode 100755 index 00000000..8c382c9b --- /dev/null +++ b/util/wmiv.c @@ -0,0 +1,815 @@ +/* + * Window Maker window manager + * + * Copyright (c) 2014 Window Maker Team - David Maciejak + * + * 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. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include "wraster.h" +#include +#include +#include +#include +#include +#include +#include +#include "config.h" +#ifdef HAVE_PTHREAD +#include +#endif + +#ifdef USE_XPM +extern int XpmCreatePixmapFromData(Display *, Drawable, char **, Pixmap *, Pixmap *, void *); +/* this is the icon from eog project + git.gnome.org/browse/eog +*/ +#include "wmiv.h" +#endif + +#define DEBUG 0 +#define FILE_SEPARATOR '/' + +Display *dpy; +Window win; +RContext *ctx; +RImage *img; +Pixmap pix; + +const char *APPNAME = "wmiv"; +int APPVERSION_MAJOR = 0; +int APPVERSION_MINOR = 6; +int NEXT = 0; +int PREV = 1; +float zoom_factor = 0; +int max_width = 0; +int max_height = 0; + +Bool fullscreen_flag = False; +Bool focus = False; + +#ifdef HAVE_PTHREAD +Bool diaporama_flag = False; +int diaporama_delay = 5; +pthread_t tid = 0; +#endif +XTextProperty title_property; +XTextProperty icon_property; +unsigned current_index = 1; +unsigned max_index = 1; + +RColor lightGray; +RColor darkGray; +RColor black; +RColor red; + +typedef struct link link_t; +struct link { + const void * data; + link_t *prev; + link_t *next; +}; + +typedef struct linked_list { + int count; + link_t *first; + link_t *last; +} linked_list_t; + +linked_list_t list; +link_t *current_link; + +/* + change_title: used to change window title + return EXIT_SUCCESS on success, 1 on failure +*/ +int change_title(XTextProperty *prop, char *filename) { + char *combined_title = NULL; + if (!asprintf(&combined_title, "%s - %u/%u - %s", APPNAME, current_index, max_index, filename)) + if (!asprintf(&combined_title, "%s - %u/%u", APPNAME, current_index, max_index)) + return EXIT_FAILURE; + XStringListToTextProperty(&combined_title, 1, prop); + XSetWMName(dpy, win, prop); + if (prop->value) + XFree(prop->value); + free(combined_title); + return EXIT_SUCCESS; +} + +/* + rescale_image: used to rescale the current image based on the screen size + return EXIT_SUCCESS on success +*/ +int rescale_image() { + long final_width = img->width; + long final_height = img->height; + + /* check if there is already a zoom factor applied */ + if (zoom_factor != 0) { + final_width = img->width + (int)(img->width * zoom_factor); + final_height = img->height + (int)(img->height * zoom_factor); + } + if ((max_width < final_width) || (max_height < final_height)) { + long val = 0; + if (final_width > final_height) { + val = final_height * max_width / final_width; + final_width = final_width * val / final_height; + final_height = val; + if (val > max_height) { + val = final_width * max_height / final_height; + final_height = final_height * val / final_width; + final_width = val; + } + } else { + val = final_width * max_height / final_height; + final_height = final_height * val / final_width; + final_width = val; + if (val > max_width) { + val = final_height * max_width / final_width; + final_width = final_width * val / final_height; + final_height = val; + } + } + } + if ((final_width != img->width) || (final_height != img->height)) { + RImage *old_img = img; + img = RScaleImage(img, final_width, final_height); + if (!img) { + img = old_img; + return EXIT_FAILURE; + } + RReleaseImage(old_img); + } + if (!RConvertImage(ctx, img, &pix)) { + fprintf(stderr, "%s\n", RMessageForError(RErrorCode)); + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + +/* + maximize_image: find the best image size for the current display + return EXIT_SUCCESS on success +*/ +int maximize_image() { + rescale_image(); + XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, img->width, img->height, max_width/2-img->width/2, max_height/2-img->height/2); + return EXIT_SUCCESS; +} + +/* + merge_with_background: merge the current image with with a checkboard background + return EXIT_SUCCESS on success, 1 on failure +*/ +int merge_with_background(RImage *i) { + if (i) { + RImage *back; + back = RCreateImage(i->width, i->height, True); + if (back) { + int opaq = 255; + int x=0, y=0; + + RFillImage(back, &lightGray); + for (x=0; x <= i->width; x+=8) { + if (x/8 % 2) + y = 8; + else + y = 0; + for (; y <= i->height; y+=16) + ROperateRectangle(back, RAddOperation, x,y,x+8,y+8, &darkGray); + } + + RCombineImagesWithOpaqueness(i, back, opaq); + RReleaseImage(back); + return EXIT_SUCCESS; + } + } + return EXIT_FAILURE; +} + +/* + draw_failed_image: create a red crossed image to indicate an error loading file + return the image on success, NULL on failure + +*/ +RImage* draw_failed_image() { + RImage *failed_image = NULL; + XWindowAttributes attr; + + if (win && (XGetWindowAttributes(dpy, win, &attr) >= 0)) { + failed_image = RCreateImage(attr.width, attr.height, False); + } else { + failed_image = RCreateImage(50, 50, False); + } + if (!failed_image) + return NULL; + + RFillImage(failed_image, &black); + ROperateLine(failed_image, RAddOperation, 0, 0, failed_image->width, failed_image->height, &red); + ROperateLine(failed_image, RAddOperation, 0, failed_image->height, failed_image->width, 0, &red); + + return failed_image; +} + +/* + full_screen: sending event to the window manager to switch from/to full screen mode + return EXIT_SUCCESS on success, 1 on failure +*/ +int full_screen() { + XEvent xev; + + Atom wm_state = XInternAtom(dpy, "_NET_WM_STATE", True); + Atom fullscreen = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", True); + long mask = SubstructureNotifyMask; + + if (fullscreen_flag) { + fullscreen_flag = False; + zoom_factor = 0; + } else { + fullscreen_flag = True; + zoom_factor = 1000; + } + + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.display = dpy; + xev.xclient.window = win; + xev.xclient.message_type = wm_state; + xev.xclient.format = 32; + xev.xclient.data.l[0] = fullscreen_flag; + xev.xclient.data.l[1] = fullscreen; + + if (!XSendEvent(dpy, DefaultRootWindow(dpy), False, mask, &xev)) { + fprintf(stderr, "Error: sending fullscreen event to xserver\n"); + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + +/* + zoom_in_out: apply a zoom factor on the current image + arg: 1 to zoom in, 0 to zoom out + return EXIT_SUCCESS on success, 1 on failure +*/ +int zoom_in_out(int z) { + RImage *old_img = img; + RImage *tmp = RLoadImage(ctx, current_link->data, 0); + if (!tmp) + return EXIT_FAILURE; + + if (z) { + zoom_factor += 0.2; + img = RScaleImage(tmp, tmp->width + (int)(tmp->width * zoom_factor), tmp->height + (int)(tmp->height * zoom_factor)); + if (!img) { + img = old_img; + return EXIT_FAILURE; + } + } else { + zoom_factor -= 0.2; + int new_width = tmp->width + (int) (tmp->width * zoom_factor); + int new_height = tmp->height + (int)(tmp->height * zoom_factor); + if ((new_width <= 0) || (new_height <= 0)) { + zoom_factor += 0.2; + RReleaseImage(tmp); + return EXIT_FAILURE; + } + img = RScaleImage(tmp, new_width, new_height); + if (!img) { + img = old_img; + return EXIT_FAILURE; + } + } + RReleaseImage(old_img); + RReleaseImage(tmp); + XFreePixmap(dpy, pix); + + merge_with_background(img); + if (!RConvertImage(ctx, img, &pix)) { + fprintf(stderr, "%s\n", RMessageForError(RErrorCode)); + return EXIT_FAILURE; + } + XResizeWindow(dpy, win, img->width, img->height); + return EXIT_SUCCESS; +} + +/* + zoom_in: transitional fct used to call zoom_in_out with zoom in flag + return EXIT_SUCCESS on success, 1 on failure +*/ +int zoom_in() { + return zoom_in_out(1); +} + +/* + zoom_out: transitional fct used to call zoom_in_out with zoom out flag + return EXIT_SUCCESS on success, 1 on failure +*/ +int zoom_out() { + return zoom_in_out(0); +} + +/* + change_image: load previous or next image + arg: way which could be PREV or NEXT constant + return EXIT_SUCCESS on success, 1 on failure +*/ +int change_image(int way) { + if (img && current_link) { + int old_img_width = img->width; + int old_img_height = img->height; + + RReleaseImage(img); + + if (way == NEXT) { + current_link = current_link->next; + current_index++; + } else { + current_link = current_link->prev; + current_index--; + } + if (current_link == NULL) { + if (way == NEXT) { + current_link = list.first; + current_index = 1; + } else { + current_link = list.last; + current_index = max_index; + } + } + if (DEBUG) + fprintf(stderr, "current file is> %s\n", (char *)current_link->data); + img = RLoadImage(ctx, current_link->data, 0); + + if (!img) { + fprintf(stderr, "Error: %s %s\n", (char *)current_link->data, RMessageForError(RErrorCode)); + img = draw_failed_image(); + } else { + merge_with_background(img); + } + rescale_image(); + if (!fullscreen_flag) { + if ((old_img_width != img->width) || (old_img_height != img->height)) { + XResizeWindow(dpy, win, img->width, img->height); + } else { + XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, img->width, img->height, 0, 0); + } + change_title(&title_property, (char *)current_link->data); + } else { + XClearWindow(dpy, win); + XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, img->width, img->height, max_width/2-img->width/2, max_height/2-img->height/2); + } + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} + +#ifdef HAVE_PTHREAD +/* + diaporama: send a xevent to display the next image at every delay set to diaporama_delay + arg: not used + return void +*/ +void* diaporama(void *arg) { + (void) arg; + + XKeyEvent event; + event.display = dpy; + event.window = win; + event.root = DefaultRootWindow(dpy); + event.subwindow = None; + event.time = CurrentTime; + event.x = 1; + event.y = 1; + event.x_root = 1; + event.y_root = 1; + event.same_screen = True; + event.keycode = XKeysymToKeycode(dpy, XK_Right); + event.state = 0; + event.type = KeyPress; + + while(diaporama_flag) { + int r; + r = XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *)&event); + if (!r) + fprintf(stderr, "Error sending event\n"); + XFlush(dpy); + /* default sleep time between moving to next image */ + sleep(diaporama_delay); + } + tid = 0; + return arg; +} +#endif + +/* + linked_list_init: init the linked list +*/ +void linked_list_init (linked_list_t *list) { + list->first = list->last = 0; + list->count = 0; +} + +/* + linked_list_add: add an element to the linked list + return EXIT_SUCCESS on success, 1 otherwise +*/ +int linked_list_add (linked_list_t *list, const void *data) { + link_t *link; + + /* calloc sets the "next" field to zero. */ + link = calloc (1, sizeof (link_t)); + if (! link) { + fprintf (stderr, "calloc failed.\n"); + return EXIT_FAILURE; + } + link->data = data; + if (list->last) { + /* Join the two final links together. */ + list->last->next = link; + link->prev = list->last; + list->last = link; + } else { + list->first = link; + list->last = link; + } + list->count++; + return EXIT_SUCCESS; +} + +/* + linked_list_free: deallocate the whole linked list +*/ +void linked_list_free (linked_list_t *list) { + link_t *link; + link_t *next; + for (link = list->first; link; link = next) { + /* Store the next value so that we don't access freed memory. */ + next = link->next; + if (link->data) + free((char *)link->data); + free (link); + } +} + +/* + connect_dir: list and sort by name all files from a given directory + arg: the directory path that contains images, the linked list where to add the new file refs + return: the first argument of the list or NULL on failure +*/ +link_t* connect_dir(char *dirpath, linked_list_t *li) { + struct dirent **dir; + int dv, idx; + char path[PATH_MAX] = ""; + + if (!dirpath) + return NULL; + + dv = scandir(dirpath, &dir, 0, alphasort); + if (dv < 0) { + /* maybe it's a file */ + struct stat stDirInfo; + if (lstat(dirpath, &stDirInfo) == 0) { + linked_list_add (li, strdup(dirpath)); + return li->first; + } else { + return NULL; + } + } + for (idx = 0; idx < dv; idx++) { + struct stat stDirInfo; + if (dirpath[strlen(dirpath)-1] == FILE_SEPARATOR) + snprintf(path, PATH_MAX, "%s%s", dirpath, dir[idx]->d_name); + else + snprintf(path, PATH_MAX, "%s%c%s", dirpath, FILE_SEPARATOR, dir[idx]->d_name); + + free(dir[idx]); + if ((lstat(path, &stDirInfo) == 0) && !S_ISDIR(stDirInfo.st_mode)) { + linked_list_add (li, strdup(path)); + } + } + free(dir); + return li->first; +} + +/* + main +*/ +int main(int argc, char **argv) { + int option = -1; + RContextAttributes attr; + XEvent e; + KeySym keysym; + char *reading_filename = ""; + int screen, file_i; + int quit = 0; + XClassHint *class_hints; + XSizeHints *size_hints; + XWMHints *win_hints; +#ifdef USE_XPM + Pixmap icon_pixmap, icon_shape; +#endif + + if (!(class_hints = XAllocClassHint())) { + fprintf(stderr, "Error: failure allocating memory\n"); + return EXIT_FAILURE; + } + class_hints->res_name = (char *)APPNAME; + class_hints->res_class = "default"; + + /* init colors */ + lightGray.red = lightGray.green = lightGray.blue = 211; + darkGray.red = darkGray.green = darkGray.blue = 169; + lightGray.alpha = darkGray.alpha = 1; + black.red = black.green = black.blue = 0; + red.red = 255; + red.green = red.blue = 0; + + if ((option = getopt(argc, argv, "hv")) != -1) { + switch (option) { + case 'h': + fprintf(stderr, "Usage: %s [image(s)|directory]\n" + "Keys:\n" + "+: zoom in\n" + "-: zoom out\n" + "esc: actual size\n" +#ifdef HAVE_PTHREAD + "d: launch diaporama mode\n" +#endif + "q: quit\n" + "right: next image\n" + "left: previous image\n" + "up: first image\n" + "down: last image\n", + argv[0]); + return EXIT_SUCCESS; + case 'v': + fprintf(stderr, "%s version %d.%d\n", APPNAME, APPVERSION_MAJOR, APPVERSION_MINOR); + return EXIT_SUCCESS; + case '?': + return EXIT_FAILURE; + } + } + + linked_list_init (&list); + + dpy = XOpenDisplay(NULL); + if (!dpy) { + fprintf(stderr, "Error: can't open display"); + linked_list_free (&list); + return EXIT_FAILURE; + } + + screen = DefaultScreen(dpy); + max_width = DisplayWidth(dpy, screen); + max_height = DisplayHeight(dpy, screen); + + attr.flags = RC_RenderMode | RC_ColorsPerChannel; + attr.render_mode = RDitheredRendering; + attr.colors_per_channel = 4; + ctx = RCreateContext(dpy, DefaultScreen(dpy), &attr); + + if (argc < 2) { + argv[1] = "."; + argc = 2; + } + + for (file_i = 1; file_i < argc; file_i++) { + current_link = connect_dir(argv[file_i], &list); + if (current_link) { + reading_filename = (char *)current_link->data; + max_index = list.count; + } + } + + img = RLoadImage(ctx, reading_filename, 0); + + if (!img) { + fprintf(stderr, "Error: %s %s\n", reading_filename, RMessageForError(RErrorCode)); + img = draw_failed_image(); + if (!current_link) + return EXIT_FAILURE; + } + + merge_with_background(img); + rescale_image(); + + if (DEBUG) + fprintf(stderr, "display size: %dx%d\n", max_width, max_height); + + win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, img->width, img->height, 0, 0, BlackPixel(dpy, screen)); + XSelectInput(dpy, win, KeyPressMask|StructureNotifyMask|ExposureMask|ButtonPressMask|FocusChangeMask); + + if (!(size_hints = XAllocSizeHints())) { + fprintf(stderr, "Error: failure allocating memory\n"); + return EXIT_FAILURE; + } + size_hints->width = img->width; + size_hints->height = img->height; + + Atom delWindow = XInternAtom(dpy, "WM_DELETE_WINDOW", 0); + XSetWMProtocols(dpy, win, &delWindow, 1); + change_title(&title_property, reading_filename); + + win_hints = XAllocWMHints(); + if (win_hints) { + win_hints->flags = StateHint|InputHint|WindowGroupHint; + +#ifdef USE_XPM + if ((XpmCreatePixmapFromData(dpy, win, wmiv_xpm, &icon_pixmap, &icon_shape, NULL)) == 0) { + win_hints->flags |= IconPixmapHint|IconMaskHint|IconPositionHint; + win_hints->icon_pixmap = icon_pixmap; + win_hints->icon_mask = icon_shape; + win_hints->icon_x = 0; + win_hints->icon_y = 0; + } +#endif + win_hints->initial_state = NormalState; + win_hints->input = True; + win_hints->window_group = win; + XStringListToTextProperty((char **)&APPNAME, 1, &icon_property); + XSetWMProperties(dpy, win, NULL, &icon_property, argv, argc, size_hints, win_hints, class_hints); + if (icon_property.value) + XFree(icon_property.value); + XFree(win_hints); + XFree(class_hints); + XFree(size_hints); + + } + XMapWindow(dpy, win); + XFlush(dpy); + XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, img->width, img->height, 0, 0); + + while (!quit) { + XNextEvent(dpy, &e); + if (e.type == ClientMessage) { + if (e.xclient.data.l[0] == delWindow) + quit = 1; + break; + } + if (e.type == FocusIn) { + focus = True; + continue; + } + if (e.type == FocusOut) { + focus = False; + continue; + } + if (!fullscreen_flag && (e.type == Expose)) { + XExposeEvent xev = e.xexpose; + if (xev.count == 0) + XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, img->width, img->height, 0, 0); + continue; + } + if (!fullscreen_flag && e.type == ConfigureNotify) { + XConfigureEvent xce = e.xconfigure; + if (xce.width != img->width || xce.height != img->height) { + RImage *old_img = img; + img = RLoadImage(ctx, current_link->data, 0); + if (!img) { + /* keep the old img and window size */ + img = old_img; + XResizeWindow(dpy, win, img->width, img->height); + } else { + img = RScaleImage(img, xce.width, xce.height); + if (!img) { + img = old_img; + XResizeWindow(dpy, win, img->width, img->height); + } else { + merge_with_background(img); + if (RConvertImage(ctx, img, &pix)) + RReleaseImage(old_img); + XResizeWindow(dpy, win, img->width, img->height); + } + } + } + continue; + } + if (fullscreen_flag && e.type == ConfigureNotify) { + maximize_image(); + continue; + } + if (e.type == ButtonPress) { + switch(e.xbutton.button) { + case Button1: { + if (focus) { + if (img && (e.xbutton.x > img->width/2)) + change_image(NEXT); + else + change_image(PREV); + } + } + break; + case Button4: + zoom_in(); + break; + case Button5: + zoom_out(); + break; + case 8: + change_image(PREV); + break; + case 9: + change_image(NEXT); + break; + } + continue; + } + if (e.type == KeyPress) { + keysym = XkbKeycodeToKeysym(dpy, e.xkey.keycode, 0, e.xkey.state & ShiftMask?1:0); +#ifdef HAVE_PTHREAD + if (keysym != XK_Right) + diaporama_flag = False; +#endif + switch (keysym) { + case XK_Right: + change_image(NEXT); + break; + case XK_Left: + change_image(PREV); + break; + case XK_Up: + if (current_link) { + current_link = list.last; + change_image(NEXT); + } + break; + case XK_Down: + if (current_link) { + current_link = list.first; + change_image(PREV); + } + break; +#ifdef HAVE_PTHREAD + case XK_F5: + case XK_d: + if (!tid) { + if (current_link && !diaporama_flag) { + diaporama_flag = True; + pthread_create(&tid, NULL, &diaporama, NULL); + } else { + fprintf(stderr, "Can't use diaporama mode, need a picture directory\n"); + } + } + break; +#endif + case XK_q: + quit = 1; + break; + case XK_Escape: + if (!fullscreen_flag) { + zoom_factor = -0.2; + /* zoom_in will increase the zoom factor by 0.2 */ + zoom_in(); + } else { + /* we are in fullscreen mode already, want to return to normal size */ + full_screen(); + } + break; + case XK_plus: + zoom_in(); + break; + case XK_minus: + zoom_out(); + break; + case XK_F11: + case XK_f: + full_screen(); + break; + } + + } + } + + if (img) + RReleaseImage(img); + if (pix) + XFreePixmap(dpy, pix); +#ifdef USE_XPM + if (icon_pixmap) + XFreePixmap(dpy, icon_pixmap); + if (icon_shape) + XFreePixmap(dpy, icon_shape); +#endif + linked_list_free(&list); + RDestroyContext(ctx); + RShutdown(); + XCloseDisplay(dpy); + return EXIT_SUCCESS; +} diff --git a/util/wmiv.h b/util/wmiv.h new file mode 100755 index 00000000..e196c488 --- /dev/null +++ b/util/wmiv.h @@ -0,0 +1,1279 @@ +/* XPM */ +static char * wmiv_xpm[] = { +"64 64 1212 2", +" c None", +". c #DBDBDA", +"+ c #E1E1E1", +"@ c #D9D9D9", +"# c #E4E4E4", +"$ c #ECECEB", +"% c #EAEAEA", +"& c #E8E8E8", +"* c #E2E2E2", +"= c #D6D6D6", +"- c #EDEDED", +"; c #EDEDEC", +"> c #EAEAE9", +", c #E9E9E8", +"' c #EBEBEB", +") c #E3E3E3", +"! c #EFEFEF", +"~ c #ECECEC", +"{ c #EBEBEA", +"] c #E9E9E9", +"^ c #E8E8E7", +"/ c #A5A5A5", +"( c #F2F2F1", +"_ c #EFEFEE", +": c #E7E7E7", +"< c #C7C7C7", +"[ c #DEDEDD", +"} c #F3F3F2", +"| c #EEEEEE", +"1 c #EEEEED", +"2 c #F4F4F3", +"3 c #F1F1F0", +"4 c #F0F0F0", +"5 c #F0F0EF", +"6 c #E6E6E5", +"7 c #F6F6F5", +"8 c #F4F4F2", +"9 c #EAEAED", +"0 c #D6D5D9", +"a c #CBCFC2", +"b c #AFAFB0", +"c c #F7F7F6", +"d c #F2F2F2", +"e c #F1F1F1", +"f c #EFEEF0", +"g c #DFDEE4", +"h c #C9CDBD", +"i c #B5C08E", +"j c #A3B666", +"k c #A6BF53", +"l c #A7BF53", +"m c #DDDCDF", +"n c #D4D4D5", +"o c #F8F8F7", +"p c #F5F5F4", +"q c #F4F4F4", +"r c #E7E6EC", +"s c #D1D3CC", +"t c #BAC49A", +"u c #A5B76A", +"v c #A2BB4D", +"w c #A7C04E", +"x c #A8C055", +"y c #AAC05A", +"z c #ABC15F", +"A c #ACC261", +"B c #CACFB9", +"C c #E5E5E5", +"D c #F6F6F4", +"E c #F3F3F3", +"F c #F0EFF2", +"G c #D9D9DB", +"H c #C2CAA8", +"I c #A9BA73", +"J c #9FB74C", +"K c #A3BF41", +"L c #A5C04C", +"M c #A7BF50", +"N c #A8C056", +"O c #A9C059", +"P c #ABC15D", +"Q c #ACC162", +"R c #ADC266", +"S c #AEC26A", +"T c #BAC597", +"U c #F0F0F1", +"V c #8C8C8C", +"W c #F5F5F5", +"X c #F5F4F6", +"Y c #E2E1E7", +"Z c #CAD0B6", +"` c #B0BF7F", +" . c #9DB44E", +".. c #9FBD38", +"+. c #A2BF40", +"@. c #A4BE47", +"#. c #A5BF4B", +"$. c #A6BF4F", +"%. c #A9C156", +"&. c #A9C058", +"*. c #AAC15C", +"=. c #ABC161", +"-. c #ADC265", +";. c #AFC36A", +">. c #AFC36D", +",. c #B1C372", +"'. c #ADBD7B", +"). c #EBEAED", +"!. c #BABABA", +"~. c #DDDDDC", +"{. c #F7F6F7", +"]. c #EAE8F0", +"^. c #D2D5C7", +"/. c #B8C58B", +"(. c #9EB453", +"_. c #9BBA33", +":. c #9EBE35", +"<. c #A0BD3D", +"[. c #A2BE42", +"}. c #A3BE46", +"|. c #A4BF4A", +"1. c #A6BF4E", +"2. c #A7C053", +"3. c #A9C057", +"4. c #ACC161", +"5. c #ADC269", +"6. c #AFC36C", +"7. c #B0C370", +"8. c #B3C476", +"9. c #B2C478", +"0. c #B3C479", +"a. c #D6D7D6", +"b. c #E0E0DF", +"c. c #C5C5C5", +"d. c #F6F6F6", +"e. c #F1F0F5", +"f. c #DADAD8", +"g. c #BFC99B", +"h. c #A3B85D", +"i. c #98B631", +"j. c #9BBC28", +"k. c #9DBC33", +"l. c #9CBB36", +"m. c #AEC65E", +"n. c #B2C864", +"o. c #A1BC45", +"p. c #A5BF4D", +"q. c #A7C052", +"r. c #AAC05B", +"s. c #ABC15E", +"t. c #B0C46C", +"u. c #B0C46D", +"v. c #B0C36F", +"w. c #B5C57C", +"x. c #B4C47E", +"y. c #B6C581", +"z. c #C8CDB7", +"A. c #F7F6F9", +"B. c #E1E0E5", +"C. c #C7CFAD", +"D. c #ABBD6F", +"E. c #98B439", +"F. c #98BB20", +"G. c #97BA21", +"H. c #96B726", +"I. c #98B829", +"J. c #9EBD37", +"K. c #A0BD3B", +"L. c #B1C367", +"M. c #F7EBF7", +"N. c #FFFCFF", +"O. c #FFFFFF", +"P. c #FEFEFE", +"Q. c #B1C56E", +"R. c #A9C05B", +"S. c #ABC160", +"T. c #A9BF5F", +"U. c #AABF63", +"V. c #B1C470", +"W. c #B2C574", +"X. c #B2C477", +"Y. c #B1C274", +"Z. c #B5C57D", +"`. c #B5C67D", +" + c #B3C37C", +".+ c #B2C37A", +"++ c #B7C293", +"@+ c #979797", +"#+ c #F8F8F6", +"$+ c #FAF9FB", +"%+ c #EAE8EF", +"&+ c #D0D5BF", +"*+ c #B3C280", +"=+ c #9BB445", +"-+ c #98BA23", +";+ c #9ABC25", +">+ c #9ABB28", +",+ c #9ABB2A", +"'+ c #A2BD40", +")+ c #E3E0CC", +"!+ c #FFFBFF", +"~+ c #F6F8EE", +"{+ c #B1C665", +"]+ c #9BB938", +"^+ c #EAD8E1", +"/+ c #FCF7FC", +"(+ c #FDFCFC", +"_+ c #E5E8D7", +":+ c #A3B95A", +"<+ c #A8BD5F", +"[+ c #CAD0A4", +"}+ c #F0EDE7", +"|+ c #F6F7F1", +"1+ c #D6DFB8", +"2+ c #AEC074", +"3+ c #B6C683", +"4+ c #AFC170", +"5+ c #B2C377", +"6+ c #B1C375", +"7+ c #AFC272", +"8+ c #A9BB6D", +"9+ c #E5E5E9", +"0+ c #C4C4C4", +"a+ c #F2F1F5", +"b+ c #D8DAD1", +"c+ c #BCC992", +"d+ c #A0B654", +"e+ c #99BB23", +"f+ c #9ABB27", +"g+ c #9ABA2E", +"h+ c #9BBC2B", +"i+ c #96B729", +"j+ c #EEDCE9", +"k+ c #FAF5FA", +"l+ c #FFFEFE", +"m+ c #9CB254", +"n+ c #F8E2FC", +"o+ c #FEFCFE", +"p+ c #FCFBFC", +"q+ c #FBFBFB", +"r+ c #F2F3EF", +"s+ c #8C9F4B", +"t+ c #E3DAD5", +"u+ c #FBF3FC", +"v+ c #DBDBDB", +"w+ c #A5AA92", +"x+ c #8A956A", +"y+ c #8A9467", +"z+ c #909D65", +"A+ c #9EAE66", +"B+ c #B2C56F", +"C+ c #AFC46B", +"D+ c #AABF60", +"E+ c #D0D3CA", +"F+ c #E7E7E6", +"G+ c #BCBCBC", +"H+ c #FCFBFD", +"I+ c #A5BB5B", +"J+ c #9ABB26", +"K+ c #9BBB2A", +"L+ c #9BBB2B", +"M+ c #9CBC2F", +"N+ c #9DBA3A", +"O+ c #9BB444", +"P+ c #F7E1FB", +"Q+ c #FEFCFD", +"R+ c #F9F8F9", +"S+ c #DFE0D2", +"T+ c #EFE3EC", +"U+ c #FAFBFA", +"V+ c #FBFAFA", +"W+ c #D9DACF", +"X+ c #D4CCC4", +"Y+ c #EDE6ED", +"Z+ c #A3A4A3", +"`+ c #646663", +" @ c #40433F", +".@ c #454743", +"+@ c #484A47", +"@@ c #494B49", +"#@ c #484B48", +"$@ c #444745", +"%@ c #414243", +"&@ c #404140", +"*@ c #5B6249", +"=@ c #829152", +"-@ c #C0CAA2", +";@ c #BACA82", +">@ c #9ABB2B", +",@ c #9ABB29", +"'@ c #9EBD34", +")@ c #A6C147", +"!@ c #9AB734", +"~@ c #92AF30", +"{@ c #E5D4DD", +"]@ c #FCF7FB", +"^@ c #FDFDFD", +"/@ c #F7F6F6", +"(@ c #FCFFFF", +"_@ c #FDFFFF", +":@ c #DADAD5", +"<@ c #858384", +"[@ c #434642", +"}@ c #4F514D", +"|@ c #545652", +"1@ c #494A4C", +"2@ c #3E4147", +"3@ c #343641", +"4@ c #30323F", +"5@ c #323440", +"6@ c #383A43", +"7@ c #404247", +"8@ c #484B49", +"9@ c #494B47", +"0@ c #404241", +"a@ c #404141", +"b@ c #9C9D9B", +"c@ c #A7A6A7", +"d@ c #D5DCC0", +"e@ c #99BB22", +"f@ c #9DBC31", +"g@ c #99B92A", +"h@ c #D0D2A7", +"i@ c #FFF6FF", +"j@ c #DDE5BE", +"k@ c #A5AE75", +"l@ c #F9EBFA", +"m@ c #FDFDFE", +"n@ c #F8F5F3", +"o@ c #F5D394", +"p@ c #F1BB5E", +"q@ c #EEA832", +"r@ c #EA9E1C", +"s@ c #F2A31B", +"t@ c #A78748", +"u@ c #454847", +"v@ c #52544F", +"w@ c #4A4C4E", +"x@ c #171930", +"y@ c #0F122B", +"z@ c #0C0E29", +"A@ c #0C0E28", +"B@ c #0D0F29", +"C@ c #0F112A", +"D@ c #12142B", +"E@ c #15172D", +"F@ c #191B30", +"G@ c #272938", +"H@ c #3C3F44", +"I@ c #474946", +"J@ c #3D403D", +"K@ c #3D3F3D", +"L@ c #CDCDCD", +"M@ c #F1F0F6", +"N@ c #96B724", +"O@ c #9BBC2C", +"P@ c #9CBC30", +"Q@ c #9FBC3A", +"R@ c #A7BA57", +"S@ c #F8E4FB", +"T@ c #E0DDD7", +"U@ c #FDFDFF", +"V@ c #F4D08D", +"W@ c #ECA424", +"X@ c #EDA12D", +"Y@ c #EC9D32", +"Z@ c #EB9A36", +"`@ c #ED9833", +" # c #756041", +".# c #494C4A", +"+# c #4F5250", +"@# c #2F313E", +"## c #171A30", +"$# c #13152D", +"%# c #10122B", +"&# c #090C29", +"*# c #080A23", +"=# c #1D1F35", +"-# c #2B2D41", +";# c #2A2C3F", +"># c #25263A", +",# c #0E1028", +"'# c #13152C", +")# c #17192E", +"!# c #1A1C2F", +"~# c #242737", +"{# c #3F4244", +"]# c #424441", +"^# c #3A3D3B", +"/# c #ABABAB", +"(# c #FDFCFF", +"_# c #A6BD57", +":# c #A0BD3F", +"<# c #ADB970", +"[# c #F7E6F8", +"}# c #FAFAFA", +"|# c #EEBC57", +"1# c #EFA722", +"2# c #EC9E2B", +"3# c #EB9630", +"4# c #EA9135", +"5# c #EC8D38", +"6# c #665644", +"7# c #4C4F4B", +"8# c #47494B", +"9# c #212335", +"0# c #181B30", +"a# c #14172F", +"b# c #1B1B30", +"c# c #4D4331", +"d# c #837038", +"e# c #A4A5A7", +"f# c #A6A6A5", +"g# c #A6A5A5", +"h# c #A8A8A8", +"i# c #A6A6A6", +"j# c #8D8E89", +"k# c #6E706E", +"l# c #353C30", +"m# c #191B2E", +"n# c #1A1D2F", +"o# c #1E2031", +"p# c #35373F", +"q# c #434542", +"r# c #393B39", +"s# c #C3CF99", +"t# c #9EBD35", +"u# c #A1BD3E", +"v# c #A1BD3F", +"w# c #A2BE44", +"x# c #93AC42", +"y# c #C9C2B7", +"z# c #FFF7FF", +"A# c #FDFCFD", +"B# c #F1D293", +"C# c #EFA912", +"D# c #ED9D1A", +"E# c #EB901D", +"F# c #E98720", +"G# c #EE8122", +"H# c #71563F", +"I# c #4A4D4A", +"J# c #424549", +"K# c #202334", +"L# c #1B1D31", +"M# c #181A31", +"N# c #594933", +"O# c #9C7C34", +"P# c #9C8033", +"Q# c #9D863B", +"R# c #A6A8AB", +"S# c #9A9B96", +"T# c #86897D", +"U# c #676C54", +"V# c #4E5633", +"W# c #4F592D", +"X# c #566329", +"Y# c #798453", +"Z# c #728045", +"`# c #3A432C", +" $ c #1A1B30", +".$ c #1E2130", +"+$ c #30313B", +"@$ c #363937", +"#$ c #DCDCDB", +"$$ c #DEE1D4", +"%$ c #9FBC37", +"&$ c #A3BE43", +"*$ c #A3BE4B", +"=$ c #A4BC53", +"-$ c #859B3E", +";$ c #889061", +">$ c #BFBFB0", +",$ c #E7E4E3", +"'$ c #FFFDFF", +")$ c #EEB938", +"!$ c #EFAA19", +"~$ c #EE9E1E", +"{$ c #EC9221", +"]$ c #EB8A25", +"^$ c #9F6935", +"/$ c #444846", +"($ c #474A4B", +"_$ c #222435", +":$ c #1E2032", +"<$ c #262531", +"[$ c #8E6F3C", +"}$ c #9F7D3B", +"|$ c #A58534", +"1$ c #AF943A", +"2$ c #BDAC78", +"3$ c #CECECF", +"4$ c #D7D6D7", +"5$ c #DDDCDD", +"6$ c #DDDDDD", +"7$ c #C5C7BF", +"8$ c #A9AF94", +"9$ c #839055", +"0$ c #6A7A2F", +"a$ c #667829", +"b$ c #697A2D", +"c$ c #56652B", +"d$ c #202331", +"e$ c #202230", +"f$ c #31343C", +"g$ c #3F413F", +"h$ c #373937", +"i$ c #C3C3C3", +"j$ c #F8F6FC", +"k$ c #A0B949", +"l$ c #A6BF4D", +"m$ c #A6BE57", +"n$ c #A8C057", +"o$ c #A5BD55", +"p$ c #AEBC79", +"q$ c #C1C3A9", +"r$ c #CECEC2", +"s$ c #E7E5E2", +"t$ c #FCFEFF", +"u$ c #EEB92C", +"v$ c #F1AF17", +"w$ c #EEA019", +"x$ c #EC941B", +"y$ c #DD8521", +"z$ c #3F4545", +"A$ c #4D4F4D", +"B$ c #282B38", +"C$ c #202233", +"D$ c #2F2C34", +"E$ c #967437", +"F$ c #A68134", +"G$ c #B38F36", +"H$ c #BD9F40", +"I$ c #C6AB48", +"J$ c #D6D2C8", +"K$ c #E0DFDF", +"L$ c #EEEDED", +"M$ c #F8F7F7", +"N$ c #FAF9FA", +"O$ c #D9D8DB", +"P$ c #B0B59D", +"Q$ c #738438", +"R$ c #657629", +"S$ c #66772A", +"T$ c #62722E", +"U$ c #212232", +"V$ c #232531", +"W$ c #373A3F", +"X$ c #3E403E", +"Y$ c #FCFCFC", +"Z$ c #B5C57F", +"`$ c #A8C054", +" % c #A9C159", +".% c #A8C059", +"+% c #DDD8C5", +"@% c #FDF5FF", +"#% c #FEFFFF", +"$% c #F1CE6C", +"%% c #F3BC1C", +"&% c #EFA90F", +"*% c #F19B0E", +"=% c #795E33", +"-% c #494B48", +";% c #393B42", +">% c #222434", +",% c #252735", +"'% c #98772E", +")% c #AC8A33", +"!% c #BB9B3F", +"~% c #C7AA48", +"{% c #CFB340", +"]% c #D5C8A6", +"^% c #E6E6E7", +"/% c #FAFBF7", +"(% c #DAD9DA", +"_% c #AFB694", +":% c #6D802F", +"<% c #66762A", +"[% c #616F33", +"}% c #272834", +"|% c #3E4140", +"1% c #313432", +"2% c #CED5B4", +"3% c #A9C158", +"4% c #B9C483", +"5% c #F7E4F8", +"6% c #FEFDFE", +"7% c #F9F8F8", +"8% c #F8F8F8", +"9% c #FAF9F9", +"0% c #F7F1EB", +"a% c #F2C62B", +"b% c #F4C124", +"c% c #E4A718", +"d% c #383E42", +"e% c #4B4E4B", +"f% c #262835", +"g% c #7D6930", +"h% c #B1953D", +"i% c #C0A543", +"j% c #CEB344", +"k% c #D2B64A", +"l% c #DCD1B9", +"m% c #EAEAEB", +"n% c #F8F7F8", +"o% c #ECEFE3", +"p% c #BAC29D", +"q% c #7C8E39", +"r% c #6E7F2F", +"s% c #677928", +"t% c #464E3A", +"u% c #21242F", +"v% c #33353B", +"w% c #383B38", +"x% c #3E403F", +"y% c #D5D5D5", +"z% c #E5E5E4", +"A% c #ADC268", +"B% c #AEC36A", +"C% c #AFB97F", +"D% c #F7E5F8", +"E% c #FFFEFF", +"F% c #F3E9D9", +"G% c #F1C837", +"H% c #988635", +"I% c #444644", +"J% c #3D3F43", +"K% c #262735", +"L% c #3C3B35", +"M% c #B6A03A", +"N% c #C0A739", +"O% c #C7AC51", +"P% c #D4C498", +"Q% c #E4E2E6", +"R% c #EBEAEA", +"S% c #F9F9F9", +"T% c #EBECE8", +"U% c #DCDED5", +"V% c #EDEFE7", +"W% c #DEE1D6", +"X% c #97A75E", +"Y% c #829739", +"Z% c #7B8F36", +"`% c #6B7D2D", +" & c #6C7E2F", +".& c #272933", +"+& c #3D403E", +"@& c #2F3130", +"#& c #B7B7B7", +"$& c #FBFAFC", +"%& c #ABBD71", +"&& c #B0C36E", +"*& c #93A55A", +"=& c #E0D3DB", +"-& c #F3F2F1", +";& c #B6B6A6", +">& c #E6DFE2", +",& c #55544A", +"'& c #494C48", +")& c #30323B", +"!& c #232533", +"~& c #817968", +"{& c #B8AC96", +"]& c #C8C2C3", +"^& c #DDE0DD", +"/& c #EAE9E9", +"(& c #EEEDEC", +"_& c #F3F2F2", +":& c #F4F3F3", +"<& c #FBFCFB", +"[& c #FCFCFB", +"}& c #9EA784", +"|& c #757E53", +"1& c #9CA385", +"2& c #ABB195", +"3& c #A7AE8C", +"4& c #88994B", +"5& c #8FA544", +"6& c #89A03A", +"7& c #84993B", +"8& c #758832", +"9& c #67792B", +"0& c #667729", +"a& c #484F3B", +"b& c #24262F", +"c& c #3A3D3D", +"d& c #313332", +"e& c #464846", +"f& c #C1CB9F", +"g& c #B2C473", +"h& c #B3C477", +"i& c #717F44", +"j& c #7A835B", +"k& c #7F8761", +"l& c #6A7445", +"m& c #697242", +"n& c #F1E4EF", +"o& c #FCF8FC", +"p& c #323532", +"q& c #4A4C49", +"r& c #292B35", +"s& c #242630", +"t& c #BBBBB8", +"u& c #CFCECF", +"v& c #BCBDB5", +"w& c #E1E3D8", +"x& c #F2F1F1", +"y& c #F4F4F1", +"z& c #F7F5F5", +"A& c #FDFDFC", +"B& c #E4E9D4", +"C& c #758C25", +"D& c #73872D", +"E& c #74882E", +"F& c #829835", +"G& c #8FA73A", +"H& c #99AF4B", +"I& c #90A83B", +"J& c #8CA13F", +"K& c #7D9136", +"L& c #6E802E", +"M& c #647139", +"N& c #20232D", +"O& c #343739", +"P& c #363736", +"Q& c #D6DBCA", +"R& c #B3C478", +"S& c #B5C57E", +"T& c #B5C581", +"U& c #ACBB78", +"V& c #9AAA63", +"W& c #94A560", +"X& c #91A258", +"Y& c #EFDDEC", +"Z& c #FBFAFB", +"`& c #D5D6D5", +" * c #373A37", +".* c #464947", +"+* c #282A35", +"@* c #43454B", +"#* c #C8C7C7", +"$* c #D5D5D4", +"%* c #A0A48F", +"&* c #DEE2D0", +"** c #F1F2E8", +"=* c #E2E9C8", +"-* c #90AF25", +";* c #92B02C", +">* c #93B02E", +",* c #94B22E", +"'* c #98B23D", +")* c #99B045", +"!* c #94AC40", +"~* c #90A641", +"{* c #829839", +"]* c #74872F", +"^* c #647625", +"/* c #6D7C37", +"(* c #262833", +"_* c #2F3136", +":* c #383B39", +"<* c #383A39", +"[* c #CCCCCB", +"}* c #EBEBED", +"|* c #B3C37D", +"1* c #B3C47D", +"2* c #B4C37C", +"3* c #B1C378", +"4* c #ADC06B", +"5* c #AEC16D", +"6* c #AFB780", +"7* c #F6E3F7", +"8* c #BEBFBE", +"9* c #3B3D3B", +"0* c #424543", +"a* c #282A34", +"b* c #646568", +"c* c #CCCCCC", +"d* c #D8D9D4", +"e* c #BABFA3", +"f* c #7F8E48", +"g* c #E8EBDD", +"h* c #F8F9F5", +"i* c #FCFBFB", +"j* c #FEFDFD", +"k* c #FEFEFD", +"l* c #9BB04E", +"m* c #94B328", +"n* c #95B42A", +"o* c #96B52C", +"p* c #97B52D", +"q* c #97B52F", +"r* c #97B13D", +"s* c #94AD3A", +"t* c #97AD4D", +"u* c #A0AE71", +"v* c #A4AA8E", +"w* c #A0A0A0", +"x* c #869064", +"y* c #34363D", +"z* c #2D2F33", +"A* c #393C3A", +"B* c #2E302F", +"C* c #A9A9A8", +"D* c #B5C18D", +"E* c #B1C276", +"F* c #AFC270", +"G* c #A9BE61", +"H* c #ABBF66", +"I* c #8FA151", +"J* c #ECDAE9", +"K* c #A1A39D", +"L* c #3C3F3D", +"M* c #424442", +"N* c #6C6D6F", +"O* c #D1D1D1", +"P* c #D8DBCE", +"Q* c #B4BD91", +"R* c #88A038", +"S* c #819341", +"T* c #D1D6C2", +"U* c #E6E8E1", +"V* c #7E8D48", +"W* c #87A425", +"X* c #94B327", +"Y* c #95B427", +"Z* c #92B323", +"`* c #96B42E", +" = c #B2C76A", +".= c #CED9A5", +"+= c #E2E4D9", +"@= c #E2E0E5", +"#= c #D1D1CF", +"$= c #BCBCBB", +"%= c #939785", +"&= c #393C3C", +"*= c #2D3032", +"== c #3A3C3A", +"-= c #2A2C2C", +";= c #F7F7F7", +">= c #A9BF61", +",= c #ACC06A", +"'= c #A5BC55", +")= c #A8BE5E", +"!= c #9FB553", +"~= c #809145", +"{= c #B6B89F", +"]= c #BBC1A7", +"^= c #8B9762", +"/= c #5A682E", +"(= c #3C3E3E", +"_= c #424542", +":= c #292B34", +"<= c #717274", +"[= c #D4D3D4", +"}= c #D7DBC8", +"|= c #8C9D50", +"1= c #97AF44", +"2= c #8DA831", +"3= c #788E2C", +"4= c #72823D", +"5= c #86915E", +"6= c #6E7C41", +"7= c #5E711A", +"8= c #7B971E", +"9= c #8BAB1B", +"0= c #A8C153", +"a= c #C6D592", +"b= c #E4E9D1", +"c= c #FAF8FD", +"d= c #F6F5F6", +"e= c #ECECEA", +"f= c #E1E0DF", +"g= c #D2D2D0", +"h= c #C0BFBF", +"i= c #9E9F9D", +"j= c #333737", +"k= c #2E3132", +"l= c #292C2B", +"m= c #DBDED2", +"n= c #A1BB4C", +"o= c #A5BD56", +"p= c #A2BB4E", +"q= c #9EB74B", +"r= c #91A941", +"s= c #8BA43A", +"t= c #93AD3B", +"u= c #7C9138", +"v= c #383A3A", +"w= c #434643", +"x= c #2B2D34", +"y= c #5F6063", +"z= c #CACBC7", +"A= c #919F60", +"B= c #8CA141", +"C= c #98B13E", +"D= c #97B239", +"E= c #92AF2D", +"F= c #88A427", +"G= c #7E9A1D", +"H= c #8DA53E", +"I= c #B0C178", +"J= c #D7DFBA", +"K= c #F8F7F9", +"L= c #F8F7FA", +"M= c #E2E2E0", +"N= c #D3D3D2", +"O= c #C1C1C0", +"P= c #ABABAA", +"Q= c #A09FA0", +"R= c #2F3234", +"S= c #323533", +"T= c #2D302E", +"U= c #F2F1F6", +"V= c #A5BA60", +"W= c #A4BC52", +"X= c #A2BA4C", +"Y= c #9EB942", +"Z= c #A1BA4B", +"`= c #A0BA48", +" - c #9DB943", +".- c #9DB83F", +"+- c #9BB73B", +"@- c #99B736", +"#- c #89A232", +"$- c #333538", +"%- c #434543", +"&- c #2F3135", +"*- c #647233", +"=- c #8CA045", +"-- c #96AE44", +";- c #95AE3B", +">- c #9AB836", +",- c #B6CA72", +"'- c #D2DDAD", +")- c #EEEFE8", +"!- c #F4F5F3", +"~- c #F5F5F3", +"{- c #F4F3F2", +"]- c #F3F3F1", +"^- c #E1E1E0", +"/- c #D3D3D1", +"(- c #C0C0BF", +"_- c #AAA9A9", +":- c #919291", +"<- c #25272A", +"[- c #343735", +"}- c #333634", +"|- c #363837", +"1- c #949494", +"2- c #B0C07E", +"3- c #9FBA46", +"4- c #9BB73A", +"5- c #9DB942", +"6- c #9AB738", +"7- c #9AB637", +"8- c #98B533", +"9- c #97B52E", +"0- c #99BA29", +"a- c #323435", +"b- c #424541", +"c- c #353737", +"d- c #2E2F37", +"e- c #7D8F3E", +"f- c #A0B164", +"g- c #C3CD9A", +"h- c #E3E6D5", +"i- c #F4F4F5", +"j- c #F2F2F0", +"k- c #EBEAE9", +"l- c #DFDFDE", +"m- c #BEBDBD", +"n- c #A7A7A6", +"o- c #767675", +"p- c #272A2B", +"q- c #373A38", +"r- c #C7D0A9", +"s- c #A1BB4A", +"t- c #9CB83D", +"u- c #9AB73A", +"v- c #9AB739", +"w- c #99B634", +"x- c #96B52D", +"y- c #90B11E", +"z- c #94B625", +"A- c #545C41", +"B- c #2A2C31", +"C- c #87878A", +"D- c #D8D7D8", +"E- c #E3E2E1", +"F- c #F2F1F0", +"G- c #F5F4F4", +"H- c #F0EFEE", +"I- c #E8E7E6", +"J- c #DCDBDA", +"K- c #BAB9B8", +"L- c #464847", +"M- c #2C2F2E", +"N- c #393C39", +"O- c #282B2A", +"P- c #DEE0DA", +"Q- c #9CB83C", +"R- c #9CB83F", +"S- c #99B635", +"T- c #95B42C", +"U- c #91B124", +"V- c #C3D290", +"W- c #DEE4CC", +"X- c #F4F2F9", +"Y- c #ACADAD", +"Z- c #3F423F", +"`- c #313333", +" ; c #3D3F41", +".; c #DEDEDC", +"+; c #F1F0EE", +"@; c #E3E3E1", +"#; c #D7D7D5", +"$; c #C7C7C5", +"%; c #B2B2B1", +"&; c #898989", +"*; c #292B2A", +"=; c #343635", +"-; c #292C2A", +";; c #B7B7B6", +">; c #99B342", +",; c #95B32D", +"'; c #A3BD4D", +"); c #BECE85", +"!; c #D9E0BE", +"~; c #F3F2F5", +"{; c #3E403D", +"]; c #2C2D30", +"^; c #7F807F", +"/; c #E4E4E2", +"(; c #F1F2F0", +"_; c #F5F4F3", +":; c #E8E8E6", +"<; c #DDDCDB", +"[; c #C3C3C2", +"}; c #A2A2A1", +"|; c #777777", +"1; c #2A2D2C", +"2; c #FBFBFA", +"3; c #E6EAD7", +"4; c #EEEFEA", +"5; c #F6F5F9", +"6; c #F2F1F2", +"7; c #9A9A99", +"8; c #2D3031", +"9; c #B5B5B3", +"0; c #E5E5E3", +"a; c #F1F1EF", +"b; c #E7E6E6", +"c; c #CACAC9", +"d; c #A7A6A6", +"e; c #737373", +"f; c #4E4E4E", +"g; c #2E2E2E", +"h; c #282B29", +"i; c #252828", +"j; c #303231", +"k; c #333535", +"l; c #BFBFBD", +"m; c #E5E4E3", +"n; c #EFEEED", +"o; c #D9D8D7", +"p; c #BBBABA", +"q; c #8A8A89", +"r; c #5D5D5C", +"s; c #424141", +"t; c #333331", +"u; c #434341", +"v; c #2C2F2D", +"w; c #262929", +"x; c #3B3E3C", +"y; c #CACACA", +"z; c #D1D2D0", +"A; c #2A2D2B", +"B; c #3B3D3C", +"C; c #353836", +"D; c #ADADAC", +"E; c #E0E0DE", +"F; c #E8E7E5", +"G; c #DAD8D8", +"H; c #C2C2C1", +"I; c #9B9A9A", +"J; c #656564", +"K; c #474746", +"L; c #2E2D2C", +"M; c #2B2D2C", +"N; c #A2A2A3", +"O; c #D4D4D4", +"P; c #A3A3A3", +"Q; c #4E4F4E", +"R; c #2E312F", +"S; c #2B2E2C", +"T; c #70716F", +"U; c #9C9C9B", +"V; c #6D6D6C", +"W; c #515150", +"X; c #353433", +"Y; c #3B3A39", +"Z; c #545453", +"`; c #363936", +" > c #262928", +".> c #DADADA", +"+> c #B3B3B3", +"@> c #343434", +"#> c #050505", +"$> c #000000", +"%> c #383938", +"&> c #323434", +"*> c #454746", +"=> c #595A58", +"-> c #4C4D4B", +";> c #272A29", +">> c #CECECE", +",> c #C2C2C2", +"'> c #848484", +")> c #424242", +"!> c #141414", +"~> c #323432", +"{> c #333534", +"]> c #393B3A", +"^> c #323433", +"/> c #343736", +"(> c #252827", +"_> c #909291", +":> c #C5CBCC", +"<> c #272727", +"[> c #7A7A7A", +"}> c #545454", +"|> c #222222", +"1> c #333633", +"2> c #2A2C2B", +"3> c #242726", +"4> c #7B7F80", +"5> c #6F7270", +"6> c #A2A29C", +"7> c #D0D4D5", +"8> c #CBB58E", +"9> c #393C3B", +"0> c #353735", +"a> c #727675", +"b> c #878A89", +"c> c #B28D4F", +"d> c #D2A158", +"e> c #E4B573", +"f> c #424443", +"g> c #373939", +"h> c #323534", +"i> c #2B2E2D", +"j> c #272928", +"k> c #282A29", +"l> c #2C2E2D", +"m> c #785B2A", +"n> c #A06A14", +"o> c #B78433", +"p> c #D9AA6A", +"q> c #E6B87A", +"r> c #E9BA74", +"s> c #593805", +"t> c #815103", +"u> c #9F6A14", +"v> c #BA883A", +"w> c #DCAD71", +"x> c #E6B97D", +"y> c #E9BA75", +"z> c #57390B", +"A> c #7F4F02", +"B> c #9E6913", +"C> c #BD8B40", +"D> c #DDAF75", +"E> c #E6B87F", +"F> c #E9BA77", +"G> c #553A0E", +"H> c #7D4E02", +"I> c #C28F47", +"J> c #DEB177", +"K> c #E6B97F", +"L> c #EABB78", +"M> c #553B11", +"N> c #7C4D01", +"O> c #9E6914", +"P> c #C3924C", +"Q> c #DEB178", +"R> c #E9BB79", +"S> c #553C13", +"T> c #7A4C01", +"U> c #C5944F", +"V> c #E6B87E", +"W> c #563D16", +"X> c #794B01", +"Y> c #C79653", +"Z> c #DEB078", +"`> c #E5B77C", +" , c #563E18", +"., c #784B02", +"+, c #9F6914", +"@, c #C89856", +"#, c #E4B67A", +"$, c #56401B", +"%, c #784B04", +"&, c #9F6A16", +"*, c #C99957", +"=, c #DBAC71", +"-, c #59411E", +";, c #7A4E08", +">, c #9B6712", +",, c #B48131", +"', c #513811", +"), c #734801", +" ", +" ", +" ", +" . + ", +" @ # $ % & & * ", +" = # - ; % > > , & & ' ", +" ) ; ! ~ $ ' { % > ] , , ^ & / ", +" + $ ( _ - ; ; ~ $ ' { % > ] ] & & : < ", +" [ { } ( _ _ | 1 1 ; ~ ~ $ { { % > ] , & & : ^ ", +" @ & } 2 3 4 5 5 _ _ | 1 - ; ; $ $ { % % > ] , & & : % ", +" 6 ( 7 8 ( ( ( 3 4 5 5 _ _ | 1 - ; ~ $ $ { % > ] ] { 9 0 a > b ", +" * _ c 7 2 2 } } d ( e 3 4 5 5 _ | | 1 - ; ~ $ ' { $ f g h i j k l m n ", +" [ $ c o 7 p p q 2 2 } } d ( 3 3 4 5 5 _ | | 1 ; ; - e r s t u v w x y z A B ! ", +" C o 7 7 7 7 7 D p 2 2 E } } ( ( 3 3 5 5 5 _ | 1 e F G H I J K L M N O P Q R S T U V ", +" $ 7 7 7 7 7 7 W p q 2 2 } d ( ( e 3 5 5 e X Y Z ` ...+.@.#.$.%.&.*.=.-.;.>.,.'.).!. ", +" ~.7 7 7 7 7 7 p p q 2 8 } d ( e ( {.].^./.(._.:.<.[.}.|.1.2.3.P 4.-.5.6.7.8.9.0.a.b. ", +" c.c 7 7 7 7 7 p p 2 2 } } d.e.f.g.h.i.j.k...l.m.n.o.p.q.N r.s.Q t.u.v.,.9.w.x.y.z.d ", +" c 7 7 7 7 7 p p d.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.=.T.U.V.W.X.Y.Z.`. +.+++d @+ ", +" { 7 7 7 #+$+%+&+*+=+-+;+>+,+'+)+!+~+{+]+^+/+(+P.O._+:+<+[+}+|+1+2+x.3+4+5+6+7+8+9+0+ ", +" = 7 a+b+c+d+I.e+f+>+>+g+h+i+j+k+l+O.O.m+n+o+p+q+O.r+s+t+u+O.O.v+w+x+y+z+A+B+C+D+E+F+ ", +" G+H+I+F.J+>+>+K+>+>+L+M+N+O+P+Q+R+P.O.S+T+o+U+V+O.W+X+Y+Z+`+ @.@+@@@#@$@%@&@*@=@-@E ", +" 7 ;@>+>+>+>+>@,@,+'@)@!@~@{@]@^@/@l+O.' O.(@_@O.:@<@[@}@|@1@2@3@4@5@6@7@8@9@0@a@b@c@ ", +" # d@e@>+>+,@f@g@h@i@O.O.j@k@l@o+m@n@o@p@q@r@s@t@u@v@w@4@x@y@z@A@B@C@D@E@F@G@H@I@J@K@ ", +" L@M@N@>+O@P@Q@R@S@o+(+(+O.O.T@U@V@W@X@Y@Z@`@ #.#+#@###$#%#&#*#=#-#;#>#,#'#)#!#~#{#]#^# ", +" /#(#_#M+k...:#<#[#l+P.V+{.}#O.|#1#2#3#4#5#6#7#8#9#0#a#b#c#d#e#f#g#h#i#j#k#l#m#n#o#p#q#r# ", +" 3 s#t#u#v#w#x#y#z#o+O.P.A#B#C#D#E#F#G#H#I#J#K#L#M#N#O#P#Q#R#S#T#U#V#W#X#Y#Z#`# $.$+$]#@$ ", +" #$$$%$&$*$#.=$-$;$>$,$'$O.)$!$~${$]$^$/$($_$:$<$[$}$|$1$2$3$4$5$6$7$8$9$0$a$b$c$d$e$f$g$h$ ", +" i$j$k$l$l$m$n$o$p$q$r$s$t$u$v$w$x$y$z$A$B$C$D$E$F$G$H$I$J$K$L$M$N$A#e O$P$Q$R$S$T$U$V$W$r#X$ ", +" Y$Z$x `$ %.%+%@%o+P.A##%$%%%&%*%=%-%;%>%,%'%)%!%~%{%]%^%$ {.q+A#q+/%} (%_%:%S$<%[%o#}%|%1% ", +" $ 2%3%z Q 4%5%6%q+7%8%9%0%a%b%c%d%e%f%K#g%h%i%j%k%l%m%_ 2 n%V+Y$O.O.o%C p%q%r%S$s%t%u%v%w%x% ", +" y%z%.%A%B%C%D%E%O.O.O.O.E%F%G%H%I%J%K%L%M%N%O%P%Q%R%2 c S%T%U%O.6%8%V%W%X%Y%Z%`%S$ &K%.&+&@& ", +" #&$&%&&&7.*&=&N.O.O.-&;&>&N.E%,&'&)&!&~&{&]&^&/&(&_&:&<&[&O.}&|&1&2&3&4&5&6&7&8&9&0&a&b&c&d&e& ", +" }#f&g&h&I i&j&k&l&m&n&o&n%M$p&q&r&s&t&u&v&w&x&y&z&{.7%Y$A&B&C&D&E&F&G&H&I&J&K&L&<%M&N&O&P&x% ", +" C Q&R&S&T&U&V&W&X&Y&o&Z&p+`& *.*+*@*#*$*%*&*n%**n%Y$V+A&A&=*-*;*>*,*'*)*!*~*{*]*^*/*(*_*:*<* ", +" [*}*|*1*2*3*4*5*6*7*6%P.O.8*9*0*a*b*c*d*e*f*g*h*i*Y$j*k*O.l*m*n*o*p*q*r*s*t*u*v*w*x*y*z*A*B* ", +" C*A#D*E*F*F*G*H*I*J*]@O.O.K*L*M*a*N*O*P*Q*R*S*T*O.O.O.U*V*W*X*Y*Z*`* =.=+=@=#=$=/ %=&=*===-= ", +" ;=C.F*>=,='=)=!=~={=]=^=/=(=_=:=<=[=}=|=1=2=3=4=5=6=7=8=9=0=a=b=c=d=( e=f=g=h=C*i=j=k=r#l= ", +" [ m=T.U.'=n=o=p=q=r=s=t=u=v=w=x=y=z=A=B=C=D=E=F=G=H=I=J=K=L=p q q 8 -&$ M=N=O=P=Q=R=S=@$T= ", +" i$U=V=W=X=Y=Z=`= -.-+-@-#-$-%-&-<**-=---;->-,-'-)-A.7 7 7 p p !-~-{-]-e=^-/-(-_-:-<-[-}-|- ", +" 1-E%2-=$3-4-5-Y=6-7-8-9-0-a-b-c-d-e-f-g-h-j$i-2 2 p p p p p ~-q !-8 j-k-l-#=m-n-o-p-q-B*^# ", +" e r-s-Y=t-u-v-w-x-n*y-z-A-J@9*B-C-D-E-$ F-{-~-p G-~-p p ~-q ~-8 } H-I-J-[*K-i#L-M-N-O- ", +" y%P-Q-R-4-S-T-U-x V-W-X-Y-S=Z-`- ;g=.;^ +;{-8 2 ~-p q ~-q ~-2 8 -&$ @;#;$;%;&;*;d&=;-; ", +" ;;j$>;,;';);!;a+~;! _ | } [-{;h$];^;f./;e=(;{-8 2 _;p 2 2 2 8 -&1 :;<;[;};|;K@1;q-1;:* ", +" 2;3;4;5;6;3 4 5 ! _ | _ 7;1%X$1%8;9;#$0;$ a;} {-8 {-} 8 _;( b;c;d;e;f;g;|-h;d&S=i; ", +" : d ( e 3 3 4 5 _ _ | 1 ( 0*r#N-j;k;l;#$m;> n;F-]-( 3 o;p;q;r;s;t;u; %-1;v;h$w;x; ", +" y;( ( ( 3 4 5 5 _ _ | 1 - z;A;B;C;@&c-D;~.E;F;G;H;I;J;K;L; q#O-M;h$A;T= ", +" N;7 ( ( 3 4 5 ! ! 5 | $ O;P;Q;R;^#C;R;S;T;U;V;W;X;Y; Z;`; >S;h$v;*; ", +" d.( 3 3 e a;4 .>+>e;@>#>$> %>T=:*q-R;M;&>*>=> ->:*h;O-R;C;-=;> ", +" >>p ( + ,>'>)>!>$> @&~>A*{>v;A;h;T=]>A*:*^>;> >h;v;/>S=(>M;_>:> ", +" <>[>}>|>$>$> B;O-1>w%C;j;M-1;2>A;-=M-1%`;{>O-3>h$4>5>6>7>8> ", +" 9>O-M;^>0>@$|-|-[-1%v;(> >[- a>b>c>d>e> ", +" f>g>h>i>j>k>l>d&[- m>n>o>p>q>r> ", +" s>t>u>v>w>x>y> ", +" z>A>B>C>D>E>F> ", +" G>H>B>I>J>K>L> ", +" M>N>O>P>Q>E>R> ", +" S>T>O>U>Q>V> ", +" W>X>O>Y>Z>`> ", +" ,.,+,@,Q>#, ", +" $,%,&,*,=, ", +" -,;,>,,, ", +" ',), ", +" ", +" "};