From 9557d1bfae52bdf5f1706f0b5c5fc6080790791b Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Wed, 20 Aug 2003 04:19:01 +0000 Subject: [PATCH] Dlopen libncurses.so in wineconsole. --- configure | 130 ++++++++++++++++++++++++++ configure.ac | 2 + include/config.h.in | 6 ++ programs/wineconsole/Makefile.in | 1 - programs/wineconsole/curses.c | 151 +++++++++++++++++++++++++++++++ 5 files changed, 289 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 34acbcfe3b3..80734ea5999 100755 --- a/configure +++ b/configure @@ -12997,6 +12997,136 @@ cat >>confdefs.h <<_ACEOF #define SONAME_LIBCRYPTO "$ac_cv_lib_soname_crypto" _ACEOF fi + +echo "$as_me:$LINENO: checking for -lncurses soname" >&5 +echo $ECHO_N "checking for -lncurses soname... $ECHO_C" >&6 +if test "${ac_cv_lib_soname_ncurses+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_get_soname_save_LIBS=$LIBS +LIBS="-lncurses $LIBS" + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char waddch (); +int +main () +{ +waddch (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_soname_ncurses=`$ac_cv_path_LDD conftest$ac_exeext | grep libncurses\\.so | sed 's/^.*\(libncurses\.so[^ ]*\).*$/\1/'` + if test "x$ac_cv_lib_soname_ncurses" = "x" + then + ac_cv_lib_soname_ncurses="libncurses.so" + fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_soname_ncurses="libncurses.so" +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext + LIBS=$ac_get_soname_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_soname_ncurses" >&5 +echo "${ECHO_T}$ac_cv_lib_soname_ncurses" >&6 +if test "x$ac_cv_lib_soname_ncurses" != xNONE +then +cat >>confdefs.h <<_ACEOF +#define SONAME_LIBNCURSES "$ac_cv_lib_soname_ncurses" +_ACEOF +fi + +echo "$as_me:$LINENO: checking for -lcurses soname" >&5 +echo $ECHO_N "checking for -lcurses soname... $ECHO_C" >&6 +if test "${ac_cv_lib_soname_curses+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_get_soname_save_LIBS=$LIBS +LIBS="-lcurses $LIBS" + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char waddch (); +int +main () +{ +waddch (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_soname_curses=`$ac_cv_path_LDD conftest$ac_exeext | grep libcurses\\.so | sed 's/^.*\(libcurses\.so[^ ]*\).*$/\1/'` + if test "x$ac_cv_lib_soname_curses" = "x" + then + ac_cv_lib_soname_curses="libcurses.so" + fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_soname_curses="libcurses.so" +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext + LIBS=$ac_get_soname_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_soname_curses" >&5 +echo "${ECHO_T}$ac_cv_lib_soname_curses" >&6 +if test "x$ac_cv_lib_soname_curses" != xNONE +then +cat >>confdefs.h <<_ACEOF +#define SONAME_LIBCURSES "$ac_cv_lib_soname_curses" +_ACEOF +fi fi diff --git a/configure.ac b/configure.ac index 39496ac2d77..4035be4e733 100644 --- a/configure.ac +++ b/configure.ac @@ -923,6 +923,8 @@ then WINE_GET_SONAME(jack,jack_client_new) WINE_GET_SONAME(ssl,SSL_library_init) WINE_GET_SONAME(crypto,BIO_new_socket) + WINE_GET_SONAME(ncurses,waddch) + WINE_GET_SONAME(curses,waddch) fi diff --git a/include/config.h.in b/include/config.h.in index 5a68794f3b2..3fb7b2de0e7 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -755,6 +755,9 @@ /* Define to the soname of the libcups library. */ #undef SONAME_LIBCUPS +/* Define to the soname of the libcurses library. */ +#undef SONAME_LIBCURSES + /* Define to the soname of the libfreetype library. */ #undef SONAME_LIBFREETYPE @@ -764,6 +767,9 @@ /* Define to the soname of the libjack library. */ #undef SONAME_LIBJACK +/* Define to the soname of the libncurses library. */ +#undef SONAME_LIBNCURSES + /* Define to the soname of the libssl library. */ #undef SONAME_LIBSSL diff --git a/programs/wineconsole/Makefile.in b/programs/wineconsole/Makefile.in index 61d363ddf09..f03b71870d3 100644 --- a/programs/wineconsole/Makefile.in +++ b/programs/wineconsole/Makefile.in @@ -4,7 +4,6 @@ TOPOBJDIR = ../.. SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = wineconsole.exe -EXTRALIBS = @CURSESLIBS@ APPMODE = gui IMPORTS = advapi32 kernel32 ntdll DELAYIMPORTS = comctl32 user32 gdi32 diff --git a/programs/wineconsole/curses.c b/programs/wineconsole/curses.c index 0f9dedd308f..ec16e2b692e 100644 --- a/programs/wineconsole/curses.c +++ b/programs/wineconsole/curses.c @@ -30,6 +30,7 @@ */ #include "config.h" +#include "wine/port.h" #include #include @@ -44,6 +45,7 @@ #include #include "winecon_private.h" +#include "wine/library.h" #include "wine/server.h" #include "wine/debug.h" @@ -53,6 +55,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(wineconsole); #if defined(HAVE_CURSES_H) || defined(HAVE_NCURSES_H) +#ifdef HAVE_NCURSES_H + #define CURSES_NAME "ncurses" +#else + #define CURSES_NAME "curses" +#endif + struct inner_data_curse { mmask_t initial_mouse_mask; @@ -63,6 +71,146 @@ struct inner_data_curse }; +static void *nc_handle = NULL; + +#define MAKE_FUNCPTR(f) static typeof(f) * p_##f; + +MAKE_FUNCPTR(curs_set) +MAKE_FUNCPTR(delwin) +MAKE_FUNCPTR(endwin) +MAKE_FUNCPTR(getmouse) +MAKE_FUNCPTR(has_colors) +MAKE_FUNCPTR(init_pair) +#ifndef initscr +MAKE_FUNCPTR(initscr) +#endif +#ifndef intrflush +MAKE_FUNCPTR(intrflush) +#endif +MAKE_FUNCPTR(keypad) +MAKE_FUNCPTR(mouseinterval) +MAKE_FUNCPTR(mousemask) +MAKE_FUNCPTR(newpad) +#ifndef nodelay +MAKE_FUNCPTR(nodelay) +#endif +#ifndef noecho +MAKE_FUNCPTR(noecho) +#endif +MAKE_FUNCPTR(prefresh) +MAKE_FUNCPTR(raw) +MAKE_FUNCPTR(start_color) +MAKE_FUNCPTR(stdscr) +MAKE_FUNCPTR(waddchnstr) +MAKE_FUNCPTR(wmove) +MAKE_FUNCPTR(wgetch) + +#undef MAKE_FUNCPTR + +/**********************************************************************/ + +typedef struct { + LPVOID lpCallback; + LPVOID lpContext; +} DirectDrawEnumerateProcData; + +static BOOL WCCURSES_bind_libcurses(void) +{ +#ifdef HAVE_NCURSES_H + static const char *ncname = SONAME_LIBNCURSES; +#else + static const char *ncname = SONAME_LIBCURSES; +#endif + + nc_handle = wine_dlopen(ncname, RTLD_NOW, NULL, 0); + if(!nc_handle) + { + WINE_MESSAGE("Wine cannot find the " CURSES_NAME " library (%s).\n", + ncname); + return FALSE; + } + +#define LOAD_FUNCPTR(f) \ + if((p_##f = wine_dlsym(nc_handle, #f, NULL, 0)) == NULL) \ + { \ + WINE_WARN("Can't find symbol %s\n", #f); \ + goto sym_not_found; \ + } + + LOAD_FUNCPTR(curs_set) + LOAD_FUNCPTR(delwin) + LOAD_FUNCPTR(endwin) + LOAD_FUNCPTR(getmouse) + LOAD_FUNCPTR(has_colors) + LOAD_FUNCPTR(init_pair) +#ifndef initscr + LOAD_FUNCPTR(initscr) +#endif +#ifndef intrflush + LOAD_FUNCPTR(intrflush) +#endif + LOAD_FUNCPTR(keypad) + LOAD_FUNCPTR(mouseinterval) + LOAD_FUNCPTR(mousemask) + LOAD_FUNCPTR(newpad) +#ifndef nodelay + LOAD_FUNCPTR(nodelay) +#endif +#ifndef noecho + LOAD_FUNCPTR(noecho) +#endif + LOAD_FUNCPTR(prefresh) + LOAD_FUNCPTR(raw) + LOAD_FUNCPTR(start_color) + LOAD_FUNCPTR(stdscr) + LOAD_FUNCPTR(waddchnstr) + LOAD_FUNCPTR(wmove) + LOAD_FUNCPTR(wgetch) + +#undef LOAD_FUNCPTR + + return TRUE; + +sym_not_found: + WINE_MESSAGE( + "Wine cannot find certain functions that it needs inside the " + CURSES_NAME "\nlibrary. To enable Wine to use " CURSES_NAME + " please upgrade your " CURSES_NAME "\nlibraries\n"); + wine_dlclose(nc_handle, NULL, 0); + nc_handle = NULL; + return FALSE; +} + +#define curs_set p_curs_set +#define delwin p_delwin +#define endwin p_endwin +#define getmouse p_getmouse +#define has_colors p_has_colors +#define init_pair p_init_pair +#ifndef initscr +#define initscr p_initscr +#endif +#ifndef intrflush +#define intrflush p_intrflush +#endif +#define keypad p_keypad +#define mouseinterval p_mouseinterval +#define mousemask p_mousemask +#define newpad p_newpad +#ifndef nodelay +#define nodelay p_nodelay +#endif +#ifndef noecho +#define noecho p_noecho +#endif +#define prefresh p_prefresh +#define raw p_raw +#define start_color p_start_color +#define stdscr (*p_stdscr) +#define waddchnstr p_waddchnstr +#define wmove p_wmove +#define wgetch p_wgetch + /****************************************************************** * WCCURSES_ResizeScreenBuffer * @@ -719,6 +867,9 @@ static int WCCURSES_MainLoop(struct inner_data* data) */ enum init_return WCCURSES_InitBackend(struct inner_data* data) { + if( !WCCURSES_bind_libcurses() ) + return init_failed; + data->private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct inner_data_curse)); if (!data->private) return init_failed;