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).
This commit is contained in:
Thomas E. Dickey 2011-09-18 01:02:06 +00:00
parent 3c19a91c36
commit f3eb40315f
14 changed files with 278 additions and 174 deletions

9
NEWS
View File

@ -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"

View File

@ -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<chtype>(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<chtype>(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<chtype>(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<chtype>(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<chtype>(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<chtype>(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<chtype>(COLOR_PAIR(6)) : A_BOLD;
}
};

View File

@ -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<NCursesFormField*>(const_cast<void *>(u));
assert(F != 0);
UserDefinedFieldType* udf = reinterpret_cast<UserDefinedFieldType*>(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<NCursesFormField*>(const_cast<void *>(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<NCursesFormField*>(const_cast<void *>(u));
assert(F != 0);
UserDefinedFieldType_With_Choice* udf =

View File

@ -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();
}

View File

@ -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 ();

View File

@ -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 <etip.h>
#include <cursesw.h>
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();

View File

@ -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++;

View File

@ -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 <etip.h>
@ -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

View File

@ -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) {

View File

@ -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)

View File

@ -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)
{

View File

@ -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 <tic.h>
@ -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) \
do { \
eventp->bstate = MASK_PRESS(n); \
if (kbuf[0] & 0x40) \
eventp->bstate = MASK_RELEASE(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) \
do { \
eventp->bstate = (mmask_t) (sp->_mouse_bstate & MASK_PRESS(n) \
? REPORT_MOUSE_POSITION \
: MASK_PRESS(n))
: 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 (!MASK_CHANGED(b)) {
changed = FALSE;
break;
}
}
if (changed) {
merge = FALSE;
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);
next->bstate &= ~MASK_RELEASE(b);
next->bstate |= MASK_CLICK(b);
merge = TRUE;
}
}
if (merge)
next->id = INVALID_EVENT;
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:");
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, runp),
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,26 +1238,26 @@ _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;
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)
&& (follower->bstate & BUTTON_CLICKED)) {
&& (next->bstate & BUTTON_CLICKED)) {
merge = FALSE;
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);
&& (ep->bstate & MASK_CLICK(b))
&& (next->bstate & MASK_CLICK(b))) {
next->bstate &= ~MASK_CLICK(b);
next->bstate |= MASK_DOUBLE_CLICK(b);
merge = TRUE;
}
}
@ -1216,12 +1267,14 @@ _nc_mouse_parse(SCREEN *sp, int runcount)
/* merge double-click events forward */
if ((ep->bstate & BUTTON_DOUBLE_CLICKED)
&& (follower->bstate & BUTTON_CLICKED)) {
&& (next->bstate & BUTTON_CLICKED)) {
merge = FALSE;
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);
&& (ep->bstate & MASK_DOUBLE_CLICK(b))
&& (next->bstate & MASK_CLICK(b))) {
next->bstate &= ~MASK_CLICK(b);
next->bstate |= MASK_TRIPLE_CLICK(b);
merge = TRUE;
}
}
@ -1229,45 +1282,54 @@ _nc_mouse_parse(SCREEN *sp, int runcount)
ep->id = INVALID_EVENT;
}
}
} while
(merge);
/* Discard event if it does not match event mask */
if (!(ep->bstate & sp->_mouse_mask)) {
ep->id = INVALID_EVENT;
}
/* 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, "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 */
/*
* 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;
}
#ifdef TRACE
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, eventp, runp),
RunParams(sp, first_invalid, first_valid),
runcount);
_nc_unlock_global(tracef);
}
for (ep = runp; ep != eventp; ep = NEXT(ep))
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)));
}
}
#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);
}

View File

@ -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 */

View File

@ -40,7 +40,7 @@ AUTHOR
Author: Eric S. Raymond <esr@snark.thyrsus.com> 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);