Exemplo n.º 1
0
trace(const unsigned int tracelevel GCC_UNUSED)
{
    static bool been_here = FALSE;
    static char my_name[] = "trace";

    if (!been_here && tracelevel) {
	been_here = TRUE;

	_nc_tracing = tracelevel;
	if (_nc_access(my_name, W_OK) < 0
	    || (tracefp = fopen(my_name, "wb")) == 0) {
	    perror("curses: Can't open 'trace' file: ");
	    exit(EXIT_FAILURE);
	}
	/* Try to set line-buffered mode, or (failing that) unbuffered,
	 * so that the trace-output gets flushed automatically at the
	 * end of each line.  This is useful in case the program dies. 
	 */
#if HAVE_SETVBUF		/* ANSI */
	(void) setvbuf(tracefp, (char *) 0, _IOLBF, 0);
#elif HAVE_SETBUF		/* POSIX */
	(void) setbuffer(tracefp, (char *) 0);
#endif
	_tracef("TRACING NCURSES version %s (tracelevel=%#x)",
		curses_version(), tracelevel);
    } else if (_nc_tracing != tracelevel) {
	_nc_tracing = tracelevel;
	_tracef("tracelevel=%#x", tracelevel);
    }
}
Exemplo n.º 2
0
static void _trace_slot(const char *tag)
{
	MEVENT *ep;

	_tracef(tag);

	for (ep = events; ep < events + EV_MAX; ep++)
		_tracef("mouse event queue slot %d = %s", ep-events, _tracemouse(ep));
}
Exemplo n.º 3
0
static void
_trace_slot(SCREEN *sp, const char *tag)
{
    MEVENT *ep;

    _tracef("%s", tag);

    for (ep = FirstEV(sp); ep <= LastEV(sp); ep++)
	_tracef("mouse event queue slot %ld = %s",
		(long) IndexEV(sp, ep),
		_nc_tracemouse(sp, ep));
}
Exemplo n.º 4
0
trace(const unsigned int tracelevel)
{
    if ((TraceFP == 0) && tracelevel) {
	const char *mode = _nc_globals.init_trace ? "ab" : "wb";

	if (TracePath[0] == '\0') {
	    int size = sizeof(TracePath) - 12;
	    if (getcwd(TracePath, size) == 0) {
		perror("curses: Can't get working directory");
		exit(EXIT_FAILURE);
	    }
	    TracePath[size] = '\0';
	    assert(strlen(TracePath) <= size);
	    strlcat(TracePath, "/trace", sizeof(TracePath));
	    if (_nc_is_dir_path(TracePath)) {
		strlcat(TracePath, ".log", sizeof(TracePath));
	    }
	}

	_nc_globals.init_trace = TRUE;
	_nc_tracing = tracelevel;
	if (_nc_access(TracePath, W_OK) < 0
	    || (TraceFP = fopen(TracePath, mode)) == 0) {
	    perror("curses: Can't open 'trace' file");
	    exit(EXIT_FAILURE);
	}
	/* Try to set line-buffered mode, or (failing that) unbuffered,
	 * so that the trace-output gets flushed automatically at the
	 * end of each line.  This is useful in case the program dies. 
	 */
#if HAVE_SETVBUF		/* ANSI */
	(void) setvbuf(TraceFP, (char *) 0, _IOLBF, 0);
#elif HAVE_SETBUF		/* POSIX */
	(void) setbuffer(TraceFP, (char *) 0);
#endif
	_tracef("TRACING NCURSES version %s.%d (tracelevel=%#x)",
		NCURSES_VERSION,
		NCURSES_VERSION_PATCH,
		tracelevel);
    } else if (tracelevel == 0) {
	if (TraceFP != 0) {
	    fclose(TraceFP);
	    TraceFP = 0;
	}
	_nc_tracing = tracelevel;
    } else if (_nc_tracing != tracelevel) {
	_nc_tracing = tracelevel;
	_tracef("tracelevel=%#x", tracelevel);
    }
}
Exemplo n.º 5
0
int wdelch(WINDOW *win)
{
	chtype	*temp1, *temp2;
	chtype	*end;

#ifdef TRACE
	if (_tracing)
	    _tracef("wdelch(%x) called", win);
#endif

	end = &win->_line[win->_cury][win->_maxx];
	temp2 = &win->_line[win->_cury][win->_curx + 1];
	temp1 = temp2 - 1;

	while (temp1 < end)
	    *temp1++ = *temp2++;

	*temp1 = ' ' | win->_attrs;

	win->_lastchar[win->_cury] = win->_maxx;

	if (win->_firstchar[win->_cury] == _NOCHANGE
				   || win->_firstchar[win->_cury] > win->_curx)
	    win->_firstchar[win->_cury] = win->_curx;

}
Exemplo n.º 6
0
static void
show_window_sizes(const char *name)
{
    WINDOWLIST *wp;

    _tracef("%s resizing: %2d x %2d (%2d x %2d)", name, LINES, COLS,
	    screen_lines, screen_columns);
    for (wp = _nc_windows; wp != 0; wp = wp->next) {
	_tracef("  window %p is %2d x %2d at %2d,%2d",
		&(wp->win),
		wp->win._maxy + 1,
		wp->win._maxx + 1,
		wp->win._begy,
		wp->win._begx);
    }
}
Exemplo n.º 7
0
int whline(WINDOW *win, chtype ch, int n)
{
int line;
int start;
int end;

#ifdef TRACE
	if (_tracing)
	    _tracef("whline(%x,%x,%d) called", win, ch, n);
#endif

	line = win->_cury;
	start = win->_curx + 1;
	end = start + n;
	if (end > win->_maxx) end = win->_maxx;

	if (win->_firstchar[line] > start) win->_firstchar[line] = start;
	if (win->_lastchar[line] < start) win->_lastchar[line] = end;

	while ( end >= start) {
		win->_line[line][end] = ch;
		end--;
	}

	return OK;
}
Exemplo n.º 8
0
void trace(const unsigned int tracelevel GCC_UNUSED)
{
#ifdef TRACE
static bool	been_here = FALSE;

   	_nc_tracing = tracelevel;
	if (! been_here && tracelevel) {
		been_here = TRUE;

		if ((tracefp = fopen("trace", "w")) == 0) {
			perror("curses: Can't open 'trace' file: ");
			exit(EXIT_FAILURE);
		}
		/* Try to set line-buffered mode, or (failing that) unbuffered,
		 * so that the trace-output gets flushed automatically at the
		 * end of each line.  This is useful in case the program dies. 
		 */
#if HAVE_SETVBUF	/* ANSI */
		(void) setvbuf(tracefp, (char *)0, _IOLBF, 0);
#elif HAVE_SETBUF	/* POSIX */
		(void) setbuffer(tracefp, (char *)0);
#endif
		_tracef("TRACING NCURSES version %s (%d)",
			NCURSES_VERSION, NCURSES_VERSION_PATCH);
	}
#endif
}
Exemplo n.º 9
0
_nc_dStack(const char *fmt, int num, const PANEL * pan)
{
  char s80[80];

  sprintf(s80, fmt, num, pan);
  _tracef("%s b=%s t=%s", s80,
	  (_nc_bottom_panel) ? USER_PTR(_nc_bottom_panel->user) : "--",
	  (_nc_top_panel) ? USER_PTR(_nc_top_panel->user) : "--");
  if (pan)
    _tracef("pan id=%s", USER_PTR(pan->user));
  pan = _nc_bottom_panel;
  while (pan)
    {
      dPanel("stk", pan);
      pan = pan->above;
    }
}
Exemplo n.º 10
0
_nc_dPanel(const char *text, const PANEL * pan)
{
  _tracef("%s id=%s b=%s a=%s y=%d x=%d",
	  text, USER_PTR(pan->user),
	  (pan->below) ? USER_PTR(pan->below->user) : "--",
	  (pan->above) ? USER_PTR(pan->above->user) : "--",
	  PSTARTY(pan), PSTARTX(pan));
}
Exemplo n.º 11
0
int wborder(WINDOW *win, chtype ls, chtype rs, chtype ts,
	chtype bs, chtype tl, chtype tr, chtype bl, chtype br)
{
int i;
int endx, endy;

#ifdef TRACE
	if (_tracing)
	    _tracef("wborder() called");
#endif

	if (ls == 0) ls = ACS_VLINE;
	if (rs == 0) rs = ACS_VLINE;
	if (ts == 0) ts = ACS_HLINE;
	if (bs == 0) bs = ACS_HLINE;
	if (tl == 0) tl = ACS_ULCORNER;
	if (tr == 0) tr = ACS_URCORNER;
	if (bl == 0) bl = ACS_LLCORNER;
	if (br == 0) br = ACS_LRCORNER;

	ls |= win->_attrs;
	rs |= win->_attrs;
	ts |= win->_attrs;
	bs |= win->_attrs;
	tl |= win->_attrs;
	tr |= win->_attrs;
	bl |= win->_attrs;
	br |= win->_attrs;

	endx = win->_maxx;
	endy = win->_maxy;

	for (i = 0; i <= endx; i++) {
		win->_line[0][i] = ts; 
		win->_line[endy][i] = bs; 
	}
	win->_firstchar[endy] = win->_firstchar[0] = 0;
	win->_lastchar[endy] = win->_lastchar[0] = endx;

	for (i = 0; i <= endy; i++)
	{
		win->_line[i][0] =  ls;
		win->_line[i][endx] =  rs;
		win->_firstchar[i] = 0;
		win->_lastchar[i] = endx;
	}
	win->_line[0][0] = tl;
	win->_line[0][endx] = tr;
	win->_line[endy][0] = bl;
	win->_line[endy][endx] = br;

#if 0
	if (! win->_scroll  &&  (win->_flags & _SCROLLWIN))
	    fp[0] = fp[endx] = lp[0] = lp[endx] = ' ';
#endif

	return OK;
}
Exemplo n.º 12
0
static void
show_window_sizes(const char *name)
{
    WINDOWLIST *wp;

    _nc_lock_global(curses);
    _tracef("%s resizing: %2d x %2d (%2d x %2d)", name, LINES, COLS,
	    screen_lines, screen_columns);
    for (each_window(wp)) {
	_tracef("  window %p is %2ld x %2ld at %2ld,%2ld",
		&(wp->win),
		(long) wp->win._maxy + 1,
		(long) wp->win._maxx + 1,
		(long) wp->win._begy,
		(long) wp->win._begx);
    }
    _nc_unlock_global(curses);
}
Exemplo n.º 13
0
void
_nc_dPanel(const char *text, const PANEL *pan)
{
	_tracef("%s id=%s b=%s a=%s y=%d x=%d",
		text, USER_PTR(pan->user),
		(pan->below) ?  USER_PTR(pan->below->user) : "--",
		(pan->above) ?  USER_PTR(pan->above->user) : "--",
		pan->wstarty, pan->wstartx);
}
Exemplo n.º 14
0
int wclear(WINDOW *win)
{
#ifdef TRACE
	if (_tracing)
	    _tracef("wclear(%x) called", win);
#endif

	werase(win);

	win->_clear = TRUE;

	return ERR;
}
Exemplo n.º 15
0
int wrefresh(WINDOW *win)
{
#ifdef TRACE
	if (_tracing)
	    _tracef("wrefresh(%x) called", win);
#endif

	if (win == curscr)
	    curscr->_clear = TRUE;
	else
	    wnoutrefresh(win);
	doupdate();
}
Exemplo n.º 16
0
int wnoutrefresh(WINDOW *win)
{
	int	i, j;
	int	begx = win->_begx;
	int	begy = win->_begy;
	int	m, n;

#ifdef TRACE
	if (_tracing)
	    _tracef("wnoutrefresh(%x) called", win);
#endif

	for (i=0, m=begy; i <= win->_maxy; i++, m++)
	{

	    if (win->_firstchar[i] != _NOCHANGE)
	    {
		j = win->_firstchar[i];
		n = j + begx;
		for (; j <= win->_lastchar[i]; j++, n++)
		{
		    if (win->_line[i][j] != newscr->_line[m][n])
		    {
			newscr->_line[m][n] = win->_line[i][j];

			if (newscr->_firstchar[m] == _NOCHANGE)
			    newscr->_firstchar[m] = newscr->_lastchar[m] = n;
			else if (n < newscr->_firstchar[m])
			    newscr->_firstchar[m] = n;
			else if (n > newscr->_lastchar[m])
			    newscr->_lastchar[m] = n;
		    }
		}
	    }

	    win->_firstchar[i] = win->_lastchar[i] = _NOCHANGE;
	}

	if (win->_clear)
	{
	    win->_clear = FALSE;
	    newscr->_clear = TRUE;
	}

	if (! win->_leave)
	{
	    newscr->_cury = win->_cury + win->_begy;
	    newscr->_curx = win->_curx + win->_begx;
	}
}
Exemplo n.º 17
0
static void recur_tries(struct tries *tree, unsigned level)
{
	if (level > len)
		buffer = (unsigned char *)realloc(buffer, len = (level + 1) * 4);

	while (tree != 0) {
		if ((buffer[level] = tree->ch) == 0)
			buffer[level] = 128;
		buffer[level+1] = 0;
		if (tree->value != 0) {
			_tracef("%5d: %s (%s)", tree->value, _nc_visbuf((char *)buffer), keyname(tree->value));
		}
		if (tree->child)
			recur_tries(tree->child, level+1);
		tree = tree->sibling;
	}
}
Exemplo n.º 18
0
int wsetscrreg(WINDOW *win, int top, int bottom)
{
#ifdef TRACE
	if (_tracing)
	    _tracef("wsetscrreg(%x,%d,%d) called", win, top, bottom);
#endif

    	if (top >= win->_begy  && top <= win->_maxy &&
		bottom >= win->_begy  &&  bottom <= win->_maxy &&
		bottom > top)
	{
	    win->_regtop = top;
	    win->_regbottom = bottom;

	    return(OK);
	}
	else
	    return(ERR);
}
Exemplo n.º 19
0
int  wclrtoeol(WINDOW *win)
{
	chtype	*maxx, *ptr, *end;
	int	y, x, minx;
	chtype	blank = ' ' | win->_attrs;

#ifdef TRACE
	if (_tracing)
	    _tracef("wclrtoeol(%x) called", win);
#endif

	y = win->_cury;
	x = win->_curx;

	end = &win->_line[y][win->_maxx];
	minx = _NOCHANGE;
	maxx = &win->_line[y][x];

	for (ptr = maxx; ptr < end; ptr++)
	{
	    if (*ptr != blank)
	    {
		maxx = ptr;
		if (minx == _NOCHANGE)
		    minx = ptr - win->_line[y];
		*ptr = blank;
	    }
	}

	if (minx != _NOCHANGE)
	{
	    if (win->_firstchar[y] > minx || win->_firstchar[y] == _NOCHANGE)
		win->_firstchar[y] = minx;

	    if (win->_lastchar[y] < maxx - win->_line[y])
		win->_lastchar[y] = maxx - win->_line[y];
	}
}
Exemplo n.º 20
0
int wvline(WINDOW *win, chtype ch, int n)
{
int row, col;
int end;

#ifdef TRACE
	if (_tracing)
	    _tracef("wvline(%x,%x,%d) called", win, ch, n);
#endif

	row = win->_cury + 1;
	col = win->_curx;
	end = row + n;
	if (end > win->_maxy) end = win->_maxy;
	while(end >= row) {
		win->_line[end][col] = ch;
		if (win->_firstchar[end] > col) win->_firstchar[end] = col;
		if (win->_lastchar[end] < col) win->_lastchar[end] = col;
		end--;
	}

	return OK;
}
Exemplo n.º 21
0
int setupterm(char *termname, int filedes, int *errret)
{
    static int	_been_here = FALSE;
    char		filename1[1024];
    char		filename2[1024];
    char		*directory = SRCDIR;
    char		*terminfo;
    struct term	*term_ptr;
    char 		*rows, *cols;

    if (_been_here == FALSE) {
        _been_here = TRUE;
#ifdef TRACE
        _init_trace();
        if (_tracing)
            _tracef("setupterm(%s,%d,%x) called", termname, filedes, errret);
#endif

        if (termname == NULL)
        {
            termname = getenv("TERM");
            if (termname == NULL)
                ret_error0(-1, "TERM environment variable not set.\n");
        }

        term_ptr = (struct term *) malloc(sizeof(struct term));

        if (term_ptr == NULL)
            ret_error0(-1, "Not enough memory to create terminal structure.\n") ;

        if ((terminfo = getenv("TERMINFO")) != NULL)
            directory = terminfo;

        sprintf(filename1, "%s/%c/%s", directory, termname[0], termname);
        sprintf(filename2, "%s/%c/%s", SRCDIR, termname[0], termname);

        if (read_entry(filename1, term_ptr) < 0 &&  read_entry(filename2, term_ptr) < 0)
            ret_error(0, "'%s': Unknown terminal type.\n", termname);

        if (command_character  &&  getenv("CC"))
            do_prototype();

        cur_term = term_ptr;
        strncpy(ttytype, cur_term->term_names, NAMESIZE - 1);
        ttytype[NAMESIZE - 1] = '\0';
        cur_term->Filedes = filedes;

        /* figure out the size of the screen */

        rows = getenv("LINES");
        if (rows != (char *)NULL)
            LINES = atoi(rows);

        cols = getenv("COLUMNS");
        if (cols != (char *)NULL)
            COLS = atoi(cols);

        if (_use_env == FALSE)
            if (lines > 0 && columns > 0) {
                LINES = lines;
                COLS  = columns;
            }
        /* use envirronment; if not set then use window size */
#ifdef TRACE
        _tracef("using environment to find screen size");
#endif
        if (LINES <= 0 || COLS <= 0) {
            if (resize(filedes) == 1) {
                fprintf(stderr, "can't find the screen size");
                exit(1);
            }
        }
        lines = LINES;
        columns = COLS;

#ifdef TRACE
        _tracef("screen size is %dx%d and %dx%d", COLS, LINES, columns, lines);
#endif

#ifdef TERMIOS
        tcgetattr(filedes, &cur_term->Ottyb);
        if (cur_term->Ottyb.c_oflag & XTABS)
            tab = back_tab = NULL;

        cur_term->Nttyb = cur_term->Ottyb;
        cur_term->Nttyb.c_oflag &= ~XTABS;
#else
        gtty(filedes, &cur_term->Ottyb);
        if (cur_term->Ottyb.sg_flags & XTABS)
            tab = back_tab = NULL;

        cur_term->Nttyb = cur_term->Ottyb;
        cur_term->Nttyb.sg_flags &= ~XTABS;
#endif

        def_prog_mode();

        if (errret)
            *errret = 1;
    }
    return(1);
}
Exemplo n.º 22
0
static bool
_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);
    int n;
    int b;
    bool merge;

    TR(MY_TRACE, ("_nc_mouse_parse(%d) called", runcount));

    /*
     * When we enter this routine, the event list next-free pointer
     * points just past a run of mouse events that we know were separated
     * in time by less than the critical click interval. The job of this
     * routine is to collapse this run into a single higher-level event
     * or gesture.
     *
     * We accomplish this in two passes.  The first pass merges press/release
     * pairs into click events.  The second merges runs of click events into
     * double or triple-click events.
     *
     * 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.
     *
     * 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
     * gestures on anything that reports press/release events on a per-
     * 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);
    }

#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),
		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) {

#define MASK_CHANGED(x) (!(ep->bstate & MASK_PRESS(x)) \
		      == !(next->bstate & MASK_RELEASE(x)))

	    if (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
		) {
		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 (merge)
		    next->id = INVALID_EVENT;
	    }
	}
    } while
	(merge);

#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);
    }
#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.
     *
     * NOTE: There is a problem with this design!  If the application
     * allows enough click events to pile up in the circular queue so
     * they wrap around, it will cheerfully merge the newest forward
     * into the oldest, creating a bogus doubleclick and confusing
     * the queue-traversal logic rather badly.  Generally this won't
     * happen, because calling getmouse() marks old events invalid and
     * ineligible for merges.  The true solution to this problem would
     * be to timestamp each MEVENT and perform the obvious sanity check,
     * 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;
			}
		    }
		    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;
			}
		    }
		    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 */

    /*
     * 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 (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);
    }
    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);
}
Exemplo n.º 23
0
_nc_init_acs(void)
{
    chtype *fake_map = acs_map;
    chtype *real_map = SP != 0 ? SP->_acs_map : fake_map;
    int j;

    T(("initializing ACS map"));

    /*
     * If we're using this from curses (rather than terminfo), we are storing
     * the mapping information in the SCREEN struct so we can decide how to
     * render it.
     */
    if (real_map != fake_map) {
	for (j = 1; j < ACS_LEN; ++j) {
	    real_map[j] = 0;
	    fake_map[j] = A_ALTCHARSET | j;
	    SP->_screen_acs_map[j] = FALSE;
	}
    } else {
	for (j = 1; j < ACS_LEN; ++j) {
	    real_map[j] = 0;
	}
    }

    /*
     * Initializations for a UNIX-like multi-terminal environment.  Use
     * ASCII chars and count on the terminfo description to do better.
     */
    real_map['l'] = '+';	/* should be upper left corner */
    real_map['m'] = '+';	/* should be lower left corner */
    real_map['k'] = '+';	/* should be upper right corner */
    real_map['j'] = '+';	/* should be lower right corner */
    real_map['u'] = '+';	/* should be tee pointing left */
    real_map['t'] = '+';	/* should be tee pointing right */
    real_map['v'] = '+';	/* should be tee pointing up */
    real_map['w'] = '+';	/* should be tee pointing down */
    real_map['q'] = '-';	/* should be horizontal line */
    real_map['x'] = '|';	/* should be vertical line */
    real_map['n'] = '+';	/* should be large plus or crossover */
    real_map['o'] = '~';	/* should be scan line 1 */
    real_map['s'] = '_';	/* should be scan line 9 */
    real_map['`'] = '+';	/* should be diamond */
    real_map['a'] = ':';	/* should be checker board (stipple) */
    real_map['f'] = '\'';	/* should be degree symbol */
    real_map['g'] = '#';	/* should be plus/minus */
    real_map['~'] = 'o';	/* should be bullet */
    real_map[','] = '<';	/* should be arrow pointing left */
    real_map['+'] = '>';	/* should be arrow pointing right */
    real_map['.'] = 'v';	/* should be arrow pointing down */
    real_map['-'] = '^';	/* should be arrow pointing up */
    real_map['h'] = '#';	/* should be board of squares */
    real_map['i'] = '#';	/* should be lantern symbol */
    real_map['0'] = '#';	/* should be solid square block */
    /* these defaults were invented for ncurses */
    real_map['p'] = '-';	/* should be scan line 3 */
    real_map['r'] = '-';	/* should be scan line 7 */
    real_map['y'] = '<';	/* should be less-than-or-equal-to */
    real_map['z'] = '>';	/* should be greater-than-or-equal-to */
    real_map['{'] = '*';	/* should be greek pi */
    real_map['|'] = '!';	/* should be not-equal */
    real_map['}'] = 'f';	/* should be pound-sterling symbol */

