From f3eb40315f9e5eff503a172aed6d325b4e1f20c6 Mon Sep 17 00:00:00 2001 From: "Thomas E. Dickey" Date: Sun, 18 Sep 2011 01:02:06 +0000 Subject: [PATCH] ncurses 5.9 - patch 20110917 + fix compiler warning for clang 2.9 + improve merging of mouse events (integrated patch by Damien Guibouret). + correct mask-check used in lib_mouse for wheel mouse buttons 4/5 (patch by Damien Guibouret). --- NEWS | 9 +- c++/cursesapp.h | 21 ++- c++/cursesf.cc | 12 +- c++/cursesm.cc | 10 +- c++/cursesm.h | 3 +- c++/cursespad.cc | 5 +- c++/cursesw.cc | 6 +- c++/cursesw.h | 11 +- c++/demo.cc | 5 +- dist.mk | 4 +- form/frm_driver.c | 6 +- ncurses/base/lib_mouse.c | 346 +++++++++++++++++++++++---------------- ncurses/curses.priv.h | 3 +- test/ncurses.c | 3 +- 14 files changed, 274 insertions(+), 170 deletions(-) diff --git a/NEWS b/NEWS index 436a726b..a5c63a54 100644 --- a/NEWS +++ b/NEWS @@ -25,7 +25,7 @@ -- sale, use or other dealings in this Software without prior written -- -- authorization. -- ------------------------------------------------------------------------------- --- $Id: NEWS,v 1.1781 2011/09/11 00:50:29 tom Exp $ +-- $Id: NEWS,v 1.1784 2011/09/17 22:05:18 tom Exp $ ------------------------------------------------------------------------------- This is a log of changes that ncurses has gone through since Zeyd started @@ -45,6 +45,13 @@ See the AUTHORS file for the corresponding full names. Changes through 1.9.9e did not credit all contributions; it is not possible to add this information. +20110917 + + fix compiler warning for clang 2.9 + + improve merging of mouse events (integrated patch by Damien + Guibouret). + + correct mask-check used in lib_mouse for wheel mouse buttons 4/5 + (patch by Damien Guibouret). + 20110910 + modify misc/gen_edit.sh to select a "linux" entry which works with the current kernel rather than assuming it is always "linux3.0" diff --git a/c++/cursesapp.h b/c++/cursesapp.h index 7e995d2e..e3cbc04c 100644 --- a/c++/cursesapp.h +++ b/c++/cursesapp.h @@ -1,6 +1,6 @@ // * This makes emacs happy -*-Mode: C++;-*- /**************************************************************************** - * Copyright (c) 1998-2003,2005 Free Software Foundation, Inc. * + * Copyright (c) 1998-2005,2011 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,7 +31,7 @@ * Author: Juergen Pfeifer, 1997 * ****************************************************************************/ -// $Id: cursesapp.h,v 1.11 2005/05/28 21:57:44 tom Exp $ +// $Id: cursesapp.h,v 1.12 2011/09/17 22:12:10 tom Exp $ #ifndef NCURSES_CURSESAPP_H_incl #define NCURSES_CURSESAPP_H_incl @@ -80,6 +80,7 @@ protected: // This method is called to initialize the SLKs. Default is nothing. // You may rewrite this in your derived class virtual void init_labels(Soft_Label_Key_Set& S) const { + (void) S; } // Your derived class must implement this method. The return value must @@ -118,6 +119,8 @@ public: // Process the commandline arguments. The default implementation simply // ignores them. Your derived class may rewrite this. virtual void handleArgs(int argc, char* argv[]) { + (void) argc; + (void) argv; } // Does this application use colors? @@ -138,37 +141,37 @@ public: // Attributes to use for menu and forms foregrounds virtual chtype foregrounds() const { - return b_Colors ? COLOR_PAIR(1) : A_BOLD; + return b_Colors ? static_cast(COLOR_PAIR(1)) : A_BOLD; } // Attributes to use for menu and forms backgrounds virtual chtype backgrounds() const { - return b_Colors ? COLOR_PAIR(2) : A_NORMAL; + return b_Colors ? static_cast(COLOR_PAIR(2)) : A_NORMAL; } // Attributes to use for inactive (menu) elements virtual chtype inactives() const { - return b_Colors ? (COLOR_PAIR(3)|A_DIM) : A_DIM; + return b_Colors ? static_cast(COLOR_PAIR(3)|A_DIM) : A_DIM; } // Attributes to use for (form) labels and SLKs virtual chtype labels() const { - return b_Colors ? COLOR_PAIR(4) : A_NORMAL; + return b_Colors ? static_cast(COLOR_PAIR(4)) : A_NORMAL; } // Attributes to use for form backgrounds virtual chtype dialog_backgrounds() const { - return b_Colors ? COLOR_PAIR(4) : A_NORMAL; + return b_Colors ? static_cast(COLOR_PAIR(4)) : A_NORMAL; } // Attributes to use as default for (form) window backgrounds virtual chtype window_backgrounds() const { - return b_Colors ? COLOR_PAIR(5) : A_NORMAL; + return b_Colors ? static_cast(COLOR_PAIR(5)) : A_NORMAL; } // Attributes to use for the title window virtual chtype screen_titles() const { - return b_Colors ? COLOR_PAIR(6) : A_BOLD; + return b_Colors ? static_cast(COLOR_PAIR(6)) : A_BOLD; } }; diff --git a/c++/cursesf.cc b/c++/cursesf.cc index aaf1202c..79560547 100644 --- a/c++/cursesf.cc +++ b/c++/cursesf.cc @@ -1,6 +1,6 @@ // * this is for making emacs happy: -*-Mode: C++;-*- /**************************************************************************** - * Copyright (c) 1998-2003,2005 Free Software Foundation, Inc. * + * Copyright (c) 1998-2005,2011 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -35,7 +35,7 @@ #include "cursesf.h" #include "cursesapp.h" -MODULE_ID("$Id: cursesf.cc,v 1.21 2005/08/13 18:09:06 tom Exp $") +MODULE_ID("$Id: cursesf.cc,v 1.22 2011/09/17 22:12:10 tom Exp $") NCursesFormField::~NCursesFormField () { @@ -234,11 +234,13 @@ NCursesForm::On_Form_Termination() void NCursesForm::On_Field_Init(NCursesFormField& field) { + (void) field; } void NCursesForm::On_Field_Termination(NCursesFormField& field) { + (void) field; } // call the form driver and do basic error checking. @@ -260,16 +262,19 @@ NCursesForm::driver (int c) void NCursesForm::On_Request_Denied(int c) const { + (void) c; ::beep(); } void NCursesForm::On_Invalid_Field(int c) const { + (void) c; ::beep(); } void NCursesForm::On_Unknown_Command(int c) const { + (void) c; ::beep(); } @@ -373,6 +378,7 @@ NCursesForm::virtualize(int c) // bool _nc_xx_fld_fcheck(FIELD *f, const void *u) { + (void) f; NCursesFormField* F = reinterpret_cast(const_cast(u)); assert(F != 0); UserDefinedFieldType* udf = reinterpret_cast(F->fieldtype()); @@ -405,6 +411,7 @@ FIELDTYPE* UserDefinedFieldType_With_Choice::generic_fieldtype_with_choice = bool _nc_xx_next_choice(FIELD *f, const void *u) { + (void) f; NCursesFormField* F = reinterpret_cast(const_cast(u)); assert(F != 0); UserDefinedFieldType_With_Choice* udf = @@ -415,6 +422,7 @@ bool _nc_xx_next_choice(FIELD *f, const void *u) bool _nc_xx_prev_choice(FIELD *f, const void *u) { + (void) f; NCursesFormField* F = reinterpret_cast(const_cast(u)); assert(F != 0); UserDefinedFieldType_With_Choice* udf = diff --git a/c++/cursesm.cc b/c++/cursesm.cc index c253a679..222de46c 100644 --- a/c++/cursesm.cc +++ b/c++/cursesm.cc @@ -1,6 +1,6 @@ // * this is for making emacs happy: -*-Mode: C++;-*- /**************************************************************************** - * Copyright (c) 1998-2003,2005 Free Software Foundation, Inc. * + * Copyright (c) 1998-2005,2011 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -35,7 +35,7 @@ #include "cursesm.h" #include "cursesapp.h" -MODULE_ID("$Id: cursesm.cc,v 1.22 2005/04/02 20:39:05 tom Exp $") +MODULE_ID("$Id: cursesm.cc,v 1.23 2011/09/17 22:11:32 tom Exp $") NCursesMenuItem::~NCursesMenuItem() { @@ -375,33 +375,39 @@ NCursesMenu::On_Menu_Termination() void NCursesMenu::On_Item_Init(NCursesMenuItem& item) { + (void) item; } void NCursesMenu::On_Item_Termination(NCursesMenuItem& item) { + (void) item; } void NCursesMenu::On_Request_Denied(int c) const { + (void) c; ::beep(); } void NCursesMenu::On_Not_Selectable(int c) const { + (void) c; ::beep(); } void NCursesMenu::On_No_Match(int c) const { + (void) c; ::beep(); } void NCursesMenu::On_Unknown_Command(int c) const { + (void) c; ::beep(); } diff --git a/c++/cursesm.h b/c++/cursesm.h index 4058ed07..d629e8ee 100644 --- a/c++/cursesm.h +++ b/c++/cursesm.h @@ -31,7 +31,7 @@ * Author: Juergen Pfeifer, 1997 * ****************************************************************************/ -// $Id: cursesm.h,v 1.26 2011/04/09 18:07:08 Alexander.Kolesen Exp $ +// $Id: cursesm.h,v 1.27 2011/09/17 21:37:01 tom Exp $ #ifndef NCURSES_CURSESM_H_incl #define NCURSES_CURSESM_H_incl 1 @@ -82,6 +82,7 @@ public: NCursesMenuItem(const NCursesMenuItem& rhs) : item(0) { + (void) rhs; } virtual ~NCursesMenuItem (); diff --git a/c++/cursespad.cc b/c++/cursespad.cc index 28c58fab..b5690a3e 100644 --- a/c++/cursespad.cc +++ b/c++/cursespad.cc @@ -1,6 +1,6 @@ // * this is for making emacs happy: -*-Mode: C++;-*- /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright (c) 1998-2008,2011 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -36,7 +36,7 @@ #include #include -MODULE_ID("$Id: cursespad.cc,v 1.13 2008/08/04 18:59:22 tom Exp $") +MODULE_ID("$Id: cursespad.cc,v 1.14 2011/09/17 22:12:10 tom Exp $") NCursesPad::NCursesPad(int nlines, int ncols) : NCursesWindow(), @@ -220,6 +220,7 @@ void NCursesPad::setSubWindow(NCursesWindow& sub) void NCursesFramedPad::OnOperation(int pad_req) { + (void) pad_req; NCursesWindow* W = Win(); NCursesWindow* W2 = getWindow(); diff --git a/c++/cursesw.cc b/c++/cursesw.cc index 47e5cf64..f2e7e948 100644 --- a/c++/cursesw.cc +++ b/c++/cursesw.cc @@ -1,6 +1,6 @@ // * this is for making emacs happy: -*-Mode: C++;-*- /**************************************************************************** - * Copyright (c) 2007-2008,2009 Free Software Foundation, Inc. * + * Copyright (c) 2007-2009,2011 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -42,7 +42,7 @@ #include "internal.h" #include "cursesw.h" -MODULE_ID("$Id: cursesw.cc,v 1.51 2009/03/28 21:31:37 tom Exp $") +MODULE_ID("$Id: cursesw.cc,v 1.52 2011/09/17 22:12:10 tom Exp $") #define COLORS_NEED_INITIALIZATION -1 #define COLORS_NOT_INITIALIZED 0 @@ -285,12 +285,14 @@ static RIPOFFINIT* prip = R_INIT; NCursesWindow::NCursesWindow(WINDOW *win, int ncols) : w(0), alloced(FALSE), par(0), subwins(0), sib(0) { + (void) ncols; initialize(); w = win; } int _nc_xx_ripoff_init(WINDOW *w, int ncols) { + (void) ncols; int res = ERR; RIPOFFINIT init = *prip++; diff --git a/c++/cursesw.h b/c++/cursesw.h index b8e921a9..4472ea9c 100644 --- a/c++/cursesw.h +++ b/c++/cursesw.h @@ -1,7 +1,7 @@ // * This makes emacs happy -*-Mode: C++;-*- // vile:cppmode /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright (c) 1998-2008,2011 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,7 +31,7 @@ #ifndef NCURSES_CURSESW_H_incl #define NCURSES_CURSESW_H_incl 1 -// $Id: cursesw.h,v 1.48 2008/01/19 21:09:10 tom Exp $ +// $Id: cursesw.h,v 1.49 2011/09/17 22:12:10 tom Exp $ #include @@ -1438,16 +1438,19 @@ protected: // The driver translates the keystroke c into an Pad_Request virtual void OnUnknownOperation(int pad_req) { + (void) pad_req; ::beep(); } // This is called if the driver returns an unknown op-code virtual void OnNavigationError(int pad_req) { + (void) pad_req; ::beep(); } // This is called if a navigation request couldn't be satisfied virtual void OnOperation(int pad_req) { + (void) pad_req; }; // OnOperation is called if a Pad_Operation was executed and just before // the refresh() operation is done. @@ -1542,11 +1545,15 @@ public: } void setWindow(NCursesWindow& view, int v_grid = 1, int h_grid = 1) { + (void) view; + (void) v_grid; + (void) h_grid; err_handler("Operation not allowed"); } // Disable this call; the viewport is already defined void setSubWindow(NCursesWindow& sub) { + (void) sub; err_handler("Operation not allowed"); } // Disable this call; the viewport subwindow is already defined diff --git a/c++/demo.cc b/c++/demo.cc index 35433425..7acdd093 100644 --- a/c++/demo.cc +++ b/c++/demo.cc @@ -1,6 +1,6 @@ // * This makes emacs happy -*-Mode: C++;-*- /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright (c) 1998-2008,2011 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -35,7 +35,7 @@ * Demo code for NCursesMenu and NCursesForm written by * Juergen Pfeifer * - * $Id: demo.cc,v 1.39 2008/12/07 02:07:34 juergen Exp $ + * $Id: demo.cc,v 1.40 2011/09/17 22:12:10 tom Exp $ */ #include "internal.h" @@ -220,6 +220,7 @@ private: int chk; protected: bool field_check(NCursesFormField& f) { + (void) f; return TRUE; } bool char_check(int c) { diff --git a/dist.mk b/dist.mk index 21f8935b..400632bb 100644 --- a/dist.mk +++ b/dist.mk @@ -25,7 +25,7 @@ # use or other dealings in this Software without prior written # # authorization. # ############################################################################## -# $Id: dist.mk,v 1.833 2011/09/10 15:46:42 tom Exp $ +# $Id: dist.mk,v 1.834 2011/09/17 16:04:54 tom Exp $ # Makefile for creating ncurses distributions. # # This only needs to be used directly as a makefile by developers, but @@ -37,7 +37,7 @@ SHELL = /bin/sh # These define the major/minor/patch versions of ncurses. NCURSES_MAJOR = 5 NCURSES_MINOR = 9 -NCURSES_PATCH = 20110910 +NCURSES_PATCH = 20110917 # We don't append the patch to the version, since this only applies to releases VERSION = $(NCURSES_MAJOR).$(NCURSES_MINOR) diff --git a/form/frm_driver.c b/form/frm_driver.c index e0892bf8..f335ed26 100644 --- a/form/frm_driver.c +++ b/form/frm_driver.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. * + * Copyright (c) 1998-2010,2011 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,7 +32,7 @@ #include "form.priv.h" -MODULE_ID("$Id: frm_driver.c,v 1.98 2010/05/01 21:11:43 tom Exp $") +MODULE_ID("$Id: frm_driver.c,v 1.99 2011/09/17 22:12:10 tom Exp $") /*---------------------------------------------------------------------------- This is the core module of the form library. It contains the majority @@ -1326,7 +1326,7 @@ _nc_Synchronize_Options(FIELD *field, Field_Options newopts) field->opts = oldopts; returnCode(E_CURRENT); } - if ((form->curpage == field->page)) + if (form->curpage == field->page) { if (changed_opts & O_VISIBLE) { diff --git a/ncurses/base/lib_mouse.c b/ncurses/base/lib_mouse.c index 43169579..350eaa7b 100644 --- a/ncurses/base/lib_mouse.c +++ b/ncurses/base/lib_mouse.c @@ -84,7 +84,7 @@ #define CUR SP_TERMTYPE #endif -MODULE_ID("$Id: lib_mouse.c,v 1.122 2011/09/10 22:23:38 tom Exp $") +MODULE_ID("$Id: lib_mouse.c,v 1.129 2011/09/17 21:52:30 tom Exp $") #include @@ -750,6 +750,7 @@ _nc_mouse_event(SCREEN *sp) eventp->bstate |= BUTTON3_RELEASED; break; default: + eventp->bstate |= REPORT_MOUSE_POSITION; break; } @@ -830,7 +831,6 @@ _nc_mouse_inline(SCREEN *sp) if (sp->_mouse_type == M_XTERM) { unsigned char kbuf[4]; - mmask_t prev; size_t grabbed; int res; @@ -896,35 +896,51 @@ _nc_mouse_inline(SCREEN *sp) /* processing code goes here */ eventp->bstate = 0; - prev = PREV(eventp)->bstate; #if USE_EMX_MOUSE #define PRESS_POSITION(n) \ - eventp->bstate = MASK_PRESS(n); \ - if (kbuf[0] & 0x40) \ - eventp->bstate = MASK_RELEASE(n) + do { \ + eventp->bstate = MASK_PRESS(n); \ + sp->_mouse_bstate |= MASK_PRESS(n); \ + if (kbuf[0] & 0x40) { \ + eventp->bstate = MASK_RELEASE(n); \ + sp->_mouse_bstate &= ~MASK_PRESS(n); \ + } \ + } while (0) #else #define PRESS_POSITION(n) \ - eventp->bstate = (mmask_t) (prev & MASK_PRESS(n) \ - ? REPORT_MOUSE_POSITION \ - : MASK_PRESS(n)) + do { \ + eventp->bstate = (mmask_t) (sp->_mouse_bstate & MASK_PRESS(n) \ + ? REPORT_MOUSE_POSITION \ + : MASK_PRESS(n)); \ + sp->_mouse_bstate |= MASK_PRESS(n); \ + } while (0) #endif switch (kbuf[0] & 0x3) { case 0x0: - if (kbuf[0] & 64) + if ((kbuf[0] & 96) == 96) { eventp->bstate = MASK_PRESS(4); - else + /* Do not record in sp->_mouse_bstate; there will be no + * corresponding release event. + */ + } else { PRESS_POSITION(1); + } break; case 0x1: + if ((kbuf[0] & 96) == 96) { #if NCURSES_MOUSE_VERSION == 2 - if (kbuf[0] & 64) eventp->bstate = MASK_PRESS(5); - else + /* See comment above for button 4 */ +#else + /* Ignore this event as it is not a true press of the button */ + eventp->bstate = REPORT_MOUSE_POSITION; #endif + } else { PRESS_POSITION(2); + } break; case 0x2: @@ -939,12 +955,13 @@ _nc_mouse_inline(SCREEN *sp) * release, we can infer the button actually released by looking at * the previous event. */ - if (prev & (BUTTON_PRESSED | BUTTON_RELEASED)) { + if (sp->_mouse_bstate & BUTTON_PRESSED) { eventp->bstate = BUTTON_RELEASED; for (b = 1; b <= MAX_BUTTONS; ++b) { - if (!(prev & MASK_PRESS(b))) + if (!(sp->_mouse_bstate & MASK_PRESS(b))) eventp->bstate &= ~MASK_RELEASE(b); } + sp->_mouse_bstate = 0; } else { /* * XFree86 xterm will return a stream of release-events to @@ -994,7 +1011,7 @@ mouse_activate(SCREEN *sp, bool on) return; if (on) { - + sp->_mouse_bstate = 0; switch (sp->_mouse_type) { case M_XTERM: #if NCURSES_EXT_FUNCS @@ -1074,10 +1091,13 @@ _nc_mouse_parse(SCREEN *sp, int runcount) /* parse a run of atomic mouse events into a gesture */ { MEVENT *eventp = sp->_mouse_eventp; - MEVENT *ep, *runp, *next, *prev = PREV(eventp); + MEVENT *next, *ep; + MEVENT *first_valid = NULL; + MEVENT *first_invalid = NULL; int n; int b; bool merge; + bool endLoop; TR(MY_TRACE, ("_nc_mouse_parse(%d) called", runcount)); @@ -1094,7 +1114,8 @@ _nc_mouse_parse(SCREEN *sp, int runcount) * * It's possible that the run may not resolve to a single event (for * example, if the user quadruple-clicks). If so, leading events - * in the run are ignored. + * in the run are ignored if user does not call getmouse in a loop (getting + * them from newest to older). * * Note that this routine is independent of the format of the specific * format of the pointing-device's reports. We can use it to parse @@ -1102,79 +1123,109 @@ _nc_mouse_parse(SCREEN *sp, int runcount) * button basis, as long as the device-dependent mouse code puts stuff * on the queue in MEVENT format. */ - if (runcount == 1) { - TR(MY_TRACE, - ("_nc_mouse_parse: returning simple mouse event %s at slot %ld", - _nc_tracemouse(sp, prev), - (long) IndexEV(sp, prev))); - return (prev->id >= NORMAL_EVENT) - ? ((prev->bstate & sp->_mouse_mask) ? TRUE : FALSE) - : FALSE; - } - /* find the start of the run */ - runp = eventp; - for (n = runcount; n > 0; n--) { - runp = PREV(runp); + /* + * Reset all events that were not set, in case the user sometimes calls + * getmouse only once and other times until there are no more events in + * queue. + * + * This also allows reaching the beginning of the run. + */ + ep = eventp; + for (n = runcount; n < EV_MAX; n++) { + ep->id = INVALID_EVENT; + ep = NEXT(ep); } #ifdef TRACE if (USE_TRACEF(TRACE_IEVENT)) { _trace_slot(sp, "before mouse press/release merge:"); _tracef("_nc_mouse_parse: run starts at %ld, ends at %ld, count %d", - RunParams(sp, eventp, runp), + RunParams(sp, eventp, ep), runcount); _nc_unlock_global(tracef); } #endif /* TRACE */ /* first pass; merge press/release pairs */ - do { - merge = FALSE; - for (ep = runp; (next = NEXT(ep)) != eventp; ep = next) { + endLoop = FALSE; + while (!endLoop) { + next = NEXT(ep); + if (next == eventp) { + /* Will end the loop, but compact before */ + endLoop = TRUE; + } else { #define MASK_CHANGED(x) (!(ep->bstate & MASK_PRESS(x)) \ == !(next->bstate & MASK_RELEASE(x))) - if (ep->x == next->x && ep->y == next->y + if (ep->id != INVALID_EVENT && next->id != INVALID_EVENT + && ep->x == next->x && ep->y == next->y && (ep->bstate & BUTTON_PRESSED) - && MASK_CHANGED(1) - && MASK_CHANGED(2) - && MASK_CHANGED(3) - && MASK_CHANGED(4) -#if NCURSES_MOUSE_VERSION == 2 - && MASK_CHANGED(5) -#endif - ) { + && (!(next->bstate & BUTTON_PRESSED))) { + bool changed = TRUE; + for (b = 1; b <= MAX_BUTTONS; ++b) { - if ((sp->_mouse_mask & MASK_CLICK(b)) - && (ep->bstate & MASK_PRESS(b))) { - ep->bstate &= ~MASK_PRESS(b); - ep->bstate |= MASK_CLICK(b); - merge = TRUE; + if (!MASK_CHANGED(b)) { + changed = FALSE; + break; } } - if (merge) - next->id = INVALID_EVENT; + + if (changed) { + merge = FALSE; + for (b = 1; b <= MAX_BUTTONS; ++b) { + if ((sp->_mouse_mask & MASK_CLICK(b)) + && (ep->bstate & MASK_PRESS(b))) { + next->bstate &= ~MASK_RELEASE(b); + next->bstate |= MASK_CLICK(b); + merge = TRUE; + } + } + if (merge) + ep->id = INVALID_EVENT; + } } } - } while - (merge); + /* Compact valid events */ + if (ep->id == INVALID_EVENT) { + if ((first_valid != NULL) && (first_invalid == NULL)) { + first_invalid = ep; + } + } else { + if (first_valid == NULL) { + first_valid = ep; + } else if (first_invalid != NULL) { + *first_invalid = *ep; + ep->id = INVALID_EVENT; + first_invalid = NEXT(first_invalid); + } + } + + ep = next; + } + + if (first_invalid != NULL) { + eventp = first_invalid; + } #ifdef TRACE if (USE_TRACEF(TRACE_IEVENT)) { _trace_slot(sp, "before mouse click merge:"); - _tracef("_nc_mouse_parse: run starts at %ld, ends at %ld, count %d", - RunParams(sp, eventp, runp), - runcount); - _nc_unlock_global(tracef); + if (first_valid == NULL) { + _tracef("_nc_mouse_parse: no valid event"); + } else { + _tracef("_nc_mouse_parse: run starts at %ld, ends at %ld, count %d", + RunParams(sp, eventp, first_valid), + runcount); + _nc_unlock_global(tracef); + } } #endif /* TRACE */ /* - * Second pass; merge click runs. At this point, click events are - * each followed by one invalid event. We merge click events - * forward in the queue. + * Second pass; merge click runs. We merge click events forward in the + * queue. For example, double click can be changed to triple click. * * NOTE: There is a problem with this design! If the application * allows enough click events to pile up in the circular queue so @@ -1187,87 +1238,98 @@ _nc_mouse_parse(SCREEN *sp, int runcount) * but the timer element would have to have sub-second resolution, * which would get us into portability trouble. */ - do { - MEVENT *follower; - - merge = FALSE; - for (ep = runp; (next = NEXT(ep)) != eventp; ep = next) - if (ep->id != INVALID_EVENT) { - if (next->id != INVALID_EVENT) - continue; - follower = NEXT(next); - if (follower->id == INVALID_EVENT) - continue; - - /* merge click events forward */ - if ((ep->bstate & BUTTON_CLICKED) - && (follower->bstate & BUTTON_CLICKED)) { - for (b = 1; b <= MAX_BUTTONS; ++b) { - if ((sp->_mouse_mask & MASK_DOUBLE_CLICK(b)) - && (follower->bstate & MASK_CLICK(b))) { - follower->bstate &= ~MASK_CLICK(b); - follower->bstate |= MASK_DOUBLE_CLICK(b); - merge = TRUE; - } + first_invalid = NULL; + endLoop = (first_valid == NULL); + ep = first_valid; + while (!endLoop) { + next = NEXT(ep); + + if (next == eventp) { + /* Will end the loop, but check event type and compact before */ + endLoop = true; + } else { + /* merge click events forward */ + if ((ep->bstate & BUTTON_CLICKED) + && (next->bstate & BUTTON_CLICKED)) { + merge = FALSE; + for (b = 1; b <= MAX_BUTTONS; ++b) { + if ((sp->_mouse_mask & MASK_DOUBLE_CLICK(b)) + && (ep->bstate & MASK_CLICK(b)) + && (next->bstate & MASK_CLICK(b))) { + next->bstate &= ~MASK_CLICK(b); + next->bstate |= MASK_DOUBLE_CLICK(b); + merge = TRUE; } - if (merge) - ep->id = INVALID_EVENT; } + if (merge) + ep->id = INVALID_EVENT; + } - /* merge double-click events forward */ - if ((ep->bstate & BUTTON_DOUBLE_CLICKED) - && (follower->bstate & BUTTON_CLICKED)) { - for (b = 1; b <= MAX_BUTTONS; ++b) { - if ((sp->_mouse_mask & MASK_TRIPLE_CLICK(b)) - && (follower->bstate & MASK_CLICK(b))) { - follower->bstate &= ~MASK_CLICK(b); - follower->bstate |= MASK_TRIPLE_CLICK(b); - merge = TRUE; - } + /* merge double-click events forward */ + if ((ep->bstate & BUTTON_DOUBLE_CLICKED) + && (next->bstate & BUTTON_CLICKED)) { + merge = FALSE; + for (b = 1; b <= MAX_BUTTONS; ++b) { + if ((sp->_mouse_mask & MASK_TRIPLE_CLICK(b)) + && (ep->bstate & MASK_DOUBLE_CLICK(b)) + && (next->bstate & MASK_CLICK(b))) { + next->bstate &= ~MASK_CLICK(b); + next->bstate |= MASK_TRIPLE_CLICK(b); + merge = TRUE; } - if (merge) - ep->id = INVALID_EVENT; } + if (merge) + ep->id = INVALID_EVENT; } - } while - (merge); + } -#ifdef TRACE - if (USE_TRACEF(TRACE_IEVENT)) { - _trace_slot(sp, "before mouse event queue compaction:"); - _tracef("_nc_mouse_parse: run starts at %ld, ends at %ld, count %d", - RunParams(sp, eventp, runp), - runcount); - _nc_unlock_global(tracef); - } -#endif /* TRACE */ + /* Discard event if it does not match event mask */ + if (!(ep->bstate & sp->_mouse_mask)) { + ep->id = INVALID_EVENT; + } - /* - * Now try to throw away trailing events flagged invalid, or that - * don't match the current event mask. - */ - for (; runcount; prev = PREV(eventp), runcount--) - if (prev->id == INVALID_EVENT || !(prev->bstate & sp->_mouse_mask)) { - sp->_mouse_eventp = eventp = prev; + /* Compact valid events */ + if (ep->id == INVALID_EVENT) { + if (ep == first_valid) { + first_valid = next; + } else if (first_invalid == NULL) { + first_invalid = ep; + } + } else if (first_invalid != NULL) { + *first_invalid = *ep; + ep->id = INVALID_EVENT; + first_invalid = NEXT(first_invalid); } + + ep = next; + } + + if (first_invalid == NULL) { + first_invalid = eventp; + } + sp->_mouse_eventp = first_invalid; + #ifdef TRACE - if (USE_TRACEF(TRACE_IEVENT)) { - _trace_slot(sp, "after mouse event queue compaction:"); - _tracef("_nc_mouse_parse: run starts at %ld, ends at %ld, count %d", - RunParams(sp, eventp, runp), - runcount); - _nc_unlock_global(tracef); + if (first_valid != NULL) { + if (USE_TRACEF(TRACE_IEVENT)) { + _trace_slot(sp, "after mouse event queue compaction:"); + _tracef("_nc_mouse_parse: run starts at %ld, ends at %ld, count %d", + RunParams(sp, first_invalid, first_valid), + runcount); + _nc_unlock_global(tracef); + } + for (ep = first_valid; ep != first_invalid; ep = NEXT(ep)) { + if (ep->id != INVALID_EVENT) + TR(MY_TRACE, + ("_nc_mouse_parse: returning composite mouse event %s at slot %ld", + _nc_tracemouse(sp, ep), + (long) IndexEV(sp, ep))); + } } - for (ep = runp; ep != eventp; ep = NEXT(ep)) - if (ep->id != INVALID_EVENT) - TR(MY_TRACE, - ("_nc_mouse_parse: returning composite mouse event %s at slot %ld", - _nc_tracemouse(sp, ep), - (long) IndexEV(sp, ep))); #endif /* TRACE */ /* after all this, do we have a valid event? */ - return (PREV(eventp)->id != INVALID_EVENT); + return (PREV(first_invalid)->id != INVALID_EVENT); } static void @@ -1359,17 +1421,15 @@ NCURSES_SP_NAME(getmouse) (NCURSES_SP_DCLx MEVENT * aevent) /* compute the current-event pointer */ MEVENT *prev = PREV(eventp); -#if 1 - /* copy the event we find there */ - *aevent = *prev; - - TR(TRACE_IEVENT, ("getmouse: returning event %s from slot %ld", - _nc_tracemouse(SP_PARM, prev), - (long) IndexEV(SP_PARM, prev))); - - prev->id = INVALID_EVENT; /* so the queue slot becomes free */ - result = OK; -#else /* 20100102 change prevented "release" events from returning to caller */ + /* + * Discard events not matching mask (there could be still some if + * _nc_mouse_parse was not called, e.g., when _nc_mouse_inline returns + * false). + */ + while ((prev->id != INVALID_EVENT) && (!(prev->bstate & SP_PARM->_mouse_mask))) { + prev->id = INVALID_EVENT; + prev = PREV(prev); + } if (prev->id != INVALID_EVENT) { /* copy the event we find there */ *aevent = *prev; @@ -1379,10 +1439,16 @@ NCURSES_SP_NAME(getmouse) (NCURSES_SP_DCLx MEVENT * aevent) (long) IndexEV(SP_PARM, prev))); prev->id = INVALID_EVENT; /* so the queue slot becomes free */ - SP_PARM->_mouse_eventp = PREV(prev); + SP_PARM->_mouse_eventp = prev; result = OK; + } else { + /* Reset the provided event */ + aevent->bstate = 0; + aevent->id = INVALID_EVENT; + aevent->x = 0; + aevent->y = 0; + aevent->z = 0; } -#endif } returnCode(result); } diff --git a/ncurses/curses.priv.h b/ncurses/curses.priv.h index e0992ab5..309c3e82 100644 --- a/ncurses/curses.priv.h +++ b/ncurses/curses.priv.h @@ -34,7 +34,7 @@ ****************************************************************************/ /* - * $Id: curses.priv.h,v 1.482 2011/08/13 14:28:05 tom Exp $ + * $Id: curses.priv.h,v 1.483 2011/09/17 19:08:20 tom Exp $ * * curses.priv.h * @@ -1075,6 +1075,7 @@ struct screen { int _mouse_fd; /* file-descriptor, if any */ bool _mouse_active; /* true if initialized */ mmask_t _mouse_mask; + mmask_t _mouse_bstate; NCURSES_CONST char *_mouse_xtermcap; /* string to enable/disable mouse */ MEVENT _mouse_events[EV_MAX]; /* hold the last mouse event seen */ MEVENT *_mouse_eventp; /* next free slot in event queue */ diff --git a/test/ncurses.c b/test/ncurses.c index ea5f5f86..d5b5a63f 100644 --- a/test/ncurses.c +++ b/test/ncurses.c @@ -40,7 +40,7 @@ AUTHOR Author: Eric S. Raymond 1993 Thomas E. Dickey (beginning revision 1.27 in 1996). -$Id: ncurses.c,v 1.369 2011/08/20 15:49:08 tom Exp $ +$Id: ncurses.c,v 1.370 2011/09/17 21:57:49 tom Exp $ ***************************************************************************/ @@ -3360,6 +3360,7 @@ show_upper_widechars(int first, int repeat, int space, attr_t attr, short pair) * The repeat-count may make text wrap - avoid that. */ getyx(stdscr, y, x); + (void) y; if (x >= col + (COLS / 2) - 2) break; } while (--count > 0); -- 2.44.0