From e15e962928fc43c414f2078986be902eb3a52190 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Sun, 16 Dec 2007 01:50:41 +0000 Subject: [PATCH] * Implement caca_create_display_with_driver() to specify an output driver without using environment variables.. * Implement caca_get_display_driver() to return the current display's output driver. * Add a simple example program to test caca_create_display_with_driver(). --- caca/caca.c | 74 +++++++++++++++++++++++++++++++++++-------- caca/caca.h | 5 ++- caca/caca_internals.h | 3 +- caca/driver_cocoa.m | 3 +- caca/driver_conio.c | 3 +- caca/driver_gl.c | 3 +- caca/driver_ncurses.c | 3 +- caca/driver_raw.c | 3 +- caca/driver_slang.c | 3 +- caca/driver_vga.c | 3 +- caca/driver_win32.c | 3 +- caca/driver_x11.c | 3 +- caca/event.c | 4 +-- examples/.gitignore | 1 + examples/Makefile.am | 5 ++- examples/driver.c | 71 +++++++++++++++++++++++++++++++++++++++++ 16 files changed, 163 insertions(+), 27 deletions(-) create mode 100644 examples/driver.c diff --git a/caca/caca.c b/caca/caca.c index a81a6fe..eee78f3 100644 --- a/caca/caca.c +++ b/caca/caca.c @@ -37,12 +37,12 @@ #include "caca_internals.h" #if defined(USE_PLUGINS) -# define gl_install(p) caca_plugin_install("gl", p) -# define x11_install(p) caca_plugin_install("x11", p) +# define gl_install(p) caca_plugin_install(p, "gl") +# define x11_install(p) caca_plugin_install(p, "x11") #endif static int caca_can_resize(caca_display_t *); -static int caca_select_driver(caca_display_t *); +static int caca_select_driver(caca_display_t *, char const *); #if defined(USE_PLUGINS) static int caca_plugin_install(char const *, caca_display_t *); #endif @@ -58,14 +58,44 @@ static int caca_plugin_install(char const *, caca_display_t *); * retrieved using caca_get_canvas() and it is automatically destroyed when * caca_free_display() is called. * + * See also caca_create_display_with_driver(). + * * If an error occurs, NULL is returned and \b errno is set accordingly: * - \c ENOMEM Not enough memory. * - \c ENODEV Graphical device could not be initialised. * - * \param cv The cucul cavas. + * \param cv The cucul canvas or NULL to create a canvas automatically. * \return The caca graphical context or NULL if an error occurred. */ caca_display_t * caca_create_display(cucul_canvas_t *cv) +{ + return caca_create_display_with_driver(cv, NULL); +} + +/** \brief Attach a caca graphical context to a cucul canvas. + * + * Create a graphical context using device-dependent features (ncurses for + * terminals, an X11 window, a DOS command window...) that attaches to a + * libcucul canvas. Everything that gets drawn in the libcucul canvas can + * then be displayed by the libcaca driver. + * + * If no cucul canvas is provided, a new one is created. Its handle can be + * retrieved using caca_get_canvas() and it is automatically destroyed when + * caca_free_display() is called. + * + * See also caca_create_display(). + * + * If an error occurs, NULL is returned and \b errno is set accordingly: + * - \c ENOMEM Not enough memory. + * - \c ENODEV Graphical device could not be initialised. + * + * \param cv The cucul canvas or NULL to create a canvas automatically. + * \param driver A string describing the desired output driver or NULL to + * choose the best driver automatically. + * \return The caca graphical context or NULL if an error occurred. + */ +caca_display_t * caca_create_display_with_driver(cucul_canvas_t *cv, + char const *driver) { caca_display_t *dp = malloc(sizeof(caca_display_t)); @@ -95,7 +125,7 @@ caca_display_t * caca_create_display(cucul_canvas_t *cv) dp->plugin = NULL; #endif - if(caca_select_driver(dp)) + if(caca_select_driver(dp, driver)) { #if defined(USE_PLUGINS) if(dp->plugin) @@ -154,6 +184,20 @@ caca_display_t * caca_create_display(cucul_canvas_t *cv) return dp; } +/** \brief Return the current output driver + * + * Return the given display's current output driver. + * + * This function never fails. + * + * \param dp The caca display. + * \return A static string. + */ +char const * caca_get_display_driver(caca_display_t *dp) +{ + return dp->drv.driver; +} + /** \brief Detach a caca graphical context from a cucul backend context. * * Detach a graphical context from its cucul backend and destroy it. The @@ -223,7 +267,7 @@ char const * caca_get_version(void) * \param dp Display object. * \return An array of strings. */ -char const * const * caca_get_display_driver_list(caca_display_t *dp) +char const * const * caca_get_display_driver_list(void) { static char const * const list[] = { @@ -269,11 +313,15 @@ static int caca_can_resize(caca_display_t *dp) return dp->resize.allow; } -static int caca_select_driver(caca_display_t *dp) +static int caca_select_driver(caca_display_t *dp, char const *driver) { -#if defined(HAVE_GETENV) && defined(HAVE_STRCASECMP) - char *var = getenv("CACA_DRIVER"); + char const *var = driver; +#if defined(HAVE_GETENV) + if(!var) + var = getenv("CACA_DRIVER"); +#endif +#if defined(HAVE_STRCASECMP) /* If the environment variable was set, use it */ if(var && *var) { @@ -339,22 +387,22 @@ static int caca_select_driver(caca_display_t *dp) } #if defined(USE_PLUGINS) -static int caca_plugin_install(char const *name, caca_display_t *dp) +static int caca_plugin_install(caca_display_t *dp, char const *driver) { char buf[512]; int (*sym) (caca_display_t *); - sprintf(buf, "%s/lib%s_plugin.so", PLUGINDIR, name); + sprintf(buf, "%s/lib%s_plugin.so", PLUGINDIR, driver); dp->plugin = dlopen(buf, RTLD_NOW); if(!dp->plugin) { - sprintf(buf, "lib%s_plugin.so", name); + sprintf(buf, "lib%s_plugin.so", driver); dp->plugin = dlopen(buf, RTLD_NOW); if(!dp->plugin) return -1; } - sprintf(buf, "%s_install", name); + sprintf(buf, "%s_install", driver); sym = dlsym(dp->plugin, buf); if(!sym) { diff --git a/caca/caca.h b/caca/caca.h index ad1da9d..99afff2 100644 --- a/caca/caca.h +++ b/caca/caca.h @@ -154,10 +154,13 @@ enum caca_key * * @{ */ __extern caca_display_t * caca_create_display(cucul_canvas_t *); +__extern caca_display_t * caca_create_display_with_driver(cucul_canvas_t *, + char const *); +__extern char const * caca_get_display_driver(caca_display_t *); __extern int caca_free_display(caca_display_t *); __extern cucul_canvas_t * caca_get_canvas(caca_display_t *); __extern int caca_refresh_display(caca_display_t *); -__extern char const * const * caca_get_display_driver_list(caca_display_t *); +__extern char const * const * caca_get_display_driver_list(void); __extern int caca_set_display_time(caca_display_t *, unsigned int); __extern unsigned int caca_get_display_time(caca_display_t const *); __extern unsigned int caca_get_display_width(caca_display_t const *); diff --git a/caca/caca_internals.h b/caca/caca_internals.h index a06ef04..34bece9 100644 --- a/caca/caca_internals.h +++ b/caca/caca_internals.h @@ -117,7 +117,8 @@ struct caca_display /* Device-specific functions */ struct drv { - enum caca_driver driver; + char const * driver; + enum caca_driver id; struct driver_private *p; int (* init_graphics) (caca_display_t *); diff --git a/caca/driver_cocoa.m b/caca/driver_cocoa.m index 9377822..c651374 100644 --- a/caca/driver_cocoa.m +++ b/caca/driver_cocoa.m @@ -997,7 +997,8 @@ static void cocoa_set_mouse(caca_display_t *dp, int flag) int cocoa_install(caca_display_t *dp) { - dp->drv.driver = CACA_DRIVER_RAW; + dp->drv.id = CACA_DRIVER_COCOA; + dp->drv.driver = "cocoa"; dp->drv.init_graphics = cocoa_init_graphics; dp->drv.end_graphics = cocoa_end_graphics; diff --git a/caca/driver_conio.c b/caca/driver_conio.c index f3adb89..5527c04 100644 --- a/caca/driver_conio.c +++ b/caca/driver_conio.c @@ -166,7 +166,8 @@ static int conio_get_event(caca_display_t *dp, caca_privevent_t *ev) int conio_install(caca_display_t *dp) { - dp->drv.driver = CACA_DRIVER_CONIO; + dp->drv.id = CACA_DRIVER_CONIO; + dp->drv.driver = "conio"; dp->drv.init_graphics = conio_init_graphics; dp->drv.end_graphics = conio_end_graphics; diff --git a/caca/driver_gl.c b/caca/driver_gl.c index 1e2472c..e49dafc 100644 --- a/caca/driver_gl.c +++ b/caca/driver_gl.c @@ -597,7 +597,8 @@ int gl_install(caca_display_t *dp) return -1; #endif - dp->drv.driver = CACA_DRIVER_GL; + dp->drv.id = CACA_DRIVER_GL; + dp->drv.driver = "gl"; dp->drv.init_graphics = gl_init_graphics; dp->drv.end_graphics = gl_end_graphics; diff --git a/caca/driver_ncurses.c b/caca/driver_ncurses.c index 96f1a60..a4b1c79 100644 --- a/caca/driver_ncurses.c +++ b/caca/driver_ncurses.c @@ -808,7 +808,8 @@ static void ncurses_write_utf32(uint32_t ch) int ncurses_install(caca_display_t *dp) { - dp->drv.driver = CACA_DRIVER_NCURSES; + dp->drv.id = CACA_DRIVER_NCURSES; + dp->drv.driver = "ncurses"; dp->drv.init_graphics = ncurses_init_graphics; dp->drv.end_graphics = ncurses_end_graphics; diff --git a/caca/driver_raw.c b/caca/driver_raw.c index c1da860..5777edc 100644 --- a/caca/driver_raw.c +++ b/caca/driver_raw.c @@ -97,7 +97,8 @@ static int raw_get_event(caca_display_t *dp, caca_privevent_t *ev) int raw_install(caca_display_t *dp) { - dp->drv.driver = CACA_DRIVER_RAW; + dp->drv.id = CACA_DRIVER_RAW; + dp->drv.driver = "raw"; dp->drv.init_graphics = raw_init_graphics; dp->drv.end_graphics = raw_end_graphics; diff --git a/caca/driver_slang.c b/caca/driver_slang.c index 786239d..ac5869c 100644 --- a/caca/driver_slang.c +++ b/caca/driver_slang.c @@ -522,7 +522,8 @@ static void slang_check_terminal(void) int slang_install(caca_display_t *dp) { - dp->drv.driver = CACA_DRIVER_SLANG; + dp->drv.id = CACA_DRIVER_SLANG; + dp->drv.driver = "slang"; dp->drv.init_graphics = slang_init_graphics; dp->drv.end_graphics = slang_end_graphics; diff --git a/caca/driver_vga.c b/caca/driver_vga.c index 48a648e..0e6d27b 100644 --- a/caca/driver_vga.c +++ b/caca/driver_vga.c @@ -159,7 +159,8 @@ static int vga_get_event(caca_display_t *dp, caca_privevent_t *ev) int vga_install(caca_display_t *dp) { - dp->drv.driver = CACA_DRIVER_VGA; + dp->drv.id = CACA_DRIVER_VGA; + dp->drv.driver = "vga"; dp->drv.init_graphics = vga_init_graphics; dp->drv.end_graphics = vga_end_graphics; diff --git a/caca/driver_win32.c b/caca/driver_win32.c index d2b5e4e..30442f4 100644 --- a/caca/driver_win32.c +++ b/caca/driver_win32.c @@ -349,7 +349,8 @@ static int win32_get_event(caca_display_t *dp, caca_privevent_t *ev) int win32_install(caca_display_t *dp) { - dp->drv.driver = CACA_DRIVER_WIN32; + dp->drv.id = CACA_DRIVER_WIN32; + dp->drv.driver = "win32"; dp->drv.init_graphics = win32_init_graphics; dp->drv.end_graphics = win32_end_graphics; diff --git a/caca/driver_x11.c b/caca/driver_x11.c index 7051105..007874a 100644 --- a/caca/driver_x11.c +++ b/caca/driver_x11.c @@ -789,7 +789,8 @@ int x11_install(caca_display_t *dp) return -1; #endif - dp->drv.driver = CACA_DRIVER_X11; + dp->drv.id = CACA_DRIVER_X11; + dp->drv.driver = "x11"; dp->drv.init_graphics = x11_init_graphics; dp->drv.end_graphics = x11_end_graphics; diff --git a/caca/event.c b/caca/event.c index 8f2f1df..5f4b841 100644 --- a/caca/event.c +++ b/caca/event.c @@ -344,10 +344,10 @@ static int _get_next_event(caca_display_t *dp, caca_privevent_t *ev) ret = _lowlevel_event(dp, ev); #if defined(USE_SLANG) - if(dp->drv.driver != CACA_DRIVER_SLANG) + if(dp->drv.id != CACA_DRIVER_SLANG) #endif #if defined(USE_NCURSES) - if(dp->drv.driver != CACA_DRIVER_NCURSES) + if(dp->drv.id != CACA_DRIVER_NCURSES) #endif return ret; diff --git a/examples/.gitignore b/examples/.gitignore index 620262e..e039596 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -4,6 +4,7 @@ cucul demo demo0 dithering +driver event export figfont diff --git a/examples/Makefile.am b/examples/Makefile.am index 3699ac5..f931a24 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -2,7 +2,7 @@ AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/cucul -I$(top_srcdir)/caca -DDATADIR=\"$(pkgdatadir)\" -noinst_PROGRAMS = blit colors cucul demo demo0 dithering event export figfont font font2tga frames fullwidth gamma hsv input spritedit swallow text transform truecolor unicode import +noinst_PROGRAMS = blit colors cucul demo demo0 dithering driver event export figfont font font2tga frames fullwidth gamma hsv input spritedit swallow text transform truecolor unicode import blit_SOURCES = blit.c blit_LDADD = ../caca/libcaca.la ../cucul/libcucul.la @@ -24,6 +24,9 @@ demo0_LDFLAGS = @MATH_LIBS@ dithering_SOURCES = dithering.c dithering_LDADD = ../caca/libcaca.la ../cucul/libcucul.la +driver_SOURCES = driver.c +driver_LDADD = ../caca/libcaca.la ../cucul/libcucul.la + event_SOURCES = event.c event_LDADD = ../caca/libcaca.la ../cucul/libcucul.la diff --git a/examples/driver.c b/examples/driver.c new file mode 100644 index 0000000..afaf050 --- /dev/null +++ b/examples/driver.c @@ -0,0 +1,71 @@ +/* + * driver libcaca Unicode rendering test program + * Copyright (c) 2007 Sam Hocevar + * All Rights Reserved + * + * $Id$ + * + * This program is free software. It comes without any warranty, to + * the extent permitted by applicable law. You can redistribute it + * and/or modify it under the terms of the Do What The Fuck You Want + * To Public License, Version 2, as published by Sam Hocevar. See + * http://sam.zoy.org/wtfpl/COPYING for more details. + */ + +#include "config.h" +#include "common.h" + +#if !defined(__KERNEL__) +# include +#endif + +#include "cucul.h" +#include "caca.h" + +int main(int argc, char *argv[]) +{ + char const * const * list; + caca_display_t *dp; + cucul_canvas_t *cv; + + list = caca_get_display_driver_list(); + if(argc <= 1) + { + printf("Available drivers:\n"); + + while(*list) + { + printf(" %s (%s)\n", list[0], list[1]); + list += 2; + } + + return 0; + } + + cv = cucul_create_canvas(0, 0); + if(cv == NULL) + { + printf("cannot create canvas\n"); + return -1; + } + dp = caca_create_display_with_driver(cv, argv[1]); + if(dp == NULL) + { + printf("cannot create display\n"); + return -1; + } + + cucul_set_color_ansi(cv, CUCUL_WHITE, CUCUL_BLUE); + cucul_draw_line(cv, 0, 0, 9999, 0, ' '); + cucul_printf(cv, 1, 0, "Current driver: %s", argv[1]); + + caca_refresh_display(dp); + + caca_get_event(dp, CACA_EVENT_KEY_PRESS, NULL, -1); + + caca_free_display(dp); + cucul_free_canvas(cv); + + return 0; +} +