#if !USE_WIDEC_SUPPORT
    if (_nc_unicode_locale() && _nc_locale_breaks_acs()) {
	acs_chars = NULL;
	ena_acs = NULL;
	enter_alt_charset_mode = NULL;
	exit_alt_charset_mode = NULL;
	set_attributes = NULL;
    }
#endif

    if (ena_acs != NULL) {
	TPUTS_TRACE("ena_acs");
	putp(ena_acs);
    }
#if NCURSES_EXT_FUNCS
    /*
     * Linux console "supports" the "PC ROM" character set by the coincidence
     * that smpch/rmpch and smacs/rmacs have the same values.  ncurses has
     * no codepage support (see SCO Merge for an example).  Outside of the
     * values defined in acsc, there are no definitions for the "PC ROM"
     * character set (assumed by some applications to be codepage 437), but we
     * allow those applications to use those codepoints.
     *
     * test/blue.c uses this feature.
     */
#define PCH_KLUDGE(a,b) (a != 0 && b != 0 && !strcmp(a,b))
    if (PCH_KLUDGE(enter_pc_charset_mode, enter_alt_charset_mode) &&
	PCH_KLUDGE(exit_pc_charset_mode, exit_alt_charset_mode)) {
	size_t i;
	for (i = 1; i < ACS_LEN; ++i) {
	    if (real_map[i] == 0) {
		real_map[i] = i;
		if (real_map != fake_map) {
		    if (SP != 0)
			SP->_screen_acs_map[i] = TRUE;
		}
	    }
	}
    }
