From 2d3d9441ef456b36766a6a9958d39eec6ce6f098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Santos=20Costa?= Date: Wed, 26 Feb 2014 22:10:17 +0000 Subject: [PATCH] update to latest swi console code --- console/LGPL/pl-ntconsole.c | 49 +++- swi/console/Makefile.in | 106 +++---- swi/console/common.h | 4 +- swi/console/complete.c | 16 +- swi/console/console.c | 540 +++++++++++++++++++++++------------- swi/console/console.h | 32 ++- swi/console/console_i.h | 35 ++- swi/console/edit.c | 32 +-- swi/console/history.c | 29 +- swi/console/history.h | 4 +- swi/console/menu.c | 34 ++- swi/console/menu.h | 13 +- swi/console/registry.c | 4 +- 13 files changed, 558 insertions(+), 340 deletions(-) diff --git a/console/LGPL/pl-ntconsole.c b/console/LGPL/pl-ntconsole.c index ec16cc2b4..9fce92955 100755 --- a/console/LGPL/pl-ntconsole.c +++ b/console/LGPL/pl-ntconsole.c @@ -1,4 +1,4 @@ - /* $Id$ +/* $Id$ Part of SWI-Prolog @@ -20,7 +20,7 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define WINDOWS_LEAN_AND_MEAN 1 @@ -43,6 +43,10 @@ typedef enum CMD_ANSI } astate; +typedef enum +{ HDL_CONSOLE = 0, + HDL_FILE +} htype; typedef struct { int magic; @@ -57,6 +61,7 @@ typedef struct int argstat; astate cmdstat; /* State for sequence processing */ WORD def_attr; /* Default attributes */ + htype handletype; /* Type of stream handle */ } ansi_stream; @@ -85,11 +90,19 @@ flush_ansi(ansi_stream *as) { BOOL rc; DWORD done; - rc = WriteConsoleW(as->hConsole, - &as->buffer[written], - (DWORD)(as->buffered-written), - &done, - NULL); + if (as->handletype == HDL_CONSOLE) + { rc = WriteConsoleW(as->hConsole, + &as->buffer[written], + (DWORD)(as->buffered-written), + &done, + NULL); + } else + { rc = WriteFile(as->hConsole, + &as->buffer[written], + (DWORD)(as->buffered-written), + &done, + NULL); + } if ( rc ) { written += done; @@ -347,7 +360,20 @@ control_ansi(void *handle, int op, void *data) case SIO_SETENCODING: return -1; /* We cannot change the encoding! */ case SIO_LASTERROR: - return 0; /* TBD */ + { const char *s; + if ( (s = WinError()) ); + { const char **sp = data; + *sp = s; + return 0; + } + return -1; + } + case SIO_GETFILENO: + { int *fp = data; + + *fp = (int)(intptr_t)as->saved_handle; /* is one of 0,1,2 */ + return 0; + } default: return -1; } @@ -402,10 +428,16 @@ error: static int wrap_console(HANDLE h, IOSTREAM *s, IOFUNCTIONS *funcs) { ansi_stream *as; + DWORD mode; as = PL_malloc(sizeof(*as)); memset(as, 0, sizeof(*as)); + if (GetConsoleMode(h, &mode)) + as->handletype = HDL_CONSOLE; + else + as->handletype = HDL_FILE; + as->hConsole = h; as->pStream = s; as->saved_handle = s->handle; @@ -413,6 +445,7 @@ wrap_console(HANDLE h, IOSTREAM *s, IOFUNCTIONS *funcs) s->handle = as; s->encoding = ENC_WCHAR; s->functions = funcs; + s->flags &= ~SIO_FILE; return TRUE; } diff --git a/swi/console/Makefile.in b/swi/console/Makefile.in index 6a3f2c015..d966a3f2e 100644 --- a/swi/console/Makefile.in +++ b/swi/console/Makefile.in @@ -1,75 +1,53 @@ -# -# default base directory for YAP installation -# (EROOT for architecture-dependent files) -# -prefix = @prefix@ -exec_prefix = @exec_prefix@ -ROOTDIR = $(prefix) -EROOTDIR = @exec_prefix@ -# -# where YAP should look for libraries -# -LIBDIR=@libdir@/Yap -# -# -CC=@CC@ -municode -DUNICODE -D_UNICODE -CPPFLAGS=@CPPFLAGS@ -CFLAGS= @CFLAGS@ $(DEFS) $(CPPFLAGS) -I$(srcdir) -DRLC_VENDOR="\"YAP\"" -# -# -# You shouldn't need to change what follows. -# -INSTALL=@INSTALL@ -INSTALL_DATA=@INSTALL_DATA@ -INSTALL_PROGRAM=@INSTALL_PROGRAM@ -RANLIB=@RANLIB@ -AR=@AR@ +################################################################ +# Makefile for the SWI-Prolog console window. +################################################################ + srcdir=@srcdir@ +@VPATH@ @srcdir@ -SOURCES= \ - $(srcdir)/complete.c $(srcdir)/console.c \ - $(srcdir)/edit.c $(srcdir)/history.c \ - $(srcdir)/menu.c -HEADERS= \ - $(srcdir)/common.h $(srcdir)/console.h \ - $(srcdir)/console_i.h $(srcdir)/history.h \ - $(srcdir)/menu.h +CC=@CC@ +LDEXE=@LDEXE@ +PLARCH=@PLARCH@ +XLIBS=@XLIBS@ +SOEXT=@SO_EXT@ -OBJECTS= complete.o console.o edit.o history.o menu.o +COFLAGS=@COFLAGS@ +CWFLAGS=@CWFLAGS@ +CIFLAGS=@CIFLAGS@ +CMFLAGS=@CMFLAGS@ -DUNICODE -D_UNICODE +CPFLAGS= +CFLAGS= $(CWFLAGS) $(COFLAGS) $(CIFLAGS) $(CMFLAGS) $(CPFLAGS) +LDFLAGS=@LDFLAGS@ $(CPFLAGS) -LIBS=-lgdi32 -lcomdlg32 +PLHOME=../../.. -all: ../../plterm.dll +include $(srcdir)/../../common.mk -../../plterm.dll: libplterm.a - $(CC) $(CFLAGS) -shared -o ../../plterm.dll \ - -Wl,--export-all-symbols \ - -Wl,--enable-auto-import \ - -Wl,--whole-archive libplterm.a \ - -Wl,--no-whole-archive $(LIBS) $(LDFLAGS) +OBJ= complete.o console.o edit.o history.o menu.o +OUT= $(PLHOME)/lib/$(PLARCH)/plterm.$(SOEXT) +INCLDIR=$(PLHOME)/include +HDR= $(INCLDIR)/console.h -libplterm.a: $(OBJECTS) $(SOURCES) $(HEADERS) - -rm -f libplterm.a - $(AR) rc libplterm.a $(OBJECTS) - $(RANLIB) libplterm.a +all: $(OUT) $(HDR) -install: +$(OUT): $(OBJ) + $(CC) -shared $(COFLAGS) -o $@ -Wl,--out-implib,$@.a $(OBJ) $(XLIBS) + +$(HDR): $(INCLDIR) + +$(INCLDIR): + mkdir -p $@ + +$(PLHOME)/include/console.h: $(srcdir)/console.h + cp -f $< $@ + +console.o: $(srcdir)/console_i.h $(srcdir)/console.h clean: - rm -f *.o *~ *.dll - -complete.o: $(srcdir)/complete.c - $(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/complete.c -o complete.o - -console.o: $(srcdir)/console.c - $(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/console.c -o console.o - -history.o: $(srcdir)/history.c - $(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/history.c -o history.o - -menu.o: $(srcdir)/menu.c - $(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/menu.c -o menu.o - -edit.o: $(srcdir)/edit.c - $(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/edit.c -o edit.o + rm -f *.o + rm -f *~ +distclean: clean + rm -f $(PLHOME)/lib/$(PLARCH)/plterm.$(SOEXT) + rm -f $(PLHOME)/lib/$(PLARCH)/plterm.$(SOEXT).a + rm -f $(INCLDIR)/console.h diff --git a/swi/console/common.h b/swi/console/common.h index a565ae6ae..8392fdd9a 100644 --- a/swi/console/common.h +++ b/swi/console/common.h @@ -1,4 +1,4 @@ -/* $Id: common.h,v 1.1 2008-04-01 08:50:48 vsc Exp $ +/* $Id$ Part of SWI-Prolog @@ -19,7 +19,7 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define IMODE_SWITCH_CHAR -2 diff --git a/swi/console/complete.c b/swi/console/complete.c index 701c70768..05791e509 100644 --- a/swi/console/complete.c +++ b/swi/console/complete.c @@ -1,4 +1,4 @@ -/* $Id: complete.c,v 1.1 2008-03-27 00:41:33 vsc Exp $ +/* $Id$ Part of SWI-Prolog @@ -19,21 +19,21 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "console.h" -#ifndef __TCHAR_DEFINED -typedef wint_t _TINT; -#endif - #ifndef EOS #define EOS 0 #endif +#ifndef _TINT +typedef wint_t _TINT; +#endif + static TCHAR *completion_chars = TEXT("~:\\/-."); static size_t @@ -77,7 +77,7 @@ rlc_complete_file_function(RlcCompleteData data) for( ; n < ln->point; n++) { int c = ln->data[n]; - + if ( c == '/' ) c = '\\'; if ( c == '\\' ) @@ -108,7 +108,7 @@ rlc_complete_file_function(RlcCompleteData data) { _tcscpy(data->candidate, fdata.cFileName); return TRUE; } - + return FALSE; } diff --git a/swi/console/console.c b/swi/console/console.c index 358d3c0e7..324fb7dcf 100644 --- a/swi/console/console.c +++ b/swi/console/console.c @@ -1,11 +1,10 @@ -/* $Id: console.c,v 1.1 2008-03-27 00:41:33 vsc Exp $ - - Part of SWI-Prolog +/* Part of SWI-Prolog Author: Jan Wielemaker - E-mail: jan@swi.psy.uva.nl + E-mail: J.Wielemaker@vu.nl WWW: http://www.swi-prolog.org - Copyright (C): 1985-2002, University of Amsterdam + Copyright (C): 1985-2012, University of Amsterdam + VU University Amsterdam This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -19,7 +18,7 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -88,7 +87,7 @@ static void initHeapDebug(void); #define UNICODE_NOCHAR 0xFFFF #endif -#if (_MSC_VER < 1400) && !_WIN64 +#if (_MSC_VER < 1400) && !defined(__MINGW32__) typedef DWORD DWORD_PTR; #endif @@ -182,6 +181,7 @@ static HICON _rlc_hicon; /* Global icon */ static LRESULT WINAPI rlc_wnd_proc(HWND win, UINT msg, WPARAM wP, LPARAM lP); +static void rcl_setup_ansi_colors(RlcData b); static void rlc_place_caret(RlcData b); static void rlc_resize_pixel_units(RlcData b, int w, int h); static RlcData rlc_make_buffer(int w, int h); @@ -200,6 +200,8 @@ static int rlc_add_lines(RlcData b, int here, int add); static void rlc_start_selection(RlcData b, int x, int y); static void rlc_extend_selection(RlcData b, int x, int y); static void rlc_word_selection(RlcData b, int x, int y); +static int rlc_has_selection(RlcData b); +static void rlc_set_selection(RlcData b, int sl, int sc, int el, int ec); static void rlc_copy(RlcData b); static void rlc_destroy(RlcData b); static void rlc_request_redraw(RlcData b); @@ -207,7 +209,8 @@ static void rlc_redraw(RlcData b); static int rlc_breakargs(TCHAR *line, TCHAR **argv); static void rlc_resize(RlcData b, int w, int h); static void rlc_adjust_line(RlcData b, int line); -static int text_width(RlcData b, HDC hdc, const TCHAR *text, int len); +static int text_width(RlcData b, HDC hdc, const text_char *text, int len); +static int tchar_width(RlcData b, HDC hdc, const TCHAR *text, int len); static void rlc_queryfont(RlcData b); static void rlc_do_write(RlcData b, TCHAR *buf, int count); static void rlc_reinit_line(RlcData b, int line); @@ -216,12 +219,10 @@ static int rlc_between(RlcData b, int f, int t, int v); static void free_user_data(RlcData b); static RlcQueue rlc_make_queue(int size); -static void rlc_free_queue(RlcQueue q); static int rlc_from_queue(RlcQueue q); static int rlc_is_empty_queue(RlcQueue q); -static void rlc_empty_queue(RlcQueue q); -extern int main(void); +extern int main(); static RlcUpdateHook _rlc_update_hook; static RlcTimerHook _rlc_timer_hook; @@ -268,7 +269,7 @@ rlc_check_assertions(RlcData b) assert(b->caret_x >= 0 && b->caret_x < b->width); /* TBD: debug properly */ /*assert(rlc_between(b, b->window_start, window_last, b->caret_y));*/ - + for(y=0; yheight; y++) { TextLine tl = &b->lines[y]; @@ -345,9 +346,10 @@ rlc_window_class(HICON icon) HINSTANCE instance = _rlc_hinstance; if ( !winclassname[0] ) - { if ( !GetEnvironmentVariable(TEXT("PLTERM_CLASS"), + { if ( !GetEnvironmentVariable(_T("PLTERM_CLASS"), winclassname, sizeof(winclassname)) ) - _stprintf(winclassname, TEXT("PlTerm-%d"), instance); + snwprintf(winclassname, sizeof(winclassname)/sizeof(TCHAR), + _T("PlTerm-%d"), instance); wndClass.lpszClassName = winclassname; wndClass.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS; @@ -389,7 +391,7 @@ rlc_main(HANDLE hInstance, HANDLE hPrevInstance, { TCHAR * argv[100]; int argc; TCHAR program[MAXPATHLEN]; - TCHAR progbase[100]; + TCHAR progbase[100]; RlcData b; rlc_console_attr attr; @@ -487,14 +489,15 @@ rlc_create_window(RlcData b) NULL, NULL, _rlc_hinstance, NULL); b->window = hwnd; - SetWindowLong(hwnd, GWL_DATA, (LONG) b); + SetWindowLongPtr(hwnd, GWL_DATA, (LONG_PTR) b); SetScrollRange(hwnd, SB_VERT, 0, b->sb_lines, FALSE); SetScrollPos(hwnd, SB_VERT, b->sb_start, TRUE); b->queue = rlc_make_queue(256); - b->sb_lines = rlc_count_lines(b, b->first, b->last); - b->sb_start = rlc_count_lines(b, b->first, b->window_start); + b->sb_lines = rlc_count_lines(b, b->first, b->last); + b->sb_start = rlc_count_lines(b, b->first, b->window_start); + rcl_setup_ansi_colors(b); b->foreground = GetSysColor(COLOR_WINDOWTEXT); b->background = GetSysColor(COLOR_WINDOW); b->sel_foreground = GetSysColor(COLOR_HIGHLIGHTTEXT); @@ -551,13 +554,14 @@ rlc_kill_wnd_proc(HWND hwnd, UINT message, UINT wParam, LONG lParam) } static TCHAR * -rlc_kill_window_class(void) +rlc_kill_window_class() { static TCHAR winclassname[32]; static WNDCLASS wndClass; HINSTANCE instance = _rlc_hinstance; if ( !winclassname[0] ) - { _stprintf(winclassname, _T("Console-hidden-win%d"), instance); + { snwprintf(winclassname, sizeof(winclassname)/sizeof(TCHAR), + _T("Console-hidden-win%d"), instance); wndClass.style = 0; wndClass.lpfnWndProc = (LPVOID) rlc_kill_wnd_proc; @@ -668,7 +672,7 @@ reg_get_int(HKEY key, const TCHAR *name, int mn, int def, int mx, int *value) else if ( v > mx ) v = mx; } - + *value = v; } } @@ -734,7 +738,7 @@ static HKEY rlc_option_key(rlc_console_attr *attr, int create) { TCHAR Prog[256]; TCHAR *address[] = { _T("Software"), - RLC_VENDOR, + RLC_VENDOR, Prog, _T("Console"), (TCHAR *)attr->key, /* possible secondary key */ @@ -834,8 +838,61 @@ rlc_breakargs(TCHAR *line, TCHAR **argv) argv[argc] = NULL; /* add trailing NULL pointer to argv */ return argc; -} - +} + + + /******************************* + * ANSI COLORS * + *******************************/ + +/* See http://en.wikipedia.org/wiki/ANSI_escape_code */ + +static void +rcl_setup_ansi_colors(RlcData b) +{ b->sgr_flags = TF_DEFAULT; + +#ifdef ANSI_VGA_COLORS + /* normal versions */ + b->ansi_color[0] = RGB( 0, 0, 0); /* black */ + b->ansi_color[1] = RGB(170, 0, 0); /* red */ + b->ansi_color[2] = RGB(0, 170, 0); /* green */ + b->ansi_color[3] = RGB(170, 85, 0); /* yellow */ + b->ansi_color[4] = RGB( 0, 0,170); /* blue */ + b->ansi_color[5] = RGB(170, 0,170); /* magenta */ + b->ansi_color[6] = RGB( 0,170,170); /* cyan */ + b->ansi_color[7] = RGB(170,170,170); /* white */ + /* bright/light versions */ + b->ansi_color[8] = RGB( 85, 85, 85); /* black */ + b->ansi_color[9] = RGB(255, 85, 85); /* red */ + b->ansi_color[10] = RGB( 85,255, 85); /* green */ + b->ansi_color[11] = RGB(255,255, 85); /* yellow */ + b->ansi_color[12] = RGB( 85, 85,255); /* blue */ + b->ansi_color[13] = RGB(255, 85,255); /* magenta */ + b->ansi_color[14] = RGB( 85,255,255); /* cyan */ + b->ansi_color[15] = RGB(255,255,255); /* white */ +#else /*XTERM*/ + /* normal versions */ + b->ansi_color[0] = RGB( 0, 0, 0); /* black */ + b->ansi_color[1] = RGB(205, 0, 0); /* red */ + b->ansi_color[2] = RGB(0, 205, 0); /* green */ + b->ansi_color[3] = RGB(205,205, 0); /* yellow */ + b->ansi_color[4] = RGB( 0, 0,238); /* blue */ + b->ansi_color[5] = RGB(205, 0,205); /* magenta */ + b->ansi_color[6] = RGB( 0,205,205); /* cyan */ + b->ansi_color[7] = RGB(229,229,229); /* white */ + /* bright/light versions */ + b->ansi_color[8] = RGB(127,127,127); /* black */ + b->ansi_color[9] = RGB(255, 0, 0); /* red */ + b->ansi_color[10] = RGB( 0,255, 0); /* green */ + b->ansi_color[11] = RGB(255,255, 0); /* yellow */ + b->ansi_color[12] = RGB( 92, 92,255); /* blue */ + b->ansi_color[13] = RGB(255, 0,255); /* magenta */ + b->ansi_color[14] = RGB( 0,255,255); /* cyan */ + b->ansi_color[15] = RGB(255,255,255); /* white */ +#endif +} + + /******************************* * ATTRIBUTES * @@ -910,7 +967,7 @@ rlc_kill(RlcData b) return FALSE; } TerminateThread(b->application_thread, 1); - + return TRUE; } } @@ -931,7 +988,14 @@ rlc_interrupt(RlcData b) static void typed_char(RlcData b, int chr) -{ if ( chr == Control('C') ) +{ if ( chr == Control('C') && rlc_has_selection(b) ) + { rlc_copy(b); + return; + } + + rlc_set_selection(b, 0, 0, 0, 0); + + if ( chr == Control('C') ) rlc_interrupt(b); else if ( chr == Control('V') || chr == Control('Y') ) rlc_paste(b); @@ -964,7 +1028,7 @@ IsDownKey(code) static LRESULT WINAPI rlc_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ RlcData b = (RlcData) GetWindowLong(hwnd, GWL_DATA); +{ RlcData b = (RlcData) GetWindowLongPtr(hwnd, GWL_DATA); switch(message) { case WM_CREATE: @@ -982,10 +1046,10 @@ rlc_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) placement.length = sizeof(placement); GetWindowPlacement(hwnd, &placement); - + if ( placement.showCmd == SW_SHOWNORMAL ) { b->win_x = placement.rcNormalPosition.left; - b->win_y = placement.rcNormalPosition.top; + b->win_y = placement.rcNormalPosition.top; b->modified_options |= OPT_POSITION; } @@ -1019,6 +1083,7 @@ rlc_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) rlc_paste(b); return 0; case IDM_COPY: + rlc_copy(b); return 0; /* no op: already done */ case IDM_CUT: break; /* TBD: cut */ @@ -1045,7 +1110,7 @@ rlc_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) break; } - { int chr; + { int chr; case WM_KEYDOWN: /* up is sent only once */ { switch((int) wParam) @@ -1056,6 +1121,7 @@ rlc_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case VK_DOWN: chr = Control('N'); break; case VK_HOME: chr = Control('A'); break; case VK_END: chr = Control('E'); break; + case VK_CANCEL: rlc_interrupt(b); return 0; case VK_PRIOR: /* page up */ { int maxdo = rlc_count_lines(b, b->first, b->window_start); @@ -1132,7 +1198,7 @@ rlc_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) return 0; } - + case WM_LBUTTONUP: case WM_RBUTTONUP: if ( emu_hwnd == hwnd ) @@ -1383,7 +1449,7 @@ rlc_yield() *******************************/ static void -rlc_init_word_chars(void) +rlc_init_word_chars() { int i; for(i=0; isize == 0 ) { *chr = 0; } else - { TCHAR *s = tl->text; + { text_char *s = tl->text; HDC hdc = GetDC(b->window); int f = 0; int t = tl->size; @@ -1532,12 +1598,12 @@ rlc_translate_mouse(RlcData b, int x, int y, int *line, int *chr) for(i=10; --i > 0; m=(f+t)/2) { int w; - + w = text_width(b, hdc, s, m); if ( x > w ) { int cw; - GetCharWidth32(hdc, s[m], s[m], &cw); + GetCharWidth32(hdc, s[m].code, s[m].code, &cw); if ( x < w+cw ) { *chr = m; return; @@ -1547,7 +1613,7 @@ rlc_translate_mouse(RlcData b, int x, int y, int *line, int *chr) { t = m; } } - + *chr = m; } } @@ -1565,21 +1631,8 @@ rlc_start_selection(RlcData b, int x, int y) } -static void -rlc_end_selection(RlcData b, int x, int y) -{ int l, c; - - rlc_translate_mouse(b, x, y, &l, &c); - if ( SelLT(l, c, b->sel_org_line, b->sel_org_char) ) - rlc_set_selection(b, l, c, b->sel_org_line, b->sel_org_char); - else if ( SelLT(b->sel_org_line, b->sel_org_char, l, c) ) - rlc_set_selection(b, b->sel_org_line, b->sel_org_char, l, c); - rlc_set_selection(b, l, c, l, c); -} - - static int /* v >= f && v <= t */ -rlc_between(RlcData b, int f, int t, int v) +rlc_between(RlcData b, int f, int t, int v) { int h = rlc_count_lines(b, b->first, v); if ( h >= rlc_count_lines(b, b->first, f) && @@ -1598,12 +1651,12 @@ rlc_word_selection(RlcData b, int x, int y) if ( rlc_between(b, b->first, b->last, l) ) { TextLine tl = &b->lines[l]; - if ( c < tl->size && rlc_is_word_char(tl->text[c]) ) + if ( c < tl->size && rlc_is_word_char(tl->text[c].code) ) { int f, t; - for(f=c; f>0 && rlc_is_word_char(tl->text[f-1]); f--) + for(f=c; f>0 && rlc_is_word_char(tl->text[f-1].code); f--) ; - for(t=c; tsize && rlc_is_word_char(tl->text[t]); t++) + for(t=c; tsize && rlc_is_word_char(tl->text[t].code); t++) ; rlc_set_selection(b, l, f, l, t); } @@ -1616,6 +1669,8 @@ rlc_word_selection(RlcData b, int x, int y) static void rlc_extend_selection(RlcData b, int x, int y) { int l, c; + int el = b->sel_org_line; + int ec = b->sel_org_char; rlc_translate_mouse(b, x, y, &l, &c); if ( SelLT(l, c, b->sel_org_line, b->sel_org_char) ) @@ -1623,25 +1678,39 @@ rlc_extend_selection(RlcData b, int x, int y) { if ( rlc_between(b, b->first, b->last, l) ) { TextLine tl = &b->lines[l]; - if ( c < tl->size && rlc_is_word_char(tl->text[c]) ) - for(; c > 0 && rlc_is_word_char(tl->text[c-1]); c--) + if ( c < tl->size && rlc_is_word_char(tl->text[c].code) ) + for(; c > 0 && rlc_is_word_char(tl->text[c-1].code); c--) + ; + } + if ( rlc_between(b, b->first, b->last, el) ) + { TextLine tl = &b->lines[el]; + + if ( ec < tl->size && rlc_is_word_char(tl->text[ec].code) ) + for(; ec < tl->size && rlc_is_word_char(tl->text[ec].code); ec++) ; } } else if ( b->sel_unit == SEL_LINE ) c = 0; - rlc_set_selection(b, l, c, b->sel_end_line, b->sel_end_char); + rlc_set_selection(b, l, c, el, ec); } else if ( SelLT(b->sel_org_line, b->sel_org_char, l, c) ) { if ( b->sel_unit == SEL_WORD ) { if ( rlc_between(b, b->first, b->last, l) ) { TextLine tl = &b->lines[l]; - if ( c < tl->size && rlc_is_word_char(tl->text[c]) ) - for(; c < tl->size && rlc_is_word_char(tl->text[c]); c++) + if ( c < tl->size && rlc_is_word_char(tl->text[c].code) ) + for(; c < tl->size && rlc_is_word_char(tl->text[c].code); c++) + ; + } + if ( rlc_between(b, b->first, b->last, el) ) + { TextLine tl = &b->lines[el]; + + if ( ec < tl->size && rlc_is_word_char(tl->text[ec].code) ) + for(; ec > 0 && rlc_is_word_char(tl->text[ec-1].code); ec--) ; } } else if ( b->sel_unit == SEL_LINE ) c = b->width; - rlc_set_selection(b, b->sel_start_line, b->sel_start_char, l, c); + rlc_set_selection(b, el, ec, l, c); } } @@ -1666,22 +1735,22 @@ rlc_read_from_window(RlcData b, int sl, int sc, int el, int ec) e = tl->size; while(sc < e) - { if ( i >= bufsize ) + { if ( i+1 >= bufsize ) { bufsize *= 2; if ( !(buf = rlc_realloc(buf, bufsize * sizeof(TCHAR))) ) return NULL; /* not enough memory */ } - buf[i++] = tl->text[sc++]; + buf[i++] = tl->text[sc++].code; } } - + if ( sl == el || sl == b->last ) - { buf[i++] = '\0'; + { buf[i++] = '\0'; /* Always room for the 0 */ return buf; } if ( tl && !tl->softreturn ) - { if ( i+1 >= bufsize ) + { if ( i+2 >= bufsize ) { bufsize *= 2; if ( !(buf = rlc_realloc(buf, bufsize * sizeof(TCHAR))) ) return NULL; /* not enough memory */ @@ -1693,16 +1762,23 @@ rlc_read_from_window(RlcData b, int sl, int sc, int el, int ec) } -static TCHAR * -rlc_selection(RlcData b) +static int +rlc_has_selection(RlcData b) { if ( SelEQ(b->sel_start_line, b->sel_start_char, b->sel_end_line, b->sel_end_char) ) - return NULL; + return FALSE; + return TRUE; +} - return rlc_read_from_window(b, - b->sel_start_line, b->sel_start_char, - b->sel_end_line, b->sel_end_char); -} + +static TCHAR * +rlc_selection(RlcData b) +{ if ( rlc_has_selection(b) ) + return rlc_read_from_window(b, + b->sel_start_line, b->sel_start_char, + b->sel_end_line, b->sel_end_char); + return NULL; +} static void @@ -1755,16 +1831,16 @@ rlc_place_caret(RlcData b) { SetCaretPos((b->caret_x + 1) * b->cw, line * b->ch); } else { HDC hdc = GetDC(b->window); - SIZE tsize; + int tw; TextLine tl = &b->lines[b->caret_y]; HFONT old; old = SelectObject(hdc, b->hfont); - GetTextExtentPoint32(hdc, tl->text, b->caret_x, &tsize); + tw = text_width(b, hdc, tl->text, b->caret_x); SelectObject(hdc, old); ReleaseDC(b->window, hdc); - SetCaretPos(b->cw + tsize.cx, line * b->ch); + SetCaretPos(b->cw + tw, line * b->ch); } if ( !b->caret_is_shown ) { ShowCaret(b->window); @@ -1789,12 +1865,12 @@ rlc_update_scrollbar(RlcData b) { if ( b->window ) { int nsb_lines = rlc_count_lines(b, b->first, b->last); int nsb_start = rlc_count_lines(b, b->first, b->window_start); - + if ( nsb_lines != b->sb_lines || nsb_start != b->sb_start ) { SetScrollRange(b->window, SB_VERT, 0, nsb_lines, FALSE); SetScrollPos( b->window, SB_VERT, nsb_start, TRUE); - + b->sb_lines = nsb_lines; b->sb_start = nsb_start; } @@ -1802,6 +1878,80 @@ rlc_update_scrollbar(RlcData b) } +static void +rcl_paint_text(RlcData b, HDC hdc, + TextLine tl, int from, int to, + int ty, int *cx, int insel) +{ text_char *chars, *s; + text_char buf[MAXLINE]; + TCHAR text[MAXLINE]; + TCHAR *t; + int len = to-from; + int i; + + if ( len <= 0 ) + return; + + if ( tl->text && to <= tl->size ) + { chars = &tl->text[from]; + } else + { text_char *o; + int copy; + + o = chars = buf; + s = &tl->text[from]; + copy = tl->text ? tl->size-from : 0; + for(i=0; icode = ' '; + o->flags = TF_DEFAULT; + } + } + + for(t=text, s=chars, i=0; i < len; i++, t++, s++) + *t = s->code; + + if ( insel ) /* TBD: Cache */ + { SetBkColor(hdc, b->sel_background); + SetTextColor(hdc, b->sel_foreground); + TextOut(hdc, *cx, ty, text, len); + *cx += tchar_width(b, hdc, text, len); + } else + { int start, segment; + + for(start=0, s=chars, t=text; + startflags; + int left = len-start; + + for(segment=0; s[segment].flags == flags && segmentforeground); + else + SetTextColor(hdc, b->ansi_color[TF_FG(flags)]); + + if ( TF_BG(flags) == ANSI_COLOR_DEFAULT ) + SetBkColor(hdc, b->background); + else + SetBkColor(hdc, b->ansi_color[TF_BG(flags)]); + + TextOut(hdc, *cx, ty, t, segment); + if ( TF_BOLD(flags) ) + { SetBkMode(hdc, TRANSPARENT); + TextOut(hdc, (*cx)+1, ty, t, segment); + TextOut(hdc, *cx, ty+1, t, segment); + SetBkMode(hdc, OPAQUE); + } + *cx += tchar_width(b, hdc, t, segment); + } + } +} + + static void rlc_redraw(RlcData b) { PAINTSTRUCT ps; @@ -1818,7 +1968,7 @@ rlc_redraw(RlcData b) SelectObject(hdc, b->hfont); SetTextColor(hdc, b->foreground); SetBkColor(hdc, b->background); - + if ( b->background == RGB(255, 255, 255) ) { bg = GetStockObject(WHITE_BRUSH); stockbg = TRUE; @@ -1845,27 +1995,9 @@ rlc_redraw(RlcData b) for(; pl <= el; l = NextLine(b, l), pl++) { TextLine tl = &b->lines[l]; - TCHAR text[MAXLINE]; int ty = b->ch * pl; int cx = b->cw; - if ( !tl->text ) - { int i; - TCHAR *t; - - tl->size = 0; - for(i=0, t=text; iwidth; i++) - *t++ = ' '; - } else - { int i; - TCHAR *t, *s; - - for(i=0, t=text, s=tl->text; isize; i++) - *t++ = *s++; - for(; iwidth; i++) - *t++ = ' '; - } - rect.top = ty; rect.bottom = rect.top + b->ch; @@ -1874,34 +2006,23 @@ rlc_redraw(RlcData b) { int cf = b->sel_start_char; int ce = (b->sel_end_line != b->sel_start_line ? b->width : b->sel_end_char); - if ( cf > 0 ) - { TextOut(hdc, cx, ty, text, cf); - cx += text_width(b, hdc, text, cf); - } - SetBkColor(hdc, b->sel_background); - SetTextColor(hdc, b->sel_foreground); - TextOut(hdc, cx, ty, &text[cf], ce-cf); - cx += text_width(b, hdc, &text[cf], ce-cf); + + rcl_paint_text(b, hdc, tl, 0, cf, ty, &cx, insel); + insel = TRUE; + rcl_paint_text(b, hdc, tl, cf, ce, ty, &cx, insel); if ( l == b->sel_end_line ) - { SetBkColor(hdc, b->background); - SetTextColor(hdc, b->foreground); - TextOut(hdc, cx, ty, &text[ce], b->width - ce); - cx += text_width(b, hdc, &text[ce], b->width - ce); + { insel = FALSE; + rcl_paint_text(b, hdc, tl, ce, b->width, ty, &cx, insel); } else insel = TRUE; } else if ( l == b->sel_end_line ) /* end of selection */ { int ce = b->sel_end_char; + rcl_paint_text(b, hdc, tl, 0, ce, ty, &cx, insel); insel = FALSE; - TextOut(hdc, cx, ty, text, ce); - cx += text_width(b, hdc, text, ce); - SetBkColor(hdc, b->background); - SetTextColor(hdc, b->foreground); - TextOut(hdc, cx, ty, &text[ce], b->width - ce); - cx += text_width(b, hdc, &text[ce], b->width - ce); + rcl_paint_text(b, hdc, tl, ce, b->width, ty, &cx, insel); } else /* entire line in/out selection */ - { TextOut(hdc, cx, ty, text, b->width); - cx += text_width(b, hdc, text, b->width); + { rcl_paint_text(b, hdc, tl, 0, b->width, ty, &cx, insel); } /* clear remainder of line */ @@ -1947,14 +2068,13 @@ rlc_request_redraw(RlcData b) int y = 0; RECT rect; int first = TRUE; - int clear = FALSE; rect.left = b->cw; rect.right = (b->width+1) * b->cw; - + for(; y < b->window_size; y++, i = NextLine(b, i)) { TextLine l = &b->lines[i]; - + if ( l->changed & CHG_CHANGED ) { if ( first ) { rect.top = y * b->ch; @@ -1962,16 +2082,13 @@ rlc_request_redraw(RlcData b) first = FALSE; } else rect.bottom = (y+1) * b->ch; - - if ( l->changed & CHG_CLEAR ) - clear = TRUE; } if ( i == b->last ) break; } if ( !first && b->window ) - InvalidateRect(b->window, &rect, FALSE); /*clear);*/ + InvalidateRect(b->window, &rect, FALSE); else if ( b->changed & CHG_CARET ) rlc_place_caret(b); } @@ -1992,7 +2109,7 @@ static void rlc_resize_pixel_units(RlcData b, int w, int h) { int nw = max(20, w/b->cw)-2; /* 1 character space for margins */ int nh = max(1, h/b->ch); - + DEBUG(Dprintf(_T("rlc_resize_pixel_units(%p, %d, %d) (%dx%d)\n"), b, w, h, nw, nh)); @@ -2000,7 +2117,7 @@ rlc_resize_pixel_units(RlcData b, int w, int h) return; /* no real change */ rlc_resize(b, nw, nh); - + if ( _rlc_resize_hook ) (*_rlc_resize_hook)(b->width, b->window_size); else @@ -2030,15 +2147,15 @@ rlc_init_text_dimensions(RlcData b, HFONT font) b->hfont = GetStockObject(ANSI_FIXED_FONT); else { LOGFONT lfont; - + memset(&lfont, 0, sizeof(lfont)); - + lfont.lfHeight = a->font_size; lfont.lfWeight = a->font_weight; lfont.lfPitchAndFamily = a->font_family; lfont.lfCharSet = a->font_char_set; _tcsncpy(lfont.lfFaceName, a->face_name, 31); - + if ( !(b->hfont = CreateFontIndirect(&lfont)) ) b->hfont = GetStockObject(ANSI_FIXED_FONT); } @@ -2070,7 +2187,25 @@ rlc_init_text_dimensions(RlcData b, HFONT font) static int -text_width(RlcData b, HDC hdc, const TCHAR *text, int len) +text_width(RlcData b, HDC hdc, const text_char *text, int len) +{ if ( b->fixedfont ) + { return len * b->cw; + } else + { SIZE size; + TCHAR tmp[MAXLINE]; + int i; + + for(i=0; ifixedfont ) { return len * b->cw; } else @@ -2121,7 +2256,7 @@ rlc_queryfont(RlcData b) cf.hwndOwner = b->window; cf.lpLogFont = &lf; cf.Flags = CF_SCREENFONTS| - CF_NOVERTFONTS| + CF_NOVERTFONTS| CF_NOSIMULATIONS| CF_FORCEFONTEXIST| CF_INITTOLOGFONTSTRUCT; @@ -2159,9 +2294,9 @@ rlc_make_buffer(int w, int h) b->changed = CHG_CARET|CHG_CHANGED|CHG_CLEAR; b->imode = IMODE_COOKED; /* switch on first rlc_read() call */ b->imodeswitch = FALSE; - b->lhead = NULL; - b->ltail = NULL; - + b->lhead = NULL; + b->ltail = NULL; + memset(b->lines, 0, sizeof(text_line) * h); for(i=0; ilines[i].adjusted = TRUE; @@ -2226,7 +2361,7 @@ rlc_resize(RlcData b, int w, int h) b->window_size = h; b->width = w; - + for(i = b->first; /*i != b->last*/; i = NextLine(b, i)) { TextLine tl = &b->lines[i]; @@ -2241,15 +2376,15 @@ rlc_resize(RlcData b, int w, int h) DEBUG(Dprint_lines(b, b->first, b->first)); DEBUG(Dprintf(_T("b->first = %d, b->last = %d\n"), b->first, b->last)); pl = &b->lines[PrevLine(b, i)]; /* this is the moved line */ - tl->text = rlc_malloc((pl->size - w)*sizeof(TCHAR)); - memmove(tl->text, &pl->text[w], (pl->size - w)*sizeof(TCHAR)); + tl->text = rlc_malloc((pl->size - w)*sizeof(text_char)); + memmove(tl->text, &pl->text[w], (pl->size - w)*sizeof(text_char)); DEBUG(Dprintf(_T("Copied %d chars from line %d to %d\n"), pl->size - w, pl - b->lines, i)); tl->size = pl->size - w; tl->adjusted = TRUE; tl->softreturn = FALSE; pl->softreturn = TRUE; - pl->text = rlc_realloc(pl->text, w * sizeof(TCHAR)); + pl->text = rlc_realloc(pl->text, w * sizeof(text_char)); pl->size = w; pl->adjusted = TRUE; i = (int)(pl - b->lines); @@ -2261,12 +2396,12 @@ rlc_resize(RlcData b, int w, int h) if ( i == b->last ) rlc_add_line(b); nl = &b->lines[NextLine(b, i)]; - nl->text = rlc_realloc(nl->text, (nl->size + move)*sizeof(TCHAR)); - memmove(&nl->text[move], nl->text, nl->size*sizeof(TCHAR)); - memmove(nl->text, &tl->text[w], move*sizeof(TCHAR)); + nl->text = rlc_realloc(nl->text, (nl->size + move)*sizeof(text_char)); + memmove(&nl->text[move], nl->text, nl->size*sizeof(text_char)); + memmove(nl->text, &tl->text[w], move*sizeof(text_char)); nl->size += move; tl->size = w; - } + } } else if ( tl->text && tl->softreturn && tl->size < w ) { TextLine nl; @@ -2274,9 +2409,9 @@ rlc_resize(RlcData b, int w, int h) rlc_add_line(b); nl = &b->lines[NextLine(b, i)]; - nl->text = rlc_realloc(nl->text, (nl->size + tl->size)*sizeof(TCHAR)); - memmove(&nl->text[tl->size], nl->text, nl->size*sizeof(TCHAR)); - memmove(nl->text, tl->text, tl->size*sizeof(TCHAR)); + nl->text = rlc_realloc(nl->text, (nl->size + tl->size)*sizeof(text_char)); + memmove(&nl->text[tl->size], nl->text, nl->size*sizeof(text_char)); + memmove(nl->text, tl->text, tl->size*sizeof(text_char)); nl->size += tl->size; nl->adjusted = TRUE; rlc_shift_lines_up(b, i); @@ -2330,8 +2465,8 @@ rlc_adjust_line(RlcData b, int line) if ( tl->text && !tl->adjusted ) { tl->text = rlc_realloc(tl->text, tl->size == 0 - ? sizeof(TCHAR) - : tl->size * sizeof(TCHAR)); + ? sizeof(text_char) + : tl->size * sizeof(text_char)); tl->adjusted = TRUE; } } @@ -2343,11 +2478,11 @@ rlc_unadjust_line(RlcData b, int line) if ( tl->text ) { if ( tl->adjusted ) - { tl->text = rlc_realloc(tl->text, (b->width + 1)*sizeof(TCHAR)); + { tl->text = rlc_realloc(tl->text, (b->width + 1)*sizeof(text_char)); tl->adjusted = FALSE; } } else - { tl->text = rlc_malloc((b->width + 1)*sizeof(TCHAR)); + { tl->text = rlc_malloc((b->width + 1)*sizeof(text_char)); tl->adjusted = FALSE; tl->size = 0; } @@ -2365,7 +2500,7 @@ rlc_open_line(RlcData b) b->first = NextLine(b, b->first); } - b->lines[i].text = rlc_malloc((b->width + 1)*sizeof(TCHAR)); + b->lines[i].text = rlc_malloc((b->width + 1)*sizeof(text_char)); b->lines[i].adjusted = FALSE; b->lines[i].size = 0; b->lines[i].softreturn = FALSE; @@ -2476,7 +2611,7 @@ rlc_cariage_return(RlcData b) { b->caret_x = 0; b->changed |= CHG_CARET; -} +} static void @@ -2491,7 +2626,11 @@ rlc_tab(RlcData b) { rlc_unadjust_line(b, b->caret_y); while ( tl->size < b->caret_x ) - tl->text[tl->size++] = ' '; + { text_char *tc = &tl->text[tl->size++]; + + tc->code = ' '; + tc->flags = b->sgr_flags; + } } b->changed |= CHG_CARET; @@ -2553,14 +2692,45 @@ rlc_erase_line(RlcData b) } +static void +rlc_sgr(RlcData b, int sgr) +{ if ( sgr == 0 ) + { b->sgr_flags = TF_DEFAULT; + } else if ( sgr >= 30 && sgr <= 39 ) + { b->sgr_flags = TF_SET_FG(b->sgr_flags, + sgr == 39 ? ANSI_COLOR_DEFAULT : sgr-30); + } else if ( sgr >= 40 && sgr <= 49 ) + { b->sgr_flags = TF_SET_BG(b->sgr_flags, + sgr == 49 ? ANSI_COLOR_DEFAULT : sgr-40); + } else if ( sgr >= 90 && sgr <= 99 ) + { b->sgr_flags = TF_SET_FG(b->sgr_flags, + sgr == 99 ? ANSI_COLOR_DEFAULT : sgr-90+8); + } else if ( sgr >= 100 && sgr <= 109 ) + { b->sgr_flags = TF_SET_BG(b->sgr_flags, + sgr == 109 ? ANSI_COLOR_DEFAULT : sgr-100+8); + } else if ( sgr == 1 ) + { b->sgr_flags = TF_SET_BOLD(b->sgr_flags, 1); + } else if ( sgr == 4 ) + { b->sgr_flags = TF_SET_UNDERLINE(b->sgr_flags, 1); + } +} + + static void rlc_put(RlcData b, int chr) { TextLine tl = &b->lines[b->caret_y]; + text_char *tc; rlc_unadjust_line(b, b->caret_y); while( tl->size < b->caret_x ) - tl->text[tl->size++] = ' '; - tl->text[b->caret_x] = chr; + { tc = &tl->text[tl->size++]; + + tc->code = ' '; + tc->flags = b->sgr_flags; + } + tc = &tl->text[b->caret_x]; + tc->code = chr; + tc->flags = b->sgr_flags; if ( tl->size <= b->caret_x ) tl->size = b->caret_x + 1; tl->changed |= CHG_CHANGED; @@ -2629,7 +2799,7 @@ rlc_putansi(RlcData b, int chr) } break; - } + } if ( !b->argstat && chr == '-' ) { b->argstat = -1; /* negative */ break; @@ -2642,7 +2812,7 @@ rlc_putansi(RlcData b, int chr) } switch(chr) { case ';': - break; /* wait for more args */ + return; /* wait for more args */ case 'H': case 'f': rlc_need_arg(b, 1, 0); @@ -2678,6 +2848,14 @@ rlc_putansi(RlcData b, int chr) case 'K': CMD(rlc_erase_line(b)); break; + case 'm': + { int i; + rlc_need_arg(b, 1, 0); + + for(i=0; iargc; i++) + CMD(rlc_sgr(b, b->argv[i])); + break; + } } b->cmdstat = CMD_INITIAL; } @@ -2700,7 +2878,7 @@ rlc_paste(RlcData b) { wchar_t *data = GlobalLock(mem); int i; RlcQueue q = b->queue; - + if ( q ) { for(i=0; data[i]; i++) { rlc_add_queue(b, q, data[i]); @@ -2708,13 +2886,13 @@ rlc_paste(RlcData b) i++; } } - + GlobalUnlock(mem); } else if ( (mem = GetClipboardData(CF_TEXT)) ) { char far *data = GlobalLock(mem); int i; RlcQueue q = b->queue; - + if ( q ) { for(i=0; data[i]; i++) { rlc_add_queue(b, q, data[i]); @@ -2722,7 +2900,7 @@ rlc_paste(RlcData b) i++; } } - + GlobalUnlock(mem); } CloseClipboard(); @@ -2745,7 +2923,7 @@ rlc_get_mark(rlc_console c, RlcMark m) void rlc_goto_mark(rlc_console c, RlcMark m, const TCHAR *data, size_t offset) { RlcData b = rlc_get_data(c); - + b->caret_x = m->mark_x; b->caret_y = m->mark_y; @@ -2841,10 +3019,10 @@ window_loop(LPVOID arg) if ( line != RL_CANCELED_CHARP ) { LQueued lq = rlc_malloc(sizeof(lqueued)); - + lq->next = NULL; lq->line = line; - + if ( b->ltail ) { b->ltail->next = lq; b->ltail = lq; @@ -2859,7 +3037,7 @@ window_loop(LPVOID arg) } case IMODE_RAW: { MSG msg; - + if ( rlc_get_message(&msg, NULL, 0, 0) ) { TranslateMessage(&msg); DispatchMessage(&msg); @@ -2877,8 +3055,8 @@ window_loop(LPVOID arg) if ( b->closing <= 2 ) { MSG msg; TCHAR *waiting = _T("\r\nWaiting for Prolog. ") - _T("Close again to force termination .."); - + _T("Close again to force termination .."); + rlc_write(b, waiting, _tcslen(waiting)); while ( b->closing <= 2 && rlc_get_message(&msg, NULL, 0, 0) ) @@ -3032,16 +3210,6 @@ rlc_make_queue(int size) } -void -rlc_free_queue(RlcQueue q) -{ if ( q ) - { if ( q->buffer ) - rlc_free(q->buffer); - rlc_free(q); - } -} - - static int rlc_resize_queue(RlcQueue q, int size) { TCHAR *newbuf; @@ -3075,7 +3243,7 @@ rlc_add_queue(RlcData b, RlcQueue q, int chr) { if ( QN(q, q->last) != q->first ) { q->buffer[q->last] = chr; q->last = QN(q, q->last); - + if ( empty ) PostThreadMessage(b->application_thread_id, WM_RLC_INPUT, 0, 0); @@ -3098,12 +3266,6 @@ rlc_is_empty_queue(RlcQueue q) } -void -rlc_empty_queue(RlcQueue q) -{ q->first = q->last = 0; -} - - static int rlc_from_queue(RlcQueue q) { if ( q->first != q->last ) @@ -3239,7 +3401,7 @@ rlc_write(rlc_console c, TCHAR *buf, size_t count) return -1; for(s=buf, e=&buf[count]; spromptlen = 0; else if ( b->promptlen < MAXPROMPT-1 ) b->promptbuf[b->promptlen++] = *s; @@ -3248,7 +3410,7 @@ rlc_write(rlc_console c, TCHAR *buf, size_t count) if ( b->window ) { if ( SendMessageTimeout(b->window, WM_RLC_WRITE, - (WPARAM)count, + (WPARAM)count, (LPARAM)buf, SMTO_NORMAL, 10000, @@ -3334,7 +3496,7 @@ rlc_prompt(rlc_console c, const TCHAR *new) return b->prompt; } - + return _T(""); } @@ -3354,8 +3516,6 @@ rlc_clearprompt(rlc_console c) * MISC STUFF * *******************************/ -static TCHAR current_title[RLC_TITLE_MAX]; - void rlc_title(rlc_console c, TCHAR *title, TCHAR *old, int size) { RlcData b = rlc_get_data(c); @@ -3375,11 +3535,7 @@ rlc_title(rlc_console c, TCHAR *title, TCHAR *old, int size) void rlc_icon(rlc_console c, HICON icon) { -#ifdef WIN64 - SetClassLong(rlc_hwnd(c), GCLP_HICON, (LONG) icon); -#else - SetClassLong(rlc_hwnd(c), GCL_HICON, (LONG) icon); -#endif + SetClassLongPtr(rlc_hwnd(c), GCLP_HICON, (LONG_PTR) icon); } @@ -3634,7 +3790,7 @@ Dprintf(const TCHAR *fmt, ...) va_list args; va_start(args, fmt); - _vstprintf(buf, fmt, args); + vswprintf(buf, sizeof(buf)/sizeof(TCHAR), fmt, args); va_end(args); OutputDebugString(buf); diff --git a/swi/console/console.h b/swi/console/console.h index 6ce41e978..75b54b6a7 100644 --- a/swi/console/console.h +++ b/swi/console/console.h @@ -1,4 +1,4 @@ -/* $Id: console.h,v 1.1 2008-04-01 08:45:42 vsc Exp $ +/* $Id$ Part of SWI-Prolog @@ -19,7 +19,7 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _CONSOLE_H_INCLUDED @@ -41,21 +41,21 @@ #include #include -#if __GNUC__ -#include -#else +#ifdef _MSC_VER #if (_MSC_VER < 1300) typedef long intptr_t; typedef unsigned long uintptr_t; #endif +#else +#include #endif #define RLC_APPTIMER_ID 100 /* >=100: application timer */ typedef struct -{ int first; - int last; - int size; /* size of the buffer */ +{ int first; + int last; + int size; /* size of the buffer */ TCHAR *buffer; /* character buffer */ int flags; /* flags for the queue */ } rlc_queue, *RlcQueue; @@ -75,7 +75,7 @@ typedef struct int x; /* # pixels (0: default) */ int y; /* # pixels (0: default) */ int savelines; /* # lines to save (0: default) */ - TCHAR face_name[32]; /* font name */ + TCHAR face_name[32]; /* font name */ int font_family; /* family id */ int font_size; int font_weight; @@ -94,7 +94,7 @@ typedef void (*RlcResizeHook)(int, int); /* Hook for window change */ typedef void (*RlcMenuHook)(rlc_console, const TCHAR *id); /* Hook for menu-selection */ typedef void (*RlcFreeDataHook)(uintptr_t data); /* release data */ -#if defined(_WINDOWS_) || defined(_WINDOWS_H) /* is included */ +#ifdef __WINDOWS__ /* is included */ /* rlc_color(which, ...) */ #define RLC_WINDOW (0) /* window background */ #define RLC_TEXT (1) /* text color */ @@ -116,7 +116,7 @@ typedef LRESULT (*RlcMessageHook)(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); _export RlcMessageHook rlc_message_hook(RlcMessageHook hook); -#endif /*_WINDOWS_*/ +#endif /*__WINDOWS__*/ _export RlcUpdateHook rlc_update_hook(RlcUpdateHook updatehook); _export RlcTimerHook rlc_timer_hook(RlcTimerHook timerhook); @@ -182,9 +182,9 @@ _export int rlc_set(rlc_console c, int what, typedef struct _line { rlc_mark origin; /* origin of edit */ - size_t point; /* location of the caret */ + size_t point; /* location of the caret */ size_t size; /* # characters in buffer */ - size_t allocated; /* # characters allocated */ + size_t allocated; /* # characters allocated */ size_t change_start; /* start of change */ int complete; /* line is completed */ int reprompt; /* repeat the prompt */ @@ -199,6 +199,8 @@ typedef struct _line #define COMPLETE_ENUMERATE 1 #define COMPLETE_CLOSE 2 +struct _complete_data; + typedef int (*RlcCompleteFunc)(struct _complete_data *); typedef struct _complete_data @@ -221,5 +223,9 @@ _export int rlc_complete_file_function(RlcCompleteData data); _export void rlc_init_history(rlc_console c, int size); _export void rlc_add_history(rlc_console c, const TCHAR *line); _export int rlc_bind(int chr, const char *fname); +_export int rlc_for_history( + rlc_console b, + int (*handler)(void *ctx, int no, const TCHAR *line), + void *ctx); #endif /* _CONSOLE_H_INCLUDED */ diff --git a/swi/console/console_i.h b/swi/console/console_i.h index 16ede8462..9ddcf9897 100644 --- a/swi/console/console_i.h +++ b/swi/console/console_i.h @@ -1,4 +1,4 @@ -/* $Id: console_i.h,v 1.1 2008-04-01 08:50:44 vsc Exp $ +/* $Id$ Part of SWI-Prolog @@ -19,7 +19,7 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -45,7 +45,7 @@ typedef struct _history #define ANSI_MAX_ARGC 10 /* Ansi-escape sequence argv */ #define MAXPROMPT 80 /* max size of prompt */ -#define OQSIZE 4096 /* output queue size */ +#define OQSIZE 4096 /* output queue size */ #define MAX_USER_VALUES 10 /* max user data-handles */ typedef struct lqueued @@ -53,8 +53,29 @@ typedef struct lqueued struct lqueued* next; /* Next in queue */ } lqueued, *LQueued; +typedef unsigned short text_flags; + +#define ANSI_COLOR_DEFAULT 31 + +#define TF_FG(f) ((f)&0x1f) /* foreground */ +#define TF_BG(f) (((f)>>5)&0x1f) /* background */ +#define TF_BOLD(f) ((f)&(1<<10)) /* bold */ +#define TF_UNDERLINE(f) ((f)&(1<<11)) /* underline */ + +#define TF_DEFAULT (ANSI_COLOR_DEFAULT | ANSI_COLOR_DEFAULT<<5) + +#define TF_SET_FG(f,c) (((f)&~0x1f)|(c)) +#define TF_SET_BG(f,c) (((f)&~(0x1f<<5))|((c)<<5)) +#define TF_SET_BOLD(f,v) (((f)&~(1<<10))|((v)<<10)) +#define TF_SET_UNDERLINE(f,v) (((f)&~(1<<11))|((v)<<11)) + typedef struct -{ TCHAR * text; /* the storage */ +{ TCHAR code; /* character code */ + text_flags flags; /* flags for the text */ +} text_char; + +typedef struct +{ text_char *text; /* the storage */ unsigned short size; /* #characters in line */ unsigned adjusted : 1; /* line has been adjusted? */ unsigned changed : 1; /* line needs redraw */ @@ -78,7 +99,7 @@ typedef struct int caret_y; /* its line */ int window_start; /* start line of the window */ int window_size; /* #lines on the window */ - TextLine lines; /* the actual lines */ + TextLine lines; /* the actual lines */ int sel_unit; /* SEL_CHAR, SEL_WORD, SEL_LINE */ int sel_org_line; /* line origin of the selection */ int sel_org_char; /* char origin of the selection */ @@ -100,6 +121,8 @@ typedef struct COLORREF background; /* Background color */ COLORREF sel_foreground; /* Selection foreground */ COLORREF sel_background; /* Selection background */ + COLORREF ansi_color[16]; /* ANSI colors (8 normal + 8 bright) */ + text_flags sgr_flags; /* Current SGR flags */ int cw; /* character width */ int ch; /* character height */ int cb; /* baseline */ @@ -139,7 +162,7 @@ typedef struct DWORD console_thread_id; /* I/O thread id */ DWORD application_thread_id; HWND kill_window; /* window in app thread for destroy */ - + user_data values[MAX_USER_VALUES]; /* associated user data */ } rlc_data, *RlcData; diff --git a/swi/console/edit.c b/swi/console/edit.c index 61bafeae6..0de90ca93 100644 --- a/swi/console/edit.c +++ b/swi/console/edit.c @@ -1,4 +1,4 @@ -/* $Id: edit.c,v 1.1 2008-03-27 00:41:33 vsc Exp $ +/* $Id$ Part of SWI-Prolog @@ -19,13 +19,13 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#define _MAKE_DLL 1 -#undef _export #include #include +#define _MAKE_DLL 1 +#undef _export #include "console.h" #include "console_i.h" #include "common.h" @@ -127,7 +127,7 @@ delete(Line ln, size_t from, size_t len) _tcsncpy(&ln->data[from], &ln->data[from+len], ln->size - (from+len)); ln->size -= len; -} +} /******************************* @@ -232,7 +232,7 @@ forward_word(Line ln, int chr) static void backward_delete_word(Line ln, int chr) { size_t from = back_word(ln, ln->point); - + memmove(&ln->data[from], &ln->data[ln->point], (ln->size - ln->point)*sizeof(TCHAR)); ln->size -= ln->point - from; @@ -244,7 +244,7 @@ backward_delete_word(Line ln, int chr) static void forward_delete_word(Line ln, int chr) { size_t to = forw_word(ln, ln->point); - + memmove(&ln->data[ln->point], &ln->data[to], (ln->size - to)*sizeof(TCHAR)); ln->size -= to - ln->point; changed(ln, ln->point); @@ -258,7 +258,7 @@ transpose_chars(Line ln, int chr) ln->data[ln->point-1] = ln->data[ln->point]; ln->data[ln->point] = c0; changed(ln, ln->point-1); - } + } } @@ -291,7 +291,7 @@ empty_line(Line ln, int chr) static void enter(Line ln, int chr) { ln->point = ln->size; -#ifdef DOS_CRNL +#ifdef DOS_CRNL make_room(ln, 2); ln->data[ln->point++] = '\r'; ln->data[ln->point++] = '\n'; @@ -325,7 +325,7 @@ delete_character_or_eof(Line ln, int chr) static void undefined(Line ln, int chr) -{ +{ } @@ -442,7 +442,7 @@ complete(Line ln, int chr) } data->call_type = COMPLETE_CLOSE; (*data->function)(data); - + delete(ln, data->replace_from, patlen); ln->point = data->replace_from; make_room(ln, ncommon); @@ -487,7 +487,7 @@ list_completions(Line ln, int chr) if ( nmatches > COMPLETE_MAX_MATCHES ) { TCHAR *msg = _T("\r\n! Too many matches\r\n"); - + while(*msg) rlc_putchar(ln->console, *msg++); ln->reprompt = TRUE; @@ -511,7 +511,7 @@ list_completions(Line ln, int chr) { len++; rlc_putchar(ln->console, *s++); } - + rlc_free(buf[n++]); if ( n % cols == 0 ) @@ -552,7 +552,7 @@ update_display(Line ln) { if ( ln->reprompt ) { const TCHAR *prompt = rlc_prompt(ln->console, NULL); const TCHAR *s = prompt; - + rlc_putchar(ln->console, '\r'); while(*s) rlc_putchar(ln->console, *s++); @@ -646,7 +646,7 @@ init_dispatch_table() dispatch_table[n] = insert_self; for(n=0; n<256; n++) dispatch_meta[n] = undefined; - + bind_actions(); done = TRUE; @@ -704,7 +704,7 @@ int rlc_bind(int chr, const char *fname) { if ( chr >= 0 && chr <= 256 ) { Action a = actions; - + for( ; a->name; a++ ) { if ( strcmp(a->name, fname) == 0 ) { if ( chr > META_OFFSET ) diff --git a/swi/console/history.c b/swi/console/history.c index 2131d7d68..1958bc4b7 100644 --- a/swi/console/history.c +++ b/swi/console/history.c @@ -1,4 +1,4 @@ -/* $Id: history.c,v 1.1 2008-03-27 00:41:33 vsc Exp $ +/* $Id$ Part of SWI-Prolog @@ -19,13 +19,13 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#define _MAKE_DLL 1 -#undef _export #include #include +#define _MAKE_DLL 1 +#undef _export #include "console.h" /* public stuff */ #include "console_i.h" /* internal stuff */ #include @@ -100,7 +100,7 @@ rlc_add_history(rlc_console c, const TCHAR *line) { b->history.current = -1; return; /* same as last line added */ } - + if ( i == b->history.tail ) /* this one is lost */ b->history.tail = next(b, b->history.tail); b->history.head = i; @@ -120,6 +120,25 @@ rlc_add_history(rlc_console c, const TCHAR *line) } +int +rlc_for_history(rlc_console c, + int (*handler)(void *ctx, int no, const TCHAR *line), + void *ctx) +{ RlcData b = rlc_get_data(c); + int here = b->history.head; + int no = 1; + + for( ; here != b->history.tail; here = prev(b, here)) + { int rc; + + if ( (rc=(*handler)(ctx, no++, b->history.lines[here])) != 0 ) + return rc; + } + + return 0; +} + + int rlc_at_head_history(RlcData b) { return b->history.current == -1 ? TRUE : FALSE; diff --git a/swi/console/history.h b/swi/console/history.h index 3e6a8e2bc..8f0380298 100644 --- a/swi/console/history.h +++ b/swi/console/history.h @@ -1,4 +1,4 @@ -/* $Id: history.h,v 1.1 2008-04-01 08:52:50 vsc Exp $ +/* $Id$ Part of SWI-Prolog @@ -19,7 +19,7 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* history.c */ diff --git a/swi/console/menu.c b/swi/console/menu.c index 65e19c27b..40263cb77 100644 --- a/swi/console/menu.c +++ b/swi/console/menu.c @@ -1,4 +1,4 @@ -/* $Id: menu.c,v 1.1 2008-03-27 00:41:33 vsc Exp $ +/* $Id$ Part of SWI-Prolog @@ -19,12 +19,13 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include -#define _MAKE_DLL +#define _MAKE_DLL 1 +#undef _export #include "console.h" #include "console_i.h" #include "menu.h" @@ -83,7 +84,7 @@ lookupMenuLabel(const TCHAR *label) llen = _tcslen(label); menuids[nmenus] = rlc_malloc((llen+1)*sizeof(TCHAR)); _tcsncpy(menuids[nmenus], label, llen+1); - + return nmenus++ + IDM_USER; } @@ -109,7 +110,7 @@ insertMenu(HMENU in, const TCHAR *label, const TCHAR *before) AppendMenu(in, MF_SEPARATOR, 0, NULL); else { UINT id = lookupMenuLabel(label); - + AppendMenu(in, MF_STRING, id, label); } } else @@ -199,15 +200,15 @@ rlc_add_menu_bar(HWND cwin) /*append_builtin(edit, IDM_CUT);*/ append_builtin(edit, IDM_COPY); append_builtin(edit, IDM_PASTE); - + append_builtin(settings, IDM_FONT); append_builtin(run, IDM_BREAK); - AppendMenu(menu, MF_POPUP, (UINT)file, _T("&File")); - AppendMenu(menu, MF_POPUP, (UINT)edit, _T("&Edit")); - AppendMenu(menu, MF_POPUP, (UINT)settings, _T("&Settings")); - AppendMenu(menu, MF_POPUP, (UINT)run, _T("&Run")); + AppendMenu(menu, MF_POPUP, (UINT_PTR)file, _T("&File")); + AppendMenu(menu, MF_POPUP, (UINT_PTR)edit, _T("&Edit")); + AppendMenu(menu, MF_POPUP, (UINT_PTR)settings, _T("&Settings")); + AppendMenu(menu, MF_POPUP, (UINT_PTR)run, _T("&Run")); SetMenu(cwin, menu); } @@ -218,13 +219,22 @@ rlc_add_menu_bar(HWND cwin) #define MEN_MAGIC 0x6c4a58e0 +typedef struct menu_data +{ intptr_t magic; /* safety */ + const TCHAR *menu; /* menu to operate on */ + const TCHAR *label; /* new label */ + const TCHAR *before; /* add before this one */ + int rc; /* result */ +} menu_data; + + void rlc_menu_action(rlc_console c, menu_data *data) { RlcData b = rlc_get_data(c); if ( !data || !data->magic == MEN_MAGIC ) return; - + if ( data->menu ) /* rlc_insert_menu_item() */ { HMENU popup; @@ -255,7 +265,7 @@ rlc_menu_action(rlc_console c, menu_data *data) info.hSubMenu = CreatePopupMenu(); info.dwTypeData = (TCHAR *)data->label; info.cch = (int)_tcslen(data->label); - + InsertMenuItem(mb, bid, TRUE, &info); /* force redraw; not automatic! */ DrawMenuBar(hwnd); diff --git a/swi/console/menu.h b/swi/console/menu.h index f3653d112..aee7875df 100644 --- a/swi/console/menu.h +++ b/swi/console/menu.h @@ -1,4 +1,4 @@ -/* $Id: menu.h,v 1.1 2008-04-01 08:50:44 vsc Exp $ +/* $Id$ Part of SWI-Prolog @@ -19,7 +19,7 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* see also console.c */ @@ -35,14 +35,7 @@ #define IDM_BREAK 14 #define IDM_FONT 15 -typedef struct menu_data -{ intptr_t magic; /* safety */ - const TCHAR *menu; /* menu to operate on */ - const TCHAR *label; /* new label */ - const TCHAR *before; /* add before this one */ - int rc; /* result */ -} menu_data; - +struct menu_data; const TCHAR *lookupMenuId(UINT id); void rlc_add_menu_bar(HWND win); diff --git a/swi/console/registry.c b/swi/console/registry.c index 8f387e623..5e33c0c24 100644 --- a/swi/console/registry.c +++ b/swi/console/registry.c @@ -1,4 +1,4 @@ -/* $Id: registry.c,v 1.1 2008-03-27 00:41:33 vsc Exp $ +/* $Id$ Part of SWI-Prolog @@ -19,7 +19,7 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include