From c95ef32a700132a134f335f857ca6f1b6f3c169f Mon Sep 17 00:00:00 2001 From: Arun Persaud Date: Tue, 30 Mar 2010 20:24:49 -0700 Subject: [PATCH] adding gnu-readline support should make the user interface for xboard a bit nicer. In the end we want to have a separate input window, but this probably will have to wait until the GTK version. --- Makefile.am | 2 +- backend.c | 15 ++++- configure.ac | 24 +++++++- xboard.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 195 insertions(+), 27 deletions(-) diff --git a/Makefile.am b/Makefile.am index fba80a8..a669994 100644 --- a/Makefile.am +++ b/Makefile.am @@ -30,7 +30,7 @@ xboard_SOURCES = backend.c backend.h backendz.h \ filebrowser/draw.c filebrowser/path.c \ filebrowser/dir.c filebrowser/xstat.h \ $(ZPY) -xboard_LDADD = -lm @XAW_LIBS@ @X_LIBS@ +xboard_LDADD = -lm @XAW_LIBS@ @X_LIBS@ @LIBREADLINE@ EXTRA_DIST = pixmaps bitmaps winboard sounds filebrowser/README \ xboard.texi gpl.texinfo texi2man texinfo.tex xboard.man \ diff --git a/backend.c b/backend.c index f936459..eed8bff 100644 --- a/backend.c +++ b/backend.c @@ -449,7 +449,11 @@ int adjudicateLossPlies = 6; char white_holding[64], black_holding[64]; TimeMark lastNodeCountTime; long lastNodeCount=0; + int have_sent_ICS_logon = 0; +int sending_ICS_login = 0; +int sending_ICS_password = 0; + int movesPerSession; int suddenDeath, whiteStartMove, blackStartMove; /* [HGM] for implementation of 'any per time' sessions, as in first part of byoyomi TC */ long whiteTimeRemaining, blackTimeRemaining, timeControl, timeIncrement, lastWhite, lastBlack; @@ -3108,10 +3112,17 @@ read_from_ics(isr, closure, data, count, error) if (!have_sent_ICS_logon && looking_at(buf, &i, "login:")) { ICSInitScript(); have_sent_ICS_logon = 1; + sending_ICS_password = 0; // in case we come back to login + sending_ICS_login = 1; continue; } - - if (ics_getting_history != H_GETTING_MOVES /*smpos kludge*/ && + /* need to shadow the password */ + if (!sending_ICS_password && looking_at(buf, &i, "password:")) { + sending_ICS_password = 1; + continue; + } + + if (ics_getting_history != H_GETTING_MOVES /*smpos kludge*/ && (looking_at(buf, &i, "\n<12> ") || looking_at(buf, &i, "<12> "))) { loggedOn = TRUE; diff --git a/configure.ac b/configure.ac index 712c250..64844e1 100644 --- a/configure.ac +++ b/configure.ac @@ -61,7 +61,6 @@ AH_TEMPLATE([USE_XAW3D],[template]) AH_TEMPLATE([X_LOCALE],[template]) - if test -z "$CFLAGS" ; then dnl| Prevent the next macro from setting CFLAGS to -g CFLAGS=" " @@ -164,6 +163,28 @@ if test "$xaw_headers" = "no" ; then fi +dnl | test for readline +AC_ARG_WITH([readline], + [AS_HELP_STRING([--with-readline], + [support fancy command line editing @<:@default=yes@:>@]) + ], + [], + [with_readline=yes]) + +LIBREADLINE= +AS_IF([test "x$with_readline" != xno], + [AC_CHECK_LIB([readline], [main], + [AC_SUBST([LIBREADLINE], ["-lreadline "]) + AC_DEFINE([HAVE_LIBREADLINE], [1], + [Define if you have libreadline]) + ], + [if test "x$with_readline" != xyes; then + AC_MSG_FAILURE( + [--with-readline was given, but test for readline failed]) + fi + ], "")]) + + AC_CANONICAL_HOST dnl| The following info is mostly gathered from GNU Emacs 19.24. Basically, @@ -441,6 +462,7 @@ echo " infodir: $infodir (info files will go here)" echo " sysconfdir: $sysconfdir (xboard.conf will go here)" echo "" echo " Xaw3d: $with_xaw3d" +echo " readline: $with_readline" echo "" echo " xpm: $enable_xpm" echo " ptys: $enable_ptys" diff --git a/xboard.c b/xboard.c index 9a073d0..0f12af6 100644 --- a/xboard.c +++ b/xboard.c @@ -141,6 +141,12 @@ extern char *getenv(); # endif #endif + +# if HAVE_LIBREADLINE /* add gnu-readline support */ +#include +#include +# endif + #include #include #include @@ -468,6 +474,11 @@ void SettingsPopDown P(()); void update_ics_width P(()); int get_term_width P(()); int CopyMemoProc P(()); + +# if HAVE_LIBREADLINE /* add gnu-readline support */ +static void ReadlineCompleteHandler P((char *)); +# endif + /* * XBoard depends on Xt R4 or higher */ @@ -503,6 +514,13 @@ FileProc fileProc; char *fileOpenMode; char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion +# if HAVE_LIBREADLINE /* gnu readline support */ +static char* readline_buffer; +static int readline_complete=0; +extern int sending_ICS_login; +extern int sending_ICS_password; +#endif + Position commentX = -1, commentY = -1; Dimension commentW, commentH; typedef unsigned int BoardSize; @@ -1773,6 +1791,12 @@ main(argc, argv) setbuf(stdout, NULL); setbuf(stderr, NULL); debugFP = stderr; + +# if HAVE_LIBREADLINE + /* install gnu-readline handler */ + rl_callback_handler_install("> ", ReadlineCompleteHandler); + rl_readline_name="XBoard"; +# endif if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) { printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION); @@ -2596,6 +2620,13 @@ ShutDownFrontEnd() if (saveSettingsOnExit) SaveSettings(settingsFileName); unlink(gameCopyFilename); unlink(gamePasteFilename); + +# if HAVE_LIBREADLINE + /* remove gnu-readline handler. */ + rl_callback_handler_remove(); +#endif + + return; } RETSIGTYPE TermSizeSigHandler(int sig) @@ -8075,16 +8106,97 @@ DoInputCallback(closure, source, xid) } q = is->buf; while (p < is->unused) { - *q++ = *p++; + *q++ = *p++; } is->unused = q; } else { - count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE); - if (count == -1) - error = errno; - else - error = 0; - (is->func)(is, is->closure, is->buf, count, error); +# if HAVE_LIBREADLINE + /* check if input is from stdin, if yes, use gnu-readline */ + if( is->fd==fileno(stdin) ) + { + /* to clear the line */ + printf("\r \r"); + + /* read from stdin */ + rl_callback_read_char(); + /* redisplay the current line */ + if(sending_ICS_password) + { + int i; char buf[MSG_SIZ]; + + bzero(buf,MSG_SIZ); + + /* blank the password */ + count = strlen(rl_line_buffer); + if(count>MSG_SIZ-1) + { + printf("PROBLEM with readline\n"); + count=MSG_SIZ; + } + for(i=0;iINPUT_SOURCE_BUF_SIZE-1) + { + printf("PROBLEM with readline\n"); + count = INPUT_SOURCE_BUF_SIZE; + }; + strncpy(is->buf,readline_buffer,count); + is->buf[count]='\n';count++; + + /* reset gnu-readline state */ + free(readline_buffer); + readline_buffer=NULL; + readline_complete=0; + + if (count == -1) + error = errno; + else + error = 0; + (is->func)(is, is->closure, is->buf, count, error); + + /* are we done with the password? */ + if(sending_ICS_password) + sending_ICS_password=0; + if(sending_ICS_login) + sending_ICS_login=0; + } + } + else + { + /* input not from stdin, use default method */ + count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE); + if (count == -1) + error = errno; + else + error = 0; + (is->func)(is, is->closure, is->buf, count, error); + }; +#else /* no readline support */ + count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE); + if (count == -1) + error = errno; + else + error = 0; + (is->func)(is, is->closure, is->buf, count, error); +#endif + } } @@ -8140,28 +8252,36 @@ int OutputToProcess(pr, message, count, outError) ChildProc *cp = (ChildProc *) pr; int outCount; + if (pr == NoProc) { - if (appData.noJoin || !appData.useInternalWrap) - outCount = fwrite(message, 1, count, stdout); - else + if (appData.noJoin || !appData.useInternalWrap) + outCount = fwrite(message, 1, count, stdout); + else { - int width = get_term_width(); - int len = wrap(NULL, message, count, width, &line); - char *msg = malloc(len); - int dbgchk; - - if (!msg) - outCount = fwrite(message, 1, count, stdout); - else + int width = get_term_width(); + int len = wrap(NULL, message, count, width, &line); + char *msg = malloc(len); + int dbgchk; + + if (!msg) + outCount = fwrite(message, 1, count, stdout); + else { - dbgchk = wrap(msg, message, count, width, &line); - if (dbgchk != len && appData.debugMode) - fprintf(debugFP, "wrap(): dbgchk(%d) != len(%d)\n", dbgchk, len); - outCount = fwrite(msg, 1, dbgchk, stdout); - free(msg); + dbgchk = wrap(msg, message, count, width, &line); + if (dbgchk != len && appData.debugMode) + fprintf(debugFP, "wrap(): dbgchk(%d) != len(%d)\n", dbgchk, len); + outCount = fwrite(msg, 1, dbgchk, stdout); + free(msg); } } + +# if HAVE_LIBREADLINE + /* readline support */ + if(strlen(rl_line_buffer)) + printf("\n> %s",rl_line_buffer); +#endif + } else outCount = write(cp->fdTo, message, count); @@ -8964,3 +9084,18 @@ void NotifyFrontendLogin() { update_ics_width(); } + +# if HAVE_LIBREADLINE +static void +ReadlineCompleteHandler(char* ptr) +{ + /* make gnu-readline keep the history */ + readline_buffer = ptr; + readline_complete = 1; + + if (ptr && *ptr && !sending_ICS_password && !sending_ICS_login) + add_history(ptr); + + return; +} +#endif -- 1.7.0.4