#endif

    if (acs_chars != NULL) {
	size_t i = 0;
	size_t length = strlen(acs_chars);

	while (i + 1 < length) {
	    if (acs_chars[i] != 0 && UChar(acs_chars[i]) < ACS_LEN) {
		real_map[UChar(acs_chars[i])] = UChar(acs_chars[i + 1]) | A_ALTCHARSET;
		if (SP != 0)
		    SP->_screen_acs_map[UChar(acs_chars[i])] = TRUE;
	    }
	    i += 2;
	}
    }
#ifdef TRACE
    /* Show the equivalent mapping, noting if it does not match the
     * given attribute, whether by re-ordering or duplication.
     */
    if (_nc_tracing & TRACE_CALLS) {
	size_t n, m;
	char show[ACS_LEN * 2 + 1];
	for (n = 1, m = 0; n < ACS_LEN; n++) {
	    if (real_map[n] != 0) {
		show[m++] = (char) n;
		show[m++] = ChCharOf(real_map[n]);
	    }
	}
	show[m] = 0;
	if (acs_chars == NULL || strcmp(acs_chars, show))
	    _tracef("%s acs_chars %s",
		    (acs_chars == NULL) ? "NULL" : "READ",
		    _nc_visbuf(acs_chars));
	_tracef("%s acs_chars %s",
		(acs_chars == NULL)
		? "NULL"
		: (strcmp(acs_chars, show)
		   ? "DIFF"
		   : "SAME"),
		_nc_visbuf(show));
    }
