xcowsay-1.3/ 0000755 0001750 0001750 00000000000 11467062121 010053 5 0000000 0000000 xcowsay-1.3/NEWS 0000644 0001750 0001750 00000002011 11062526715 010471 0000000 0000000 Changes since 1.0
=================
- Added a new option --dream which displays an image instead
of text.
- Added a new --think mode which displays a thought bubble
instead of the usual speech bubble
- Added new wrapper scripts xcowdream and xcowthink as
shortcuts for the above.
- Added a new Portuguese translation (courtesy of Vincius
Moreira de Oliveira)
- Made --disable-dbus the default configure option as not
many people seem to be using the daemon. Hopefully this
will be replaced by the GNOME applet soon anyway.
- Removed the xcowat script as it was pretty useless.
- You can now click on the bubble as well as the cow to close
the window.
- Fixed a bug where the cow could appear off the left edge
of the screen in some circumstances. (Although this will
still occur if the cow and bubble are wider than the screen.)
- Fixed a separate bug where the bubble could appear cut off
at the top of the screen.
- Fixed various bugs with the daemon mode.
- A few other bug fixes ;-)
xcowsay-1.3/src/ 0000755 0001750 0001750 00000000000 11467062122 010643 5 0000000 0000000 xcowsay-1.3/src/xcowdream 0000755 0001750 0001750 00000000042 11041115620 012464 0000000 0000000 #!/bin/sh
exec xcowsay --dream $*
xcowsay-1.3/src/display_cow.h 0000644 0001750 0001750 00000002622 11062526715 013257 0000000 0000000 /* display_cow.h -- Display a cow in a popup window.
* Copyright (C) 2008 Nick Gasson
*
* 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 .
*/
#ifndef INC_DISPLAY_COW_H
#define INC_DISPLAY_COW_H
#include
#include
#include
#define CALCULATE_DISPLAY_TIME -1 // Work out display time from word count
#define debug_msg(...) if (debug) printf(__VA_ARGS__);
#define debug_err(...) if (debug) g_printerr(__VA_ARGS__);
typedef enum {
COWMODE_NORMAL,
COWMODE_DREAM,
COWMODE_THINK,
} cowmode_t;
// Show a cow with the given string and clean up afterwards
void display_cow(bool debug, const char *text, bool run_main, cowmode_t mode);
void display_cow_or_invoke_daemon(bool debug, const char *text, cowmode_t mode);
void cowsay_init(int *argc, char ***argv);
#endif
xcowsay-1.3/src/xcowfortune 0000755 0001750 0001750 00000000670 11022570537 013100 0000000 0000000 #!/bin/sh
#
# Display the output of fortune via xcowsay
#
# I run this via a cron job where DISPLAY isn't set
if [ "$DISPLAY" = "" ]; then
DISPLAY=:0.0
fi
# xcowsay may not be on the PATH...
# ...but it should be in the same directory as xcowfortune
PATH=$PATH:`dirname $0`
# fortune is often in /usr/games which may not be on the PATH
PATH=$PATH:/usr/games
exec env PATH=$PATH fortune | env PATH=$PATH DISPLAY=$DISPLAY xcowsay $@
xcowsay-1.3/src/settings.h 0000644 0001750 0001750 00000002405 11022570537 012576 0000000 0000000 /* settings.h -- Manage user options.
* Copyright (C) 2008 Nick Gasson
*
* 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 .
*/
#ifndef INC_SETTINGS_H
#define INC_SETTINGS_H
#include
#include
void add_int_option(const char *name, int ival);
void add_bool_option(const char *name, bool bval);
void add_string_option(const char *name, const char *sval);
int get_int_option(const char *name);
bool get_bool_option(const char *name);
const char *get_string_option(const char *name);
void set_int_option(const char *name, int ival);
void set_bool_option(const char *name, bool bval);
void set_string_option(const char *name, const char *sval);
#endif
xcowsay-1.3/src/settings.c 0000644 0001750 0001750 00000007204 11450177110 012566 0000000 0000000 /* settings.c -- Manage user options.
* Copyright (C) 2008 Nick Gasson
*
* 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 .
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include
#include
#include
#include "settings.h"
typedef enum {
optInt, optBool, optString
} option_type_t;
typedef union {
int ival;
bool bval;
char *sval;
} option_value_t;
typedef struct {
option_type_t type;
option_value_t u;
const char *name;
} option_t;
typedef struct _option_list_t {
struct _option_list_t *next;
option_t opt;
} option_list_t;
static option_list_t *options = NULL;
static option_list_t *alloc_node()
{
option_list_t *node = (option_list_t*)malloc(sizeof(option_list_t));
assert(node);
node->next = NULL;
return node;
}
static option_t *get_option(const char *name)
{
option_list_t *it;
for (it = options; it != NULL; it = it->next) {
if (strcmp(name, it->opt.name) == 0)
return &it->opt;
}
fprintf(stderr, "Invalid option '%s'\n", name);
exit(EXIT_FAILURE);
}
static void assert_string(const option_t *opt)
{
if (optString != opt->type) {
fprintf(stderr, "Error: Option '%s' is not of type string\n", opt->name);
exit(EXIT_FAILURE);
}
}
static void assert_int(const option_t *opt)
{
if (optInt != opt->type) {
fprintf(stderr, "Error: Option '%s' is not of type integer\n", opt->name);
exit(EXIT_FAILURE);
}
}
static void assert_bool(const option_t *opt)
{
if (optBool != opt->type) {
fprintf(stderr, "Error: Option '%s' is not of type Boolean\n", opt->name);
exit(EXIT_FAILURE);
}
}
int get_int_option(const char *name)
{
option_t *opt = get_option(name);
assert_int(opt);
return opt->u.ival;
}
bool get_bool_option(const char *name)
{
option_t *opt = get_option(name);
assert_bool(opt);
return opt->u.bval;
}
const char *get_string_option(const char *name)
{
option_t *opt = get_option(name);
assert_string(opt);
return opt->u.sval;
}
static void add_option(const char *name, option_type_t type, option_value_t def)
{
option_t opt = { type, def, name };
option_list_t *node = alloc_node();
node->opt = opt;
node->next = options;
options = node;
}
void add_int_option(const char *name, int ival)
{
option_value_t u;
u.ival = ival;
add_option(name, optInt, u);
}
void add_bool_option(const char *name, bool bval)
{
option_value_t u;
u.bval = bval;
add_option(name, optBool, u);
}
void add_string_option(const char *name, const char *sval)
{
option_value_t u;
u.sval = strdup(sval);
add_option(name, optString, u);
}
void set_int_option(const char *name, int ival)
{
option_t *opt = get_option(name);
assert_int(opt);
opt->u.ival = ival;
}
void set_bool_option(const char *name, bool bval)
{
option_t *opt = get_option(name);
assert_bool(opt);
opt->u.bval = bval;
}
void set_string_option(const char *name, const char *sval)
{
option_t *opt = get_option(name);
assert_string(opt);
free(opt->u.sval);
opt->u.sval = strdup(sval);
}
xcowsay-1.3/src/i18n.h 0000644 0001750 0001750 00000000256 11022570537 011517 0000000 0000000 #ifndef INC_18N_H
#define INC_18N_H
#include
#include
// Macros which xgettext extracts translatable strings from
#define i18n(s) gettext(s)
#endif
xcowsay-1.3/src/display_cow.c 0000644 0001750 0001750 00000025642 11465267760 013272 0000000 0000000 /* display_cow.c -- Display a cow in a popup window.
* Copyright (C) 2008-2010 Nick Gasson
*
* 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 .
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define _GNU_SOURCE
#include
#include
#include
#include
#include
#include
#include
#ifdef WITH_DBUS
#include
#define XCOWSAY_PATH "/uk/me/doof/Cowsay"
#define XCOWSAY_NAMESPACE "uk.me.doof.Cowsay"
#endif
#include "floating_shape.h"
#include "display_cow.h"
#include "settings.h"
#include "i18n.h"
GdkPixbuf *make_text_bubble(char *text, int *p_width, int *p_height,
int max_width, cowmode_t mode);
GdkPixbuf *make_dream_bubble(const char *file, int *p_width, int *p_height);
#define TICK_TIMEOUT 100
#define max(a, b) ((a) > (b) ? (a) : (b))
typedef enum {
csLeadIn, csDisplay, csLeadOut, csCleanup
} cowstate_t;
typedef struct {
float_shape_t *cow, *bubble;
int bubble_width, bubble_height;
GdkPixbuf *cow_pixbuf, *bubble_pixbuf;
cowstate_t state;
int transition_timeout;
int display_time;
int screen_width, screen_height;
} xcowsay_t;
static xcowsay_t xcowsay;
static gboolean tick(gpointer data);
static cowstate_t next_state(cowstate_t state)
{
switch (state) {
case csLeadIn:
return csDisplay;
case csDisplay:
return csLeadOut;
case csLeadOut:
return csCleanup;
case csCleanup:
default:
return csCleanup;
}
}
static GdkPixbuf *load_cow()
{
char *cow_path;
const char *alt_image = get_string_option("alt_image");
if (*alt_image)
cow_path = strdup(alt_image);
else
asprintf(&cow_path, "%s/%s_%s.png", DATADIR,
get_string_option("image_base"),
get_string_option("cow_size"));
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(cow_path, NULL);
if (NULL == pixbuf) {
fprintf(stderr, i18n("Failed to load cow image: %s\n"), cow_path);
exit(EXIT_FAILURE);
}
free(cow_path);
return pixbuf;
}
static gboolean cow_clicked(GtkWidget *widget, GdkEventButton *event, gpointer data)
{
if (csDisplay == xcowsay.state) {
xcowsay.transition_timeout = 0;
tick(NULL);
}
return true;
}
/*
* Set up a shape to call cow_clicked when it's clicked.
*/
static void close_when_clicked(float_shape_t *shape)
{
GdkEventMask events = gdk_window_get_events(shape_window(shape)->window);
events |= GDK_BUTTON_PRESS_MASK;
gdk_window_set_events(shape_window(shape)->window, events);
g_signal_connect(G_OBJECT(shape_window(shape)), "button-press-event",
G_CALLBACK(cow_clicked), NULL);
}
static gboolean tick(gpointer data)
{
xcowsay.transition_timeout -= TICK_TIMEOUT;
if (xcowsay.transition_timeout <= 0) {
xcowsay.state = next_state(xcowsay.state);
switch (xcowsay.state) {
case csLeadIn:
fprintf(stderr, "Internal Error: Invalid state csLeadIn\n");
exit(EXIT_FAILURE);
case csDisplay:
show_shape(xcowsay.bubble);
close_when_clicked(xcowsay.bubble);
xcowsay.transition_timeout = xcowsay.display_time;
break;
case csLeadOut:
hide_shape(xcowsay.bubble);
xcowsay.transition_timeout = get_int_option("lead_out_time");
break;
case csCleanup:
destroy_shape(xcowsay.cow);
xcowsay.cow = NULL;
destroy_shape(xcowsay.bubble);
xcowsay.bubble = NULL;
break;
}
}
return (xcowsay.state != csCleanup);
}
void cowsay_init(int *argc, char ***argv)
{
gtk_init(argc, argv);
xcowsay.cow = NULL;
xcowsay.bubble = NULL;
xcowsay.bubble_pixbuf = NULL;
xcowsay.cow_pixbuf = load_cow();
}
static int count_words(const char *s)
{
bool last_was_space = false;
int words;
for (words = 1; *s; s++) {
if (isspace(*s) && !last_was_space) {
words++;
last_was_space = true;
}
else
last_was_space = false;
}
return words;
}
static void normal_setup(const char *text, bool debug, cowmode_t mode)
{
char *text_copy = strdup(text);
// Trim any trailing newline
size_t len = strlen(text_copy);
if ('\n' == text_copy[len-1])
text_copy[len-1] = '\0';
// Count the words and work out the display time, if neccessary
xcowsay.display_time = get_int_option("display_time");
if (xcowsay.display_time < 0) {
int words = count_words(text_copy);
xcowsay.display_time = words * get_int_option("reading_speed");
debug_msg("Calculated display time as %dms from %d words\n",
xcowsay.display_time, words);
}
else {
debug_msg("Using default display time %dms\n", xcowsay.display_time);
}
int min_display = get_int_option("min_display_time");
int max_display = get_int_option("max_display_time");
if (xcowsay.display_time == 0) {
xcowsay.display_time = INT_MAX;
debug_msg("Set display time to permanent\n");
}
else if (xcowsay.display_time < min_display) {
xcowsay.display_time = min_display;
debug_msg("Display time too short: clamped to %d\n", min_display);
}
else if (xcowsay.display_time > max_display) {
xcowsay.display_time = max_display;
debug_msg("Display time too long: clamped to %d\n", max_display);
}
const int cow_width = shape_width(xcowsay.cow);
const int max_width = xcowsay.screen_width - cow_width;
xcowsay.bubble_pixbuf = make_text_bubble(
text_copy, &xcowsay.bubble_width, &xcowsay.bubble_height,
max_width, mode);
free(text_copy);
}
static void dream_setup(const char *file, bool debug)
{
debug_msg("Dreaming file: %s\n", file);
xcowsay.display_time = get_int_option("display_time");
if (xcowsay.display_time < 0)
xcowsay.display_time = get_int_option("dream_time");
xcowsay.bubble_pixbuf = make_dream_bubble(file, &xcowsay.bubble_width,
&xcowsay.bubble_height);
}
void display_cow(bool debug, const char *text, bool run_main, cowmode_t mode)
{
GdkScreen *screen = gdk_screen_get_default();
gint n_monitors = gdk_screen_get_n_monitors(screen);
gint pick = get_int_option("monitor");
if (pick < 0 || pick >= n_monitors)
pick = random() % n_monitors;
GdkRectangle geom;
gdk_screen_get_monitor_geometry(screen, pick, &geom);
xcowsay.screen_width = geom.width;
xcowsay.screen_height = geom.height;
g_assert(xcowsay.cow_pixbuf);
xcowsay.cow = make_shape_from_pixbuf(xcowsay.cow_pixbuf);
switch (mode) {
case COWMODE_NORMAL:
case COWMODE_THINK:
normal_setup(text, debug, mode);
break;
case COWMODE_DREAM:
dream_setup(text, debug);
break;
default:
fprintf(stderr, "Error: Unsupported cow mode %d\n", mode);
exit(1);
}
xcowsay.bubble = make_shape_from_pixbuf(xcowsay.bubble_pixbuf);
int total_width = shape_width(xcowsay.cow)
+ get_int_option("bubble_x")
+ xcowsay.bubble_width;
int total_height = max(shape_height(xcowsay.cow), xcowsay.bubble_height);
int bubble_off = max((xcowsay.bubble_height - shape_height(xcowsay.cow))/2, 0);
int area_w = xcowsay.screen_width - total_width;
int area_h = xcowsay.screen_height - total_height;
// Fit the cow on the screen as best as we can
// The area can't be be zero or we'd get an FPE
if (area_w < 1)
area_w = 1;
if (area_h < 1)
area_h = 1;
int cow_x = get_int_option("at_x");
if (cow_x < 0)
cow_x = random() % area_w;
else if (cow_x >= area_w)
cow_x = area_w - 1;
int cow_y = get_int_option("at_y");
if (cow_y < 0)
cow_y = random() % area_h;
else if (cow_y >= area_h)
cow_y = area_h - 1;
if (get_bool_option("left")) {
move_shape(xcowsay.cow,
geom.x + cow_x + xcowsay.bubble_width,
geom.y + bubble_off + cow_y);
show_shape(xcowsay.cow);
int bx = shape_x(xcowsay.cow) - xcowsay.bubble_width
+ get_int_option("bubble_x");
int by = shape_y(xcowsay.cow)
+ (shape_height(xcowsay.cow) - shape_height(xcowsay.bubble))/2
+ get_int_option("bubble_y");
move_shape(xcowsay.bubble, bx, by);
}
else {
move_shape(xcowsay.cow,
geom.x + cow_x,
geom.y + bubble_off + cow_y);
show_shape(xcowsay.cow);
int bx = shape_x(xcowsay.cow) + shape_width(xcowsay.cow)
+ get_int_option("bubble_x");
int by = shape_y(xcowsay.cow)
+ (shape_height(xcowsay.cow) - shape_height(xcowsay.bubble))/2
+ get_int_option("bubble_y");
move_shape(xcowsay.bubble, bx, by);
}
xcowsay.state = csLeadIn;
xcowsay.transition_timeout = get_int_option("lead_in_time");
g_timeout_add(TICK_TIMEOUT, tick, NULL);
close_when_clicked(xcowsay.cow);
if (run_main)
gtk_main();
g_object_unref(xcowsay.bubble_pixbuf);
xcowsay.bubble_pixbuf = NULL;
}
#ifndef WITH_DBUS
bool try_dbus(bool debug, const char *text, cowmode_t mode)
{
debug_msg("Skipping DBus (disabled by configure)\n");
return false;
}
#else
bool try_dbus(bool debug, const char *text, cowmode_t mode)
{
DBusGConnection *connection;
GError *error;
DBusGProxy *proxy;
g_type_init();
error = NULL;
connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
if (NULL == connection) {
debug_err("Failed to open connection to bus: %s\n", error->message);
g_error_free(error);
return false;
}
proxy = dbus_g_proxy_new_for_name(connection, XCOWSAY_NAMESPACE,
XCOWSAY_PATH, XCOWSAY_NAMESPACE);
g_assert(proxy);
const char *method = NULL;
switch (mode) {
case COWMODE_NORMAL:
method = "ShowCow";
break;
case COWMODE_THINK:
method = "Think";
break;
case COWMODE_DREAM:
method = "Dream";
break;
default:
g_assert(false);
}
error = NULL;
if (!dbus_g_proxy_call(proxy, method, &error, G_TYPE_STRING, text,
G_TYPE_INVALID, G_TYPE_INVALID)) {
debug_err("ShowCow failed: %s\n", error->message);
g_error_free(error);
return false;
}
return true;
}
#endif /* #ifndef WITH_DBUS */
void display_cow_or_invoke_daemon(bool debug, const char *text, cowmode_t mode)
{
if (!try_dbus(debug, text, mode))
display_cow(debug, text, true, mode);
}
xcowsay-1.3/src/Makefile.in 0000644 0001750 0001750 00000044202 11465271303 012633 0000000 0000000 # Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
# Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
bin_PROGRAMS = xcowsay$(EXEEXT)
subdir = src
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \
$(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
$(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \
$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)"
PROGRAMS = $(bin_PROGRAMS)
am_xcowsay_OBJECTS = xcowsay.$(OBJEXT) display_cow.$(OBJEXT) \
floating_shape.$(OBJEXT) settings.$(OBJEXT) xcowsayd.$(OBJEXT) \
config_file.$(OBJEXT) bubblegen.$(OBJEXT)
xcowsay_OBJECTS = $(am_xcowsay_OBJECTS)
xcowsay_LDADD = $(LDADD)
am__DEPENDENCIES_1 =
xcowsay_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
SCRIPTS = $(bin_SCRIPTS)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
SOURCES = $(xcowsay_SOURCES)
DIST_SOURCES = $(xcowsay_SOURCES)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DATADIR = @DATADIR@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
GMSGFMT = @GMSGFMT@
GMSGFMT_015 = @GMSGFMT_015@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INTLLIBS = @INTLLIBS@
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
LDFLAGS = @LDFLAGS@
LIBICONV = @LIBICONV@
LIBINTL = @LIBINTL@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LN_S = @LN_S@
LOCALEDIR = @LOCALEDIR@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
MSGFMT = @MSGFMT@
MSGFMT_015 = @MSGFMT_015@
MSGMERGE = @MSGMERGE@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
POSUB = @POSUB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
USE_NLS = @USE_NLS@
VERSION = @VERSION@
XCOWSAY_CFLAGS = @XCOWSAY_CFLAGS@
XCOWSAY_LIBS = @XCOWSAY_LIBS@
XGETTEXT = @XGETTEXT@
XGETTEXT_015 = @XGETTEXT_015@
XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
bin_SCRIPTS = xcowfortune xcowdream xcowthink
AM_CFLAGS = $(XCOWSAY_CFLAGS) -Wall
LDADD = $(XCOWSAY_LIBS)
xcowsay_SOURCES = xcowsay.c display_cow.c display_cow.h floating_shape.h \
floating_shape.c settings.h settings.c Cowsay_glue.h xcowsayd.h \
xcowsayd.c config_file.h config_file.c i18n.h bubblegen.c
EXTRA_DIST = xcowfortune xcowdream xcowthink
all: all-am
.SUFFIXES:
.SUFFIXES: .c .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu src/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
while read p p1; do if test -f $$p; \
then echo "$$p"; echo "$$p"; else :; fi; \
done | \
sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
if ($$2 == $$4) files[d] = files[d] " " $$1; \
else { print "f", $$3 "/" $$4, $$1; } } \
END { for (d in files) print "f", d, files[d] }' | \
while read type dir files; do \
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
test -z "$$files" || { \
echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
$(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
} \
; done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
-e 's/$$/$(EXEEXT)/' `; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(bindir)" && rm -f $$files
clean-binPROGRAMS:
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
xcowsay$(EXEEXT): $(xcowsay_OBJECTS) $(xcowsay_DEPENDENCIES)
@rm -f xcowsay$(EXEEXT)
$(LINK) $(xcowsay_OBJECTS) $(xcowsay_LDADD) $(LIBS)
install-binSCRIPTS: $(bin_SCRIPTS)
@$(NORMAL_INSTALL)
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
@list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
done | \
sed -e 'p;s,.*/,,;n' \
-e 'h;s|.*|.|' \
-e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
if ($$2 == $$4) { files[d] = files[d] " " $$1; \
if (++n[d] == $(am__install_max)) { \
print "f", d, files[d]; n[d] = 0; files[d] = "" } } \
else { print "f", d "/" $$4, $$1 } } \
END { for (d in files) print "f", d, files[d] }' | \
while read type dir files; do \
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
test -z "$$files" || { \
echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \
$(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
} \
; done
uninstall-binSCRIPTS:
@$(NORMAL_UNINSTALL)
@list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 's,.*/,,;$(transform)'`; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(bindir)" && rm -f $$files
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bubblegen.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config_file.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/display_cow.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/floating_shape.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/settings.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xcowsay.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xcowsayd.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(PROGRAMS) $(SCRIPTS)
installdirs:
for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am: install-binPROGRAMS install-binSCRIPTS
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
clean-generic ctags distclean distclean-compile \
distclean-generic distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-binPROGRAMS \
install-binSCRIPTS install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
tags uninstall uninstall-am uninstall-binPROGRAMS \
uninstall-binSCRIPTS
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
xcowsay-1.3/src/xcowsayd.c 0000644 0001750 0001750 00000016452 11450177110 012574 0000000 0000000 /* xcowsayd.c -- DBus xcowsay daemon.
* Copyright (C) 2008 Nick Gasson
*
* 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 .
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include
#include
#include
#include
#include
#include "xcowsayd.h"
#ifdef WITH_DBUS
#include
#include "display_cow.h"
typedef struct {
GObject parent;
DBusGConnection *connection;
} Cowsay;
typedef struct {
GObjectClass parent_class;
} CowsayClass;
static void cowsayd_init(Cowsay *server);
static void cowsayd_class_init(CowsayClass *class);
static gboolean cowsay_show_cow(Cowsay *obj, const gchar *mess, GError **error);
static gboolean cowsay_think(Cowsay *obj, const gchar *mess, GError **error);
static gboolean cowsay_dream(Cowsay *obj, const gchar *file, GError **error);
G_DEFINE_TYPE(Cowsay, cowsayd, G_TYPE_OBJECT);
#include "Cowsay_glue.h"
typedef struct _cowsay_queue_t {
struct _cowsay_queue_t *next;
char *message;
cowmode_t mode;
} cowsay_queue_t;
static cowsay_queue_t *requests = NULL;
static GMutex *queue_lock = NULL;
static GCond *request_ready = NULL;
static GMutex *display_lock = NULL;
static GCond *display_complete = NULL;
#define QUEUE_MUTEX_LOCK g_mutex_lock(queue_lock)
#define QUEUE_MUTEX_UNLOCK g_mutex_unlock(queue_lock)
#define REQUEST_READY_WAIT g_cond_wait(request_ready, queue_lock)
#define REQUEST_READY_SIGNAL g_cond_signal(request_ready)
static void enqueue_request(const char *mess, cowmode_t mode)
{
cowsay_queue_t *req = (cowsay_queue_t*)malloc(sizeof(cowsay_queue_t));
req->next = NULL;
req->message = malloc(strlen(mess)+1);
req->mode = mode;
g_assert(req->message);
strcpy(req->message, mess);
// Append the request to the end of the queue
QUEUE_MUTEX_LOCK;
{
if (NULL == requests) {
requests = req;
}
else {
cowsay_queue_t *it;
for (it = requests; it->next; it = it->next);
it->next = req;
}
REQUEST_READY_SIGNAL;
}
QUEUE_MUTEX_UNLOCK;
}
static void wait_for_request(const char** mess, cowmode_t *mode)
{
QUEUE_MUTEX_LOCK;
{
while (NULL == requests) {
REQUEST_READY_WAIT;
}
*mess = requests->message;
*mode = requests->mode;
}
QUEUE_MUTEX_UNLOCK;
}
static void request_complete()
{
QUEUE_MUTEX_LOCK;
{
cowsay_queue_t *req = requests;
g_assert(req);
requests = req->next;
free(req->message);
free(req);
}
QUEUE_MUTEX_UNLOCK;
}
static gpointer cow_display_thread(gpointer data)
{
bool debug = *(bool*)data;
debug_msg("In the cow display thread\n");
for (;;) {
const char *mess;
cowmode_t mode;
wait_for_request(&mess, &mode);
debug_msg("Processing request: %s\n", mess);
// We need to wrap the GTK+ stuff in gdk_threads_X since
// GTK assumes it is being called from the main thread
// (and it isn't here)
gdk_threads_enter();
display_cow(debug, mess, false, mode);
gdk_threads_leave();
g_cond_wait(display_complete, display_lock);
request_complete();
}
return NULL;
}
static void cowsayd_class_init(CowsayClass *class)
{
// Nothing to do here
}
static void cowsayd_init(Cowsay *server)
{
GError *error = NULL;
DBusGProxy *driver_proxy;
guint request_ret;
// Initialise the DBus connection
server->connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
if (NULL == server->connection) {
g_warning("Unable to connect to DBus: %s", error->message);
g_error_free(error);
exit(EXIT_FAILURE);
}
dbus_g_object_type_install_info(cowsayd_get_type(),
&dbus_glib_cowsay_object_info);
// Register DBus path
dbus_g_connection_register_g_object(server->connection,
"/uk/me/doof/Cowsay",
G_OBJECT(server));
// Register the service name
driver_proxy = dbus_g_proxy_new_for_name(server->connection,
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS);
if (!org_freedesktop_DBus_request_name(driver_proxy,
"uk.me.doof.Cowsay",
0, &request_ret, &error)) {
g_warning("Unable to register service: %s", error->message);
g_error_free(error);
exit(EXIT_FAILURE);
}
g_object_unref(driver_proxy);
}
static gboolean cowsay_show_cow(Cowsay *obj, const gchar *mess, GError **error)
{
printf("cowsay_show_cow mess=%s\n", mess);
enqueue_request(mess, COWMODE_NORMAL);
return true;
}
static gboolean cowsay_think(Cowsay *obj, const gchar *mess, GError **error)
{
printf("cowsay_think mess=%s\n", mess);
enqueue_request(mess, COWMODE_THINK);
return true;
}
static gboolean cowsay_dream(Cowsay *obj, const gchar *file, GError **error)
{
printf("cowsay_dream file=%s\n", file);
enqueue_request(file, COWMODE_DREAM);
return true;
}
void run_cowsay_daemon(bool debug, int argc, char **argv)
{
if (!debug) {
// Fork away from the terminal
int pid = fork();
if (pid < 0) {
perror("fork");
exit(EXIT_FAILURE);
}
else if (pid > 0) {
exit(EXIT_SUCCESS);
}
// Detach from the terminal
if (setsid() == -1) {
perror("setsid");
exit(EXIT_FAILURE);
}
// Close existing handles
int fd;
for (fd = 0; fd < getdtablesize(); fd++)
close(fd);
// Redirect everything to /dev/null
fd = open("/dev/null", O_RDWR); // fd = stdin
if (-1 == fd)
abort();
dup(fd); // stdout
dup(fd); // stderr
}
// g_thread_init must come before all other GLib calls
g_thread_init(NULL);
gdk_threads_init();
queue_lock = g_mutex_new();
request_ready = g_cond_new();
display_complete = g_cond_new();
display_lock = g_mutex_new();
cowsay_init(&argc, &argv);
g_type_init();
Cowsay *server = g_object_new(cowsayd_get_type(), NULL);
GThread *displ = g_thread_create(cow_display_thread, (gpointer)&debug, FALSE, NULL);
g_assert(displ);
debug_msg("Cowsay daemon starting...\n");
for (;;) {
gtk_main();
g_cond_signal(display_complete);
}
g_object_unref(server);
exit(EXIT_SUCCESS);
}
#else /* #ifdef WITH_DBUS */
void run_cowsay_daemon(bool debug, int argc, char **argv)
{
fprintf(stderr, "Error: Daemon mode unavailable as xcowsay was compiled "
"without DBus support.\n");
exit(EXIT_FAILURE);
}
#endif /* #ifdef WITH_DBUS */
xcowsay-1.3/src/floating_shape.c 0000644 0001750 0001750 00000010357 11450177110 013714 0000000 0000000 /* floating_shape.c -- Low-ish level window creation and management.
* Copyright (C) 2008 Nick Gasson
*
* 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 .
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include
#include
#include "floating_shape.h"
static float_shape_t *alloc_shape()
{
float_shape_t *s = (float_shape_t*)malloc(sizeof(float_shape_t));
g_assert(s);
return s;
}
static void quit_callback(GtkWidget *widget, gpointer data)
{
gtk_main_quit();
}
static void get_alpha_mask(float_shape_t *shape)
{
GdkColormap *colormap;
GdkColor black;
GdkColor white;
GdkGC *gc;
int rowstride, nchannels, x, y;
guchar *pixels, *p;
bool bright_green, has_alpha;
colormap = gdk_colormap_get_system();
gdk_color_black(colormap, &black);
gdk_color_white(colormap, &white);
shape->mask_bitmap =
(GdkDrawable*)gdk_pixmap_new(NULL, shape->width, shape->height, 1);
gc = gdk_gc_new(shape->mask_bitmap);
gdk_gc_set_foreground(gc, &black);
gdk_gc_set_background(gc, &white);
gdk_draw_rectangle(shape->mask_bitmap, gc, TRUE, 0, 0,
shape->width, shape->height);
nchannels = gdk_pixbuf_get_n_channels(shape->pixbuf);
g_assert(gdk_pixbuf_get_colorspace(shape->pixbuf) == GDK_COLORSPACE_RGB);
g_assert(gdk_pixbuf_get_bits_per_sample(shape->pixbuf) == 8);
has_alpha = gdk_pixbuf_get_has_alpha(shape->pixbuf);
rowstride = gdk_pixbuf_get_rowstride(shape->pixbuf);
pixels = gdk_pixbuf_get_pixels(shape->pixbuf);
gdk_gc_set_foreground(gc, &white);
gdk_gc_set_background(gc, &black);
for (y = 0; y < shape->height; y++) {
for (x = 0; x < shape->width; x++) {
p = pixels + y*rowstride + x*nchannels;
bright_green = 0 == p[0] && 255 == p[1] && 0 == p[2];
if (has_alpha) {
if (255 == p[3]) // p[3] is alpha channel
gdk_draw_point(shape->mask_bitmap, gc, x, y);
}
else if (!bright_green) { // Bright green is alpha for RGB images
gdk_draw_point(shape->mask_bitmap, gc, x, y);
}
}
}
}
float_shape_t *make_shape_from_pixbuf(GdkPixbuf *pixbuf)
{
float_shape_t *s = alloc_shape();
s->x = 0;
s->y = 0;
s->pixbuf = pixbuf;
s->width = gdk_pixbuf_get_width(pixbuf);
s->height = gdk_pixbuf_get_height(pixbuf);
s->window = gtk_window_new(GTK_WINDOW_POPUP);
gtk_window_set_decorated(GTK_WINDOW(s->window), FALSE);
gtk_window_set_title(GTK_WINDOW(s->window), "shape");
gtk_window_set_skip_taskbar_hint(GTK_WINDOW(s->window), TRUE);
gtk_window_set_keep_above(GTK_WINDOW(s->window), TRUE);
s->image = gtk_image_new_from_pixbuf(pixbuf);
gtk_container_add(GTK_CONTAINER(s->window), s->image);
get_alpha_mask(s);
gtk_widget_shape_combine_mask(s->window, s->mask_bitmap, 0, 0);
g_signal_connect(G_OBJECT(s->window), "destroy",
G_CALLBACK(quit_callback), NULL);
return s;
}
void show_shape(float_shape_t *shape)
{
gtk_window_move(GTK_WINDOW(shape->window), shape->x, shape->y);
gtk_window_resize(GTK_WINDOW(shape->window), shape->width, shape->height);
gtk_widget_show_all(shape->window);
gdk_window_set_back_pixmap(shape->window->window, NULL, TRUE);
}
void hide_shape(float_shape_t *shape)
{
gtk_widget_hide_all(shape->window);
}
void move_shape(float_shape_t *shape, int x, int y)
{
shape->x = x;
shape->y = y;
gtk_window_move(GTK_WINDOW(shape->window), shape->x, shape->y);
}
void destroy_shape(float_shape_t *shape)
{
g_assert(shape);
gtk_widget_destroy(shape->window);
g_object_unref(shape->mask_bitmap);
free(shape);
}
xcowsay-1.3/src/Cowsay_glue.h 0000644 0001750 0001750 00000012765 11332752653 013236 0000000 0000000 /* Generated by dbus-binding-tool; do not edit! */
#ifndef __dbus_glib_marshal_cowsay_MARSHAL_H__
#define __dbus_glib_marshal_cowsay_MARSHAL_H__
#include
G_BEGIN_DECLS
#ifdef G_ENABLE_DEBUG
#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
#define g_marshal_value_peek_char(v) g_value_get_char (v)
#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
#define g_marshal_value_peek_int(v) g_value_get_int (v)
#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
#define g_marshal_value_peek_long(v) g_value_get_long (v)
#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
#define g_marshal_value_peek_float(v) g_value_get_float (v)
#define g_marshal_value_peek_double(v) g_value_get_double (v)
#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
#define g_marshal_value_peek_param(v) g_value_get_param (v)
#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
#define g_marshal_value_peek_object(v) g_value_get_object (v)
#else /* !G_ENABLE_DEBUG */
/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
* Do not access GValues directly in your code. Instead, use the
* g_value_get_*() functions
*/
#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
#define g_marshal_value_peek_char(v) (v)->data[0].v_int
#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
#define g_marshal_value_peek_int(v) (v)->data[0].v_int
#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
#define g_marshal_value_peek_long(v) (v)->data[0].v_long
#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
#define g_marshal_value_peek_enum(v) (v)->data[0].v_long
#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
#define g_marshal_value_peek_float(v) (v)->data[0].v_float
#define g_marshal_value_peek_double(v) (v)->data[0].v_double
#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
#endif /* !G_ENABLE_DEBUG */
/* BOOLEAN:STRING,POINTER */
extern void dbus_glib_marshal_cowsay_BOOLEAN__STRING_POINTER (GClosure *closure,
GValue *return_value,
guint n_param_values,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
void
dbus_glib_marshal_cowsay_BOOLEAN__STRING_POINTER (GClosure *closure,
GValue *return_value G_GNUC_UNUSED,
guint n_param_values,
const GValue *param_values,
gpointer invocation_hint G_GNUC_UNUSED,
gpointer marshal_data)
{
typedef gboolean (*GMarshalFunc_BOOLEAN__STRING_POINTER) (gpointer data1,
gpointer arg_1,
gpointer arg_2,
gpointer data2);
register GMarshalFunc_BOOLEAN__STRING_POINTER callback;
register GCClosure *cc = (GCClosure*) closure;
register gpointer data1, data2;
gboolean v_return;
g_return_if_fail (return_value != NULL);
g_return_if_fail (n_param_values == 3);
if (G_CCLOSURE_SWAP_DATA (closure))
{
data1 = closure->data;
data2 = g_value_peek_pointer (param_values + 0);
}
else
{
data1 = g_value_peek_pointer (param_values + 0);
data2 = closure->data;
}
callback = (GMarshalFunc_BOOLEAN__STRING_POINTER) (marshal_data ? marshal_data : cc->callback);
v_return = callback (data1,
g_marshal_value_peek_string (param_values + 1),
g_marshal_value_peek_pointer (param_values + 2),
data2);
g_value_set_boolean (return_value, v_return);
}
G_END_DECLS
#endif /* __dbus_glib_marshal_cowsay_MARSHAL_H__ */
#include
static const DBusGMethodInfo dbus_glib_cowsay_methods[] = {
{ (GCallback) cowsay_show_cow, dbus_glib_marshal_cowsay_BOOLEAN__STRING_POINTER, 0 },
{ (GCallback) cowsay_think, dbus_glib_marshal_cowsay_BOOLEAN__STRING_POINTER, 38 },
{ (GCallback) cowsay_dream, dbus_glib_marshal_cowsay_BOOLEAN__STRING_POINTER, 74 },
};
const DBusGObjectInfo dbus_glib_cowsay_object_info = {
0,
dbus_glib_cowsay_methods,
3,
"uk.me.doof.Cowsay\0ShowCow\0S\0mess\0I\0s\0\0uk.me.doof.Cowsay\0Think\0S\0mess\0I\0s\0\0uk.me.doof.Cowsay\0Dream\0S\0file\0I\0s\0\0\0",
"\0",
"\0"
};
xcowsay-1.3/src/xcowsay.c 0000644 0001750 0001750 00000024607 11465272423 012442 0000000 0000000 /* xcowsay.c -- Cute talking cow for GTK+.
* Copyright (C) 2008-2010 Nick Gasson
*
* 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 .
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define _GNU_SOURCE
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "display_cow.h"
#include "settings.h"
#include "xcowsayd.h"
#include "config_file.h"
#include "i18n.h"
// Default settings
#define DEF_LEAD_IN_TIME 250
#define DEF_DISPLAY_TIME CALCULATE_DISPLAY_TIME
#define DEF_LEAD_OUT_TIME LEAD_IN_TIME
#define DEF_MIN_TIME 3000
#define DEF_MAX_TIME 30000
#define DEF_FONT "Bitstream Vera Sans 14"
#define DEF_READING_SPEED 400 // Human average is apparently 200-250 WPM (=5 WPS)
#define DEF_COW_SIZE "med"
#define DEF_IMAGE_BASE "cow"
#define DEF_DREAM_TIME 10000
#define DEF_ALT_IMAGE ""
#define DEF_BUBBLE_X 5 // Distance from cow to bubble
#define MAX_STDIN 4096 // Maximum chars to read from stdin
static int daemon_flag = 0;
static int debug = 0;
static int think_flag = 0;
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'v'},
{"time", required_argument, 0, 't'},
{"font", required_argument, 0, 'f'},
{"dream", required_argument, 0, 'd'},
{"think", no_argument, &think_flag, 1},
{"cow-size", required_argument, 0, 'c'},
{"reading-speed", required_argument, 0, 'r'},
{"daemon", no_argument, &daemon_flag, 1},
{"image", required_argument, 0, 'i'},
{"monitor", required_argument, 0, 'm'},
{"bubble-at", required_argument, 0, 'b'},
{"at", required_argument, 0, 'a'},
{"no-wrap", no_argument, 0, 'w'},
{"left", no_argument, 0, 'l'},
{"config", required_argument, 0, 'o'},
{"debug", no_argument, &debug, 1},
{0, 0, 0, 0}
};
static void read_from_stdin(cowmode_t mode)
{
char *data = malloc(MAX_STDIN);
size_t n = fread(data, 1, MAX_STDIN, stdin);
if (n == MAX_STDIN) {
fprintf(stderr, "Warning: Excess input truncated\n");
n--;
}
data[n] = '\0';
display_cow_or_invoke_daemon(debug, data, mode);
free(data);
}
static void usage()
{
printf(
"%s: xcowsay [OPTION]... [MESSAGE]...\n"
"%s\n\n"
"%s:\n"
" -h, --help\t\t%s\n"
" -v, --version\t\t%s\n"
" -t, --time=SECONDS\t%s\n"
" -r, --reading-speed=N\t%s\n"
" -f, --font=FONT\t%s\n"
" -d, --dream=FILE\t%s\n"
" -l, --left\t\t%s\n"
" --think\t\t%s\n"
" --daemon\t\t%s\n"
" --cow-size=SIZE\t%s\n"
" --image=FILE\t%s\n"
" --monitor=N\t%s\n"
" --at=X,Y\t\t%s\n"
" --bubble-at=X,Y\t%s\n"
" --no-wrap\t\t%s\n"
" --config=FILE\t%s\n"
" --debug\t\t%s\n\n"
"%s\n\n"
"%s\n\n"
"%s\n",
i18n("Usage"),
i18n("Display a cow on your desktop with MESSAGE or standard input."),
i18n("Options"),
i18n("Display this message and exit."),
i18n("Print version information."),
i18n("Number of seconds to display message for"),
i18n("Number of milliseconds to delay per word."),
i18n("Set message font (Pango format)."),
i18n("Display an image instead of text."),
i18n("Make the bubble appear to the left of cow."),
i18n("Display a thought bubble rather than a speech bubble."),
i18n("Run xcowsay in daemon mode."),
i18n("Size of the cow (small, med, large)."),
i18n("Use a different image instead of the cow."),
i18n("Display cow on monitor N."),
i18n("Force the cow to appear at screen location (X,Y)."),
i18n("Change relative position of bubble."),
i18n("Disable wrapping if text cannot fit on screen."),
i18n("Specify alternative config file."),
i18n("Keep daemon attached to terminal."),
i18n("Default values for these options can be specified in the "
"xcowsay config\nfile. See the man page for more information."),
i18n("If the display_time option is not set the display time will "
"be calcuated\nfrom the reading_speed parameter multiplied by "
"the word count. Set the\ndisplay time to zero to display the "
"cow until it is clicked on."),
i18n("Report bugs to nick@nickg.me.uk"));
}
static void version()
{
static const char *copy =
"Copyright (C) 2008-2010 Nick Gasson\n"
"This program comes with ABSOLUTELY NO WARRANTY. This is free software, and\n"
"you are welcome to redistribute it under certain conditions. See the GNU\n"
"General Public Licence for details.";
#ifdef HAVE_CONFIG_H
puts(PACKAGE_STRING);
#endif
puts(copy);
}
static int parse_int_option(const char *optarg)
{
char *endptr;
int r = strtol(optarg, &endptr, 10);
if ('\0' == *endptr)
return r;
else {
fprintf(stderr, i18n("Error: %s is not a valid integer\n"), optarg);
exit(EXIT_FAILURE);
}
}
static void parse_position_option(const char *optarg, int *x, int *y)
{
const char *failmsg = i18n("Error: failed to parse '%s' as position\n");
char *comma = strchr(optarg, ',');
if (comma == NULL) {
fprintf(stderr, failmsg, optarg);
exit(EXIT_FAILURE);
}
char *endptr;
*x = strtol(optarg, &endptr, 10);
if (endptr != comma || endptr == optarg) {
fprintf(stderr, failmsg, optarg);
exit(EXIT_FAILURE);
}
*y = strtol(comma + 1, &endptr, 10);
if (*endptr != '\0') {
fprintf(stderr, failmsg, optarg);
exit(EXIT_FAILURE);
}
}
/*
* Join all the strings in argv from ind to argc-1 into one big
* string with spaces between the words.
*/
static char *cat_from_index(int ind, int argc, char **argv)
{
size_t len = 0, i;
for (i = ind; i < argc; i++)
len += strlen(argv[i]) + (i < argc - 1 ? 1 : 0);
char *buf = malloc(len+1);
assert(buf);
char *p = buf;
for (i = ind; i < argc; i++) {
strcpy(p, argv[i]);
p += strlen(argv[i]);
if (i < argc - 1) // No space at the end
*p++ = ' ';
}
return buf;
}
int main(int argc, char **argv)
{
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
add_int_option("lead_in_time", DEF_LEAD_IN_TIME);
add_int_option("display_time", DEF_DISPLAY_TIME);
add_int_option("lead_out_time", get_int_option("lead_in_time"));
add_int_option("min_display_time", DEF_MIN_TIME);
add_int_option("max_display_time", DEF_MAX_TIME);
add_int_option("reading_speed", DEF_READING_SPEED);
add_int_option("dream_time", DEF_DREAM_TIME);
add_string_option("font", DEF_FONT);
add_string_option("cow_size", DEF_COW_SIZE);
add_string_option("image_base", DEF_IMAGE_BASE);
add_string_option("alt_image", DEF_ALT_IMAGE);
add_int_option("monitor", -1);
add_int_option("at_x", -1);
add_int_option("at_y", -1);
add_int_option("bubble_x", DEF_BUBBLE_X);
add_int_option("bubble_y", 0);
add_string_option("alt_config_file", "");
add_bool_option("wrap", true);
add_bool_option("left", false);
parse_config_file();
int c, index = 0, failure = 0;
const char *spec = "hvld:rt:f:";
const char *dream_file = NULL;
while ((c = getopt_long(argc, argv, spec, long_options, &index)) != -1) {
switch (c) {
case 0:
// Set a flag
break;
case 'd':
dream_file = optarg;
break;
case 'c':
set_string_option("cow_size", optarg);
break;
case 'h':
usage();
exit(EXIT_SUCCESS);
case 'v':
version();
exit(EXIT_SUCCESS);
case 't':
set_int_option("display_time", parse_int_option(optarg)*1000);
break;
case 'r':
set_int_option("reading_speed", parse_int_option(optarg));
break;
case 'f':
set_string_option("font", optarg);
break;
case 'i':
set_string_option("alt_image", optarg);
break;
case 'm':
set_int_option("monitor", parse_int_option(optarg));
break;
case 'a':
{
int x, y;
parse_position_option(optarg, &x, &y);
set_int_option("at_x", x);
set_int_option("at_y", y);
}
break;
case 'b':
{
int x, y;
parse_position_option(optarg, &x, &y);
set_int_option("bubble_x", x);
set_int_option("bubble_y", y);
}
break;
case 'o':
set_string_option("alt_config_file", optarg);
parse_config_file();
break;
case 'w':
set_bool_option("wrap", false);
break;
case 'l':
set_bool_option("left", true);
break;
case '?':
// getopt_long already printed an error message
failure = 1;
break;
default:
abort();
}
}
if (failure)
exit(EXIT_FAILURE);
srandom((unsigned)time(NULL));
cowmode_t mode = think_flag ? COWMODE_THINK : COWMODE_NORMAL;
if (daemon_flag) {
run_cowsay_daemon(debug, argc, argv);
}
else {
cowsay_init(&argc, &argv);
if (dream_file != NULL) {
// Make path absolute
char *abs_path = realpath(dream_file, NULL);
if (abs_path == NULL) {
perror(dream_file);
exit(EXIT_FAILURE);
}
if (access(abs_path, R_OK) != 0) {
perror(abs_path);
exit(EXIT_FAILURE);
}
display_cow_or_invoke_daemon(debug, abs_path, COWMODE_DREAM);
free(abs_path);
}
else if (optind == argc) {
read_from_stdin(mode);
}
else {
char *str = cat_from_index(optind, argc, argv);
display_cow_or_invoke_daemon(debug, str, mode);
free(str);
}
}
return EXIT_SUCCESS;
}
xcowsay-1.3/src/xcowsayd.h 0000644 0001750 0001750 00000000210 11022570537 012567 0000000 0000000 #ifndef INC_XCOWSAYD_H
#define INC_XCOWSAYD_H
#include
void run_cowsay_daemon(bool debug, int argc, char **argv);
#endif
xcowsay-1.3/src/config_file.c 0000644 0001750 0001750 00000014527 11440671671 013212 0000000 0000000 /* config_file.c -- Config file parser.
* Copyright (C) 2008-2010 Nick Gasson
*
* 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 .
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define _GNU_SOURCE
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "config_file.h"
#include "settings.h"
typedef enum { tEOF, tTOKEN, tNEWLINE, tEQUALS } token_t;
static const char* tok_names[] = { "EOF", "token", "newline", "'='" };
typedef struct {
char *buf;
int len, off;
} strbuf_t;
static strbuf_t *make_str_buf(int len)
{
strbuf_t *p = (strbuf_t*)malloc(sizeof(strbuf_t));
p->len = len;
p->off = 0;
p->buf = malloc(len);
assert(p->buf);
return p;
}
static void free_str_buf(strbuf_t *sbuf)
{
free(sbuf->buf);
free(sbuf);
}
static void push_char(strbuf_t *sbuf, char ch)
{
if (sbuf->off + 1 == sbuf->len)
return; // Silently truncate too long tokens :S
else {
sbuf->buf[sbuf->off++] = ch;
sbuf->buf[sbuf->off] = '\0';
}
}
#define clear_buf(sbuf) sbuf->off = 0
#define has_chars(sbuf) (sbuf->off > 0)
#define string(sbuf) (sbuf->buf)
static token_t next_token(FILE *f, strbuf_t* sbuf, int *lineno, jmp_buf *escape)
{
clear_buf(sbuf);
bool skip_to_eol = false;
for (;;) {
char next = fgetc(f);
if (EOF == next)
return (has_chars(sbuf) && !skip_to_eol) ? tTOKEN : tEOF;
else if ('\n' == next) {
skip_to_eol = false;
if (has_chars(sbuf)) {
ungetc('\n', f);
return tTOKEN;
}
else {
(*lineno)++;
return tNEWLINE;
}
}
else if (!skip_to_eol) {
if (isalpha(next) || isdigit(next) || '_' == next
|| '/' == next || '.' == next || '-' == next)
push_char(sbuf, next);
else if (has_chars(sbuf)) {
ungetc(next, f);
return tTOKEN;
}
else if (isspace(next))
; // Skip
else if ('=' == next)
return tEQUALS;
else if ('#' == next)
skip_to_eol = true;
else {
fprintf(stderr, "Illegal character in xcowsayrc: %c\n", next);
longjmp(*escape, 3);
}
}
}
}
static void expect(token_t want, token_t got, bool allow_eof,
int lineno, jmp_buf *escape)
{
if (tEOF == got && allow_eof)
longjmp(*escape, 1);
else if (want != got) {
fprintf(stderr, "xcowsayrc: line %d: Expected %s but found %s\n",
lineno, tok_names[want], tok_names[got]);
longjmp(*escape, 2);
}
}
static bool is_int_option(const char *s, int *ival)
{
const char *p = s;
while (*p) {
if (isdigit(*p))
++p;
else
return false;
}
*ival = atoi(s);
return true;
}
static bool is_bool_option(const char *s, bool *bval)
{
if (strcasecmp(s, "true") == 0) {
*bval = true;
return true;
}
else if (strcasecmp(s, "false") == 0) {
*bval = false;
return true;
}
else
return false;
}
static char *config_file_name(void)
{
// There are three possible locations for the config file:
// - Specifed on the command line with --config
// - $XDG_CONFIG_HOME/xcowsayrc
// - $HOME/.xcowsayrc
// We prefer them in the above order
// Need to free the result of this function
const char *alt_config_file = get_string_option("alt_config_file");
if (*alt_config_file)
return strdup(alt_config_file); // We always free the result
const char *home = getenv("HOME");
if (NULL == home)
return NULL;
char *fname = NULL;
const char *xdg_config_home = getenv("XDG_CONFIG_HOME");
if (xdg_config_home == NULL || *xdg_config_home == '\0') {
// Defaults to $HOME/.config
if (asprintf(&fname, "%s/.config/xcowsayrc", home) == -1)
return NULL;
}
else
if (asprintf(&fname, "%s/xcowsayrc", xdg_config_home) == -1)
return NULL;
struct stat dummy;
if (stat(fname, &dummy) == 0)
return fname;
free(fname);
// Try the home directory
if (asprintf(&fname, "%s/.xcowsayrc", home) == -1)
return NULL;
if (stat(fname, &dummy) == 0)
return fname;
free(fname);
return NULL;
}
void parse_config_file(void)
{
char *fname = config_file_name();
if (fname == NULL)
return;
FILE *frc = fopen(fname, "r");
free(fname);
if (NULL == frc)
return;
const int MAX_TOKEN = 256;
strbuf_t *opt_buf = make_str_buf(MAX_TOKEN);
strbuf_t *val_buf = make_str_buf(MAX_TOKEN);
strbuf_t *dummy_buf = make_str_buf(0);
jmp_buf escape;
if (setjmp(escape) == 0) {
token_t tok;
int lineno = 1;
for (;;) {
while ((tok = next_token(frc, opt_buf, &lineno, &escape))
== tNEWLINE)
expect(tNEWLINE, tok, true, lineno, &escape);
expect(tTOKEN, tok, true, lineno, &escape);
tok = next_token(frc, dummy_buf, &lineno, &escape);
expect(tEQUALS, tok, false, lineno, &escape);
tok = next_token(frc, val_buf, &lineno, &escape);
expect(tTOKEN, tok, false, lineno, &escape);
int ival;
bool bval;
if (is_int_option(string(val_buf), &ival))
set_int_option(string(opt_buf), ival);
else if (is_bool_option(string(val_buf), &bval))
set_bool_option(string(opt_buf), bval);
else
set_string_option(string(opt_buf), string(val_buf));
tok = next_token(frc, dummy_buf, &lineno, &escape);
expect(tNEWLINE, tok, true, lineno, &escape);
}
}
free_str_buf(opt_buf);
free_str_buf(val_buf);
free_str_buf(dummy_buf);
fclose(frc);
}
xcowsay-1.3/src/xcowthink 0000755 0001750 0001750 00000000042 11062526715 012527 0000000 0000000 #!/bin/sh
exec xcowsay --think $*
xcowsay-1.3/src/config_file.h 0000644 0001750 0001750 00000001472 11022570537 013205 0000000 0000000 /* config_file.h -- Config file parser.
* Copyright (C) 2008 Nick Gasson
*
* 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 .
*/
#ifndef INC_CONFIGFILE_H
#define INC_CONFIGFILE_H
void parse_config_file();
#endif
xcowsay-1.3/src/Makefile.am 0000644 0001750 0001750 00000000572 11450177110 012617 0000000 0000000 bin_PROGRAMS = xcowsay
bin_SCRIPTS = xcowfortune xcowdream xcowthink
AM_CFLAGS = $(XCOWSAY_CFLAGS) -Wall
LDADD = $(XCOWSAY_LIBS)
xcowsay_SOURCES = xcowsay.c display_cow.c display_cow.h floating_shape.h \
floating_shape.c settings.h settings.c Cowsay_glue.h xcowsayd.h \
xcowsayd.c config_file.h config_file.c i18n.h bubblegen.c
EXTRA_DIST = xcowfortune xcowdream xcowthink
xcowsay-1.3/src/bubblegen.c 0000644 0001750 0001750 00000044202 11465267760 012673 0000000 0000000 /* bubblegen.c -- Generate various sorts of bubbles.
* Copyright (C) 2008-2010 Nick Gasson
*
* 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 .
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include
#include
#include
#include
#include
#include
#include "floating_shape.h"
#include "display_cow.h"
#include "settings.h"
#include "i18n.h"
#define LEFT_BUF 5 // Amount of pixels to leave after cow's tail
#define TIP_WIDTH 20 // Length of the triangle bit on the speech bubble
#define THINK_WIDTH 80 // Spaces for thinking circles
#define CORNER_RADIUS 30 // Radius of corners on the speech bubble
#define CORNER_DIAM CORNER_RADIUS*2
#define BUBBLE_BORDER 5 // Pixels to leave free around edge of bubble
#define MIN_TIP_HEIGHT 15
// These next ones control the size and position of the "thinking circles"
// (or whatever you call them)
#define BIG_KIRCLE_X 38
#define BIG_KIRCLE_Y 70
#define BIG_KIRCLE_DIAM 35
#define SMALL_KIRCLE_X 5
#define SMALL_KIRCLE_Y 40
#define SMALL_KIRCLE_DIAM 20
// Min distance from top of the big kircle to the top of the bubble
#define KIRCLE_TOP_MIN 10
typedef struct {
int width, height;
GdkPixmap *pixmap;
GdkGC *gc;
} bubble_t;
typedef enum { NORMAL, THOUGHT } bubble_style_t;
static void bubble_init_left(bubble_t *b, bubble_style_t style)
{
GdkColor black, white, bright_green;
GdkColormap *colormap;
GdkPoint tip_points[5];
colormap = gdk_colormap_get_system();
gdk_color_black(colormap, &black);
gdk_color_white(colormap, &white);
bright_green.red = 0;
bright_green.green = 65535; // Bright green is alpha
bright_green.blue = 0;
gdk_gc_set_background(b->gc, &black);
gdk_gc_set_rgb_fg_color(b->gc, &bright_green);
gdk_draw_rectangle(b->pixmap, b->gc, TRUE, 0, 0, b->width, b->height);
b->width -= BUBBLE_BORDER;
b->height -= BUBBLE_BORDER;
// Space between cow and bubble
int middle = style == NORMAL ? TIP_WIDTH : THINK_WIDTH;
// Draw the white corners
gdk_gc_set_foreground(b->gc, &white);
gdk_draw_arc(b->pixmap, b->gc, TRUE, BUBBLE_BORDER,
BUBBLE_BORDER, CORNER_DIAM, CORNER_DIAM, 90*64, 90*64);
gdk_draw_arc(b->pixmap, b->gc, TRUE, BUBBLE_BORDER,
b->height - CORNER_DIAM, CORNER_DIAM,
CORNER_DIAM, 180*64, 90*64);
gdk_draw_arc(b->pixmap, b->gc, TRUE,
b->width - CORNER_DIAM - BUBBLE_BORDER - middle,
b->height - CORNER_DIAM, CORNER_DIAM,
CORNER_DIAM, 270*64, 90*64);
gdk_draw_arc(b->pixmap, b->gc, TRUE,
b->width - CORNER_DIAM - BUBBLE_BORDER - middle,
BUBBLE_BORDER, CORNER_DIAM, CORNER_DIAM, 0*64, 90*64);
// Fill in the middle of the bubble
gdk_draw_rectangle(b->pixmap, b->gc, TRUE,
CORNER_RADIUS + BUBBLE_BORDER,
BUBBLE_BORDER,
b->width - middle - BUBBLE_BORDER - CORNER_DIAM,
b->height - BUBBLE_BORDER);
gdk_draw_rectangle(b->pixmap, b->gc, TRUE,
BUBBLE_BORDER, BUBBLE_BORDER + CORNER_RADIUS,
b->width - middle - BUBBLE_BORDER*2,
b->height - BUBBLE_BORDER - CORNER_DIAM);
if (style == NORMAL) {
// The points on the tip part
int tip_compute_offset = (b->height - BUBBLE_BORDER - CORNER_DIAM)/3;
int tip_offset[3] = { tip_compute_offset, tip_compute_offset, tip_compute_offset };
if (tip_compute_offset < MIN_TIP_HEIGHT) {
int new_offset = (b->height - BUBBLE_BORDER - CORNER_DIAM - MIN_TIP_HEIGHT)/2;
tip_offset[0] = new_offset;
tip_offset[1] = MIN_TIP_HEIGHT;
tip_offset[2] = new_offset;
}
tip_points[0].x = b->width - middle - BUBBLE_BORDER;
tip_points[0].y = BUBBLE_BORDER + CORNER_RADIUS;
tip_points[1].x = b->width - middle - BUBBLE_BORDER;
tip_points[1].y = BUBBLE_BORDER + CORNER_RADIUS + tip_offset[0];
tip_points[2].x = b->width - BUBBLE_BORDER;
tip_points[2].y = BUBBLE_BORDER + CORNER_RADIUS + tip_offset[0] + tip_offset[1]/2;
tip_points[3].x = b->width - middle - BUBBLE_BORDER;
tip_points[3].y = BUBBLE_BORDER + CORNER_RADIUS + tip_offset[0] + tip_offset[1];
tip_points[4].x = b->width - middle - BUBBLE_BORDER;
tip_points[4].y = b->height - CORNER_RADIUS;
gdk_draw_polygon(b->pixmap, b->gc, TRUE, tip_points, 5);
}
else {
// Incrementally move the top kircle down so it's within the
// bubble's border
int big_y = BIG_KIRCLE_Y;
int small_y = SMALL_KIRCLE_Y;
while (big_y + KIRCLE_TOP_MIN > b->height/2) {
big_y /= 2;
small_y /= 2;
}
// Draw two think kircles
gdk_draw_arc(b->pixmap, b->gc, TRUE,
b->width - BIG_KIRCLE_X - BIG_KIRCLE_DIAM,
b->height/2 - big_y, BIG_KIRCLE_DIAM,
BIG_KIRCLE_DIAM, 0, 360*64);
gdk_draw_arc(b->pixmap, b->gc, TRUE,
b->width - SMALL_KIRCLE_X - SMALL_KIRCLE_DIAM,
b->height/2 - small_y, SMALL_KIRCLE_DIAM,
SMALL_KIRCLE_DIAM, 0, 360*64);
gdk_gc_set_line_attributes(b->gc, 4, GDK_LINE_SOLID,
GDK_CAP_ROUND, GDK_JOIN_ROUND);
gdk_gc_set_foreground(b->gc, &black);
gdk_draw_arc(b->pixmap, b->gc, FALSE,
b->width - BIG_KIRCLE_X - BIG_KIRCLE_DIAM,
b->height/2 - big_y, BIG_KIRCLE_DIAM,
BIG_KIRCLE_DIAM, 0, 360*64);
gdk_draw_arc(b->pixmap, b->gc, FALSE,
b->width - SMALL_KIRCLE_X - SMALL_KIRCLE_DIAM,
b->height/2 - small_y, SMALL_KIRCLE_DIAM,
SMALL_KIRCLE_DIAM, 0, 360*64);
}
// Draw the black rounded corners
gdk_gc_set_line_attributes(b->gc, 4, GDK_LINE_SOLID,
GDK_CAP_ROUND, GDK_JOIN_ROUND);
gdk_gc_set_foreground(b->gc, &black);
gdk_draw_arc(b->pixmap, b->gc, FALSE, BUBBLE_BORDER,
BUBBLE_BORDER, CORNER_DIAM, CORNER_DIAM, 90*64, 90*64);
gdk_draw_arc(b->pixmap, b->gc, FALSE, BUBBLE_BORDER,
b->height - CORNER_DIAM, CORNER_DIAM,
CORNER_DIAM, 180*64, 90*64);
gdk_draw_arc(b->pixmap, b->gc, FALSE,
b->width - middle - CORNER_DIAM - BUBBLE_BORDER,
b->height - CORNER_DIAM, CORNER_DIAM,
CORNER_DIAM, 270*64, 90*64);
gdk_draw_arc(b->pixmap, b->gc, FALSE,
b->width - middle - CORNER_DIAM - BUBBLE_BORDER,
BUBBLE_BORDER, CORNER_DIAM, CORNER_DIAM, 0*64, 90*64);
// Draw the top, bottom, and left sides (easy as they're straight!)
gdk_draw_line(b->pixmap, b->gc,
BUBBLE_BORDER,
CORNER_RADIUS + BUBBLE_BORDER,
BUBBLE_BORDER, b->height - CORNER_RADIUS);
gdk_draw_line(b->pixmap, b->gc,
BUBBLE_BORDER + CORNER_RADIUS, BUBBLE_BORDER,
b->width - CORNER_RADIUS - middle, BUBBLE_BORDER);
gdk_draw_line(b->pixmap, b->gc,
BUBBLE_BORDER + CORNER_RADIUS, b->height,
b->width - CORNER_RADIUS - middle, b->height);
if (style == NORMAL)
gdk_draw_lines(b->pixmap, b->gc, tip_points, 5);
else
gdk_draw_line(b->pixmap, b->gc,
b->width - THINK_WIDTH - BUBBLE_BORDER,
CORNER_RADIUS + BUBBLE_BORDER,
b->width - THINK_WIDTH - BUBBLE_BORDER,
b->height - CORNER_RADIUS);
}
static void bubble_init_right(bubble_t *b, bubble_style_t style)
{
GdkColor black, white, bright_green;
GdkColormap *colormap;
GdkPoint tip_points[5];
colormap = gdk_colormap_get_system();
gdk_color_black(colormap, &black);
gdk_color_white(colormap, &white);
bright_green.red = 0;
bright_green.green = 65535; // Bright green is alpha
bright_green.blue = 0;
gdk_gc_set_background(b->gc, &black);
gdk_gc_set_rgb_fg_color(b->gc, &bright_green);
gdk_draw_rectangle(b->pixmap, b->gc, TRUE, 0, 0, b->width, b->height);
b->width -= BUBBLE_BORDER;
b->height -= BUBBLE_BORDER;
// Space between cow and bubble
int middle = style == NORMAL ? TIP_WIDTH : THINK_WIDTH;
// Draw the white corners
gdk_gc_set_foreground(b->gc, &white);
gdk_draw_arc(b->pixmap, b->gc, TRUE, middle + BUBBLE_BORDER,
BUBBLE_BORDER, CORNER_DIAM, CORNER_DIAM, 90*64, 90*64);
gdk_draw_arc(b->pixmap, b->gc, TRUE, middle + BUBBLE_BORDER,
b->height - CORNER_DIAM, CORNER_DIAM,
CORNER_DIAM, 180*64, 90*64);
gdk_draw_arc(b->pixmap, b->gc, TRUE,
b->width - CORNER_DIAM - BUBBLE_BORDER,
b->height - CORNER_DIAM, CORNER_DIAM,
CORNER_DIAM, 270*64, 90*64);
gdk_draw_arc(b->pixmap, b->gc, TRUE,
b->width - CORNER_DIAM - BUBBLE_BORDER,
BUBBLE_BORDER, CORNER_DIAM, CORNER_DIAM, 0*64, 90*64);
// Fill in the middle of the bubble
gdk_draw_rectangle(b->pixmap, b->gc, TRUE,
CORNER_RADIUS + middle + BUBBLE_BORDER,
BUBBLE_BORDER,
b->width - middle - BUBBLE_BORDER - CORNER_DIAM,
b->height - BUBBLE_BORDER);
gdk_draw_rectangle(b->pixmap, b->gc, TRUE,
middle + BUBBLE_BORDER, BUBBLE_BORDER + CORNER_RADIUS,
b->width - middle - BUBBLE_BORDER*2,
b->height - BUBBLE_BORDER - CORNER_DIAM);
if (style == NORMAL) {
// The points on the tip part
int tip_compute_offset = (b->height - BUBBLE_BORDER - CORNER_DIAM)/3;
int tip_offset[3] = { tip_compute_offset, tip_compute_offset, tip_compute_offset };
if (tip_compute_offset < MIN_TIP_HEIGHT) {
int new_offset = (b->height - BUBBLE_BORDER - CORNER_DIAM - MIN_TIP_HEIGHT)/2;
tip_offset[0] = new_offset;
tip_offset[1] = MIN_TIP_HEIGHT;
tip_offset[2] = new_offset;
}
tip_points[0].x = middle + BUBBLE_BORDER;
tip_points[0].y = BUBBLE_BORDER + CORNER_RADIUS;
tip_points[1].x = middle + BUBBLE_BORDER;
tip_points[1].y = BUBBLE_BORDER + CORNER_RADIUS + tip_offset[0];
tip_points[2].x = BUBBLE_BORDER;
tip_points[2].y = BUBBLE_BORDER + CORNER_RADIUS + tip_offset[0] + tip_offset[1]/2;
tip_points[3].x = middle + BUBBLE_BORDER;
tip_points[3].y = BUBBLE_BORDER + CORNER_RADIUS + tip_offset[0] + tip_offset[1];
tip_points[4].x = middle + BUBBLE_BORDER;
tip_points[4].y = b->height - CORNER_RADIUS;
gdk_draw_polygon(b->pixmap, b->gc, TRUE, tip_points, 5);
}
else {
// Incrementally move the top kircle down so it's within the
// bubble's border
int big_y = BIG_KIRCLE_Y;
int small_y = SMALL_KIRCLE_Y;
while (big_y + KIRCLE_TOP_MIN > b->height/2) {
big_y /= 2;
small_y /= 2;
}
// Draw two think kircles
gdk_draw_arc(b->pixmap, b->gc, TRUE,
BIG_KIRCLE_X,
b->height/2 - big_y, BIG_KIRCLE_DIAM,
BIG_KIRCLE_DIAM, 0, 360*64);
gdk_draw_arc(b->pixmap, b->gc, TRUE,
SMALL_KIRCLE_X,
b->height/2 - small_y, SMALL_KIRCLE_DIAM,
SMALL_KIRCLE_DIAM, 0, 360*64);
gdk_gc_set_line_attributes(b->gc, 4, GDK_LINE_SOLID,
GDK_CAP_ROUND, GDK_JOIN_ROUND);
gdk_gc_set_foreground(b->gc, &black);
gdk_draw_arc(b->pixmap, b->gc, FALSE,
BIG_KIRCLE_X,
b->height/2 - big_y, BIG_KIRCLE_DIAM,
BIG_KIRCLE_DIAM, 0, 360*64);
gdk_draw_arc(b->pixmap, b->gc, FALSE,
SMALL_KIRCLE_X,
b->height/2 - small_y, SMALL_KIRCLE_DIAM,
SMALL_KIRCLE_DIAM, 0, 360*64);
}
// Draw the black rounded corners
gdk_gc_set_line_attributes(b->gc, 4, GDK_LINE_SOLID,
GDK_CAP_ROUND, GDK_JOIN_ROUND);
gdk_gc_set_foreground(b->gc, &black);
gdk_draw_arc(b->pixmap, b->gc, FALSE, middle + BUBBLE_BORDER,
BUBBLE_BORDER, CORNER_DIAM, CORNER_DIAM, 90*64, 90*64);
gdk_draw_arc(b->pixmap, b->gc, FALSE, middle + BUBBLE_BORDER,
b->height - CORNER_DIAM, CORNER_DIAM,
CORNER_DIAM, 180*64, 90*64);
gdk_draw_arc(b->pixmap, b->gc, FALSE,
b->width - CORNER_DIAM - BUBBLE_BORDER,
b->height - CORNER_DIAM, CORNER_DIAM,
CORNER_DIAM, 270*64, 90*64);
gdk_draw_arc(b->pixmap, b->gc, FALSE,
b->width - CORNER_DIAM - BUBBLE_BORDER,
BUBBLE_BORDER, CORNER_DIAM, CORNER_DIAM, 0*64, 90*64);
// Draw the top, bottom, and right sides (easy as they're straight!)
gdk_draw_line(b->pixmap, b->gc,
b->width - BUBBLE_BORDER,
CORNER_RADIUS + BUBBLE_BORDER,
b->width - BUBBLE_BORDER, b->height - CORNER_RADIUS);
gdk_draw_line(b->pixmap, b->gc,
BUBBLE_BORDER + middle + CORNER_RADIUS, BUBBLE_BORDER,
b->width - CORNER_RADIUS, BUBBLE_BORDER);
gdk_draw_line(b->pixmap, b->gc,
BUBBLE_BORDER + middle + CORNER_RADIUS, b->height,
b->width - CORNER_RADIUS, b->height);
if (style == NORMAL)
gdk_draw_lines(b->pixmap, b->gc, tip_points, 5);
else
gdk_draw_line(b->pixmap, b->gc,
BUBBLE_BORDER + middle,
CORNER_RADIUS + BUBBLE_BORDER,
BUBBLE_BORDER + middle,
b->height - CORNER_RADIUS);
}
static void bubble_init(bubble_t *b, bubble_style_t style)
{
GdkVisual *root_visual;
root_visual = gdk_visual_get_system();
b->pixmap = gdk_pixmap_new(NULL, b->width, b->height, root_visual->depth);
g_assert(b->pixmap);
b->gc = gdk_gc_new(b->pixmap);
if (get_bool_option("left"))
bubble_init_left(b, style);
else
bubble_init_right(b, style);
}
static void bubble_size_from_content(bubble_t *b, bubble_style_t style,
int c_width, int c_height)
{
int middle = style == NORMAL ? TIP_WIDTH : THINK_WIDTH;
b->width = 2*BUBBLE_BORDER + CORNER_DIAM + middle + c_width;
b->height = BUBBLE_BORDER + CORNER_DIAM + c_height;
}
static GdkPixbuf *bubble_tidy(bubble_t *b)
{
GdkPixbuf *pixbuf =
gdk_pixbuf_get_from_drawable(NULL, b->pixmap, NULL,
0, 0, 0, 0,
b->width + BUBBLE_BORDER,
b->height + BUBBLE_BORDER);
g_object_unref(b->pixmap);
return pixbuf;
}
static int bubble_content_left(bubble_style_t style)
{
if (get_bool_option("left")) {
return BUBBLE_BORDER + CORNER_RADIUS;
}
else {
const int middle = style == NORMAL ? TIP_WIDTH : THINK_WIDTH;
return BUBBLE_BORDER + middle + CORNER_RADIUS;
}
}
static int bubble_content_top()
{
return CORNER_RADIUS;
}
GdkPixbuf *make_dream_bubble(const char *file, int *p_width, int *p_height)
{
bubble_t bubble;
GError *error = NULL;
GdkPixbuf *image = gdk_pixbuf_new_from_file(file, &error);
if (NULL == image) {
fprintf(stderr, "Error: failed to load %s\n", file);
exit(1);
}
bubble_size_from_content(&bubble, THOUGHT, gdk_pixbuf_get_width(image),
gdk_pixbuf_get_height(image));
*p_width = bubble.width;
*p_height = bubble.height;
bubble_init(&bubble, THOUGHT);
gdk_draw_pixbuf(bubble.pixmap, bubble.gc, image, 0, 0,
bubble_content_left(THOUGHT), bubble_content_top(),
-1, -1, GDK_RGB_DITHER_NONE, 0, 0);
gdk_pixbuf_unref(image);
return bubble_tidy(&bubble);
}
GdkPixbuf *make_text_bubble(char *text, int *p_width, int *p_height,
int max_width, cowmode_t mode)
{
bubble_t bubble;
int text_width, text_height;
// Work out the size of the bubble from the text
PangoContext *pango_context = gdk_pango_context_get();
PangoLayout *layout = pango_layout_new(pango_context);
PangoFontDescription *font =
pango_font_description_from_string(get_string_option("font"));
PangoAttrList *pango_attrs = NULL;
// Adjust max width to account for bubble edges
max_width -= LEFT_BUF;
max_width -= TIP_WIDTH;
max_width -= 2 * BUBBLE_BORDER;
max_width -= CORNER_DIAM;
if (get_bool_option("wrap")) {
pango_layout_set_width(layout, max_width * PANGO_SCALE);
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
}
char *stripped;
if (!pango_parse_markup(text, -1, 0, &pango_attrs,
&stripped, NULL, NULL)) {
// This isn't fatal as the the text may contain angled brackets, etc.
stripped = text;
}
else {
pango_layout_set_attributes(layout, pango_attrs);
}
pango_layout_set_font_description(layout, font);
pango_layout_set_text(layout, stripped, -1);
pango_layout_get_pixel_size(layout, &text_width, &text_height);
bubble_style_t style = mode == COWMODE_NORMAL ? NORMAL : THOUGHT;
bubble_size_from_content(&bubble, style, text_width, text_height);
*p_width = bubble.width;
*p_height = bubble.height;
bubble_init(&bubble, style);
// Render the text
gdk_draw_layout(bubble.pixmap, bubble.gc,
bubble_content_left(mode), bubble_content_top(), layout);
// Make sure to free the Pango objects
g_object_unref(pango_context);
g_object_unref(layout);
pango_font_description_free(font);
if (NULL != pango_attrs)
pango_attr_list_unref(pango_attrs);
return bubble_tidy(&bubble);
}
xcowsay-1.3/src/floating_shape.h 0000644 0001750 0001750 00000002730 11022570537 013722 0000000 0000000 /* floating_shape.h -- Low-ish level window creation and management.
* Copyright (C) 2008 Nick Gasson
*
* 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 .
*/
#ifndef INC_FLOATING_SHAPE_H
#define INC_FLOATING_SHAPE_H
#include
#include
/*
* A widget type thing which used the XShape extension.
*/
typedef struct {
GtkWidget *window;
GtkWidget *image;
GdkPixbuf *pixbuf;
GdkDrawable *mask_bitmap;
int x, y, width, height;
} float_shape_t;
float_shape_t *make_shape_from_pixbuf(GdkPixbuf *pixbuf);
void move_shape(float_shape_t *shape, int x, int y);
void show_shape(float_shape_t *shape);
void hide_shape(float_shape_t *shape);
void destroy_shape(float_shape_t *shape);
#define shape_window(s) (s->window)
#define shape_x(s) (s->x)
#define shape_y(s) (s->y)
#define shape_width(s) (s->width)
#define shape_height(s) (s->height)
#endif
xcowsay-1.3/xcowsay.6 0000644 0001750 0001750 00000011151 11465272274 011570 0000000 0000000 .\" man page for xcowsay
.TH "xcowsay" 6
.SH NAME
xcowsay \- Display a cute cow and speech bubble.
.SH SYNOPSIS
.B xcowsay
.RB [ "-h" ]
.RB [ "-t"
.RI \| time \|]
.RB [ "-r"
.RI \| speed \|]
.RB [ "-d" ]
.RB [ "-f"
.RI \| font \|]
.RI [\| text \|]...
.SH DESCRIPTION
Display a cow with a speech bubble containing some text. If
.I text
is specified it will be displayed in the bubble. Otherwise the text
will be read from the standard input and displayed when end of file
is encountered.
The cow is displayed for either a fixed amount of time, or an amount
of time calculated from the size of the text. Click on the cow to
dismiss it immediately.
If
.B xcowsay
is started with
.B "--daemon"
it will fork away from the terminal and run in daemon mode. The
daemon provides a DBus service
.B uk.me.doof.Cowsay
that responds to
.B ShowCow
requests. The daemon can queue up any number of requests and displays
them in order.
When
.B xcowsay
starts it checks to see if a daemon is running, and if it is, sends a
.B ShowCow
request and returns immediately. Otherwise
.B xcowsay
will block until the cow has disappeared.
.SH CONFIGURATION FILE
xcowsay reads a configuration file on startup. The configuration file
can be stored in the XDG compliant location
.I $XDG_CONFIG_HOME/xcowsayrc
(which will default to
.IR $HOME/.config/xcowsayrc )
or in your home directory at
.IR $HOME/.xcowsayrc .
If the
.BI --config= FILE
command line option is passed
.I FILE
will be processed after your personal configuration file.
The configuration file consists of 'option = value' pairs, one per line. The
valid keys are given in the next section. For example, the following line sets
display time to 10 seconds:
.PP
.RS
display_time = 10000
.RE
.PP
The character '#' begins a comment which lasts until the end of the line.
.SH OPTIONS
Note that these options override any settings in the config file.
.TP
.B "-h, --help"
Display usage information.
.TP
.BI "-t " time ", --time=" time
Display the cow for
.I time
seconds. This overrides any value set for
.IR reading_speed .
Setting
.I time
to zero displays the cow until it is clicked.
The corresponding config file option is
.IR display_time .
.TP
.BI "-r " speed ", --reading-speed=" speed
Number of milliseconds to display the cow for each word in the input
text. This is clamped to a minimum of
.I min_display_time
and a maximum of
.IR max_display_time .
The defaults are 1 second and 30 seconds respectively. The corresponding
config file option is
.IR reading_speed .
.TP
.BI "-f " font ", --font=" font
Font for the speech bubble text. Accepts Pango font strings. The
corresponding config file option is
.IR font .
.TP
.BI "-d " file ", --dream=" file
Display an image instead of text in the cow's bubble. The
.I dream_time
config file option sets the numer of milliseconds to display the
image for. The default is 10 seconds.
.TP
.B "--think"
Display a thought bubble instead of a speech bubble.
.TP
.B "--daemon"
Run xcowsay in daemon mode if DBus support has been enabled. See the
description for more information.
.TP
.BI "--cow-size=" size
Size of the cow image. Current choices are
.BR small ", " med ", or " large .
The corresponding config file option is
.IR cow_size .
.TP
.BI "--image=" file
Use a different image instead of the cow. The corresponding config file
option is
.IR alt_image .
.TP
.BI "--monitor=" N
Make the cow appear on monitor N.
.TP
.BI "--at=" X,Y
Force that cow to appear at screen location (X,Y). The config file options
are
.I at_x
and
.IR at_y .
.TP
.BI "--bubble-at=" X,Y
Change position of bubble relative to where it would normally appear. This
is most useful when combined with the
.I alt_image
option to create your own characters. The config file options are
.I bubble_x
and
.IR bubble_y .
.TP
.B "--no-wrap"
Disable word wrapping when the bubble is too wide to fit on the screen.
The config file option
.I wrap
can be set to
.I true
or
.I false
to set this explicitly.
.TP
.B "-l, --left"
Make the bubble appear on the left hand side of the cow. This is useful
if you are using your own image.
.TP
.B "--debug"
Print messages about what
.B xcowsay
is doing. Useful for finding out why the daemon fails.
.TP
.B "-v, --version"
Print version information.
.SH "AUTHOR"
Written by Nick Gasson.
.SH "REPORTING BUGS"
Report all bugs to nick@nickg.me.uk
.BR
The xcowsay home page is
.SH "SEE ALSO"
.BR cowsay (6)
.SH BUGS
The cow and speech bubble have jagged edges which would be improved by
anti-aliasing. Unfortunately this isn't possible without a compositing
window manager since X can only cut holes in windows using a binary
mask, so I wouldn't expect this any time soon.
xcowsay-1.3/AUTHORS 0000644 0001750 0001750 00000000232 11062526715 011045 0000000 0000000 This was all written by:
Nick Gasson
The pt_BR translation was made by:
Phantom X
xcowsay-1.3/cow_med.png 0000644 0001750 0001750 00000035240 11022570537 012124 0000000 0000000 PNG
IHDR V D sRGB bKGD C pHYs tIME)7" IDATx{\MǟN"TrP 0cdC$anT&_ȸafjJcT眽9{^8{^뽟g=D"H$D"H$D"H$D"H$fJD")*DD!U8@CRo"H (,,8|0AAABfƌ&&&e H$CoرcW0k,ذab+D"
Ԍ]vD"?BƍW+Db%%%yfo!77W9::'M6+D"1RݻM4,\De.[\\\Xj+aȑPRRH`%H@E xpvvkBYY~:̟?˘J"4J-..@puusv;wBTTFÕ|$^v.26y&L:tz
~k:3f<_ze ..N0υH
R)D8fӫ椘iXRR2TD"C~֘hmm3,0'OpҥجY3NaZSiԨN4 ?`̙3
tuN^]ts R
P/>]\\j