From 83c20c89439386f31050718c94551d863298cdb9 Mon Sep 17 00:00:00 2001 From: mitchell <70453897+667e-11@users.noreply.github.com> Date: Sat, 25 Oct 2014 00:30:36 -0400 Subject: Improvements to terminal mouse handling. Emit events for unhandled mouse events and connect to such events in order to focus and resize views. Patch libtermkey with new Win32 PDCurses driver for unified key/mouse input. Update CDK patch to always use libtermkey and to ignore mouse events. Requires Scinterm r97 (changeset 8d1a625c9b4d). Thanks to Chris Emerson for proof of concept code that handles mouse events and for the code that focuses and resizes views. --- core/.buffer.luadoc | 6 + core/events.lua | 18 ++- core/iface.lua | 2 +- core/ui.lua | 49 ++++++++ properties.lua | 8 +- scripts/gen_iface.lua | 5 + src/Makefile | 27 ++-- src/cdk.patch | 17 ++- src/termkey.patch | 339 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/textadept.c | 99 +++++---------- 10 files changed, 473 insertions(+), 97 deletions(-) create mode 100644 src/termkey.patch diff --git a/core/.buffer.luadoc b/core/.buffer.luadoc index c5e5e2fd..f9b92834 100644 --- a/core/.buffer.luadoc +++ b/core/.buffer.luadoc @@ -1002,6 +1002,12 @@ -- -- @field MOD_SUPER (number, Read-only) -- +-- @field MOUSE_DRAG (number, Read-only) +-- +-- @field MOUSE_PRESS (number, Read-only) +-- +-- @field MOUSE_RELEASE (number, Read-only) +-- -- @field VS_NONE (number, Read-only) -- -- @field VS_RECTANGULARSELECTION (number, Read-only) diff --git a/core/events.lua b/core/events.lua index 56331196..c63e98a8 100644 --- a/core/events.lua +++ b/core/events.lua @@ -192,6 +192,18 @@ local M = {} -- Arguments: -- -- * _`menu_id`_: The numeric ID of the menu item set in [`ui.menu()`](). +-- @field MOUSE (string) +-- Emitted by the terminal version for an unhandled mouse event. +-- Arguments: +-- +-- * _`event`_: The mouse event: `buffer.MOUSE_PRESS`, `buffer.MOUSE_DRAG`, or +-- `buffer.MOUSE_RELEASE`. +-- * _`button`_: The mouse button number. +-- * _`y`_: The y-coordinate of the mouse event, starting from 1. +-- * _`x`_: The x-coordinate of the mouse event, starting from 1. +-- * _`shift`_: The "Shift" modifier key is held down. +-- * _`ctrl`_: The "Control" modifier key is held down. +-- * _`alt`_: The "Alt"/"Option" modifier key is held down. -- @field QUIT (string) -- Emitted when quitting Textadept. -- When connecting to this event, connect with an index of 1 or the handler @@ -366,9 +378,9 @@ for _, n in pairs(scnotifications) do M[n[1]:upper()] = n[1] end local ta_events = { 'appleevent_odoc', 'buffer_after_switch', 'buffer_before_switch', 'buffer_deleted', 'buffer_new', 'csi', 'error', 'find', 'focus', - 'initialized', 'keypress', 'menu_clicked', 'quit', 'replace', 'replace_all', - 'reset_after', 'reset_before', 'view_after_switch', 'view_before_switch', - 'view_new' + 'initialized', 'keypress', 'menu_clicked', 'mouse', 'quit', 'replace', + 'replace_all', 'reset_after', 'reset_before', 'view_after_switch', + 'view_before_switch', 'view_new' } for _, e in pairs(ta_events) do M[e:upper()] = e end diff --git a/core/iface.lua b/core/iface.lua index c56ccca3..1fbc89e5 100644 --- a/core/iface.lua +++ b/core/iface.lua @@ -14,7 +14,7 @@ module('_SCINTILLA')]] -- @class table -- @name constants -- @see _G.buffer -M.constants = {ALPHA_NOALPHA=256,ALPHA_OPAQUE=255,ALPHA_TRANSPARENT=0,ANNOTATION_BOXED=2,ANNOTATION_HIDDEN=0,ANNOTATION_STANDARD=1,AUTOMATICFOLD_CHANGE=0x0004,AUTOMATICFOLD_CLICK=0x0002,AUTOMATICFOLD_SHOW=0x0001,CARETSTICKY_OFF=0,CARETSTICKY_ON=1,CARETSTICKY_WHITESPACE=2,CARETSTYLE_BLOCK=2,CARETSTYLE_INVISIBLE=0,CARETSTYLE_LINE=1,CARET_EVEN=0x08,CARET_JUMPS=0x10,CARET_SLOP=0x01,CARET_STRICT=0x04,CASEINSENSITIVEBEHAVIOUR_IGNORECASE=1,CASEINSENSITIVEBEHAVIOUR_RESPECTCASE=0,CASE_LOWER=2,CASE_MIXED=0,CASE_UPPER=1,CP_UTF8=65001,CURSORARROW=2,CURSORNORMAL=-1,CURSORREVERSEARROW=7,CURSORWAIT=4,EDGE_BACKGROUND=2,EDGE_LINE=1,EDGE_NONE=0,EOL_CR=1,EOL_CRLF=0,EOL_LF=2,FIND_MATCHCASE=0x4,FIND_REGEXP=6291456,FIND_WHOLEWORD=0x2,FIND_WORDSTART=0x00100000,FOLDACTION_CONTRACT=0,FOLDACTION_EXPAND=1,FOLDACTION_TOGGLE=2,FOLDFLAG_LEVELNUMBERS=0x0040,FOLDFLAG_LINEAFTER_CONTRACTED=0x0010,FOLDFLAG_LINEAFTER_EXPANDED=0x0008,FOLDFLAG_LINEBEFORE_CONTRACTED=0x0004,FOLDFLAG_LINEBEFORE_EXPANDED=0x0002,FOLDFLAG_LINESTATE=0x0080,FOLDLEVELBASE=0x400,FOLDLEVELHEADERFLAG=0x2000,FOLDLEVELNUMBERMASK=0x0FFF,FOLDLEVELWHITEFLAG=0x1000,IME_INLINE=1,IME_WINDOWED=0,INDIC_BOX=6,INDIC_COMPOSITIONTHICK=14,INDIC_CONTAINER=8,INDIC_DASH=9,INDIC_DIAGONAL=3,INDIC_DOTBOX=12,INDIC_DOTS=10,INDIC_HIDDEN=5,INDIC_MAX=31,INDIC_PLAIN=0,INDIC_ROUNDBOX=7,INDIC_SQUIGGLE=1,INDIC_SQUIGGLELOW=11,INDIC_SQUIGGLEPIXMAP=13,INDIC_STRAIGHTBOX=8,INDIC_STRIKE=4,INDIC_TT=2,IV_LOOKBOTH=3,IV_LOOKFORWARD=2,IV_NONE=0,IV_REAL=1,LASTSTEPINUNDOREDO=0x100,MARGINOPTION_NONE=0,MARGINOPTION_SUBLINESELECT=1,MARGIN_BACK=2,MARGIN_FORE=3,MARGIN_NUMBER=1,MARGIN_RTEXT=5,MARGIN_SYMBOL=0,MARGIN_TEXT=4,MARKER_MAX=31,MARKNUM_FOLDER=30,MARKNUM_FOLDEREND=25,MARKNUM_FOLDERMIDTAIL=27,MARKNUM_FOLDEROPEN=31,MARKNUM_FOLDEROPENMID=26,MARKNUM_FOLDERSUB=29,MARKNUM_FOLDERTAIL=28,MARK_ARROW=2,MARK_ARROWDOWN=6,MARK_ARROWS=24,MARK_AVAILABLE=28,MARK_BACKGROUND=22,MARK_BOOKMARK=31,MARK_BOXMINUS=14,MARK_BOXMINUSCONNECTED=15,MARK_BOXPLUS=12,MARK_BOXPLUSCONNECTED=13,MARK_CHARACTER=10000,MARK_CIRCLE=0,MARK_CIRCLEMINUS=20,MARK_CIRCLEMINUSCONNECTED=21,MARK_CIRCLEPLUS=18,MARK_CIRCLEPLUSCONNECTED=19,MARK_DOTDOTDOT=23,MARK_EMPTY=5,MARK_FULLRECT=26,MARK_LCORNER=10,MARK_LCORNERCURVE=16,MARK_LEFTRECT=27,MARK_MINUS=7,MARK_PIXMAP=25,MARK_PLUS=8,MARK_RGBAIMAGE=30,MARK_ROUNDRECT=1,MARK_SHORTARROW=4,MARK_SMALLRECT=3,MARK_TCORNER=11,MARK_TCORNERCURVE=17,MARK_UNDERLINE=29,MARK_VLINE=9,MASK_FOLDERS=-33554432,MAX_MARGIN=4,MODEVENTMASKALL=0x3FFFFF,MOD_ALT=4,MOD_BEFOREDELETE=0x800,MOD_BEFOREINSERT=0x400,MOD_CHANGEANNOTATION=0x20000,MOD_CHANGEFOLD=0x8,MOD_CHANGEINDICATOR=0x4000,MOD_CHANGELINESTATE=0x8000,MOD_CHANGEMARGIN=0x10000,MOD_CHANGEMARKER=0x200,MOD_CHANGESTYLE=0x4,MOD_CHANGETABSTOPS=0x200000,MOD_CONTAINER=0x40000,MOD_CTRL=2,MOD_DELETETEXT=0x2,MOD_INSERTCHECK=0x100000,MOD_INSERTTEXT=0x1,MOD_LEXERSTATE=0x80000,MOD_META=16,MOD_NORM=0,MOD_SHIFT=1,MOD_SUPER=8,MULTIAUTOC_EACH=1,MULTIAUTOC_ONCE=0,MULTILINEUNDOREDO=0x1000,MULTIPASTE_EACH=1,MULTIPASTE_ONCE=0,MULTISTEPUNDOREDO=0x80,ORDER_CUSTOM=2,ORDER_PERFORMSORT=1,ORDER_PRESORTED=0,PERFORMED_REDO=0x40,PERFORMED_UNDO=0x20,PERFORMED_USER=0x10,PHASES_MULTIPLE=2,PHASES_ONE=0,PHASES_TWO=1,SCN_AUTOCCANCELLED=2025,SCN_AUTOCCHARDELETED=2026,SCN_AUTOCSELECTION=2022,SCN_CALLTIPCLICK=2021,SCN_CHARADDED=2001,SCN_DOUBLECLICK=2006,SCN_DWELLEND=2017,SCN_DWELLSTART=2016,SCN_FOCUSIN=2028,SCN_FOCUSOUT=2029,SCN_HOTSPOTCLICK=2019,SCN_HOTSPOTDOUBLECLICK=2020,SCN_HOTSPOTRELEASECLICK=2027,SCN_INDICATORCLICK=2023,SCN_INDICATORRELEASE=2024,SCN_KEY=2005,SCN_MACRORECORD=2009,SCN_MARGINCLICK=2010,SCN_MODIFIED=2008,SCN_MODIFYATTEMPTRO=2004,SCN_NEEDSHOWN=2011,SCN_PAINTED=2013,SCN_SAVEPOINTLEFT=2003,SCN_SAVEPOINTREACHED=2002,SCN_STYLENEEDED=2000,SCN_UPDATEUI=2007,SCN_URIDROPPED=2015,SCN_USERLISTSELECTION=2014,SCN_ZOOM=2018,SEL_LINES=2,SEL_RECTANGLE=1,SEL_STREAM=0,SEL_THIN=3,STARTACTION=0x2000,STYLE_BRACEBAD=35,STYLE_BRACELIGHT=34,STYLE_CALLTIP=38,STYLE_CONTROLCHAR=36,STYLE_DEFAULT=32,STYLE_INDENTGUIDE=37,STYLE_LASTPREDEFINED=39,STYLE_LINENUMBER=33,STYLE_MAX=255,TIME_FOREVER=10000000,UPDATE_CONTENT=0x1,UPDATE_H_SCROLL=0x8,UPDATE_SELECTION=0x2,UPDATE_V_SCROLL=0x4,VISIBLE_SLOP=0x01,VISIBLE_STRICT=0x04,VS_NONE=0,VS_RECTANGULARSELECTION=1,VS_USERACCESSIBLE=2,WRAPINDENT_FIXED=0,WRAPINDENT_INDENT=2,WRAPINDENT_SAME=1,WRAPVISUALFLAGLOC_DEFAULT=0x0000,WRAPVISUALFLAGLOC_END_BY_TEXT=0x0001,WRAPVISUALFLAGLOC_START_BY_TEXT=0x0002,WRAPVISUALFLAG_END=0x0001,WRAPVISUALFLAG_MARGIN=0x0004,WRAPVISUALFLAG_NONE=0x0000,WRAPVISUALFLAG_START=0x0002,WRAP_CHAR=2,WRAP_NONE=0,WRAP_WHITESPACE=3,WRAP_WORD=1,WS_INVISIBLE=0,WS_VISIBLEAFTERINDENT=2,WS_VISIBLEALWAYS=1} +M.constants = {ALPHA_NOALPHA=256,ALPHA_OPAQUE=255,ALPHA_TRANSPARENT=0,ANNOTATION_BOXED=2,ANNOTATION_HIDDEN=0,ANNOTATION_STANDARD=1,AUTOMATICFOLD_CHANGE=0x0004,AUTOMATICFOLD_CLICK=0x0002,AUTOMATICFOLD_SHOW=0x0001,CARETSTICKY_OFF=0,CARETSTICKY_ON=1,CARETSTICKY_WHITESPACE=2,CARETSTYLE_BLOCK=2,CARETSTYLE_INVISIBLE=0,CARETSTYLE_LINE=1,CARET_EVEN=0x08,CARET_JUMPS=0x10,CARET_SLOP=0x01,CARET_STRICT=0x04,CASEINSENSITIVEBEHAVIOUR_IGNORECASE=1,CASEINSENSITIVEBEHAVIOUR_RESPECTCASE=0,CASE_LOWER=2,CASE_MIXED=0,CASE_UPPER=1,CP_UTF8=65001,CURSORARROW=2,CURSORNORMAL=-1,CURSORREVERSEARROW=7,CURSORWAIT=4,EDGE_BACKGROUND=2,EDGE_LINE=1,EDGE_NONE=0,EOL_CR=1,EOL_CRLF=0,EOL_LF=2,FIND_MATCHCASE=0x4,FIND_REGEXP=6291456,FIND_WHOLEWORD=0x2,FIND_WORDSTART=0x00100000,FOLDACTION_CONTRACT=0,FOLDACTION_EXPAND=1,FOLDACTION_TOGGLE=2,FOLDFLAG_LEVELNUMBERS=0x0040,FOLDFLAG_LINEAFTER_CONTRACTED=0x0010,FOLDFLAG_LINEAFTER_EXPANDED=0x0008,FOLDFLAG_LINEBEFORE_CONTRACTED=0x0004,FOLDFLAG_LINEBEFORE_EXPANDED=0x0002,FOLDFLAG_LINESTATE=0x0080,FOLDLEVELBASE=0x400,FOLDLEVELHEADERFLAG=0x2000,FOLDLEVELNUMBERMASK=0x0FFF,FOLDLEVELWHITEFLAG=0x1000,IME_INLINE=1,IME_WINDOWED=0,INDIC_BOX=6,INDIC_COMPOSITIONTHICK=14,INDIC_CONTAINER=8,INDIC_DASH=9,INDIC_DIAGONAL=3,INDIC_DOTBOX=12,INDIC_DOTS=10,INDIC_HIDDEN=5,INDIC_MAX=31,INDIC_PLAIN=0,INDIC_ROUNDBOX=7,INDIC_SQUIGGLE=1,INDIC_SQUIGGLELOW=11,INDIC_SQUIGGLEPIXMAP=13,INDIC_STRAIGHTBOX=8,INDIC_STRIKE=4,INDIC_TT=2,IV_LOOKBOTH=3,IV_LOOKFORWARD=2,IV_NONE=0,IV_REAL=1,LASTSTEPINUNDOREDO=0x100,MARGINOPTION_NONE=0,MARGINOPTION_SUBLINESELECT=1,MARGIN_BACK=2,MARGIN_FORE=3,MARGIN_NUMBER=1,MARGIN_RTEXT=5,MARGIN_SYMBOL=0,MARGIN_TEXT=4,MARKER_MAX=31,MARKNUM_FOLDER=30,MARKNUM_FOLDEREND=25,MARKNUM_FOLDERMIDTAIL=27,MARKNUM_FOLDEROPEN=31,MARKNUM_FOLDEROPENMID=26,MARKNUM_FOLDERSUB=29,MARKNUM_FOLDERTAIL=28,MARK_ARROW=2,MARK_ARROWDOWN=6,MARK_ARROWS=24,MARK_AVAILABLE=28,MARK_BACKGROUND=22,MARK_BOOKMARK=31,MARK_BOXMINUS=14,MARK_BOXMINUSCONNECTED=15,MARK_BOXPLUS=12,MARK_BOXPLUSCONNECTED=13,MARK_CHARACTER=10000,MARK_CIRCLE=0,MARK_CIRCLEMINUS=20,MARK_CIRCLEMINUSCONNECTED=21,MARK_CIRCLEPLUS=18,MARK_CIRCLEPLUSCONNECTED=19,MARK_DOTDOTDOT=23,MARK_EMPTY=5,MARK_FULLRECT=26,MARK_LCORNER=10,MARK_LCORNERCURVE=16,MARK_LEFTRECT=27,MARK_MINUS=7,MARK_PIXMAP=25,MARK_PLUS=8,MARK_RGBAIMAGE=30,MARK_ROUNDRECT=1,MARK_SHORTARROW=4,MARK_SMALLRECT=3,MARK_TCORNER=11,MARK_TCORNERCURVE=17,MARK_UNDERLINE=29,MARK_VLINE=9,MASK_FOLDERS=-33554432,MAX_MARGIN=4,MODEVENTMASKALL=0x3FFFFF,MOD_ALT=4,MOD_BEFOREDELETE=0x800,MOD_BEFOREINSERT=0x400,MOD_CHANGEANNOTATION=0x20000,MOD_CHANGEFOLD=0x8,MOD_CHANGEINDICATOR=0x4000,MOD_CHANGELINESTATE=0x8000,MOD_CHANGEMARGIN=0x10000,MOD_CHANGEMARKER=0x200,MOD_CHANGESTYLE=0x4,MOD_CHANGETABSTOPS=0x200000,MOD_CONTAINER=0x40000,MOD_CTRL=2,MOD_DELETETEXT=0x2,MOD_INSERTCHECK=0x100000,MOD_INSERTTEXT=0x1,MOD_LEXERSTATE=0x80000,MOD_META=16,MOD_NORM=0,MOD_SHIFT=1,MOD_SUPER=8,MOUSE_DRAG=2,MOUSE_PRESS=1,MOUSE_RELEASE=3,MULTIAUTOC_EACH=1,MULTIAUTOC_ONCE=0,MULTILINEUNDOREDO=0x1000,MULTIPASTE_EACH=1,MULTIPASTE_ONCE=0,MULTISTEPUNDOREDO=0x80,ORDER_CUSTOM=2,ORDER_PERFORMSORT=1,ORDER_PRESORTED=0,PERFORMED_REDO=0x40,PERFORMED_UNDO=0x20,PERFORMED_USER=0x10,PHASES_MULTIPLE=2,PHASES_ONE=0,PHASES_TWO=1,SCN_AUTOCCANCELLED=2025,SCN_AUTOCCHARDELETED=2026,SCN_AUTOCSELECTION=2022,SCN_CALLTIPCLICK=2021,SCN_CHARADDED=2001,SCN_DOUBLECLICK=2006,SCN_DWELLEND=2017,SCN_DWELLSTART=2016,SCN_FOCUSIN=2028,SCN_FOCUSOUT=2029,SCN_HOTSPOTCLICK=2019,SCN_HOTSPOTDOUBLECLICK=2020,SCN_HOTSPOTRELEASECLICK=2027,SCN_INDICATORCLICK=2023,SCN_INDICATORRELEASE=2024,SCN_KEY=2005,SCN_MACRORECORD=2009,SCN_MARGINCLICK=2010,SCN_MODIFIED=2008,SCN_MODIFYATTEMPTRO=2004,SCN_NEEDSHOWN=2011,SCN_PAINTED=2013,SCN_SAVEPOINTLEFT=2003,SCN_SAVEPOINTREACHED=2002,SCN_STYLENEEDED=2000,SCN_UPDATEUI=2007,SCN_URIDROPPED=2015,SCN_USERLISTSELECTION=2014,SCN_ZOOM=2018,SEL_LINES=2,SEL_RECTANGLE=1,SEL_STREAM=0,SEL_THIN=3,STARTACTION=0x2000,STYLE_BRACEBAD=35,STYLE_BRACELIGHT=34,STYLE_CALLTIP=38,STYLE_CONTROLCHAR=36,STYLE_DEFAULT=32,STYLE_INDENTGUIDE=37,STYLE_LASTPREDEFINED=39,STYLE_LINENUMBER=33,STYLE_MAX=255,TIME_FOREVER=10000000,UPDATE_CONTENT=0x1,UPDATE_H_SCROLL=0x8,UPDATE_SELECTION=0x2,UPDATE_V_SCROLL=0x4,VISIBLE_SLOP=0x01,VISIBLE_STRICT=0x04,VS_NONE=0,VS_RECTANGULARSELECTION=1,VS_USERACCESSIBLE=2,WRAPINDENT_FIXED=0,WRAPINDENT_INDENT=2,WRAPINDENT_SAME=1,WRAPVISUALFLAGLOC_DEFAULT=0x0000,WRAPVISUALFLAGLOC_END_BY_TEXT=0x0001,WRAPVISUALFLAGLOC_START_BY_TEXT=0x0002,WRAPVISUALFLAG_END=0x0001,WRAPVISUALFLAG_MARGIN=0x0004,WRAPVISUALFLAG_NONE=0x0000,WRAPVISUALFLAG_START=0x0002,WRAP_CHAR=2,WRAP_NONE=0,WRAP_WHITESPACE=3,WRAP_WORD=1,WS_INVISIBLE=0,WS_VISIBLEAFTERINDENT=2,WS_VISIBLEALWAYS=1} --- -- Map of Scintilla function names to tables containing their IDs, return types, diff --git a/core/ui.lua b/core/ui.lua index 9d7788be..24a5cbaf 100644 --- a/core/ui.lua +++ b/core/ui.lua @@ -401,6 +401,55 @@ events_connect(events.BUFFER_DELETED, function() if i and _BUFFERS[buffer] ~= i then view:goto_buffer(i) end end) +-- Enables and disables mouse mode in curses and focuses and resizes views based +-- on mouse events. +if CURSES then + if not WIN32 then + io.stdout:write("\x1b[?1002h") -- enable mouse mode + io.stdout:flush() + events.connect(events.QUIT, function() + io.stdout:write("\x1b[?1002l") -- disable mouse mode + io.stdout:flush() + end, 1) + end + + -- Retrieves the view or split at the given terminal coordinates. + -- @param view View or split to test for coordinates within. + -- @param y The y terminal coordinate. + -- @param x The x terminal coordinate. + local function get_view(view, y, x) + if not view[1] and not view[2] then return view end + local vertical, size = view.vertical, view.size + if vertical and x < size or not vertical and y < size then + return get_view(view[1], y, x) + elseif vertical and x > size or not vertical and y > size then + -- Zero y or x relative to the other view based on split orientation. + return get_view(view[2], vertical and y or y - size - 1, + vertical and x - size - 1 or x) + else + return view -- in-between views; return the split itself + end + end + + local resize + events.connect(events.MOUSE, function(event, button, y, x) + if event == buffer.MOUSE_RELEASE or button ~= 1 then return end + if event == buffer.MOUSE_PRESS then + local view = get_view(ui.get_split_table(), y - 1, x) -- title is at y=1 + if not view[1] and not view[2] then + ui.goto_view(_VIEWS[view]) + resize = nil + else + resize = function(y2, x2) + view[1].size = view.size + (view.vertical and x2 - x or y2 - y) + end + end + elseif resize then + resize(y, x) + end + end) +end + events_connect(events.ERROR, ui.print) --[[ The tables below were defined in C. diff --git a/properties.lua b/properties.lua index 43bc5d30..55ad116d 100644 --- a/properties.lua +++ b/properties.lua @@ -8,9 +8,11 @@ buffer.additional_selection_typing = true --buffer.multi_paste = buffer.MULTIPASTE_EACH --buffer.virtual_space_options = buffer.VS_RECTANGULARSELECTION + -- buffer.VS_USERACCESSIBLE -buffer.rectangular_selection_modifier = (WIN32 or OSX) and buffer.MOD_ALT or - buffer.MOD_SUPER --- Note: rectangular selection modifier for CURSES is always ctrl + alt. +if not CURSES then + -- Note: Always Ctrl+Alt on non-Win32 curses and always Alt on Win32 curses. + buffer.rectangular_selection_modifier = (WIN32 or OSX) and buffer.MOD_ALT or + buffer.MOD_SUPER +end --buffer.additional_carets_blink = false --buffer.additional_carets_visible = false diff --git a/scripts/gen_iface.lua b/scripts/gen_iface.lua index cf06ff75..49fd747e 100755 --- a/scripts/gen_iface.lua +++ b/scripts/gen_iface.lua @@ -77,6 +77,11 @@ for line in io.lines('../src/scintilla/include/Scintilla.iface') do ::continue:: end +-- Add mouse events from Scinterm manually. +constants[#constants + 1] = 'MOUSE_PRESS=1' +constants[#constants + 1] = 'MOUSE_DRAG=2' +constants[#constants + 1] = 'MOUSE_RELEASE=3' + table.sort(constants) table.sort(functions) table.sort(properties) diff --git a/src/Makefile b/src/Makefile index 8a17c517..9e7cf185 100644 --- a/src/Makefile +++ b/src/Makefile @@ -137,7 +137,9 @@ luajit_lib_objs = lpcapjit.o lpcodejit.o lpprintjit.o lptreejit.o lpvmjit.o \ lfsjit.o lua_spawn_objs = lspawn.o lspawnjit.o lspawn-curses.o lspawnjit-curses.o gtdialog_objs = gtdialog.o gtdialog-curses.o -termkey_objs = termkey.o driver-ti.o driver-csi.o +termkey_unix_objs = driver-ti.o driver-csi.o +termkey_win32_objs = driver-win32-pdcurses.o +termkey_objs = termkey.o $(termkey_unix_objs) $(termkey_win32_objs) windowman_objs = windowman.o cdk_objs = binding.o buttonbox.o button.o cdk.o cdk_display.o cdk_objs.o \ cdk_params.o cdkscreen.o debug.o draw.o entry.o fselect.o \ @@ -188,7 +190,8 @@ $(windowman_objs): %.o: windowman/%.c $(cdk_objs): %.o: cdk/%.c $(CROSS)$(CC) -c $(CFLAGS) -D_GNU_SOURCE -Itermkey -Icdk $(CURSES_CFLAGS) $< \ -o $@ -$(termkey_objs): %.o: termkey/%.c ; $(CROSS)$(CC) -c $(CFLAGS) -std=c99 $< -o $@ +$(termkey_objs): %.o: termkey/%.c + $(CROSS)$(CC) -c $(CFLAGS) -std=c99 $(termkey_flags) $< -o $@ textadept_rc.o: textadept.rc ; $(CROSS)$(WINDRES) $< $@ # Target-specific variables. @@ -209,6 +212,7 @@ lspawn.o lspawnjit.o: spawn_flags = -DGTK $(GLIB_CFLAGS) $(gtdialog_objs): gtdialog_flags = $(plat_flag) -DNOHELP -DLIBRARY gtdialog.o: gtdialog_flags += $(GTK_CFLAGS) gtdialog-curses.o: gtdialog_flags += -Icdk $(CURSES_CFLAGS) +$(termkey_win32_objs): termkey_flags += $(CURSES_CFLAGS) # Executables. @@ -221,14 +225,14 @@ textadeptjit: $(sci_objs) $(sci_lex_objs) $(sci_gtk_objs) scintilla-marshal.o \ $(CROSS)$(CXX) $(CXXFLAGS) -o ../$@ $^ $(GTK_LIBS) $(LDFLAGS) textadept-curses: $(sci_objs) $(sci_lex_objs) ScintillaTerm.o LexLPeg-curses.o \ textadept-curses.o $(lua_objs) $(lua_lib_objs) \ - lspawn-curses.o gtdialog-curses.o $(termkey_objs) \ - $(windowman_objs) $(cdk_objs) + lspawn-curses.o gtdialog-curses.o termkey.o \ + $(termkey_unix_objs) $(windowman_objs) $(cdk_objs) $(CROSS)$(CXX) $(CXXFLAGS) -o ../$@ $^ $(CURSES_LIBS) $(LDFLAGS) textadeptjit-curses: $(sci_objs) $(sci_lex_objs) ScintillaTerm.o \ LexLPegjit-curses.o textadeptjit-curses.o \ $(luajit_lib_objs) $(libluajit) lspawnjit-curses.o \ - gtdialog-curses.o $(termkey_objs) $(windowman_objs) \ - $(cdk_objs) + gtdialog-curses.o termkey.o $(termkey_unix_objs) \ + $(windowman_objs) $(cdk_objs) $(CROSS)$(CXX) $(CXXFLAGS) -o ../$@ $^ $(CURSES_LIBS) $(LDFLAGS) textadept.exe: $(sci_objs) $(sci_lex_objs) $(sci_gtk_objs) scintilla-marshal.o \ LexLPeg.o textadept.o textadept_rc.o $(lua_objs) \ @@ -242,13 +246,14 @@ textadeptjit.exe: $(sci_objs) $(sci_lex_objs) $(sci_gtk_objs) \ textadept-curses.exe: $(sci_objs) $(sci_lex_objs) ScintillaTerm.o \ LexLPeg-curses.o textadept-curses.o textadept_rc.o \ $(lua_objs) $(lua_lib_objs) lspawn-curses.o \ - gtdialog-curses.o $(windowman_objs) $(cdk_objs) + gtdialog-curses.o termkey.o $(termkey_win32_objs) \ + $(windowman_objs) $(cdk_objs) $(CROSS)$(CXX) $(CXXFLAGS) -o ../$@ $^ $(CURSES_LIBS) $(LDFLAGS) textadeptjit-curses.exe: $(sci_objs) $(sci_lex_objs) ScintillaTerm.o \ LexLPegjit-curses.o textadeptjit-curses.o \ textadept_rc.o $(luajit_lib_objs) $(libluajit) \ - lspawnjit-curses.o gtdialog-curses.o \ - $(windowman_objs) $(cdk_objs) + lspawnjit-curses.o gtdialog-curses.o termkey.o \ + $(termkey_win32_objs) $(windowman_objs) $(cdk_objs) $(CROSS)$(CXX) $(CXXFLAGS) -o ../$@ $^ $(CURSES_LIBS) $(LDFLAGS) # Install/uninstall. @@ -443,7 +448,9 @@ cdk: cdk.patch | $(cdk_tgz) mv $@/include/*.h $@ patch -d $@ -N -p1 < $< $(termkey_tgz): ; wget http://www.leonerd.org.uk/code/libtermkey/$@ -termkey: | $(termkey_tgz) ; mkdir $@ && tar xzf $| -C $@ && mv $@/*/* $@ +termkey: termkey.patch | $(termkey_tgz) + mkdir $@ && tar xzf $| -C $@ && mv $@/*/* $@ + patch -d $@ -N -p1 < $< $(win32gtk_zip): wget http://ftp.gnome.org/pub/gnome/binaries/win32/gtk+/2.24/$@ $(win32iconv_bin_zip): ; wget http://gnuwin32.sourceforge.net/downlinks/$@ diff --git a/src/cdk.patch b/src/cdk.patch index b9fc42b9..20ab9227 100644 --- a/src/cdk.patch +++ b/src/cdk.patch @@ -1,24 +1,24 @@ diff -r 9d0780ddcbab binding.c --- a/binding.c 2011-05-16 18:36:08.000000000 -0400 +++ b/binding.c 2013-12-18 11:51:43.781198100 -0500 -@@ -1,4 +1,8 @@ +@@ -1,4 +1,6 @@ #include -+#if !_WIN32 +#include "termkey.h" +extern TermKey *ta_tk; -+#endif /* * $Author: tom $ -@@ -167,7 +171,47 @@ +@@ -167,7 +169,47 @@ { EObjectType cdktype = ObjTypeOf (obj); CDKOBJS *test = bindableObject (&cdktype, obj); -+#if !_WIN32 +- int result = wgetch (InputWindowOf (obj)); + int result = ERR; + TermKeyKey key; + int keysyms[] = {0,KEY_BACKSPACE,KEY_TAB,KEY_ENTER,KEY_ESC,0,0,KEY_UP,KEY_DOWN,KEY_LEFT,KEY_RIGHT,0,0,KEY_IC,KEY_DC,0,KEY_PPAGE,KEY_NPAGE,KEY_HOME,KEY_END}; -+ TermKeyResult res = termkey_waitkey(ta_tk, &key); ++ TermKeyResult res; ++retry: ++ res = termkey_waitkey(ta_tk, &key); + switch (res) + { + case TERMKEY_RES_KEY: @@ -39,6 +39,8 @@ diff -r 9d0780ddcbab binding.c + case TERMKEY_TYPE_KEYSYM: + result = keysyms[key.code.sym]; + break; ++ case TERMKEY_TYPE_MOUSE: ++ goto retry; + default: + result = ERR; + } @@ -52,9 +54,6 @@ diff -r 9d0780ddcbab binding.c + result = 0; + break; + } -+#else - int result = wgetch (InputWindowOf (obj)); -+#endif if (result >= 0 && test != 0 diff --git a/src/termkey.patch b/src/termkey.patch new file mode 100644 index 00000000..f649cbaf --- /dev/null +++ b/src/termkey.patch @@ -0,0 +1,339 @@ +diff -r a94d84bdd4a6 driver-win32-pdcurses.c +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/driver-win32-pdcurses.c Fri Oct 24 21:59:44 2014 -0400 +@@ -0,0 +1,106 @@ ++// Copyright 2014 Mitchell mitchell.att.foicica.com. See LICENSE. ++ ++#include "termkey.h" ++#include "termkey-internal.h" ++ ++#include ++#include ++ ++static void *new_driver(TermKey *tk, const char *term) { return tk; } ++static void free_driver(void *info) {} ++ ++static int initialized; ++ ++// Lookup tables for keysyms and characters. ++static int keysyms[] = {0,TERMKEY_SYM_DOWN,TERMKEY_SYM_UP,TERMKEY_SYM_LEFT,TERMKEY_SYM_RIGHT,TERMKEY_SYM_HOME,TERMKEY_SYM_BACKSPACE,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,TERMKEY_SYM_DELETE,TERMKEY_SYM_INSERT,0,0,0,0,0,0,TERMKEY_SYM_PAGEDOWN,TERMKEY_SYM_PAGEUP,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,TERMKEY_SYM_END}; ++static int shift_keysyms[] = {TERMKEY_SYM_TAB,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,TERMKEY_SYM_DELETE,0,0,TERMKEY_SYM_END,0,0,0,TERMKEY_SYM_HOME,TERMKEY_SYM_INSERT,0,TERMKEY_SYM_LEFT,0,0,0,0,0,0,0,0,TERMKEY_SYM_RIGHT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,TERMKEY_SYM_UP,TERMKEY_SYM_DOWN}; ++static int ctrl_keysyms[] = {TERMKEY_SYM_LEFT,TERMKEY_SYM_RIGHT,TERMKEY_SYM_PAGEUP,TERMKEY_SYM_PAGEDOWN,TERMKEY_SYM_HOME,TERMKEY_SYM_END,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,TERMKEY_SYM_INSERT,0,0,TERMKEY_SYM_UP,TERMKEY_SYM_DOWN,TERMKEY_SYM_TAB,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,TERMKEY_SYM_BACKSPACE,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,TERMKEY_SYM_DELETE,0,TERMKEY_SYM_ENTER}; ++static int alt_keysyms[] = {TERMKEY_SYM_DELETE,TERMKEY_SYM_INSERT,0,0,0,TERMKEY_SYM_TAB,0,0,TERMKEY_SYM_HOME,TERMKEY_SYM_PAGEUP,TERMKEY_SYM_PAGEDOWN,TERMKEY_SYM_END,TERMKEY_SYM_UP,TERMKEY_SYM_DOWN,TERMKEY_SYM_RIGHT,TERMKEY_SYM_LEFT,TERMKEY_SYM_ENTER,TERMKEY_SYM_ESCAPE,0,0,0,0,0,0,0,0,TERMKEY_SYM_BACKSPACE}; // TERMKEY_SYM_RETURN does not work for me ++static int alt_keychars[] = {'-','=',0,0,0,0,0,0,0,0,0,0,'`','[',']',';','\'',',','.','/',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'\\'}; // -=`;,./ do not work for me ++static int mousesyms[] = {TERMKEY_MOUSE_RELEASE,TERMKEY_MOUSE_PRESS,0,TERMKEY_MOUSE_PRESS,0,TERMKEY_MOUSE_DRAG,0}; ++ ++static TermKeyResult peekkey(TermKey *tk, void *info, TermKeyKey *key, int force, size_t *nbytep) { ++ if (!initialized) { ++ raw(), noecho(); ++ PDC_save_key_modifiers(TRUE), mouse_set(ALL_MOUSE_EVENTS), mouseinterval(0); ++ initialized = TRUE; ++ } ++ ++ int c = wgetch((WINDOW *)tk->fd), shift = 0, ctrl = 0, alt = 0; ++ if (c == ERR) return TERMKEY_RES_EOF; ++ int codepoint = c, number = 0, button = 0; ++ TermKeyType type = TERMKEY_TYPE_UNICODE; ++ TermKeySym sym = TERMKEY_SYM_UNKNOWN; ++ TermKeyMouseEvent event = TERMKEY_MOUSE_UNKNOWN; ++ if (c != KEY_MOUSE) { ++ if (c < 0x20 && c != 8 && c != 9 && c != 13 && c != 27) ++ type = TERMKEY_TYPE_UNICODE, codepoint = tolower(c ^ 0x40); ++ else if (c == 27) ++ type = TERMKEY_TYPE_KEYSYM, sym = TERMKEY_SYM_ESCAPE; ++ else if (c >= KEY_MIN && c <= KEY_END && keysyms[c - KEY_MIN]) ++ type = TERMKEY_TYPE_KEYSYM, sym = keysyms[c - KEY_MIN]; ++ else if (c >= KEY_F(1) && c <= KEY_F(48)) ++ type = TERMKEY_TYPE_FUNCTION, number = (c - KEY_F(1)) % 12 + 1; ++ else if (c >= KEY_BTAB && c <= KEY_SDOWN && shift_keysyms[c - KEY_BTAB]) ++ type = TERMKEY_TYPE_KEYSYM, sym = shift_keysyms[c - KEY_BTAB]; ++ else if (c >= CTL_LEFT && c <= CTL_ENTER && ctrl_keysyms[c - CTL_LEFT]) ++ type = TERMKEY_TYPE_KEYSYM, sym = ctrl_keysyms[c - CTL_LEFT]; ++ else if (c >= ALT_DEL && c <= ALT_BKSP && alt_keysyms[c - ALT_DEL]) ++ type = TERMKEY_TYPE_KEYSYM, sym = alt_keysyms[c - ALT_DEL]; ++ else if (c >= ALT_MINUS && c <= ALT_BSLASH && alt_keychars[c - ALT_MINUS]) ++ type = TERMKEY_TYPE_UNICODE, codepoint = alt_keychars[c - ALT_MINUS]; ++ shift = PDC_get_key_modifiers() & PDC_KEY_MODIFIER_SHIFT; ++ ctrl = PDC_get_key_modifiers() & PDC_KEY_MODIFIER_CONTROL; ++ alt = PDC_get_key_modifiers() & PDC_KEY_MODIFIER_ALT; ++ // Do not shift printable keys. ++ if (shift && codepoint >= 32 && codepoint <= 127) shift = 0; ++ key->type = type; ++ if (type == TERMKEY_TYPE_UNICODE) { ++ key->code.codepoint = codepoint; ++ key->utf8[0] = key->code.codepoint, key->utf8[1] = '\0'; ++ } else if (type == TERMKEY_TYPE_FUNCTION) ++ key->code.number = number; ++ else if (type == TERMKEY_TYPE_KEYSYM) ++ key->code.sym = sym; ++ } else { ++ request_mouse_pos(); ++ if (A_BUTTON_CHANGED) { ++ for (int i = 1; i <= 3; i++) ++ if (BUTTON_CHANGED(i)) { ++ event = mousesyms[BUTTON_STATUS(i) & BUTTON_ACTION_MASK], button = i; ++ shift = BUTTON_STATUS(i) & PDC_BUTTON_SHIFT; ++ ctrl = BUTTON_STATUS(i) & PDC_BUTTON_CONTROL; ++ alt = BUTTON_STATUS(i) & PDC_BUTTON_ALT; ++ break; ++ } ++ } else if (MOUSE_WHEEL_UP || MOUSE_WHEEL_DOWN) ++ event = TERMKEY_MOUSE_PRESS, button = MOUSE_WHEEL_UP ? 4 : 5; ++ key->type = TERMKEY_TYPE_MOUSE; ++ key->code.mouse[0] = button | (event << 4); ++ termkey_key_set_linecol(key, MOUSE_X_POS + 1, MOUSE_Y_POS + 1); ++ } ++ key->modifiers = (shift ? TERMKEY_KEYMOD_SHIFT : 0) | ++ (ctrl ? TERMKEY_KEYMOD_CTRL : 0) | ++ (alt ? TERMKEY_KEYMOD_ALT : 0); ++ return TERMKEY_RES_KEY; ++} ++ ++TermKeyResult termkey_interpret_mouse(TermKey *tk, const TermKeyKey *key, TermKeyMouseEvent *event, int *button, int *line, int *col) { ++ if (key->type != TERMKEY_TYPE_MOUSE) return TERMKEY_RES_NONE; ++ if (event) *event = (key->code.mouse[0] & 0xF0) >> 4; ++ if (button) *button = key->code.mouse[0] & 0xF; ++ termkey_key_get_linecol(key, line, col); ++ return TERMKEY_RES_KEY; ++} ++ ++// Unimplemented. ++TermKeyResult termkey_interpret_modereport(TermKey *tk, const TermKeyKey *key, int *initial, int *mode, int *value) { return TERMKEY_RES_ERROR; } ++TermKeyResult termkey_interpret_position(TermKey *tk, const TermKeyKey *key, int *line, int *col) { return TERMKEY_RES_ERROR; } ++TermKeyResult termkey_interpret_csi(TermKey *tk, const TermKeyKey *key, long args[], size_t *nargs, unsigned long *cmd) { return TERMKEY_RES_ERROR; } ++ ++struct TermKeyDriver termkey_driver_win32_pdcurses = { ++ .name = "win32-pdcurses", ++ .new_driver = new_driver, ++ .free_driver = free_driver, ++ .peekkey = peekkey, ++}; +diff -r a94d84bdd4a6 termkey-internal.h +--- a/termkey-internal.h Fri Oct 24 21:58:29 2014 -0400 ++++ b/termkey-internal.h Fri Oct 24 21:59:44 2014 -0400 +@@ -4,7 +4,9 @@ + #include "termkey.h" + + #include ++#if !_WIN32 + #include ++#endif + + struct TermKeyDriver + { +@@ -31,7 +33,7 @@ + }; + + struct TermKey { +- int fd; ++ termkey_fd_t fd; + int flags; + int canonflags; + unsigned char *buffer; +@@ -41,7 +43,9 @@ + size_t hightide; /* Position beyond buffstart at which peekkey() should next start + * normally 0, but see also termkey_interpret_csi */ + ++#if !_WIN32 + struct termios restore_termios; ++#endif + char restore_termios_valid; + + int waittime; // msec +@@ -88,7 +92,11 @@ + key->code.mouse[3] = (line & 0xf00) >> 8 | (col & 0x300) >> 4; + } + ++#if !_WIN32 + extern struct TermKeyDriver termkey_driver_csi; + extern struct TermKeyDriver termkey_driver_ti; ++#else ++extern struct TermKeyDriver termkey_driver_win32_pdcurses; ++#endif + + #endif +diff -r a94d84bdd4a6 termkey.c +--- a/termkey.c Fri Oct 24 21:58:29 2014 -0400 ++++ b/termkey.c Fri Oct 24 21:59:44 2014 -0400 +@@ -3,8 +3,12 @@ + + #include + #include ++#if !_WIN32 + #include + #include ++#else ++#define ssize_t int ++#endif + #include + + #include +@@ -27,8 +31,12 @@ + } + + static struct TermKeyDriver *drivers[] = { ++#if !_WIN32 + &termkey_driver_ti, + &termkey_driver_csi, ++#else ++ &termkey_driver_win32_pdcurses, ++#endif + NULL, + }; + +@@ -263,7 +271,7 @@ + + /* Default all the object fields but don't allocate anything */ + +- tk->fd = -1; ++ tk->fd = FD_NONE; + tk->flags = 0; + tk->canonflags = 0; + +@@ -373,7 +381,7 @@ + return 0; + } + +-TermKey *termkey_new(int fd, int flags) ++TermKey *termkey_new(termkey_fd_t fd, int flags) + { + TermKey *tk = termkey_alloc(); + if(!tk) +@@ -414,7 +422,7 @@ + if(!tk) + return NULL; + +- tk->fd = -1; ++ tk->fd = FD_NONE; + + termkey_set_flags(tk, flags); + +@@ -457,6 +465,7 @@ + if(tk->is_started) + return 1; + ++#if !_WIN32 + if(tk->fd != -1 && !(tk->flags & TERMKEY_FLAG_NOTERMIOS)) { + struct termios termios; + if(tcgetattr(tk->fd, &termios) == 0) { +@@ -487,6 +496,7 @@ + tcsetattr(tk->fd, TCSANOW, &termios); + } + } ++#endif + + struct TermKeyDriverNode *p; + for(p = tk->drivers; p; p = p->next) +@@ -512,8 +522,10 @@ + if(p->driver->stop_driver) + (*p->driver->stop_driver)(tk, p->info); + ++#if !_WIN32 + if(tk->restore_termios_valid) + tcsetattr(tk->fd, TCSANOW, &tk->restore_termios); ++#endif + + tk->is_started = 0; + +@@ -525,11 +537,18 @@ + return tk->is_started; + } + +-int termkey_get_fd(TermKey *tk) ++termkey_fd_t termkey_get_fd(TermKey *tk) + { + return tk->fd; + } + ++#if _WIN32 ++void termkey_set_fd(TermKey *tk, termkey_fd_t fd) ++{ ++ tk->fd = fd; ++} ++#endif ++ + int termkey_get_flags(TermKey *tk) + { + return tk->flags; +@@ -1012,7 +1031,7 @@ + + TermKeyResult termkey_waitkey(TermKey *tk, TermKeyKey *key) + { +- if(tk->fd == -1) { ++ if(tk->fd == FD_NONE) { + errno = EBADF; + return TERMKEY_RES_ERROR; + } +@@ -1026,6 +1045,7 @@ + case TERMKEY_RES_ERROR: + return ret; + ++#if !_WIN32 + case TERMKEY_RES_NONE: + ret = termkey_advisereadable(tk); + if(ret == TERMKEY_RES_ERROR) +@@ -1064,6 +1084,7 @@ + return termkey_getkey_force(tk, key); + } + break; ++#endif + } + } + +@@ -1072,6 +1093,7 @@ + + TermKeyResult termkey_advisereadable(TermKey *tk) + { ++#if !_WIN32 + ssize_t len; + + if(tk->fd == -1) { +@@ -1109,6 +1131,9 @@ + tk->buffcount += len; + return TERMKEY_RES_AGAIN; + } ++#else ++ return TERMKEY_RES_NONE; ++#endif + } + + size_t termkey_push_bytes(TermKey *tk, const char *bytes, size_t len) +diff -r a94d84bdd4a6 termkey.h +--- a/termkey.h Fri Oct 24 21:58:29 2014 -0400 ++++ b/termkey.h Fri Oct 24 21:59:44 2014 -0400 +@@ -14,6 +14,14 @@ + #define TERMKEY_CHECK_VERSION \ + termkey_check_version(TERMKEY_VERSION_MAJOR, TERMKEY_VERSION_MINOR) + ++#if !_WIN32 ++#define termkey_fd_t int ++#define FD_NONE -1 ++#else ++#define termkey_fd_t void* ++#define FD_NONE NULL ++#endif ++ + typedef enum { + TERMKEY_SYM_UNKNOWN = -1, + TERMKEY_SYM_NONE = 0, +@@ -161,7 +169,7 @@ + + void termkey_check_version(int major, int minor); + +-TermKey *termkey_new(int fd, int flags); ++TermKey *termkey_new(termkey_fd_t fd, int flags); + TermKey *termkey_new_abstract(const char *term, int flags); + void termkey_free(TermKey *tk); + void termkey_destroy(TermKey *tk); +@@ -170,7 +178,10 @@ + int termkey_stop(TermKey *tk); + int termkey_is_started(TermKey *tk); + +-int termkey_get_fd(TermKey *tk); ++termkey_fd_t termkey_get_fd(TermKey *tk); ++#if _WIN32 ++void termkey_set_fd(TermKey *tk, termkey_fd_t fd); ++#endif + + int termkey_get_flags(TermKey *tk); + void termkey_set_flags(TermKey *tk, int newflags); diff --git a/src/textadept.c b/src/textadept.c index b5fe7b55..fb47bf3c 100644 --- a/src/textadept.c +++ b/src/textadept.c @@ -51,10 +51,8 @@ #include "ScintillaTerm.h" #include "windowman.h" #include "cdk_int.h" -#if !_WIN32 #include "termkey.h" #endif -#endif // GTK definitions and macros. #if GTK @@ -148,9 +146,7 @@ static ListStore *find_store, *repl_store; // curses window. static struct WindowManager *wm; static int command_entry_focused; -#if !_WIN32 TermKey *ta_tk; // global for CDK use -#endif #define SS(view, msg, w, l) scintilla_send_message(view, msg, w, l) #define focus_view(view) \ (focused_view ? SS(focused_view, SCI_SETFOCUS, 0, 0) : 0, \ @@ -192,6 +188,10 @@ static ListStore find_store[10], repl_store[10]; fcopy(&option_labels[i], lua_tostring(L, -1)); \ if (!*option) option_labels[i] += 4; \ } +#if _WIN32 +#define textadept_waitkey(tk, key) \ + (termkey_set_fd(tk, scintilla_get_window(view)), termkey_getkey(tk, key)) +#endif #endif #define set_clipboard(s) SS(focused_view, SCI_COPYTEXT, strlen(s), (sptr_t)s) @@ -2275,16 +2275,10 @@ int main(int argc, char **argv) { #if GTK gtk_init(&argc, &argv); #elif CURSES -#if !_WIN32 ta_tk = termkey_new(0, 0); - printf("\033[?1003h"); // enable mouse mode -#endif setlocale(LC_CTYPE, ""); // for displaying UTF-8 characters properly initscr(); // raw()/cbreak() and noecho() are taken care of in libtermkey curs_set(0); // disable cursor when Scintilla has focus -#if _WIN32 - raw(), noecho(); -#endif #if NCURSES_REENTRANT ESCDELAY = getenv("ESCDELAY") ? atoi(getenv("ESCDELAY")) : 100; #endif @@ -2369,66 +2363,22 @@ int main(int argc, char **argv) { act.sa_handler = resize, sigaction(SIGWINCH, &act, NULL); #else freopen("NUL", "w", stderr); // redirect stderr - PDC_save_key_modifiers(TRUE), mouse_set(ALL_MOUSE_EVENTS), mouseinterval(0); #endif Scintilla *view = focused_view; - int c = 0, shift = 0, ctrl = 0, alt = 0; // key info - int event = 0, button = 0, y = 0, x = 0, millis = 0; // mouse info -#if _WIN32 - int keysyms[] = {0,SCK_DOWN,SCK_UP,SCK_LEFT,SCK_RIGHT,SCK_HOME,SCK_BACK,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,SCK_DELETE,SCK_INSERT,0,0,0,0,0,0,SCK_NEXT,SCK_PRIOR,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,SCK_END}; - int shift_keysyms[] = {SCK_TAB,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,SCK_DELETE,0,0,SCK_END,0,0,0,SCK_HOME,SCK_INSERT,0,SCK_LEFT,0,0,0,0,0,0,0,0,SCK_RIGHT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,SCK_UP,SCK_DOWN}; - int ctrl_keysyms[] = {SCK_LEFT,SCK_RIGHT,SCK_PRIOR,SCK_NEXT,SCK_HOME,SCK_END,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,SCK_INSERT,0,0,SCK_UP,SCK_DOWN,SCK_TAB,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,SCK_BACK,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,SCK_DELETE,0,SCK_RETURN}; - int alt_keysyms[] = {SCK_DELETE,SCK_INSERT,0,0,0,SCK_TAB,'-','=',SCK_HOME,SCK_PRIOR,SCK_NEXT,SCK_END,SCK_UP,SCK_DOWN,SCK_RIGHT,SCK_LEFT,SCK_RETURN,SCK_ESCAPE,'`','[',']',';','\'',',','.','/',SCK_BACK,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'\\'}; // SCK_RETURN, '\\' do not work for me - int mousesyms[] = {SCM_RELEASE,SCM_PRESS,0,SCM_PRESS,0,SCM_DRAG,0}; - while ((c = wgetch(scintilla_get_window(view))) != ERR) { - if (c != KEY_MOUSE) { - if (c < 0x20 && c != 8 && c != 9 && c != 13 && c != 27) - c = tolower(c ^ 0x40); - else if (c == 27) - c = SCK_ESCAPE; - else if (c >= KEY_MIN && c <= KEY_END && keysyms[c - KEY_MIN]) - c = keysyms[c - KEY_MIN]; - else if (c >= KEY_F(1) && c <= KEY_F(48)) - c = 0xFFBE + (c - KEY_F(1)) % 12; // use GDK keysym values for now - else if (c >= KEY_BTAB && c <= KEY_SDOWN && shift_keysyms[c - KEY_BTAB]) - c = shift_keysyms[c - KEY_BTAB]; - else if (c >= CTL_LEFT && c <= CTL_ENTER && ctrl_keysyms[c - CTL_LEFT]) - c = ctrl_keysyms[c - CTL_LEFT]; - else if (c >= ALT_DEL && c <= ALT_BSLASH && alt_keysyms[c - ALT_DEL]) - c = alt_keysyms[c - ALT_DEL]; - shift = PDC_get_key_modifiers() & PDC_KEY_MODIFIER_SHIFT; - ctrl = PDC_get_key_modifiers() & PDC_KEY_MODIFIER_CONTROL; - alt = PDC_get_key_modifiers() & PDC_KEY_MODIFIER_ALT; - if (c >= 32 && c <= 127) shift = 0; // do not shift printable keys - } else { - request_mouse_pos(), button = 0, y = MOUSE_Y_POS, x = MOUSE_X_POS; - if (BUTTON_CHANGED(1)) { - event = mousesyms[BUTTON_STATUS(1) & BUTTON_ACTION_MASK], button = 1; - shift = BUTTON_STATUS(1) & PDC_BUTTON_SHIFT; - ctrl = BUTTON_STATUS(1) & PDC_BUTTON_CONTROL; - alt = BUTTON_STATUS(1) & PDC_BUTTON_ALT; - } else if (MOUSE_WHEEL_UP || MOUSE_WHEEL_DOWN) - event = SCM_PRESS, button = MOUSE_WHEEL_UP ? 4 : 5; - FILETIME time; - GetSystemTimeAsFileTime(&time); - ULARGE_INTEGER ticks; - ticks.LowPart = time.dwLowDateTime, ticks.HighPart = time.dwHighDateTime; - millis = ticks.QuadPart / 10000; // each tick is a 100-nanosecond interval - } -#else + int ch = 0, event = 0, button = 0, y = 0, x = 0, millis = 0; TermKeyResult res; TermKeyKey key; int keysyms[] = {0,SCK_BACK,SCK_TAB,SCK_RETURN,SCK_ESCAPE,0,SCK_BACK,SCK_UP,SCK_DOWN,SCK_LEFT,SCK_RIGHT,0,0,SCK_INSERT,SCK_DELETE,0,SCK_PRIOR,SCK_NEXT,SCK_HOME,SCK_END}; - while ((c = 0, res = textadept_waitkey(ta_tk, &key)) != TERMKEY_RES_EOF) { + while ((ch = 0, res = textadept_waitkey(ta_tk, &key)) != TERMKEY_RES_EOF) { if (res == TERMKEY_RES_ERROR) continue; if (key.type == TERMKEY_TYPE_UNICODE) - c = key.code.codepoint; + ch = key.code.codepoint; else if (key.type == TERMKEY_TYPE_FUNCTION) - c = 0xFFBD + key.code.number; // use GDK keysym values for now + ch = 0xFFBD + key.code.number; // use GDK keysym values for now else if (key.type == TERMKEY_TYPE_KEYSYM && key.code.sym >= 0 && key.code.sym <= TERMKEY_SYM_END) - c = keysyms[key.code.sym]; + ch = keysyms[key.code.sym]; else if (key.type == TERMKEY_TYPE_UNKNOWN_CSI) { long args[16]; size_t nargs = 16; @@ -2442,19 +2392,29 @@ int main(int argc, char **argv) { } else if (key.type == TERMKEY_TYPE_MOUSE) { termkey_interpret_mouse(ta_tk, &key, (TermKeyMouseEvent*)&event, &button, &y, &x), y--, x--; +#if !_WIN32 struct timeval time = {0, 0}; gettimeofday(&time, NULL); millis = time.tv_sec * 1000 + time.tv_usec / 1000; +#else + FILETIME time; + GetSystemTimeAsFileTime(&time); + ULARGE_INTEGER ticks; + ticks.LowPart = time.dwLowDateTime, ticks.HighPart = time.dwHighDateTime; + millis = ticks.QuadPart / 10000; // each tick is a 100-nanosecond interval +#endif } else continue; // skip unknown types - shift = key.modifiers & TERMKEY_KEYMOD_SHIFT; - ctrl = key.modifiers & TERMKEY_KEYMOD_CTRL; - alt = key.modifiers & TERMKEY_KEYMOD_ALT; -#endif - if (!c || c == KEY_MOUSE) - scintilla_send_mouse(view, event, millis, button, y, x, shift, ctrl, alt); - else if (!lL_event(lua, "keypress", LUA_TNUMBER, c, LUA_TBOOLEAN, shift, - LUA_TBOOLEAN, ctrl, LUA_TBOOLEAN, alt, -1)) - scintilla_send_key(view, c, shift, ctrl, alt); + int shift = key.modifiers & TERMKEY_KEYMOD_SHIFT; + int ctrl = key.modifiers & TERMKEY_KEYMOD_CTRL; + int alt = key.modifiers & TERMKEY_KEYMOD_ALT; + if (ch && !lL_event(lua, "keypress", LUA_TNUMBER, ch, LUA_TBOOLEAN, shift, + LUA_TBOOLEAN, ctrl, LUA_TBOOLEAN, alt, -1)) + scintilla_send_key(view, ch, shift, ctrl, alt); + else if (!ch && !scintilla_send_mouse(view, event, millis, button, y, x, + shift, ctrl, alt)) + lL_event(lua, "mouse", LUA_TNUMBER, event, LUA_TNUMBER, button, + LUA_TNUMBER, y, LUA_TNUMBER, x, LUA_TBOOLEAN, shift, + LUA_TBOOLEAN, ctrl, LUA_TBOOLEAN, alt, -1); if (quit && lL_event(lua, "quit", -1)) { l_close(lua); // Free some memory. @@ -2474,10 +2434,7 @@ int main(int argc, char **argv) { view = !command_entry_focused ? focused_view : command_entry; } endwin(); -#if !_WIN32 - printf("\033[?1003l"); // disable mouse mode termkey_destroy(ta_tk); -#endif #endif free(textadept_home); -- cgit v1.2.3