#endif /* TRACE */
}
Exemplo n.º 24
0
tputs(const char *string, int affcnt, int (*outc) (int))
{
    bool always_delay;
    bool normal_delay;
    int number;
#if BSD_TPUTS
    int trailpad;
#endif /* BSD_TPUTS */

#ifdef TRACE
    char addrbuf[32];

    if (_nc_tracing & TRACE_TPUTS) {
	if (outc == _nc_outch)
	    (void) strcpy(addrbuf, "_nc_outch");
	else
	    (void) sprintf(addrbuf, "%p", outc);
	if (_nc_tputs_trace) {
	    _tracef("tputs(%s = %s, %d, %s) called", _nc_tputs_trace,
		    _nc_visbuf(string), affcnt, addrbuf);
	} else {
	    _tracef("tputs(%s, %d, %s) called", _nc_visbuf(string), affcnt, addrbuf);
	}
	_nc_tputs_trace = (char *) NULL;
    }
#endif /* TRACE */

    if (!VALID_STRING(string))
	return ERR;

    if (cur_term == 0) {
	always_delay = FALSE;
	normal_delay = TRUE;
    } else {
	always_delay = (string == bell) || (string == flash_screen);
	normal_delay =
	    !xon_xoff
	    && padding_baud_rate
#if NCURSES_NO_PADDING
	    && (SP == 0 || !(SP->_no_padding))
#endif
	    && (_nc_baudrate(ospeed) >= padding_baud_rate);
    }

#if BSD_TPUTS
    /*
     * This ugly kluge deals with the fact that some ancient BSD programs
     * (like nethack) actually do the likes of tputs("50") to get delays.
     */
    trailpad = 0;
    if (isdigit(UChar(*string))) {
	while (isdigit(UChar(*string))) {
	    trailpad = trailpad * 10 + (*string - '0');
	    string++;
	}
	trailpad *= 10;
	if (*string == '.') {
	    string++;
	    if (isdigit(UChar(*string))) {
		trailpad += (*string - '0');
		string++;
	    }
	    while (isdigit(UChar(*string)))
		string++;
	}

	if (*string == '*') {
	    trailpad *= affcnt;
	    string++;
	}
    }
#endif /* BSD_TPUTS */

    my_outch = outc;		/* redirect delay_output() */
    while (*string) {
	if (*string != '$')
	    (*outc) (*string);
	else {
	    string++;
	    if (*string != '<') {
		(*outc) ('$');
		if (*string)
		    (*outc) (*string);
	    } else {
		bool mandatory;

		string++;
		if ((!isdigit(UChar(*string)) && *string != '.')
		    || !strchr(string, '>')) {
		    (*outc) ('$');
		    (*outc) ('<');
		    continue;
		}

		number = 0;
		while (isdigit(UChar(*string))) {
		    number = number * 10 + (*string - '0');
		    string++;
		}
		number *= 10;
		if (*string == '.') {
		    string++;
		    if (isdigit(UChar(*string))) {
			number += (*string - '0');
			string++;
		    }
		    while (isdigit(UChar(*string)))
			string++;
		}

		mandatory = FALSE;
		while (*string == '*' || *string == '/') {
		    if (*string == '*') {
			number *= affcnt;
			string++;
		    } else {	/* if (*string == '/') */
			mandatory = TRUE;
			string++;
		    }
		}

		if (number > 0
		    && (always_delay
			|| normal_delay
			|| mandatory))
		    delay_output(number / 10);

	    }			/* endelse (*string == '<') */
	}			/* endelse (*string == '$') */

	if (*string == '\0')
	    break;

	string++;
    }

#if BSD_TPUTS
    /*
     * Emit any BSD-style prefix padding that we've accumulated now.
     */
    if (trailpad > 0
	&& (always_delay || normal_delay))
	delay_output(trailpad / 10);
#endif /* BSD_TPUTS */

    my_outch = _nc_outch;
    return OK;
}
Exemplo n.º 25
0
_nc_get_token(bool silent)
{
    static const char terminfo_punct[] = "@%&*!#";
    long number;
    int type;
    int ch;
    char *numchk;
    char numbuf[80];
    unsigned found;
    static char buffer[MAX_ENTRY_SIZE];
    char *ptr;
    int dot_flag = FALSE;
    long token_start;

    if (pushtype != NO_PUSHBACK) {
	int retval = pushtype;

	_nc_set_type(pushname);
	DEBUG(3, ("pushed-back token: `%s', class %d",
		  _nc_curr_token.tk_name, pushtype));

	pushtype = NO_PUSHBACK;
	pushname[0] = '\0';

	/* currtok wasn't altered by _nc_push_token() */
	return (retval);
    }

    if (end_of_stream())
	return (EOF);

  start_token:
    token_start = stream_pos();
    while ((ch = next_char()) == '\n' || iswhite(ch))
	continue;

    ch = eat_escaped_newline(ch);

    if (ch == EOF)
	type = EOF;
    else {
	/* if this is a termcap entry, skip a leading separator */
	if (separator == ':' && ch == ':')
	    ch = next_char();

	if (ch == '.'
#if NCURSES_EXT_FUNCS
	    && !_nc_disable_period
#endif
	    ) {
	    dot_flag = TRUE;
	    DEBUG(8, ("dot-flag set"));

	    while ((ch = next_char()) == '.' || iswhite(ch))
		continue;
	}

	if (ch == EOF) {
	    type = EOF;
	    goto end_of_token;
	}

	/* have to make some punctuation chars legal for terminfo */
	if (!isalnum(ch)
#if NCURSES_EXT_FUNCS
	    && !(ch == '.' && _nc_disable_period)
#endif
	    && !strchr(terminfo_punct, (char) ch)) {
	    if (!silent)
		_nc_warning("Illegal character (expected alphanumeric or %s) - %s",
			    terminfo_punct, unctrl((chtype) ch));
	    _nc_panic_mode(separator);
	    goto start_token;
	}

	ptr = buffer;
	*(ptr++) = ch;

	if (first_column) {
	    char *desc;

	    _nc_comment_start = token_start;
	    _nc_comment_end = _nc_curr_file_pos;
	    _nc_start_line = _nc_curr_line;

	    _nc_syntax = ERR;
	    while ((ch = next_char()) != '\n') {
		if (ch == EOF)
		    _nc_err_abort("premature EOF");
		else if (ch == ':' && last_char() != ',') {
		    _nc_syntax = SYN_TERMCAP;
		    separator = ':';
		    break;
		} else if (ch == ',') {
		    _nc_syntax = SYN_TERMINFO;
		    separator = ',';
		    /*
		     * Fall-through here is not an accident.  The idea is that
		     * if we see a comma, we figure this is terminfo unless we
		     * subsequently run into a colon -- but we don't stop
		     * looking for that colon until hitting a newline.  This
		     * allows commas to be embedded in description fields of
		     * either syntax.
		     */
		    /* FALLTHRU */
		} else
		    ch = eat_escaped_newline(ch);

		*ptr++ = ch;
	    }
	    ptr[0] = '\0';
	    if (_nc_syntax == ERR) {
		/*
		 * Grrr...what we ought to do here is barf, complaining that
		 * the entry is malformed.  But because a couple of name fields
		 * in the 8.2 termcap file end with |\, we just have to assume
		 * it's termcap syntax.
		 */
		_nc_syntax = SYN_TERMCAP;
		separator = ':';
	    } else if (_nc_syntax == SYN_TERMINFO) {
		/* throw away trailing /, *$/ */
		for (--ptr; iswhite(*ptr) || *ptr == ','; ptr--)
		    continue;
		ptr[1] = '\0';
	    }

	    /*
	     * This is the soonest we have the terminal name fetched.  Set up
	     * for following warning messages.
	     */
	    ptr = strchr(buffer, '|');
	    if (ptr == (char *) NULL)
		ptr = buffer + strlen(buffer);
	    ch = *ptr;
	    *ptr = '\0';
	    _nc_set_type(buffer);
	    *ptr = ch;

	    /*
	     * Compute the boundary between the aliases and the description
	     * field for syntax-checking purposes.
	     */
	    desc = strrchr(buffer, '|');
	    if (!silent && desc) {
		if (*desc == '\0')
		    _nc_warning("empty longname field");
		else if (strchr(desc, ' ') == (char *) NULL)
		    _nc_warning("older tic versions may treat the description field as an alias");
	    }
	    if (!desc)
		desc = buffer + strlen(buffer);

	    /*
	     * Whitespace in a name field other than the long name can confuse
	     * rdist and some termcap tools.  Slashes are a no-no.  Other
	     * special characters can be dangerous due to shell expansion.
	     */
	    for (ptr = buffer; ptr < desc; ptr++) {
		if (isspace(CharOf(*ptr))) {
		    if (!silent)
			_nc_warning("whitespace in name or alias field");
		    break;
		} else if (*ptr == '/') {
		    if (!silent)
			_nc_warning("slashes aren't allowed in names or aliases");
		    break;
		} else if (strchr("$[]!*?", *ptr)) {
		    if (!silent)
			_nc_warning("dubious character `%c' in name or alias field", *ptr);
		    break;
		}
	    }

	    ptr = buffer;

	    _nc_curr_token.tk_name = buffer;
	    type = NAMES;
	} else {
	    while ((ch = next_char()) != EOF) {
		if (!isalnum(ch)) {
		    if (_nc_syntax == SYN_TERMINFO) {
			if (ch != '_')
			    break;
		    } else {	/* allow ';' for "k;" */
			if (ch != ';')
			    break;
		    }
		}
		*(ptr++) = ch;
	    }

	    *ptr++ = '\0';
	    switch (ch) {
	    case ',':
	    case ':':
		if (ch != separator)
		    _nc_err_abort("Separator inconsistent with syntax");
		_nc_curr_token.tk_name = buffer;
		type = BOOLEAN;
		break;
	    case '@':
		if ((ch = next_char()) != separator && !silent)
		    _nc_warning("Missing separator after `%s', have %s",
				buffer, unctrl((chtype) ch));
		_nc_curr_token.tk_name = buffer;
		type = CANCEL;
		break;

	    case '#':
		found = 0;
		while (isalnum(ch = next_char())) {
		    numbuf[found++] = ch;
		    if (found >= sizeof(numbuf) - 1)
			break;
		}
		numbuf[found] = '\0';
		number = strtol(numbuf, &numchk, 0);
		if (!silent) {
		    if (numchk == numbuf)
			_nc_warning("no value given for `%s'", buffer);
		    if ((*numchk != '\0') || (ch != separator))
			_nc_warning("Missing separator");
		}
		_nc_curr_token.tk_name = buffer;
		_nc_curr_token.tk_valnumber = number;
		type = NUMBER;
		break;

	    case '=':
		ch = _nc_trans_string(ptr, buffer + sizeof(buffer));
		if (!silent && ch != separator)
		    _nc_warning("Missing separator");
		_nc_curr_token.tk_name = buffer;
		_nc_curr_token.tk_valstring = ptr;
		type = STRING;
		break;

	    case EOF:
		type = EOF;
		break;
	    default:
		/* just to get rid of the compiler warning */
		type = UNDEF;
		if (!silent)
		    _nc_warning("Illegal character - %s", unctrl((chtype) ch));
	    }
	}			/* end else (first_column == FALSE) */
    }				/* end else (ch != EOF) */

  end_of_token:

#ifdef TRACE
    if (dot_flag == TRUE)
	DEBUG(8, ("Commented out "));

    if (_nc_tracing >= DEBUG_LEVEL(7)) {
	switch (type) {
	case BOOLEAN:
	    _tracef("Token: Boolean; name='%s'",
		    _nc_curr_token.tk_name);
	    break;

	case NUMBER:
	    _tracef("Token: Number;  name='%s', value=%d",
		    _nc_curr_token.tk_name,
		    _nc_curr_token.tk_valnumber);
	    break;

	case STRING:
	    _tracef("Token: String;  name='%s', value=%s",
		    _nc_curr_token.tk_name,
		    _nc_visbuf(_nc_curr_token.tk_valstring));
	    break;

	case CANCEL:
	    _tracef("Token: Cancel; name='%s'",
		    _nc_curr_token.tk_name);
	    break;

	case NAMES:

	    _tracef("Token: Names; value='%s'",
		    _nc_curr_token.tk_name);
	    break;

	case EOF:
	    _tracef("Token: End of file");
	    break;

	default:
	    _nc_warning("Bad token type");
	}
    }
#endif

    if (dot_flag == TRUE)	/* if commented out, use the next one */
	type = _nc_get_token(silent);

    DEBUG(3, ("token: `%s', class %d",
	      _nc_curr_token.tk_name != 0 ? _nc_curr_token.tk_name :
	      "<null>",
	      type));

    return (type);
}
Exemplo n.º 26
0
static bool
_nc_mouse_parse(SCREEN *sp, int runcount)
/* parse a run of atomic mouse events into a gesture */
{
    MEVENT *eventp = sp->_mouse_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));

    /*
     * When we enter this routine, the event list next-free pointer
     * points just past a run of mouse events that we know were separated
     * in time by less than the critical click interval. The job of this
     * routine is to collapse this run into a single higher-level event
     * or gesture.
     *
     * We accomplish this in two passes.  The first pass merges press/release
     * pairs into click events.  The second merges runs of click events into
     * double or triple-click events.
     *
     * 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 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
     * gestures on anything that reports press/release events on a per-
     * button basis, as long as the device-dependent mouse code puts stuff
     * on the queue in MEVENT format.
     */

    /*
     * 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++) {
	Invalidate(ep);
	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, ep),
		runcount);
	_nc_unlock_global(tracef);
    }
#endif /* TRACE */

    /* first pass; merge press/release pairs */
    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 (ValidEvent(ep) && ValidEvent(next)
		&& ep->x == next->x && ep->y == next->y
		&& (ep->bstate & BUTTON_PRESSED)
		&& (!(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))) {
			    next->bstate &= ~MASK_RELEASE(b);
			    next->bstate |= MASK_CLICK(b);
			    merge = TRUE;
			}
		    }
		    if (merge) {
			Invalidate(ep);
		    }
		}
	    }
	}

	/* Compact valid events */
	if (!ValidEvent(ep)) {
	    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;
		Invalidate(ep);
		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, first_valid),
		    runcount);
	    _nc_unlock_global(tracef);
	}
    }
