X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=xboard.c;h=2e8a77385923e97db535d1f72986629c591909ae;hb=61351b21b01eacc91533169be0bc04d4a2dbf4a2;hp=abf3c26a9ccddb1b981ebb50ce45d3b0f79643a8;hpb=07212f7d822ece008518a1be189444a43abbba7a;p=xboard.git diff --git a/xboard.c b/xboard.c index abf3c26..2e8a773 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 @@ -242,6 +248,7 @@ RETSIGTYPE TermSizeSigHandler P((int sig)); void CreateGCs P((void)); void CreateXIMPieces P((void)); void CreateXPMPieces P((void)); +void CreateXPMBoard P((char *s, int n)); void CreatePieces P((void)); void CreatePieceMenus P((void)); Widget CreateMenuBar P((Menu *mb)); @@ -468,6 +475,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 +515,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; @@ -544,7 +563,8 @@ Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */ Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/ Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */ Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare; -int useImages, useImageSqs; +Pixmap xpmBoardBitmap[2]; +int useImages, useImageSqs, useTexture, textureW[2], textureH[2]; XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */ Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */ Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */ @@ -1061,8 +1081,9 @@ char globalTranslations[] = \"Send to second chess program:\",,2) \n"; char boardTranslations[] = - ": HandleUserMove() \n \ - : HandleUserMove() \n \ + ": HandleUserMove(0) \n \ + Shift: HandleUserMove(1) \n \ + : HandleUserMove(0) \n \ : AnimateUserMove() \n \ : HandlePV() \n \ : PieceMenuPopup(menuB) \n \ @@ -1710,6 +1731,10 @@ void InitDrawingSizes(BoardSize boardSize, int flags) xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver]; } #endif + if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) { + xpmPieceBitmap[i][(int)WhiteAngel] = xpmPieceBitmap2[i][(int)WhiteFalcon]; + xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteAlfil]; + } #if !HAVE_LIBXPM // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used! for(p=0; p<=(int)WhiteKing; p++) @@ -1726,6 +1751,10 @@ void InitDrawingSizes(BoardSize boardSize, int flags) ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver]; } #endif + if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) { + ximMaskPm[(int)WhiteAngel] = ximMaskPm2[(int)WhiteFalcon]; + ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteAlfil]; + } #endif } } else { @@ -1745,6 +1774,10 @@ void InitDrawingSizes(BoardSize boardSize, int flags) pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver]; } #endif + if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) { + pieceBitmap[i][(int)WhiteAngel] = pieceBitmap2[i][(int)WhiteFalcon]; + pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteAlfil]; + } } } #if HAVE_LIBXPM @@ -1773,6 +1806,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); @@ -1942,6 +1981,7 @@ XBoard square size (hint): %d\n\ fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize); } } + if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap; /* [HR] height treated separately (hacked) */ boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap); @@ -2518,6 +2558,8 @@ XBoard square size (hint): %d\n\ CreatePieces(); } else { CreateXPMPieces(); + CreateXPMBoard(appData.liteBackTextureFile, 1); + CreateXPMBoard(appData.darkBackTextureFile, 0); } #else CreateXIMPieces(); @@ -2596,6 +2638,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) @@ -2642,23 +2691,33 @@ CmailSigHandlerCallBack(isr, closure, message, count, error) void ICSInitScript() { - FILE *f; - char buf[MSG_SIZ]; - char *p; + /* try to open the icsLogon script, either in the location given + * or in the users HOME directory + */ + + FILE *f; + char buf[MSG_SIZ]; + char *homedir; - f = fopen(appData.icsLogon, "r"); - if (f == NULL) { - p = getenv("HOME"); - if (p != NULL) { - safeStrCpy(buf, p, sizeof(buf)/sizeof(buf[0]) ); + f = fopen(appData.icsLogon, "r"); + if (f == NULL) + { + homedir = getenv("HOME"); + if (homedir != NULL) + { + safeStrCpy(buf, homedir, sizeof(buf)/sizeof(buf[0]) ); strncat(buf, "/", MSG_SIZ - strlen(buf) - 1); strncat(buf, appData.icsLogon, MSG_SIZ - strlen(buf) - 1); f = fopen(buf, "r"); } } - if (f != NULL) - ProcessICSInitScript(f); + if (f != NULL) + ProcessICSInitScript(f); + else + printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf); + + return; } void @@ -3358,6 +3417,16 @@ void CreateXIMPieces() } #if HAVE_LIBXPM +void CreateXPMBoard(char *s, int kind) +{ + XpmAttributes attr; + attr.valuemask = 0; + if(s == NULL || *s == 0 || *s == '*') return; + if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) { + useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height; + } +} + void CreateXPMPieces() { int piece, kind, r; @@ -4024,11 +4093,34 @@ ClearPremoveHighlights() SetPremoveHighlights(-1, -1, -1, -1); } -static void BlankSquare(x, y, color, piece, dest) - int x, y, color; +static int CutOutSquare(x, y, x0, y0, kind) + int x, y, *x0, *y0, kind; +{ + int W = BOARD_WIDTH, H = BOARD_HEIGHT; + int nx = x/(squareSize + lineGap), ny = y/(squareSize + lineGap); + *x0 = 0; *y0 = 0; + if(textureW[kind] < squareSize || textureH[kind] < squareSize) return 0; + if(textureW[kind] < W*squareSize) + *x0 = (textureW[kind] - squareSize) * nx/(W-1); + else + *x0 = textureW[kind]*nx / W + (textureW[kind] - W*squareSize) / (2*W); + if(textureH[kind] < H*squareSize) + *y0 = (textureH[kind] - squareSize) * ny/(H-1); + else + *y0 = textureH[kind]*ny / H + (textureH[kind] - H*squareSize) / (2*H); + return 1; +} + +static void BlankSquare(x, y, color, piece, dest, fac) + int x, y, color, fac; ChessSquare piece; Drawable dest; -{ +{ // [HGM] extra param 'fac' for forcing destination to (0,0) for copying to animation buffer + int x0, y0; + if (useImages && color != 2 && (useTexture & color+1) && CutOutSquare(x, y, &x0, &y0, color)) { + XCopyArea(xDisplay, xpmBoardBitmap[color], dest, wlPieceGC, x0, y0, + squareSize, squareSize, x*fac, y*fac); + } else if (useImages && useImageSqs) { Pixmap pm; switch (color) { @@ -4044,7 +4136,7 @@ static void BlankSquare(x, y, color, piece, dest) break; } XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0, - squareSize, squareSize, x, y); + squareSize, squareSize, x*fac, y*fac); } else { GC gc; switch (color) { @@ -4059,7 +4151,7 @@ static void BlankSquare(x, y, color, piece, dest) gc = jailSquareGC; break; } - XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize); + XFillRectangle(xDisplay, dest, gc, x*fac, y*fac, squareSize, squareSize); } } @@ -4152,7 +4244,7 @@ static void colorDrawPieceImage(piece, square_color, x, y, dest) int square_color, x, y; Drawable dest; { - int kind; + int kind, p = piece; switch (square_color) { case 1: /* light */ @@ -4174,6 +4266,15 @@ static void colorDrawPieceImage(piece, square_color, x, y, dest) } break; } + if(appData.upsideDown && flipView) kind ^= 2; // swap white and black pieces + if(useTexture & square_color+1) { + BlankSquare(x, y, square_color, piece, dest, 1); // erase previous contents with background + XSetClipMask(xDisplay, wlPieceGC, xpmMask[p]); + XSetClipOrigin(xDisplay, wlPieceGC, x, y); + XCopyArea(xDisplay, xpmPieceBitmap[kind][piece], dest, wlPieceGC, 0, 0, squareSize, squareSize, x, y); + XSetClipMask(xDisplay, wlPieceGC, None); + XSetClipOrigin(xDisplay, wlPieceGC, 0, 0); + } else XCopyArea(xDisplay, xpmPieceBitmap[kind][piece], dest, wlPieceGC, 0, 0, squareSize, squareSize, x, y); @@ -4255,7 +4356,7 @@ void DrawSquare(row, column, piece, do_flash) column == BOARD_LEFT-1 || column == BOARD_RGHT || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize) || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) { - BlankSquare(x, y, 2, EmptySquare, xBoardWindow); + BlankSquare(x, y, 2, EmptySquare, xBoardWindow, 1); // [HGM] print piece counts next to holdings string[1] = NULLCHAR; @@ -4287,7 +4388,7 @@ void DrawSquare(row, column, piece, do_flash) } } else { if (piece == EmptySquare || appData.blindfold) { - BlankSquare(x, y, square_color, piece, xBoardWindow); + BlankSquare(x, y, square_color, piece, xBoardWindow, 1); } else { drawfunc = ChooseDrawFunc(); if (do_flash && appData.flashCount > 0) { @@ -4297,7 +4398,7 @@ void DrawSquare(row, column, piece, do_flash) XSync(xDisplay, False); do_flash_delay(flash_delay); - BlankSquare(x, y, square_color, piece, xBoardWindow); + BlankSquare(x, y, square_color, piece, xBoardWindow, 1); XSync(xDisplay, False); do_flash_delay(flash_delay); } @@ -4609,6 +4710,7 @@ void HandleUserMove(w, event, prms, nprms) Cardinal *nprms; { if (w != boardWidget || errorExitStatus != -1) return; + if(nprms) shiftKey = !strcmp(prms[0], "1"); if (promotionUp) { if (event->type == ButtonPress) { @@ -5725,7 +5827,7 @@ SendPositionSelection(Widget w, Atom *selection, Atom *target, * automatically call XtFree on the value returned. So have to * make a copy of it allocated with XtMalloc */ selection_tmp= XtMalloc(strlen(selected_fen_position)+16); - safeStrCpy(selection_tmp, selected_fen_position, sizeof(selection_tmp)/sizeof(selection_tmp[0]) ); + safeStrCpy(selection_tmp, selected_fen_position, strlen(selected_fen_position)+16 ); *value_return=selection_tmp; *length_return=strlen(selection_tmp); @@ -8065,16 +8167,98 @@ 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, check special case for login and password */ + 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 + } } @@ -8130,28 +8314,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); @@ -8611,6 +8803,7 @@ OverlayPiece(piece, clip, outline, dest) kind = 0; else kind = 2; + if(appData.upsideDown && flipView) kind ^= 2; XCopyArea(xDisplay, xpmPieceBitmap[kind][piece], dest, clip, 0, 0, squareSize, squareSize, @@ -8630,7 +8823,7 @@ BeginAnimation(anim, piece, startColor, start) Pixmap mask; /* The old buffer is initialised with the start square (empty) */ - BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf); + BlankSquare(start->x, start->y, startColor, EmptySquare, anim->saveBuf, 0); anim->prevFrame = *start; /* The piece will be drawn using its own bitmap as a matte */ @@ -8735,6 +8928,29 @@ FrameSequence(anim, piece, startColor, start, finish, frames, nFrames) EndAnimation(anim, finish); } +void +AnimateAtomicCapture(Board board, int fromX, int fromY, int toX, int toY) +{ + int i, x, y; + ChessSquare piece = board[fromY][toY]; + board[fromY][toY] = EmptySquare; + DrawPosition(FALSE, board); + if (flipView) { + x = lineGap + ((BOARD_WIDTH-1)-toX) * (squareSize + lineGap); + y = lineGap + toY * (squareSize + lineGap); + } else { + x = lineGap + toX * (squareSize + lineGap); + y = lineGap + ((BOARD_HEIGHT-1)-toY) * (squareSize + lineGap); + } + for(i=1; i<4*kFactor; i++) { + int r = squareSize * 9 * i/(20*kFactor - 5); + XFillArc(xDisplay, xBoardWindow, highlineGC, + x + squareSize/2 - r, y+squareSize/2 - r, 2*r, 2*r, 0, 64*360); + FrameDelay(appData.animSpeed); + } + board[fromY][toY] = piece; +} + /* Main control logic for deciding what to animate and how */ void @@ -8766,7 +8982,7 @@ AnimateMove(board, fromX, fromY, toX, toY) #if DONT_HOP hop = FALSE; #else - hop = (piece == WhiteKnight || piece == BlackKnight); + hop = abs(fromX-toX) == 1 && abs(fromY-toY) == 2 || abs(fromX-toX) == 2 && abs(fromY-toY) == 1; #endif if (appData.debugMode) { @@ -8778,12 +8994,12 @@ AnimateMove(board, fromX, fromY, toX, toY) ScreenSquare(toX, toY, &finish, &endColor); if (hop) { - /* Knight: make diagonal movement then straight */ + /* Knight: make straight movement then diagonal */ if (abs(toY - fromY) < abs(toX - fromX)) { mid.x = start.x + (finish.x - start.x) / 2; - mid.y = finish.y; + mid.y = start.y; } else { - mid.x = finish.x; + mid.x = start.x; mid.y = start.y + (finish.y - start.y) / 2; } } else { @@ -8797,6 +9013,11 @@ AnimateMove(board, fromX, fromY, toX, toY) else Tween(&start, &mid, &finish, kFactor, frames, &nFrames); FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames); + if(Explode(board, fromX, fromY, toX, toY)) { // mark as damaged + int i,j; + for(i=0; i