fprintf(debugFP, "%s\n", programVersion);
}
+ set_cont_sequence(appData.wrapContSeq);
if (appData.matchGames > 0) {
appData.matchMode = TRUE;
} else if (appData.matchMode) {
}
}
}
+
+static char cseq[12] = "\\ ";
+
+Boolean set_cont_sequence(char *new_seq)
+{
+ int len;
+ Boolean ret;
+
+ // handle bad attempts to set the sequence
+ if (!new_seq)
+ return 0; // acceptable error - no debug
+
+ len = strlen(new_seq);
+ ret = (len > 0) && (len < sizeof(cseq));
+ if (ret)
+ strcpy(cseq, new_seq);
+ else if (appData.debugMode)
+ fprintf(debugFP, "Invalid continuation sequence \"%s\" (maximum length is: %d)\n", new_seq, sizeof(cseq)-1);
+ return ret;
+}
+
+/*
+ reformat a source message so words don't cross the width boundary. internal
+ newlines are not removed. returns the wrapped size (no null character unless
+ included in source message). If dest is NULL, only calculate the size required
+ for the dest buffer. lp argument indicats line position upon entry, and it's
+ passed back upon exit.
+*/
+int wrap(char *dest, char *src, int count, int width, int *lp)
+{
+ int len, i, ansi, cseq_len, line, old_line, old_i, old_len, clen;
+
+ cseq_len = strlen(cseq);
+ old_line = line = *lp;
+ ansi = len = clen = 0;
+
+ for (i=0; i < count; i++)
+ {
+ if (src[i] == '\033')
+ ansi = 1;
+
+ // if we hit the width, back up
+ if (!ansi && (line >= width) && src[i] != '\n' && src[i] != ' ')
+ {
+ // store i & len in case the word is too long
+ old_i = i, old_len = len;
+
+ // find the end of the last word
+ while (i && src[i] != ' ' && src[i] != '\n')
+ {
+ i--;
+ len--;
+ }
+
+ // word too long? restore i & len before splitting it
+ if ((old_i-i+clen) >= width)
+ {
+ i = old_i;
+ len = old_len;
+ }
+
+ // extra space?
+ if (i && src[i-1] == ' ')
+ len--;
+
+ if (src[i] != ' ' && src[i] != '\n')
+ {
+ i--;
+ if (len)
+ len--;
+ }
+
+ // now append the newline and continuation sequence
+ if (dest)
+ dest[len] = '\n';
+ len++;
+ if (dest)
+ strncpy(dest+len, cseq, cseq_len);
+ len += cseq_len;
+ line = cseq_len;
+ clen = cseq_len;
+ continue;
+ }
+
+ if (dest)
+ dest[len] = src[i];
+ len++;
+ if (!ansi)
+ line++;
+ if (src[i] == '\n')
+ line = 0;
+ if (src[i] == 'm')
+ ansi = 0;
+ }
+ if (dest && appData.debugMode)
+ {
+ fprintf(debugFP, "wrap(count:%d,width:%d,line:%d,len:%d,*lp:%d,src: ",
+ count, width, line, len, *lp);
+ show_bytes(debugFP, src, count);
+ fprintf(debugFP, "\ndest: ");
+ show_bytes(debugFP, dest, len);
+ fprintf(debugFP, "\n");
+ }
+ *lp = dest ? line : old_line;
+
+ return len;
+}
extern char* StripHighlight P((char *)); /* returns static data */
extern char* StripHighlightAndTitle P((char *)); /* returns static data */
extern void ics_update_width P((int new_width));
+extern Boolean set_cont_sequence P((char *new_seq));
+extern int wrap P((char *dest, char *src, int count, int width, int *lp));
+
typedef enum { CheckBox, ComboBox, TextBox, Button, Spin, ResetButton,
SaveButton, FileName, PathName, Slider, Message } Control;
Boolean keepAlive; /* [HGM] alive */
Boolean forceIllegal;/*[HGM] illegal */
Boolean noJoin; /* [HGM] join */
+ char *wrapContSeq; /* continuation sequence when xboard wraps text */
+ Boolean useInternalWrap; /* use internal wrapping -- noJoin usurps this if set */
} AppData, *AppDataPtr;
/* [AS] PGN tags (for showing in the game list) */
{ "secondNPS", ArgInt, (LPVOID) &appData.secondNPS, FALSE },\r
{ "noGUI", ArgTrue, (LPVOID) &appData.noGUI, FALSE },\r
{ "keepLineBreaksICS", ArgBoolean, (LPVOID) &appData.noJoin, TRUE },\r
-\r
+ { "wrapContinuationSequence", ArgString, (LPVOID) &appData.wrapContSeq, FALSE },\r
+ { "useInternalWrap", ArgTrue, (LPVOID) &appData.useInternalWrap, FALSE }, /* noJoin usurps this if set */\r
+ \r
// [HGM] placement: put all window layouts last in ini file, but man X,Y before all others\r
{ "minX", ArgZ, (LPVOID) &minX, FALSE }, // [HGM] placement: to make suer auxialary windows can be placed\r
{ "minY", ArgZ, (LPVOID) &minY, FALSE },\r
}\r
}\r
\r
+int get_term_width()\r
+{\r
+ HDC hdc;\r
+ TEXTMETRIC tm;\r
+ RECT rc;\r
+ HFONT hfont, hold_font;\r
+ LOGFONT lf;\r
+ HWND hText;\r
+\r
+ if (hwndConsole)\r
+ hText = GetDlgItem(hwndConsole, OPT_ConsoleText);\r
+ else\r
+ return 79;\r
+\r
+ // get the text metrics\r
+ hdc = GetDC(hText);\r
+ lf = font[boardSize][CONSOLE_FONT]->lf;\r
+ if (consoleCF.dwEffects & CFE_BOLD)\r
+ lf.lfWeight = FW_BOLD;\r
+ if (consoleCF.dwEffects & CFE_ITALIC)\r
+ lf.lfItalic = TRUE;\r
+ if (consoleCF.dwEffects & CFE_STRIKEOUT)\r
+ lf.lfStrikeOut = TRUE;\r
+ if (consoleCF.dwEffects & CFE_UNDERLINE)\r
+ lf.lfUnderline = TRUE;\r
+ hfont = CreateFontIndirect(&lf);\r
+ hold_font = SelectObject(hdc, hfont);\r
+ GetTextMetrics(hdc, &tm);\r
+ SelectObject(hdc, hold_font);\r
+ DeleteObject(hfont);\r
+ ReleaseDC(hText, hdc);\r
+\r
+ // get the rectangle\r
+ SendMessage(hText, EM_GETRECT, 0, (LPARAM)&rc);\r
+\r
+ return (rc.right-rc.left) / tm.tmAveCharWidth;\r
+}\r
+\r
void UpdateICSWidth(HWND hText)\r
{\r
- HDC hdc;\r
- TEXTMETRIC tm;\r
- RECT rc;\r
- HFONT hfont, hold_font;\r
- LONG old_width, new_width;\r
- \r
- // get the text metrics\r
- hdc = GetDC(hText);\r
- hfont = CreateFontIndirect(&font[boardSize][CONSOLE_FONT]->lf);\r
- hold_font = SelectObject(hdc, hfont);\r
- GetTextMetrics(hdc, &tm);\r
- SelectObject(hdc, hold_font);\r
- DeleteObject(hfont);\r
- ReleaseDC(hText, hdc);\r
-\r
- // get the rectangle\r
- SendMessage(hText, EM_GETRECT, 0, (LPARAM)&rc);\r
-\r
- // update the width\r
- new_width = (rc.right-rc.left) / tm.tmAveCharWidth;\r
- old_width = GetWindowLong(hText, GWL_USERDATA);\r
- if (new_width != old_width)\r
- {\r
- ics_update_width(new_width);\r
- SetWindowLong(hText, GWL_USERDATA, new_width);\r
- }\r
+ LONG old_width, new_width;\r
+\r
+ new_width = get_term_width(hText, FALSE);\r
+ old_width = GetWindowLong(hText, GWL_USERDATA);\r
+ if (new_width != old_width)\r
+ {\r
+ ics_update_width(new_width);\r
+ SetWindowLong(hText, GWL_USERDATA, new_width);\r
+ }\r
}\r
\r
VOID\r
}\r
\r
// Allow hText to highlight URLs and send notifications on them\r
- wMask = SendMessage(hText, EM_GETEVENTMASK, 0, 0L);\r
+ wMask = (WORD) SendMessage(hText, EM_GETEVENTMASK, 0, 0L);\r
SendMessage(hText, EM_SETEVENTMASK, 0, wMask | ENM_LINK);\r
SendMessage(hText, EM_AUTOURLDETECT, TRUE, 0L);\r
SetWindowLong(hText, GWL_USERDATA, 79); // initialize the text window's width\r
}\r
}\r
\r
+int no_wrap(char *message, int count)\r
+{\r
+ ConsoleOutput(message, count, FALSE);\r
+ return count;\r
+}\r
\r
int\r
OutputToProcess(ProcRef pr, char *message, int count, int *outError)\r
int outCount = SOCKET_ERROR;\r
ChildProc *cp = (ChildProc *) pr;\r
static OVERLAPPED ovl;\r
+ static int line = 0;\r
\r
- if (pr == NoProc) {\r
- ConsoleOutput(message, count, FALSE);\r
- return count;\r
- } \r
+ if (pr == NoProc)\r
+ {\r
+ if (appData.noJoin || !appData.useInternalWrap)\r
+ return no_wrap(message, count);\r
+ else\r
+ {\r
+ int width = get_term_width();\r
+ int len = wrap(NULL, message, count, width, &line);\r
+ char *msg = malloc(len);\r
+ int dbgchk;\r
+\r
+ if (!msg)\r
+ return no_wrap(message, count);\r
+ else\r
+ {\r
+ dbgchk = wrap(msg, message, count, width, &line);\r
+ if (dbgchk != len && appData.debugMode)\r
+ fprintf(debugFP, "wrap(): dbgchk(%d) != len(%d)\n", dbgchk, len);\r
+ ConsoleOutput(msg, len, FALSE);\r
+ free(msg);\r
+ return len;\r
+ }\r
+ }\r
+ }\r
\r
if (ovl.hEvent == NULL) {\r
ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);\r
XtRImmediate, (XtPointer) False},
{ "keepLineBreaksICS", "keepLineBreaksICS", XtRBoolean,
sizeof(Boolean), XtOffset(AppDataPtr, noJoin),
+ XtRImmediate, (XtPointer) False},
+ { "wrapContinuationSequence", "wrapContinuationSequence", XtRString,
+ sizeof(String), XtOffset(AppDataPtr, wrapContSeq),
+ XtRString, ""},
+ { "useInternalWrap", "useInternalWrap", XtRBoolean,
+ sizeof(Boolean), XtOffset(AppDataPtr, useInternalWrap),
XtRImmediate, (XtPointer) True},
};
{ "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
{ "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
{ "-keepLineBreaksICS", "keepLineBreaksICS", XrmoptionSepArg, NULL },
+ { "-wrapContinuationSequence", "wrapContinuationSequence", XrmoptionSepArg, NULL },
+ { "-useInternalWrap", "useInternalWrap", XrmoptionSepArg, NULL },
};
-
XtActionsRec boardActions[] = {
{ "DrawPosition", DrawPositionProc },
{ "HandleUserMove", HandleUserMove },
int count;
int *outError;
{
+ static int line = 0;
ChildProc *cp = (ChildProc *) pr;
int outCount;
if (pr == NoProc)
- outCount = fwrite(message, 1, count, stdout);
+ {
+ 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
+ {
+ 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);
+ }
+ }
+ }
else
outCount = write(cp->fdTo, message, count);