#endif /* TRACE */

    /*
     * 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
     * they wrap around, it will cheerfully merge the newest forward
     * into the oldest, creating a bogus doubleclick and confusing
     * the queue-traversal logic rather badly.  Generally this won't
     * happen, because calling getmouse() marks old events invalid and
     * ineligible for merges.  The true solution to this problem would
     * be to timestamp each MEVENT and perform the obvious sanity check,
     * but the timer element would have to have sub-second resolution,
     * which would get us into portability trouble.
     */
    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 if (!ValidEvent(next)) {
	    continue;
	} 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) {
		    Invalidate(ep);
		}
	    }

	    /* 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) {
		    Invalidate(ep);
		}
	    }
	}

	/* Discard event if it does not match event mask */
	if (!(ep->bstate & sp->_mouse_mask2)) {
	    Invalidate(ep);
	}

	/* Compact valid events */
	if (!ValidEvent(ep)) {
	    if (ep == first_valid) {
		first_valid = next;
	    } else if (first_invalid == NULL) {
		first_invalid = ep;
	    }
	} else if (first_invalid != NULL) {
	    *first_invalid = *ep;
	    Invalidate(ep);
	    first_invalid = NEXT(first_invalid);
	}

	ep = next;
    }

    if (first_invalid == NULL) {
	first_invalid = eventp;
    }
    sp->_mouse_eventp = first_invalid;

#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, first_invalid, first_valid),
		    runcount);
	    _nc_unlock_global(tracef);
	}
	for (ep = first_valid; ep != first_invalid; ep = NEXT(ep)) {
	    if (ValidEvent(ep))
		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 ValidEvent(PREV(first_invalid));
}
Exemplo n.º 27
0
static inline char *tparam_internal(const char *string, va_list ap)
{
#define NUM_VARS 26
int	param[9];
int	popcount;
int	variable[NUM_VARS];
static int sVariable[NUM_VARS];
char	len;
int	number;
int	level;
int	x, y;
int	i;
int	varused = -1;
register const char *cp;

	out_used = 0;
	if (string == NULL)
		return NULL;

	/*
	 * Find the highest parameter-number referred to in the format string.
	 * Use this value to limit the number of arguments copied from the
	 * variable-length argument list.
	 */
	for (cp = string, popcount = number = 0; *cp != '\0'; cp++) {
		if (cp[0] == '%' && cp[1] != '\0') {
			switch (cp[1]) {
			case '%':
				cp++;
				break;
			case 'i':
				if (popcount < 2)
					popcount = 2;
				break;
			case 'p':
				cp++;
				if (cp[1] >= '1' && cp[1] <= '9') {
					int c = cp[1] - '0';
					if (c > popcount)
						popcount = c;
				}
				break;
			case '0': case '1': case '2': case '3': case '4':
			case '5': case '6': case '7': case '8': case '9':
			case 'd': case 'c': case 's':
				++number;
				break;
			}
		}
	}

	if (number > 9) number = 9;
	for (i = 0; i < max(popcount, number); i++) {
		/*
		 * FIXME: potential loss here if sizeof(int) != sizeof(char *).
		 * A few caps (such as plab_norm) have string-valued parms.
		 */
		param[i] = va_arg(ap, int);
	}

	/*
	 * This is a termcap compatibility hack.  If there are no explicit pop
	 * operations in the string, load the stack in such a way that
	 * successive pops will grab successive parameters.  That will make
	 * the expansion of (for example) \E[%d;%dH work correctly in termcap
	 * style, which means tparam() will expand termcap strings OK.
	 */
	stack_ptr = 0;
	if (popcount == 0) {
		popcount = number;
		for (i = number - 1; i >= 0; i--)
			npush(param[i]);
	}

#ifdef TRACE
	if (_nc_tracing & TRACE_CALLS) {
		for (i = 0; i < popcount; i++)
			save_number(", %d", param[i]);
		_tracef(T_CALLED("%s(%s%s)"), tname, _nc_visbuf(string), out_buff);
		out_used = 0;
 	}
#endif /* TRACE */

	while (*string) {
		if (*string != '%')
			save_char(*string);
		else {
			string++;
			switch (*string) {
			default:
				break;
			case '%':
				save_char('%');
				break;

			case 'd':
				save_number("%d", npop());
				break;

			case 'x':
				save_number("%x", npop());
				break;

			case '0':
				string++;
				len = *string;
				if (len == '2'  ||  len == '3')
				{
					++string;
					if (*string == 'd') {
						if (len == '2')
							save_number("%02d", npop());
						else
							save_number("%03d", npop());
					}
					else if (*string == 'x') {
						if (len == '2')
							save_number("%02x", npop());
						else
							save_number("%03x", npop());
					}
				}
				break;

			case '2':
				string++;
				if (*string == 'd') {
					save_number("%2d", npop());
				}
				else if (*string == 'x') {
					save_number("%2x", npop());
				}
				break;

			case '3':
				string++;
				if (*string == 'd') {
					save_number("%3d", npop());
				}
				else if (*string == 'x') {
					save_number("%3x", npop());
				}
				break;

			case 'c':
				save_char(npop());
				break;

			case 's':
				save_text(spop());
				break;

			case 'p':
				string++;
				if (*string >= '1'  &&  *string <= '9')
					npush(param[*string - '1']);
				break;

			case 'P':
				string++;
				if (islower(*string)) {
					i = (*string - 'a');
					if (i >= 0 && i < NUM_VARS) {
						while (varused < i)
							variable[++varused] = 0;
						variable[i] = npop();
					}
				} else {
					i = (*string - 'A');
					if (i >= 0 && i < NUM_VARS)
						sVariable[i] = npop();
				}
				break;

			case 'g':
				string++;
				if (islower(*string)) {
					i = (*string - 'a');
					if (i >= 0 && i < NUM_VARS) {
						while (varused < i)
							variable[++varused] = 0;
						npush(variable[i]);
					}
				} else {
					i = (*string - 'A');
					if (i >= 0 && i < NUM_VARS)
						npush(sVariable[i]);
				}
				break;

			case '\'':
				string++;
				npush(*string);
				string++;
				break;

			case L_BRACE:
				number = 0;
				string++;
				while (*string >= '0'  &&  *string <= '9') {
					number = number * 10 + *string - '0';
					string++;
				}
				npush(number);
				break;

			case '+':
				npush(npop() + npop());
				break;

			case '-':
				y = npop();
				x = npop();
				npush(x - y);
				break;

			case '*':
				npush(npop() * npop());
				break;

			case '/':
				y = npop();
				x = npop();
				npush(x / y);
				break;

			case 'm':
				y = npop();
				x = npop();
				npush(x % y);
				break;

			case 'A':
				npush(npop() && npop());
				break;

			case 'O':
				npush(npop() || npop());
				break;

			case '&':
				npush(npop() & npop());
				break;

			case '|':
				npush(npop() | npop());
				break;

			case '^':
				npush(npop() ^ npop());
				break;

			case '=':
				y = npop();
				x = npop();
				npush(x == y);
				break;

			case '<':
				y = npop();
				x = npop();
				npush(x < y);
				break;

			case '>':
				y = npop();
				x = npop();
				npush(x > y);
				break;

			case '!':
				npush(! npop());
				break;

			case '~':
				npush(~ npop());
				break;

			case 'i':
				param[0]++;
				param[1]++;
				break;

			case '?':
				break;

			case 't':
				x = npop();
				if (!x) {
					/* scan forward for %e or %; at level zero */
					string++;
					level = 0;
					while (*string) {
						if (*string == '%') {
							string++;
							if (*string == '?')
								level++;
							else if (*string == ';') {
								if (level > 0)
									level--;
								else
									break;
							}
							else if (*string == 'e'  && level == 0)
								break;
						}

						if (*string)
							string++;
					}
				}
				break;

			case 'e':
				/* scan forward for a %; at level zero */
				string++;
				level = 0;
				while (*string) {
					if (*string == '%') {
						string++;
						if (*string == '?')
							level++;
						else if (*string == ';') {
							if (level > 0)
								level--;
							else
								break;
						}
					}

					if (*string)
						string++;
				}
				break;

			case ';':
				break;

			} /* endswitch (*string) */
		} /* endelse (*string == '%') */

		if (*string == '\0')
			break;

		string++;
	} /* endwhile (*string) */

	if (out_buff == 0)
		out_buff = calloc(1,1);
	if (out_used == 0)
		*out_buff = '\0';

	T((T_RETURN("%s"), _nc_visbuf(out_buff)));
	return(out_buff);
}
Exemplo n.º 28
0
_nc_init_acs(void)
{
    T(("initializing ACS map"));

    /*
     * Initializations for a UNIX-like multi-terminal environment.  Use
     * ASCII chars and count on the terminfo description to do better.
     */
    ACS_ULCORNER = '+';		/* should be upper left corner */
    ACS_LLCORNER = '+';		/* should be lower left corner */
    ACS_URCORNER = '+';		/* should be upper right corner */
    ACS_LRCORNER = '+';		/* should be lower right corner */
    ACS_RTEE = '+';		/* should be tee pointing left */
    ACS_LTEE = '+';		/* should be tee pointing right */
    ACS_BTEE = '+';		/* should be tee pointing up */
    ACS_TTEE = '+';		/* should be tee pointing down */
    ACS_HLINE = '-';		/* should be horizontal line */
    ACS_VLINE = '|';		/* should be vertical line */
    ACS_PLUS = '+';		/* should be large plus or crossover */
    ACS_S1 = '~';		/* should be scan line 1 */
    ACS_S9 = '_';		/* should be scan line 9 */
    ACS_DIAMOND = '+';		/* should be diamond */
    ACS_CKBOARD = ':';		/* should be checker board (stipple) */
    ACS_DEGREE = '\'';		/* should be degree symbol */
    ACS_PLMINUS = '#';		/* should be plus/minus */
    ACS_BULLET = 'o';		/* should be bullet */
    ACS_LARROW = '<';		/* should be arrow pointing left */
    ACS_RARROW = '>';		/* should be arrow pointing right */
    ACS_DARROW = 'v';		/* should be arrow pointing down */
    ACS_UARROW = '^';		/* should be arrow pointing up */
    ACS_BOARD = '#';		/* should be board of squares */
    ACS_LANTERN = '#';		/* should be lantern symbol */
    ACS_BLOCK = '#';		/* should be solid square block */
    /* these defaults were invented for ncurses */
    ACS_S3 = '-';		/* should be scan line 3 */
    ACS_S7 = '-';		/* should be scan line 7 */
    ACS_LEQUAL = '<';		/* should be less-than-or-equal-to */
    ACS_GEQUAL = '>';		/* should be greater-than-or-equal-to */
    ACS_PI = '*';		/* should be greek pi */
    ACS_NEQUAL = '!';		/* should be not-equal */
    ACS_STERLING = 'f';		/* should be pound-sterling symbol */

    if (ena_acs != NULL) {
	TPUTS_TRACE("ena_acs");
	putp(ena_acs);
    }
#define ALTCHAR(c)	((chtype)(((unsigned char)(c)) | A_ALTCHARSET))

    if (acs_chars != NULL) {
	size_t i = 0;
	size_t length = strlen(acs_chars);

	while (i < length)
	    switch (acs_chars[i]) {
	    case 'l':
	    case 'm':
	    case 'k':
	    case 'j':
	    case 'u':
	    case 't':
	    case 'v':
	    case 'w':
	    case 'q':
	    case 'x':
	    case 'n':
	    case 'o':
	    case 's':
	    case '`':
	    case 'a':
	    case 'f':
	    case 'g':
	    case '~':
	    case ',':
	    case '+':
	    case '.':
	    case '-':
	    case 'h':
	    case 'i':
	    case '0':
	    case 'p':
	    case 'r':
	    case 'y':
	    case 'z':
	    case '{':
	    case '|':
	    case '}':
		acs_map[(unsigned int) acs_chars[i]] =
		    ALTCHAR(acs_chars[i + 1]);
		i++;
		/* FALLTHRU */
	    default:
		i++;
		break;
	    }
    }
#ifdef TRACE
    /* Show the equivalent mapping, noting if it does not match the
     * given attribute, whether by re-ordering or duplication.
     */
    if (_nc_tracing & TRACE_CALLS) {
	size_t n, m;
	char show[SIZEOF(acs_map) + 1];
	for (n = 1, m = 0; n < SIZEOF(acs_map); n++) {
	    if (acs_map[n] != 0) {
		show[m++] = (char) n;
		show[m++] = TextOf(acs_map[n]);
	    }
	}
	show[m] = 0;
	_tracef("%s acs_chars %s",
		(acs_chars == NULL)
		? "NULL"
		: (strcmp(acs_chars, show)
		   ? "DIFF"
		   : "SAME"),
		_nc_visbuf(show));
    }
#endif /* TRACE */
}