mirror of
				git://git.code.sf.net/p/zsh/code
				synced 2025-11-04 07:21:06 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			1678 lines
		
	
	
	
		
			36 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1678 lines
		
	
	
	
		
			36 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * curses.c - curses windowing module for zsh
 | 
						|
 *
 | 
						|
 * This file is part of zsh, the Z shell.
 | 
						|
 *
 | 
						|
 * Copyright (c) 2007  Clint Adams
 | 
						|
 * All rights reserved.
 | 
						|
 *
 | 
						|
 * Permission is hereby granted, without written agreement and without
 | 
						|
 * license or royalty fees, to use, copy, modify, and distribute this
 | 
						|
 * software and to distribute modified versions of this software for any
 | 
						|
 * purpose, provided that the above copyright notice and the following
 | 
						|
 * two paragraphs appear in all copies of this software.
 | 
						|
 *
 | 
						|
 * In no event shall Clint Adams or the Zsh Development Group be liable
 | 
						|
 * to any party for direct, indirect, special, incidental, or consequential
 | 
						|
 * damages arising out of the use of this software and its documentation,
 | 
						|
 * even if Clint Adams and the Zsh Development Group have been advised of
 | 
						|
 * the possibility of such damage.
 | 
						|
 *
 | 
						|
 * Clint Adams and the Zsh Development Group specifically disclaim any
 | 
						|
 * warranties, including, but not limited to, the implied warranties of
 | 
						|
 * merchantability and fitness for a particular purpose.  The software
 | 
						|
 * provided hereunder is on an "as is" basis, and Clint Adams and the
 | 
						|
 * Zsh Development Group have no obligation to provide maintenance,
 | 
						|
 * support, updates, enhancements, or modifications.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#define ZSH_CURSES_SOURCE 1
 | 
						|
 | 
						|
#include "curses.mdh"
 | 
						|
#include "curses.pro"
 | 
						|
 | 
						|
#ifndef MULTIBYTE_SUPPORT
 | 
						|
# undef HAVE_GETCCHAR
 | 
						|
# undef HAVE_SETCCHAR
 | 
						|
# undef HAVE_WADDWSTR
 | 
						|
# undef HAVE_WGET_WCH
 | 
						|
# undef HAVE_WIN_WCH
 | 
						|
# undef HAVE_NCURSESW_NCURSES_H
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef ZSH_HAVE_CURSES_H
 | 
						|
# include "../zshcurses.h"
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef HAVE_SETCCHAR
 | 
						|
# include <wchar.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
 | 
						|
enum zc_win_flags {
 | 
						|
    /* Window is permanent (probably "stdscr") */
 | 
						|
    ZCWF_PERMANENT = 0x0001,
 | 
						|
    /* Scrolling enabled */
 | 
						|
    ZCWF_SCROLL = 0x0002
 | 
						|
};
 | 
						|
 | 
						|
typedef struct zc_win *ZCWin;
 | 
						|
 | 
						|
struct zc_win {
 | 
						|
    WINDOW *win;
 | 
						|
    char *name;
 | 
						|
    int flags;
 | 
						|
    LinkList children;
 | 
						|
    ZCWin parent;
 | 
						|
};
 | 
						|
 | 
						|
struct zcurses_namenumberpair {
 | 
						|
    char *name;
 | 
						|
    int number;
 | 
						|
};
 | 
						|
 | 
						|
struct colorpairnode {
 | 
						|
    struct hashnode node;
 | 
						|
    short colorpair;
 | 
						|
};
 | 
						|
typedef struct colorpairnode *Colorpairnode;
 | 
						|
 | 
						|
typedef int (*zccmd_t)(const char *nam, char **args);
 | 
						|
struct zcurses_subcommand {
 | 
						|
    const char *name;
 | 
						|
    zccmd_t cmd;
 | 
						|
    int minargs;
 | 
						|
    int maxargs;
 | 
						|
};
 | 
						|
 | 
						|
static struct ttyinfo saved_tty_state;
 | 
						|
static struct ttyinfo curses_tty_state;
 | 
						|
static LinkList zcurses_windows;
 | 
						|
static HashTable zcurses_colorpairs = NULL;
 | 
						|
#ifdef NCURSES_MOUSE_VERSION
 | 
						|
/*
 | 
						|
 * The following is in principle a general set of flags, but
 | 
						|
 * is currently only needed for mouse status.
 | 
						|
 */
 | 
						|
static int zcurses_flags;
 | 
						|
#endif
 | 
						|
 | 
						|
#define ZCURSES_EINVALID 1
 | 
						|
#define ZCURSES_EDEFINED 2
 | 
						|
#define ZCURSES_EUNDEFINED 3
 | 
						|
 | 
						|
#define ZCURSES_UNUSED 1
 | 
						|
#define ZCURSES_USED 2
 | 
						|
 | 
						|
#define ZCURSES_ATTRON 1
 | 
						|
#define ZCURSES_ATTROFF 2
 | 
						|
 | 
						|
static int zc_errno, zc_color_phase=0;
 | 
						|
static short next_cp=0;
 | 
						|
 | 
						|
enum {
 | 
						|
    ZCF_MOUSE_ACTIVE,
 | 
						|
    ZCF_MOUSE_MASK_CHANGED
 | 
						|
};
 | 
						|
 | 
						|
static const struct zcurses_namenumberpair zcurses_attributes[] = {
 | 
						|
    {"blink", A_BLINK},
 | 
						|
    {"bold", A_BOLD},
 | 
						|
    {"dim", A_DIM},
 | 
						|
    {"reverse", A_REVERSE},
 | 
						|
    {"standout", A_STANDOUT},
 | 
						|
    {"underline", A_UNDERLINE},
 | 
						|
    {NULL, 0}
 | 
						|
};
 | 
						|
 | 
						|
static const struct zcurses_namenumberpair zcurses_colors[] = {
 | 
						|
    {"black", COLOR_BLACK},
 | 
						|
    {"red", COLOR_RED},
 | 
						|
    {"green", COLOR_GREEN},
 | 
						|
    {"yellow", COLOR_YELLOW},
 | 
						|
    {"blue", COLOR_BLUE},
 | 
						|
    {"magenta", COLOR_MAGENTA},
 | 
						|
    {"cyan", COLOR_CYAN},
 | 
						|
    {"white", COLOR_WHITE},
 | 
						|
#ifdef HAVE_USE_DEFAULT_COLORS
 | 
						|
    {"default", -1},
 | 
						|
#endif
 | 
						|
    {NULL, 0}
 | 
						|
};
 | 
						|
 | 
						|
#ifdef NCURSES_MOUSE_VERSION
 | 
						|
enum zcurses_mouse_event_types {
 | 
						|
    ZCME_PRESSED,
 | 
						|
    ZCME_RELEASED,
 | 
						|
    ZCME_CLICKED,
 | 
						|
    ZCME_DOUBLE_CLICKED,
 | 
						|
    ZCME_TRIPLE_CLICKED
 | 
						|
};
 | 
						|
 | 
						|
static const struct zcurses_namenumberpair zcurses_mouse_event_list[] = {
 | 
						|
    {"PRESSED", ZCME_PRESSED},
 | 
						|
    {"RELEASED", ZCME_RELEASED},
 | 
						|
    {"CLICKED", ZCME_CLICKED},
 | 
						|
    {"DOUBLE_CLICKED", ZCME_DOUBLE_CLICKED},
 | 
						|
    {"TRIPLE_CLICKED", ZCME_TRIPLE_CLICKED},
 | 
						|
    {NULL, 0}
 | 
						|
};
 | 
						|
 | 
						|
struct zcurses_mouse_event {
 | 
						|
    int button;
 | 
						|
    int what;
 | 
						|
    mmask_t event;
 | 
						|
};
 | 
						|
 | 
						|
static const struct zcurses_mouse_event zcurses_mouse_map[] = {
 | 
						|
    { 1, ZCME_PRESSED, BUTTON1_PRESSED },
 | 
						|
    { 1, ZCME_RELEASED, BUTTON1_RELEASED },
 | 
						|
    { 1, ZCME_CLICKED, BUTTON1_CLICKED },
 | 
						|
    { 1, ZCME_DOUBLE_CLICKED, BUTTON1_DOUBLE_CLICKED },
 | 
						|
    { 1, ZCME_TRIPLE_CLICKED, BUTTON1_TRIPLE_CLICKED },
 | 
						|
 | 
						|
    { 2, ZCME_PRESSED, BUTTON2_PRESSED },
 | 
						|
    { 2, ZCME_RELEASED, BUTTON2_RELEASED },
 | 
						|
    { 2, ZCME_CLICKED, BUTTON2_CLICKED },
 | 
						|
    { 2, ZCME_DOUBLE_CLICKED, BUTTON2_DOUBLE_CLICKED },
 | 
						|
    { 2, ZCME_TRIPLE_CLICKED, BUTTON2_TRIPLE_CLICKED },
 | 
						|
 | 
						|
    { 3, ZCME_PRESSED, BUTTON3_PRESSED },
 | 
						|
    { 3, ZCME_RELEASED, BUTTON3_RELEASED },
 | 
						|
    { 3, ZCME_CLICKED, BUTTON3_CLICKED },
 | 
						|
    { 3, ZCME_DOUBLE_CLICKED, BUTTON3_DOUBLE_CLICKED },
 | 
						|
    { 3, ZCME_TRIPLE_CLICKED, BUTTON3_TRIPLE_CLICKED },
 | 
						|
 | 
						|
    { 4, ZCME_PRESSED, BUTTON4_PRESSED },
 | 
						|
    { 4, ZCME_RELEASED, BUTTON4_RELEASED },
 | 
						|
    { 4, ZCME_CLICKED, BUTTON4_CLICKED },
 | 
						|
    { 4, ZCME_DOUBLE_CLICKED, BUTTON4_DOUBLE_CLICKED },
 | 
						|
    { 4, ZCME_TRIPLE_CLICKED, BUTTON4_TRIPLE_CLICKED },
 | 
						|
 | 
						|
#ifdef BUTTON5_PRESSED
 | 
						|
    /* Not defined if only 32 bits available */
 | 
						|
    { 5, ZCME_PRESSED, BUTTON5_PRESSED },
 | 
						|
    { 5, ZCME_RELEASED, BUTTON5_RELEASED },
 | 
						|
    { 5, ZCME_CLICKED, BUTTON5_CLICKED },
 | 
						|
    { 5, ZCME_DOUBLE_CLICKED, BUTTON5_DOUBLE_CLICKED },
 | 
						|
    { 5, ZCME_TRIPLE_CLICKED, BUTTON5_TRIPLE_CLICKED },
 | 
						|
#endif
 | 
						|
    { 0, 0, 0 }
 | 
						|
};
 | 
						|
 | 
						|
mmask_t zcurses_mouse_mask = ALL_MOUSE_EVENTS;
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
/* Autogenerated keypad string/number mapping*/
 | 
						|
#include "curses_keys.h"
 | 
						|
 | 
						|
static char **
 | 
						|
zcurses_pairs_to_array(const struct zcurses_namenumberpair *nnps)
 | 
						|
{
 | 
						|
    char **arr, **arrptr;
 | 
						|
    int count;
 | 
						|
    const struct zcurses_namenumberpair *nnptr;
 | 
						|
 | 
						|
    for (nnptr = nnps; nnptr->name; nnptr++)
 | 
						|
	;
 | 
						|
    count = nnptr - nnps;
 | 
						|
 | 
						|
    arrptr = arr = (char **)zhalloc((count+1) * sizeof(char *));
 | 
						|
 | 
						|
    for (nnptr = nnps; nnptr->name; nnptr++)
 | 
						|
	*arrptr++ = dupstring(nnptr->name);
 | 
						|
    *arrptr = NULL;
 | 
						|
 | 
						|
    return arr;
 | 
						|
}
 | 
						|
 | 
						|
static const char *
 | 
						|
zcurses_strerror(int err)
 | 
						|
{
 | 
						|
    static const char *errs[] = {
 | 
						|
	"unknown error",
 | 
						|
	"window name invalid",
 | 
						|
	"window already defined",
 | 
						|
	"window undefined",
 | 
						|
	NULL };
 | 
						|
 | 
						|
    return errs[(err < 1 || err > 3) ? 0 : err];
 | 
						|
}
 | 
						|
 | 
						|
static LinkNode
 | 
						|
zcurses_getwindowbyname(const char *name)
 | 
						|
{
 | 
						|
    LinkNode node;
 | 
						|
    ZCWin w;
 | 
						|
 | 
						|
    for (node = firstnode(zcurses_windows); node; incnode(node))
 | 
						|
	if (w = (ZCWin)getdata(node), !strcmp(w->name, name))
 | 
						|
	    return node;
 | 
						|
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
static LinkNode
 | 
						|
zcurses_validate_window(char *win, int criteria)
 | 
						|
{
 | 
						|
    LinkNode target;
 | 
						|
 | 
						|
    if (win==NULL || strlen(win) < 1) {
 | 
						|
	zc_errno = ZCURSES_EINVALID;
 | 
						|
	return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    target = zcurses_getwindowbyname(win);
 | 
						|
 | 
						|
    if (target && (criteria & ZCURSES_UNUSED)) {
 | 
						|
	zc_errno = ZCURSES_EDEFINED;
 | 
						|
	return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!target && (criteria & ZCURSES_USED)) {
 | 
						|
	zc_errno = ZCURSES_EUNDEFINED;
 | 
						|
	return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    zc_errno = 0;
 | 
						|
    return target;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
zcurses_free_window(ZCWin w)
 | 
						|
{
 | 
						|
    if (!(w->flags & ZCWF_PERMANENT) && delwin(w->win)!=OK)
 | 
						|
	return 1;
 | 
						|
 | 
						|
    if (w->name)
 | 
						|
	zsfree(w->name);
 | 
						|
 | 
						|
    if (w->children)
 | 
						|
	freelinklist(w->children, (FreeFunc)NULL);
 | 
						|
 | 
						|
    zfree(w, sizeof(struct zc_win));
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
static struct zcurses_namenumberpair *
 | 
						|
zcurses_attrget(WINDOW *w, char *attr)
 | 
						|
{
 | 
						|
    struct zcurses_namenumberpair *zca;
 | 
						|
 | 
						|
    if (!attr)
 | 
						|
	return NULL;
 | 
						|
 | 
						|
    for(zca=(struct zcurses_namenumberpair *)zcurses_attributes;zca->name;zca++)
 | 
						|
	if (!strcmp(attr, zca->name)) {
 | 
						|
	    return zca;
 | 
						|
	}
 | 
						|
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
static short
 | 
						|
zcurses_color(const char *color)
 | 
						|
{
 | 
						|
    struct zcurses_namenumberpair *zc;
 | 
						|
 | 
						|
    for(zc=(struct zcurses_namenumberpair *)zcurses_colors;zc->name;zc++)
 | 
						|
	if (!strcmp(color, zc->name)) {
 | 
						|
	    return (short)zc->number;
 | 
						|
	}
 | 
						|
 | 
						|
    return (short)-1;
 | 
						|
}
 | 
						|
 | 
						|
static Colorpairnode
 | 
						|
zcurses_colorget(const char *nam, char *colorpair)
 | 
						|
{
 | 
						|
    char *bg, *cp;
 | 
						|
    short f, b;
 | 
						|
    Colorpairnode cpn;
 | 
						|
 | 
						|
    /* zcurses_colorpairs is only initialised if color is supported */
 | 
						|
    if (!zcurses_colorpairs)
 | 
						|
	return NULL;
 | 
						|
 | 
						|
    if (zc_color_phase==1 ||
 | 
						|
	!(cpn = (Colorpairnode) gethashnode(zcurses_colorpairs, colorpair))) {
 | 
						|
	zc_color_phase = 2;
 | 
						|
	cp = ztrdup(colorpair);
 | 
						|
 | 
						|
	bg = strchr(cp, '/');
 | 
						|
	if (bg==NULL) {
 | 
						|
	    zsfree(cp);
 | 
						|
	    return NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	*bg = '\0';        
 | 
						|
	f = zcurses_color(cp);
 | 
						|
	b = zcurses_color(bg+1);
 | 
						|
 | 
						|
	if (f==-1 || b==-1) {
 | 
						|
	    if (f == -1)
 | 
						|
		zwarnnam(nam, "foreground color `%s' not known", cp);
 | 
						|
	    if (b == -1)
 | 
						|
		zwarnnam(nam, "background color `%s' not known", bg+1);
 | 
						|
	    *bg = '/';
 | 
						|
	    zsfree(cp);
 | 
						|
	    return NULL;
 | 
						|
	}
 | 
						|
	*bg = '/';
 | 
						|
 | 
						|
	++next_cp;
 | 
						|
	if (next_cp >= COLOR_PAIRS || init_pair(next_cp, f, b) == ERR)  {
 | 
						|
	    zsfree(cp);
 | 
						|
	    return NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	cpn = (Colorpairnode)zalloc(sizeof(struct colorpairnode));
 | 
						|
	
 | 
						|
	if (!cpn) {
 | 
						|
	    zsfree(cp);
 | 
						|
	    return NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	cpn->colorpair = next_cp;
 | 
						|
	addhashnode(zcurses_colorpairs, cp, (void *)cpn);
 | 
						|
    }
 | 
						|
 | 
						|
    return cpn;
 | 
						|
}
 | 
						|
 | 
						|
static Colorpairnode cpn_match;
 | 
						|
 | 
						|
static void
 | 
						|
zcurses_colornode(HashNode hn, int cp)
 | 
						|
{
 | 
						|
    Colorpairnode cpn = (Colorpairnode)hn;
 | 
						|
    if (cpn->colorpair == (short)cp)
 | 
						|
	cpn_match = cpn;
 | 
						|
}
 | 
						|
 | 
						|
static Colorpairnode
 | 
						|
zcurses_colorget_reverse(short cp)
 | 
						|
{
 | 
						|
    if (!zcurses_colorpairs)
 | 
						|
	return NULL;
 | 
						|
 | 
						|
    cpn_match = NULL;
 | 
						|
    scanhashtable(zcurses_colorpairs, 0, 0, 0,
 | 
						|
		  zcurses_colornode, cp);
 | 
						|
    return cpn_match;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
freecolorpairnode(HashNode hn)
 | 
						|
{
 | 
						|
    zsfree(hn->nam);
 | 
						|
    zfree(hn, sizeof(struct colorpairnode));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*************
 | 
						|
 * Subcommands
 | 
						|
 *************/
 | 
						|
 | 
						|
static int
 | 
						|
zccmd_init(const char *nam, char **args)
 | 
						|
{
 | 
						|
    LinkNode stdscr_win = zcurses_getwindowbyname("stdscr");
 | 
						|
 | 
						|
    if (!stdscr_win) {
 | 
						|
	ZCWin w = (ZCWin)zshcalloc(sizeof(struct zc_win));
 | 
						|
	if (!w)
 | 
						|
	    return 1;
 | 
						|
 | 
						|
	gettyinfo(&saved_tty_state);
 | 
						|
	w->name = ztrdup("stdscr");
 | 
						|
	w->win = initscr();
 | 
						|
	if (w->win == NULL) {
 | 
						|
	    zsfree(w->name);
 | 
						|
	    zfree(w, sizeof(struct zc_win));
 | 
						|
	    return 1;
 | 
						|
	}
 | 
						|
	w->flags = ZCWF_PERMANENT;
 | 
						|
	zinsertlinknode(zcurses_windows, lastnode(zcurses_windows), (void *)w);
 | 
						|
	if (start_color() != ERR) {
 | 
						|
	    Colorpairnode cpn;
 | 
						|
 | 
						|
	    if(!zc_color_phase)
 | 
						|
		zc_color_phase = 1;
 | 
						|
	    zcurses_colorpairs = newhashtable(8, "zc_colorpairs", NULL);
 | 
						|
 | 
						|
	    zcurses_colorpairs->hash        = hasher;
 | 
						|
	    zcurses_colorpairs->emptytable  = emptyhashtable;
 | 
						|
	    zcurses_colorpairs->filltable   = NULL;
 | 
						|
	    zcurses_colorpairs->cmpnodes    = strcmp;
 | 
						|
	    zcurses_colorpairs->addnode     = addhashnode;
 | 
						|
	    zcurses_colorpairs->getnode     = gethashnode2;
 | 
						|
	    zcurses_colorpairs->getnode2    = gethashnode2;
 | 
						|
	    zcurses_colorpairs->removenode  = removehashnode;
 | 
						|
	    zcurses_colorpairs->disablenode = NULL;
 | 
						|
	    zcurses_colorpairs->enablenode  = NULL;
 | 
						|
	    zcurses_colorpairs->freenode    = freecolorpairnode;
 | 
						|
	    zcurses_colorpairs->printnode   = NULL;
 | 
						|
 | 
						|
#ifdef HAVE_USE_DEFAULT_COLORS
 | 
						|
	    use_default_colors();
 | 
						|
#endif
 | 
						|
	    /* Initialise the default color pair, always 0 */
 | 
						|
	    cpn = (Colorpairnode)zalloc(sizeof(struct colorpairnode));
 | 
						|
	    if (cpn) {
 | 
						|
		cpn->colorpair = 0;
 | 
						|
		addhashnode(zcurses_colorpairs,
 | 
						|
			    ztrdup("default/default"), (void *)cpn);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	/*
 | 
						|
	 * We use cbreak mode because we don't want line buffering
 | 
						|
	 * on input since we'd just need to loop over characters.
 | 
						|
	 * We use noecho since the manual says that's the right
 | 
						|
	 * thing to do with cbreak.
 | 
						|
	 *
 | 
						|
	 * Turn these on immediately to catch typeahead.
 | 
						|
	 */
 | 
						|
	cbreak();
 | 
						|
	noecho();
 | 
						|
	gettyinfo(&curses_tty_state);
 | 
						|
    } else {
 | 
						|
	settyinfo(&curses_tty_state);
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
zccmd_addwin(const char *nam, char **args)
 | 
						|
{
 | 
						|
    int nlines, ncols, begin_y, begin_x;
 | 
						|
    ZCWin w;
 | 
						|
 | 
						|
    if (zcurses_validate_window(args[0], ZCURSES_UNUSED) == NULL &&
 | 
						|
	zc_errno) {
 | 
						|
	zerrnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0], 0);
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    nlines = atoi(args[1]);
 | 
						|
    ncols = atoi(args[2]);
 | 
						|
    begin_y = atoi(args[3]);
 | 
						|
    begin_x = atoi(args[4]);
 | 
						|
 | 
						|
    w = (ZCWin)zshcalloc(sizeof(struct zc_win));
 | 
						|
    if (!w)
 | 
						|
	return 1;
 | 
						|
 | 
						|
    w->name = ztrdup(args[0]);
 | 
						|
    if (args[5]) {
 | 
						|
	LinkNode node;
 | 
						|
	ZCWin worig;
 | 
						|
 | 
						|
	node = zcurses_validate_window(args[5], ZCURSES_USED);
 | 
						|
	if (node == NULL) {
 | 
						|
	    zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0],
 | 
						|
		     0);
 | 
						|
	    zsfree(w->name);
 | 
						|
	    zfree(w, sizeof(struct zc_win));
 | 
						|
	    return 1;
 | 
						|
	}
 | 
						|
 | 
						|
	worig = (ZCWin)getdata(node);
 | 
						|
 | 
						|
	w->win = subwin(worig->win, nlines, ncols, begin_y, begin_x);
 | 
						|
	if (w->win) {
 | 
						|
	    w->parent = worig;
 | 
						|
	    if (!worig->children)
 | 
						|
		worig->children = znewlinklist();
 | 
						|
	    zinsertlinknode(worig->children, lastnode(worig->children),
 | 
						|
			    (void *)w);
 | 
						|
	}
 | 
						|
    } else {
 | 
						|
	w->win = newwin(nlines, ncols, begin_y, begin_x);
 | 
						|
    }
 | 
						|
 | 
						|
    if (w->win == NULL) {
 | 
						|
	zwarnnam(nam, "failed to create window `%s'", w->name);
 | 
						|
	zsfree(w->name);
 | 
						|
	zfree(w, sizeof(struct zc_win));
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    zinsertlinknode(zcurses_windows, lastnode(zcurses_windows), (void *)w);
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
zccmd_delwin(const char *nam, char **args)
 | 
						|
{
 | 
						|
    LinkNode node;
 | 
						|
    ZCWin w;
 | 
						|
    int ret = 0;
 | 
						|
 | 
						|
    node = zcurses_validate_window(args[0], ZCURSES_USED);
 | 
						|
    if (node == NULL) {
 | 
						|
	zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    w = (ZCWin)getdata(node);
 | 
						|
 | 
						|
    if (w == NULL) {
 | 
						|
	zwarnnam(nam, "record for window `%s' is corrupt", args[0]);
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
    if (w->flags & ZCWF_PERMANENT) {
 | 
						|
	zwarnnam(nam, "window `%s' can't be deleted", args[0]);
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if (w->children && firstnode(w->children)) {
 | 
						|
	zwarnnam(nam, "window `%s' has subwindows, delete those first",
 | 
						|
		 w->name);
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if (delwin(w->win)!=OK) {
 | 
						|
	/*
 | 
						|
	 * Not sure what to do here, but we are probably stuffed,
 | 
						|
	 * so delete the window locally anyway.
 | 
						|
	 */
 | 
						|
	ret = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if (w->parent) {
 | 
						|
	/* Remove from parent's list of children */
 | 
						|
	LinkList wpc = w->parent->children;
 | 
						|
	LinkNode pcnode;
 | 
						|
	for (pcnode = firstnode(wpc); pcnode; incnode(pcnode)) {
 | 
						|
	    ZCWin child = (ZCWin)getdata(pcnode);
 | 
						|
	    if (child == w) {
 | 
						|
		remnode(wpc, pcnode);
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	DPUTS(pcnode == NULL, "BUG: child node not found in parent's children");
 | 
						|
	/*
 | 
						|
	 * We need to touch the parent to get the parent to refresh
 | 
						|
	 * properly.
 | 
						|
	 */
 | 
						|
	touchwin(w->parent->win);
 | 
						|
    }
 | 
						|
    else
 | 
						|
	touchwin(stdscr);
 | 
						|
 | 
						|
    if (w->name)
 | 
						|
	zsfree(w->name);
 | 
						|
 | 
						|
    zfree((ZCWin)remnode(zcurses_windows, node), sizeof(struct zc_win));
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
zccmd_refresh(const char *nam, char **args)
 | 
						|
{
 | 
						|
    WINDOW *win;
 | 
						|
    int ret = 0;
 | 
						|
 | 
						|
    if (args[0]) {
 | 
						|
	for (; *args; args++) {
 | 
						|
	    LinkNode node;
 | 
						|
	    ZCWin w;
 | 
						|
 | 
						|
	    node = zcurses_validate_window(args[0], ZCURSES_USED);
 | 
						|
	    if (node == NULL) {
 | 
						|
		zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0],
 | 
						|
			 0);
 | 
						|
		return 1;
 | 
						|
	    }
 | 
						|
 | 
						|
	    w = (ZCWin)getdata(node);
 | 
						|
 | 
						|
	    if (w->parent) {
 | 
						|
		/* This is what the manual says you have to do. */
 | 
						|
		touchwin(w->parent->win);
 | 
						|
	    }
 | 
						|
	    win = w->win;
 | 
						|
	    if (wnoutrefresh(win) != OK)
 | 
						|
		ret = 1;
 | 
						|
	}
 | 
						|
	return (doupdate() != OK || ret);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	return (wrefresh(stdscr) != OK) ? 1 : 0;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
zccmd_move(const char *nam,  char **args)
 | 
						|
{
 | 
						|
    int y, x;
 | 
						|
    LinkNode node;
 | 
						|
    ZCWin w;
 | 
						|
 | 
						|
    node = zcurses_validate_window(args[0], ZCURSES_USED);
 | 
						|
    if (node == NULL) {
 | 
						|
	zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    y = atoi(args[1]);
 | 
						|
    x = atoi(args[2]);
 | 
						|
 | 
						|
    w = (ZCWin)getdata(node);
 | 
						|
 | 
						|
    if (wmove(w->win, y, x)!=OK)
 | 
						|
	return 1;
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
zccmd_clear(const char *nam, char **args)
 | 
						|
{
 | 
						|
    LinkNode node;
 | 
						|
    ZCWin w;
 | 
						|
 | 
						|
    node = zcurses_validate_window(args[0], ZCURSES_USED);
 | 
						|
    if (node == NULL) {
 | 
						|
	zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    w = (ZCWin)getdata(node);
 | 
						|
 | 
						|
    if (!args[1]) {
 | 
						|
	return werase(w->win) != OK;
 | 
						|
    } else if (!strcmp(args[1], "redraw")) {
 | 
						|
	return wclear(w->win) != OK;
 | 
						|
    } else if (!strcmp(args[1], "eol")) {
 | 
						|
	return wclrtoeol(w->win) != OK;
 | 
						|
    } else if (!strcmp(args[1], "bot")) {
 | 
						|
	return wclrtobot(w->win) != OK;
 | 
						|
    } else {
 | 
						|
	zwarnnam(nam, "`clear' expects `redraw', `eol' or `bot'");
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
zccmd_char(const char *nam, char **args)
 | 
						|
{
 | 
						|
    LinkNode node;
 | 
						|
    ZCWin w;
 | 
						|
#ifdef HAVE_SETCCHAR
 | 
						|
    wchar_t c;
 | 
						|
    cchar_t cc;
 | 
						|
#endif
 | 
						|
 | 
						|
    node = zcurses_validate_window(args[0], ZCURSES_USED);
 | 
						|
    if (node == NULL) {
 | 
						|
	zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    w = (ZCWin)getdata(node);
 | 
						|
 | 
						|
#ifdef HAVE_SETCCHAR
 | 
						|
    if (mbrtowc(&c, args[1], MB_CUR_MAX, NULL) < 1)
 | 
						|
	return 1;
 | 
						|
 | 
						|
    if (setcchar(&cc, &c, A_NORMAL, 0, NULL)==ERR)
 | 
						|
	return 1;
 | 
						|
 | 
						|
    if (wadd_wch(w->win, &cc)!=OK)
 | 
						|
	return 1;
 | 
						|
#else
 | 
						|
    if (waddch(w->win, (chtype)args[1][0])!=OK)
 | 
						|
	return 1;
 | 
						|
#endif
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
zccmd_string(const char *nam, char **args)
 | 
						|
{
 | 
						|
    LinkNode node;
 | 
						|
    ZCWin w;
 | 
						|
 | 
						|
#ifdef HAVE_WADDWSTR
 | 
						|
    int clen;
 | 
						|
    wint_t wc;
 | 
						|
    wchar_t *wstr, *wptr;
 | 
						|
    char *str = args[1];
 | 
						|
#endif
 | 
						|
 | 
						|
    node = zcurses_validate_window(args[0], ZCURSES_USED);
 | 
						|
    if (node == NULL) {
 | 
						|
	zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    w = (ZCWin)getdata(node);
 | 
						|
 | 
						|
#ifdef HAVE_WADDWSTR
 | 
						|
    mb_metacharinit();
 | 
						|
    wptr = wstr = zhalloc((strlen(str)+1) * sizeof(wchar_t));
 | 
						|
 | 
						|
    while (*str && (clen = mb_metacharlenconv(str, &wc))) {
 | 
						|
	str += clen;
 | 
						|
	if (wc == WEOF) /* TODO: replace with space? nicen? */
 | 
						|
	    continue;
 | 
						|
	*wptr++ = wc;
 | 
						|
    }
 | 
						|
    *wptr++ = L'\0';
 | 
						|
    if (waddwstr(w->win, wstr)!=OK) {
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
#else
 | 
						|
    if (waddstr(w->win, args[1])!=OK)
 | 
						|
	return 1;
 | 
						|
#endif
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
zccmd_border(const char *nam, char **args)
 | 
						|
{
 | 
						|
    LinkNode node;
 | 
						|
    ZCWin w;
 | 
						|
 | 
						|
    node = zcurses_validate_window(args[0], ZCURSES_USED);
 | 
						|
    if (node == NULL) {
 | 
						|
	zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    w = (ZCWin)getdata(node);
 | 
						|
 | 
						|
    if (wborder(w->win, 0, 0, 0, 0, 0, 0, 0, 0)!=OK)
 | 
						|
	return 1;
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
zccmd_endwin(const char *nam, char **args)
 | 
						|
{
 | 
						|
    LinkNode stdscr_win = zcurses_getwindowbyname("stdscr");
 | 
						|
 | 
						|
    if (stdscr_win) {
 | 
						|
	endwin();
 | 
						|
	/* Restore TTY as it was before zcurses -i */
 | 
						|
	settyinfo(&saved_tty_state);
 | 
						|
	/*
 | 
						|
	 * TODO: should I need the following?  Without it
 | 
						|
	 * the screen stays messed up.  Presumably we are
 | 
						|
	 * doing stuff with shttyinfo when we shouldn't really be.
 | 
						|
	 */
 | 
						|
	gettyinfo(&shttyinfo);
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
zccmd_attr(const char *nam, char **args)
 | 
						|
{
 | 
						|
    LinkNode node;
 | 
						|
    ZCWin w;
 | 
						|
    char **attrs;
 | 
						|
    int ret = 0;
 | 
						|
 | 
						|
    if (!args[0])
 | 
						|
	return 1;
 | 
						|
 | 
						|
    node = zcurses_validate_window(args[0], ZCURSES_USED);
 | 
						|
    if (node == NULL) {
 | 
						|
	zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    w = (ZCWin)getdata(node);
 | 
						|
 | 
						|
    for(attrs = args+1; *attrs; attrs++) {
 | 
						|
	if (strchr(*attrs, '/')) {
 | 
						|
	    Colorpairnode cpn;
 | 
						|
	    if ((cpn = zcurses_colorget(nam, *attrs)) == NULL ||
 | 
						|
		wcolor_set(w->win, cpn->colorpair, NULL) == ERR)
 | 
						|
		ret = 1;
 | 
						|
	} else {
 | 
						|
	    char *ptr;
 | 
						|
	    int onoff;
 | 
						|
	    struct zcurses_namenumberpair *zca;
 | 
						|
 | 
						|
	    switch(*attrs[0]) {
 | 
						|
	    case '-':
 | 
						|
		onoff = ZCURSES_ATTROFF;
 | 
						|
		ptr = (*attrs) + 1;
 | 
						|
		break;
 | 
						|
	    case '+':
 | 
						|
		onoff = ZCURSES_ATTRON;
 | 
						|
		ptr = (*attrs) + 1;
 | 
						|
		break;
 | 
						|
	    default:
 | 
						|
		onoff = ZCURSES_ATTRON;
 | 
						|
		ptr = *attrs;
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	    if ((zca = zcurses_attrget(w->win, ptr)) == NULL) {
 | 
						|
		zwarnnam(nam, "attribute `%s' not known", ptr);
 | 
						|
		ret = 1;
 | 
						|
	    } else {
 | 
						|
		switch(onoff) {
 | 
						|
		    case ZCURSES_ATTRON:
 | 
						|
			if (wattron(w->win, zca->number) == ERR)
 | 
						|
			    ret = 1;
 | 
						|
			break;
 | 
						|
		    case ZCURSES_ATTROFF:
 | 
						|
			if (wattroff(w->win, zca->number) == ERR)
 | 
						|
			    ret = 1;
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
zccmd_bg(const char *nam, char **args)
 | 
						|
{
 | 
						|
    LinkNode node;
 | 
						|
    ZCWin w;
 | 
						|
    char **attrs;
 | 
						|
    int ret = 0;
 | 
						|
    chtype ch = 0;
 | 
						|
 | 
						|
    if (!args[0])
 | 
						|
	return 1;
 | 
						|
 | 
						|
    node = zcurses_validate_window(args[0], ZCURSES_USED);
 | 
						|
    if (node == NULL) {
 | 
						|
	zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    w = (ZCWin)getdata(node);
 | 
						|
 | 
						|
    for(attrs = args+1; *attrs; attrs++) {
 | 
						|
	if (strchr(*attrs, '/')) {
 | 
						|
	    Colorpairnode cpn;
 | 
						|
	    if ((cpn = zcurses_colorget(nam, *attrs)) == NULL)
 | 
						|
		ret = 1;
 | 
						|
	    else if (cpn->colorpair >= 256) {
 | 
						|
		/* pretty unlikely, but... */
 | 
						|
		zwarnnam(nam, "bg color pair %s has index (%d) too large (max 255)",
 | 
						|
			 cpn->node.nam, cpn->colorpair);
 | 
						|
		ret = 1;
 | 
						|
	    } else {
 | 
						|
		ch |= COLOR_PAIR(cpn->colorpair);
 | 
						|
	    }
 | 
						|
	} else if (**attrs == '@') {
 | 
						|
	    ch |= (*attrs)[1] == Meta ? (*attrs)[2] ^ 32 : (*attrs)[1];
 | 
						|
	} else {
 | 
						|
	    char *ptr;
 | 
						|
	    int onoff;
 | 
						|
	    struct zcurses_namenumberpair *zca;
 | 
						|
 | 
						|
	    switch(*attrs[0]) {
 | 
						|
	    case '-':
 | 
						|
		onoff = ZCURSES_ATTROFF;
 | 
						|
		ptr = (*attrs) + 1;
 | 
						|
		break;
 | 
						|
	    case '+':
 | 
						|
		onoff = ZCURSES_ATTRON;
 | 
						|
		ptr = (*attrs) + 1;
 | 
						|
		break;
 | 
						|
	    default:
 | 
						|
		onoff = ZCURSES_ATTRON;
 | 
						|
		ptr = *attrs;
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	    if ((zca = zcurses_attrget(w->win, ptr)) == NULL) {
 | 
						|
		zwarnnam(nam, "attribute `%s' not known", ptr);
 | 
						|
		ret = 1;
 | 
						|
	    } else {
 | 
						|
		switch(onoff) {
 | 
						|
		    case ZCURSES_ATTRON:
 | 
						|
			if (wattron(w->win, zca->number) == ERR)
 | 
						|
			    ret = 1;
 | 
						|
			break;
 | 
						|
		    case ZCURSES_ATTROFF:
 | 
						|
			if (wattroff(w->win, zca->number) == ERR)
 | 
						|
			    ret = 1;
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    if (ret == 0)
 | 
						|
	return wbkgd(w->win, ch) != OK;
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
zccmd_scroll(const char *nam, char **args)
 | 
						|
{
 | 
						|
    LinkNode node;
 | 
						|
    ZCWin w;
 | 
						|
    int ret = 0;
 | 
						|
 | 
						|
    node = zcurses_validate_window(args[0], ZCURSES_USED);
 | 
						|
    if (node == NULL) {
 | 
						|
	zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    w = (ZCWin)getdata(node);
 | 
						|
 | 
						|
    if (!strcmp(args[1], "on")) {
 | 
						|
	if (scrollok(w->win, TRUE) == ERR)
 | 
						|
	    return 1;
 | 
						|
	w->flags |= ZCWF_SCROLL;
 | 
						|
    } else if (!strcmp(args[1], "off")) {
 | 
						|
	if (scrollok(w->win, FALSE) == ERR)
 | 
						|
	    return 1;
 | 
						|
	w->flags &= ~ZCWF_SCROLL;
 | 
						|
    } else {
 | 
						|
	char *endptr;
 | 
						|
	zlong sl = zstrtol(args[1], &endptr, 10);
 | 
						|
	if (*endptr) {
 | 
						|
	    zwarnnam(nam, "scroll requires `on', `off' or integer: %s",
 | 
						|
		     args[1]);
 | 
						|
	    return 1;
 | 
						|
	}
 | 
						|
	if (!(w->flags & ZCWF_SCROLL))
 | 
						|
	    scrollok(w->win, TRUE);
 | 
						|
	if (wscrl(w->win, (int)sl) == ERR)
 | 
						|
	    ret = 1;
 | 
						|
	if (!(w->flags & ZCWF_SCROLL))
 | 
						|
	    scrollok(w->win, FALSE);
 | 
						|
    }
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
zccmd_input(const char *nam, char **args)
 | 
						|
{
 | 
						|
    LinkNode node;
 | 
						|
    ZCWin w;
 | 
						|
    char *var;
 | 
						|
    int keypadnum = -1;
 | 
						|
    int nargs = arrlen(args);
 | 
						|
#ifdef HAVE_WGET_WCH
 | 
						|
    int ret;
 | 
						|
    wint_t wi;
 | 
						|
    VARARR(char, instr, 2*MB_CUR_MAX+1);
 | 
						|
#else
 | 
						|
    int ci;
 | 
						|
    char instr[3];
 | 
						|
#endif
 | 
						|
 | 
						|
    node = zcurses_validate_window(args[0], ZCURSES_USED);
 | 
						|
    if (node == NULL) {
 | 
						|
	zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    w = (ZCWin)getdata(node);
 | 
						|
 | 
						|
    if (nargs >= 3) {
 | 
						|
	keypad(w->win, TRUE);
 | 
						|
    } else {
 | 
						|
	keypad(w->win, FALSE);
 | 
						|
    }
 | 
						|
 | 
						|
    if (nargs >= 4) {
 | 
						|
#ifdef NCURSES_MOUSE_VERSION
 | 
						|
	if (!(zcurses_flags & ZCF_MOUSE_ACTIVE) ||
 | 
						|
	    (zcurses_flags & ZCF_MOUSE_MASK_CHANGED)) {
 | 
						|
	    if (mousemask(zcurses_mouse_mask, NULL) == (mmask_t)ERR) {
 | 
						|
		zwarnnam(nam, "current mouse mode is not supported");
 | 
						|
		return 1;
 | 
						|
	    }
 | 
						|
	    zcurses_flags = (zcurses_flags & ~ZCF_MOUSE_MASK_CHANGED) |
 | 
						|
		ZCF_MOUSE_ACTIVE;
 | 
						|
	}
 | 
						|
#else
 | 
						|
	zwarnnam(nam, "mouse events are not supported");
 | 
						|
	return 1;
 | 
						|
#endif
 | 
						|
    }
 | 
						|
#ifdef NCURSES_MOUSE_VERSION
 | 
						|
    else {
 | 
						|
	if (zcurses_flags & ZCF_MOUSE_ACTIVE) {
 | 
						|
	    mousemask((mmask_t)0, NULL);
 | 
						|
	    zcurses_flags &= ~ZCF_MOUSE_ACTIVE;
 | 
						|
	}
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef HAVE_WGET_WCH
 | 
						|
    switch (wget_wch(w->win, &wi)) {
 | 
						|
    case OK:
 | 
						|
	ret = wctomb(instr, (wchar_t)wi);
 | 
						|
	if (ret == 0) {
 | 
						|
	    instr[0] = Meta;
 | 
						|
	    instr[1] = '\0' ^ 32;
 | 
						|
	    instr[2] = '\0';
 | 
						|
	} else {
 | 
						|
	    (void)metafy(instr, ret, META_NOALLOC);
 | 
						|
	}
 | 
						|
	break;
 | 
						|
 | 
						|
    case KEY_CODE_YES:
 | 
						|
	*instr = '\0';
 | 
						|
	keypadnum = (int)wi;
 | 
						|
	break;
 | 
						|
 | 
						|
    case ERR:
 | 
						|
    default:
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
#else
 | 
						|
    ci = wgetch(w->win);
 | 
						|
    if (ci == ERR)
 | 
						|
	return 1;
 | 
						|
    if (ci >= 256) {
 | 
						|
	keypadnum = ci;
 | 
						|
	*instr = '\0';
 | 
						|
    } else {
 | 
						|
	if (imeta(ci)) {
 | 
						|
	    instr[0] = Meta;
 | 
						|
	    instr[1] = (char)ci ^ 32;
 | 
						|
	    instr[2] = '\0';
 | 
						|
	} else {
 | 
						|
	    instr[0] = (char)ci;
 | 
						|
	    instr[1] = '\0';
 | 
						|
	}
 | 
						|
    }
 | 
						|
#endif
 | 
						|
    if (args[1])
 | 
						|
	var = args[1];
 | 
						|
    else
 | 
						|
	var = "REPLY";
 | 
						|
    if (!setsparam(var, ztrdup(instr)))
 | 
						|
	return 1;
 | 
						|
    if (nargs >= 3) {
 | 
						|
	if (keypadnum > 0) {
 | 
						|
#ifdef NCURSES_MOUSE_VERSION
 | 
						|
	    if (nargs >= 4 && keypadnum == KEY_MOUSE) {
 | 
						|
		MEVENT mevent;
 | 
						|
		char digits[DIGBUFSIZE];
 | 
						|
		LinkList margs;
 | 
						|
		const struct zcurses_mouse_event *zcmmp = zcurses_mouse_map;
 | 
						|
 | 
						|
		if (!setsparam(args[2], ztrdup("MOUSE")))
 | 
						|
		    return 1;
 | 
						|
		if (getmouse(&mevent) == ERR) {
 | 
						|
		    /*
 | 
						|
		     * This may happen if the mouse wasn't in
 | 
						|
		     * the window, so set the array to empty
 | 
						|
		     * but return success unless the set itself
 | 
						|
		     * failed.
 | 
						|
		     */
 | 
						|
		    return !setaparam(args[3], mkarray(NULL));
 | 
						|
		}
 | 
						|
		margs = newlinklist();
 | 
						|
		sprintf(digits, "%d", (int)mevent.id);
 | 
						|
		addlinknode(margs, dupstring(digits));
 | 
						|
		sprintf(digits, "%d", mevent.x);
 | 
						|
		addlinknode(margs, dupstring(digits));
 | 
						|
		sprintf(digits, "%d", mevent.y);
 | 
						|
		addlinknode(margs, dupstring(digits));
 | 
						|
		sprintf(digits, "%d", mevent.z);
 | 
						|
		addlinknode(margs, dupstring(digits));
 | 
						|
 | 
						|
		/*
 | 
						|
		 * We only expect one event, but it doesn't hurt
 | 
						|
		 * to keep testing.
 | 
						|
		 */
 | 
						|
		for (; zcmmp->button; zcmmp++) {
 | 
						|
		    if (mevent.bstate & zcmmp->event) {
 | 
						|
			const struct zcurses_namenumberpair *zcmelp =
 | 
						|
			    zcurses_mouse_event_list;
 | 
						|
			for (; zcmelp->name; zcmelp++) {
 | 
						|
			    if (zcmelp->number == zcmmp->what) {
 | 
						|
				char *evstr = zhalloc(strlen(zcmelp->name)+2);
 | 
						|
				sprintf(evstr, "%s%d", zcmelp->name,
 | 
						|
					zcmmp->button);
 | 
						|
				addlinknode(margs, evstr);
 | 
						|
 | 
						|
				break;
 | 
						|
			    }
 | 
						|
			}
 | 
						|
		    }
 | 
						|
		}
 | 
						|
		if (mevent.bstate & BUTTON_SHIFT)
 | 
						|
		    addlinknode(margs, "SHIFT");
 | 
						|
		if (mevent.bstate & BUTTON_CTRL)
 | 
						|
		    addlinknode(margs, "CTRL");
 | 
						|
		if (mevent.bstate & BUTTON_ALT)
 | 
						|
		    addlinknode(margs, "ALT");
 | 
						|
		if (!setaparam(args[3], zlinklist2array(margs)))
 | 
						|
		    return 1;
 | 
						|
	    } else {
 | 
						|
#endif
 | 
						|
		const struct zcurses_namenumberpair *nnptr;
 | 
						|
		char fbuf[DIGBUFSIZE+1];
 | 
						|
 | 
						|
		for (nnptr = keypad_names; nnptr->name; nnptr++) {
 | 
						|
		    if (keypadnum == nnptr->number) {
 | 
						|
			if (!setsparam(args[2], ztrdup(nnptr->name)))
 | 
						|
			    return 1;
 | 
						|
			return 0;
 | 
						|
		    }
 | 
						|
		}
 | 
						|
		if (keypadnum > KEY_F0) {
 | 
						|
		    /* assume it's a function key */
 | 
						|
		    sprintf(fbuf, "F%d", keypadnum - KEY_F0);
 | 
						|
		} else {
 | 
						|
		    /* print raw number */
 | 
						|
		    sprintf(fbuf, "%d", keypadnum);
 | 
						|
		}
 | 
						|
		if (!setsparam(args[2], ztrdup(fbuf)))
 | 
						|
		    return 1;
 | 
						|
#ifdef NCURSES_MOUSE_VERSION
 | 
						|
	    }
 | 
						|
#endif
 | 
						|
	} else {
 | 
						|
	    if (!setsparam(args[2], ztrdup("")))
 | 
						|
		return 1;
 | 
						|
	}
 | 
						|
    }
 | 
						|
#ifdef NCURSES_MOUSE_VERSION
 | 
						|
    if (keypadnum != KEY_MOUSE && nargs >= 4)
 | 
						|
	return !setaparam(args[3], mkarray(NULL));
 | 
						|
#endif
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
zccmd_timeout(const char *nam, char **args)
 | 
						|
{
 | 
						|
    LinkNode node;
 | 
						|
    ZCWin w;
 | 
						|
    int to;
 | 
						|
    char *eptr;
 | 
						|
 | 
						|
    node = zcurses_validate_window(args[0], ZCURSES_USED);
 | 
						|
    if (node == NULL) {
 | 
						|
	zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    w = (ZCWin)getdata(node);
 | 
						|
 | 
						|
    to = (int)zstrtol(args[1], &eptr, 10);
 | 
						|
    if (*eptr) {
 | 
						|
	zwarnnam(nam, "timeout requires an integer: %s", args[1]);
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
 | 
						|
#if defined(__sun__) && defined(__SVR4) && !defined(HAVE_USE_DEFAULT_COLORS)
 | 
						|
    /*
 | 
						|
     * On Solaris turning a timeout off seems to be problematic.
 | 
						|
     * The following fixes it.  We test for Solaris without ncurses
 | 
						|
     * (the last test) to be specific; this may turn up in other older
 | 
						|
     * versions of curses, but it's difficult to test for.
 | 
						|
     */
 | 
						|
    if (to < 0) {
 | 
						|
	nocbreak();
 | 
						|
	cbreak();
 | 
						|
    }
 | 
						|
#endif
 | 
						|
    wtimeout(w->win, to);
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
zccmd_mouse(const char *nam, char **args)
 | 
						|
{
 | 
						|
#ifdef NCURSES_MOUSE_VERSION
 | 
						|
    int ret = 0;
 | 
						|
 | 
						|
    for (; *args; args++) {
 | 
						|
	if (!strcmp(*args, "delay")) {
 | 
						|
	    char *eptr;
 | 
						|
	    zlong delay;
 | 
						|
 | 
						|
	    if (!*++args ||
 | 
						|
		((delay = zstrtol(*args, &eptr, 10)), eptr != NULL)) {
 | 
						|
		zwarnnam(nam, "mouse delay requires an integer argument");
 | 
						|
		return 1;
 | 
						|
	    }
 | 
						|
	    if (mouseinterval((int)delay) != OK)
 | 
						|
		ret = 1;
 | 
						|
	} else {
 | 
						|
	    char *arg = *args;
 | 
						|
	    int onoff = 1;
 | 
						|
	    if (*arg == '+')
 | 
						|
		arg++;
 | 
						|
	    else if (*arg == '-') {
 | 
						|
		arg++;
 | 
						|
		onoff = 0;
 | 
						|
	    }
 | 
						|
	    if (!strcmp(arg, "motion")) {
 | 
						|
		mmask_t old_mask = zcurses_mouse_mask;
 | 
						|
		if (onoff)
 | 
						|
		    zcurses_mouse_mask |= REPORT_MOUSE_POSITION;
 | 
						|
		else
 | 
						|
		    zcurses_mouse_mask &= ~REPORT_MOUSE_POSITION;
 | 
						|
		if (old_mask != zcurses_mouse_mask)
 | 
						|
		    zcurses_flags |= ZCF_MOUSE_MASK_CHANGED;
 | 
						|
	    } else {
 | 
						|
		zwarnnam(nam, "unrecognised mouse command: %s", *arg);
 | 
						|
		return 1;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    return ret;
 | 
						|
#else
 | 
						|
    return 1;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
zccmd_position(const char *nam, char **args)
 | 
						|
{
 | 
						|
    LinkNode node;
 | 
						|
    ZCWin w;
 | 
						|
    int i, intarr[6];
 | 
						|
    char **array, dbuf[DIGBUFSIZE];
 | 
						|
 | 
						|
    node = zcurses_validate_window(args[0], ZCURSES_USED);
 | 
						|
    if (node == NULL) {
 | 
						|
	zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    w = (ZCWin)getdata(node);
 | 
						|
 | 
						|
    /* Look no pointers:  these are macros. */
 | 
						|
    getyx(w->win, intarr[0], intarr[1]);
 | 
						|
    if (intarr[0] == -1)
 | 
						|
	return 1;
 | 
						|
    getbegyx(w->win, intarr[2], intarr[3]);
 | 
						|
    if (intarr[2] == -1)
 | 
						|
	return 1;
 | 
						|
    getmaxyx(w->win, intarr[4], intarr[5]);
 | 
						|
    if (intarr[4] == -1)
 | 
						|
	return 1;
 | 
						|
 | 
						|
    array = (char **)zalloc(7*sizeof(char *));
 | 
						|
    for (i = 0; i < 6; i++) {
 | 
						|
	sprintf(dbuf, "%d", intarr[i]);
 | 
						|
	array[i] = ztrdup(dbuf);
 | 
						|
    }
 | 
						|
    array[6] = NULL;
 | 
						|
 | 
						|
    setaparam(args[1], array);
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
zccmd_querychar(const char *nam, char **args)
 | 
						|
{
 | 
						|
    LinkNode node;
 | 
						|
    ZCWin w;
 | 
						|
    short cp;
 | 
						|
    Colorpairnode cpn;
 | 
						|
    const struct zcurses_namenumberpair *zattrp;
 | 
						|
    LinkList clist;
 | 
						|
#if defined(HAVE_WIN_WCH) && defined(HAVE_GETCCHAR)
 | 
						|
    attr_t attrs;
 | 
						|
    wchar_t c;
 | 
						|
    cchar_t cc;
 | 
						|
    int count;
 | 
						|
    VARARR(char, instr, 2*MB_CUR_MAX+1);
 | 
						|
#else
 | 
						|
    chtype inc, attrs;
 | 
						|
    char instr[3];
 | 
						|
#endif
 | 
						|
 | 
						|
    node = zcurses_validate_window(args[0], ZCURSES_USED);
 | 
						|
    if (node == NULL) {
 | 
						|
	zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    w = (ZCWin)getdata(node);
 | 
						|
 | 
						|
#if defined(HAVE_WIN_WCH) && defined(HAVE_GETCCHAR)
 | 
						|
    if (win_wch(w->win, &cc) == ERR)
 | 
						|
	return 1;
 | 
						|
 | 
						|
    if (getcchar(&cc, &c, &attrs, &cp, NULL) == ERR)
 | 
						|
	return 1;
 | 
						|
    /* Hmmm... I always get 0 for cp, whereas the following works... */
 | 
						|
    cp = PAIR_NUMBER(winch(w->win));
 | 
						|
 | 
						|
    count = wctomb(instr, c);
 | 
						|
    if (count == -1)
 | 
						|
	return 1;
 | 
						|
    (void)metafy(instr, count, META_NOALLOC);
 | 
						|
#else
 | 
						|
    inc = winch(w->win);
 | 
						|
    /* I think the following is correct, the manual is a little terse */
 | 
						|
    cp = PAIR_NUMBER(inc);
 | 
						|
    inc &= A_CHARTEXT;
 | 
						|
    if (imeta(inc)) {
 | 
						|
	instr[0] = Meta;
 | 
						|
	instr[1] = STOUC(inc ^ 32);
 | 
						|
	instr[2] = '\0';
 | 
						|
    } else {
 | 
						|
	instr[0] = STOUC(inc);
 | 
						|
	instr[1] = '\0';
 | 
						|
    }
 | 
						|
    attrs = inc;
 | 
						|
#endif
 | 
						|
 | 
						|
    /*
 | 
						|
     * Attribute numbers vary, so make a linked list.
 | 
						|
     * This also saves us from doing the permanent allocation till
 | 
						|
     * the end.
 | 
						|
     */
 | 
						|
    clist = newlinklist();
 | 
						|
    /* First the (possibly multibyte) character itself. */
 | 
						|
    addlinknode(clist, instr);
 | 
						|
    /*
 | 
						|
     * Next the colo[u]r.
 | 
						|
     * We should be able to match it in the colorpair list, but
 | 
						|
     * if some reason we can't, fail safe and output the number.
 | 
						|
     */
 | 
						|
    cpn = zcurses_colorget_reverse(cp);
 | 
						|
    if (cpn) {
 | 
						|
	addlinknode(clist, cpn->node.nam);
 | 
						|
    } else {
 | 
						|
	/* report color pair number */
 | 
						|
	char digits[DIGBUFSIZE];
 | 
						|
	sprintf(digits, "%d", (int)cp);
 | 
						|
	addlinknode(clist, digits);
 | 
						|
    }
 | 
						|
    /* Now see what attributes are present. */
 | 
						|
    for (zattrp = zcurses_attributes; zattrp->name; zattrp++) {
 | 
						|
	if (attrs & zattrp->number)
 | 
						|
	    addlinknode(clist, zattrp->name);
 | 
						|
    }
 | 
						|
 | 
						|
    /* Turn this into an array and store it. */
 | 
						|
    return !setaparam(args[1] ? args[1] : "reply", zlinklist2array(clist));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
zccmd_touch(const char *nam, char **args)
 | 
						|
{
 | 
						|
    LinkNode node;
 | 
						|
    ZCWin w;
 | 
						|
    int ret = 0;
 | 
						|
 | 
						|
    for (; *args; args++) {
 | 
						|
	node = zcurses_validate_window(args[0], ZCURSES_USED);
 | 
						|
	if (node == NULL) {
 | 
						|
	    zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
 | 
						|
	    return 1;
 | 
						|
	}
 | 
						|
 | 
						|
	w = (ZCWin)getdata(node);
 | 
						|
	if (touchwin(w->win) != OK)
 | 
						|
	    ret = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*********************
 | 
						|
  Main builtin handler
 | 
						|
 *********************/
 | 
						|
 | 
						|
/**/
 | 
						|
static int
 | 
						|
bin_zcurses(char *nam, char **args, Options ops, UNUSED(int func))
 | 
						|
{
 | 
						|
    char **saargs;
 | 
						|
    struct zcurses_subcommand *zcsc;
 | 
						|
    int num_args;
 | 
						|
 | 
						|
    struct zcurses_subcommand scs[] = {
 | 
						|
	{"init", zccmd_init, 0, 0},
 | 
						|
	{"addwin", zccmd_addwin, 5, 6},
 | 
						|
	{"delwin", zccmd_delwin, 1, 1},
 | 
						|
	{"refresh", zccmd_refresh, 0, -1},
 | 
						|
	{"move", zccmd_move, 3, 3},
 | 
						|
	{"clear", zccmd_clear, 1, 2},
 | 
						|
	{"position", zccmd_position, 2, 2},
 | 
						|
	{"char", zccmd_char, 2, 2},
 | 
						|
	{"string", zccmd_string, 2, 2},
 | 
						|
	{"border", zccmd_border, 1, 1},
 | 
						|
	{"end", zccmd_endwin, 0, 0},
 | 
						|
	{"attr", zccmd_attr, 2, -1},
 | 
						|
	{"bg", zccmd_bg, 2, -1},
 | 
						|
	{"scroll", zccmd_scroll, 2, 2},
 | 
						|
	{"input", zccmd_input, 1, 4},
 | 
						|
	{"timeout", zccmd_timeout, 2, 2},
 | 
						|
	{"mouse", zccmd_mouse, 0, -1},
 | 
						|
	{"querychar", zccmd_querychar, 1, 2},
 | 
						|
	{"touch", zccmd_touch, 1, -1},
 | 
						|
	{NULL, (zccmd_t)0, 0, 0}
 | 
						|
    };
 | 
						|
 | 
						|
    for(zcsc = scs; zcsc->name; zcsc++) {
 | 
						|
	if(!strcmp(args[0], zcsc->name))
 | 
						|
	    break;
 | 
						|
    }
 | 
						|
 | 
						|
    if (zcsc->name == NULL) {
 | 
						|
	zwarnnam(nam, "unknown subcommand: %s", args[0]);
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    saargs = args;
 | 
						|
    while (*saargs++);
 | 
						|
    num_args = saargs - (args + 2);
 | 
						|
 | 
						|
    if (num_args < zcsc->minargs) {
 | 
						|
	zwarnnam(nam, "too few arguments for subcommand: %s", args[0]);
 | 
						|
	return 1;
 | 
						|
    } else if (zcsc->maxargs >= 0 && num_args > zcsc->maxargs) {
 | 
						|
	zwarnnam(nam, "too many arguments for subcommand: %s", args[0]);
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if (zcsc->cmd != zccmd_init && zcsc->cmd != zccmd_endwin &&
 | 
						|
	!zcurses_getwindowbyname("stdscr")) {
 | 
						|
	zwarnnam(nam, "command `%s' can't be used before `zcurses init'",
 | 
						|
		 zcsc->name);
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    return zcsc->cmd(nam, args+1);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static struct builtin bintab[] = {
 | 
						|
    BUILTIN("zcurses", 0, bin_zcurses, 1, -1, 0, "", NULL),
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/*******************
 | 
						|
 * Special variables
 | 
						|
 *******************/
 | 
						|
 | 
						|
static char **
 | 
						|
zcurses_colorsarrgetfn(UNUSED(Param pm))
 | 
						|
{
 | 
						|
    return zcurses_pairs_to_array(zcurses_colors);
 | 
						|
}
 | 
						|
 | 
						|
static const struct gsu_array zcurses_colorsarr_gsu =
 | 
						|
{ zcurses_colorsarrgetfn, arrsetfn, stdunsetfn };
 | 
						|
 | 
						|
 | 
						|
static char **
 | 
						|
zcurses_attrgetfn(UNUSED(Param pm))
 | 
						|
{
 | 
						|
    return zcurses_pairs_to_array(zcurses_attributes);
 | 
						|
}
 | 
						|
 | 
						|
static const struct gsu_array zcurses_attrs_gsu =
 | 
						|
{ zcurses_attrgetfn, arrsetfn, stdunsetfn };
 | 
						|
 | 
						|
 | 
						|
static char **
 | 
						|
zcurses_keycodesgetfn(UNUSED(Param pm))
 | 
						|
{
 | 
						|
    return zcurses_pairs_to_array(keypad_names);
 | 
						|
}
 | 
						|
 | 
						|
static const struct gsu_array zcurses_keycodes_gsu =
 | 
						|
{ zcurses_keycodesgetfn, arrsetfn, stdunsetfn };
 | 
						|
 | 
						|
 | 
						|
static char **
 | 
						|
zcurses_windowsgetfn(UNUSED(Param pm))
 | 
						|
{
 | 
						|
    LinkNode node;
 | 
						|
    char **arr, **arrptr;
 | 
						|
    int count = countlinknodes(zcurses_windows);
 | 
						|
 | 
						|
    arrptr = arr = (char **)zhalloc((count+1) * sizeof(char *));
 | 
						|
 | 
						|
    for (node = firstnode(zcurses_windows); node; incnode(node))
 | 
						|
	*arrptr++ = dupstring(((ZCWin)getdata(node))->name);
 | 
						|
    *arrptr = NULL;
 | 
						|
 | 
						|
    return arr;
 | 
						|
}
 | 
						|
 | 
						|
static const struct gsu_array zcurses_windows_gsu =
 | 
						|
{ zcurses_windowsgetfn, arrsetfn, stdunsetfn };
 | 
						|
 | 
						|
 | 
						|
static zlong
 | 
						|
zcurses_colorsintgetfn(UNUSED(Param pm))
 | 
						|
{
 | 
						|
    return COLORS;
 | 
						|
}
 | 
						|
 | 
						|
static const struct gsu_integer zcurses_colorsint_gsu =
 | 
						|
{ zcurses_colorsintgetfn, nullintsetfn, stdunsetfn };
 | 
						|
 | 
						|
 | 
						|
static zlong
 | 
						|
zcurses_colorpairsintgetfn(UNUSED(Param pm))
 | 
						|
{
 | 
						|
    return COLOR_PAIRS;
 | 
						|
}
 | 
						|
 | 
						|
static const struct gsu_integer zcurses_colorpairsint_gsu =
 | 
						|
{ zcurses_colorpairsintgetfn, nullintsetfn, stdunsetfn };
 | 
						|
 | 
						|
 | 
						|
static struct paramdef partab[] = {
 | 
						|
    SPECIALPMDEF("zcurses_colors", PM_ARRAY|PM_READONLY,
 | 
						|
		 &zcurses_colorsarr_gsu, NULL, NULL),
 | 
						|
    SPECIALPMDEF("zcurses_attrs", PM_ARRAY|PM_READONLY,
 | 
						|
		 &zcurses_attrs_gsu, NULL, NULL),
 | 
						|
    SPECIALPMDEF("zcurses_keycodes", PM_ARRAY|PM_READONLY,
 | 
						|
		 &zcurses_keycodes_gsu, NULL, NULL),
 | 
						|
    SPECIALPMDEF("zcurses_windows", PM_ARRAY|PM_READONLY,
 | 
						|
		 &zcurses_windows_gsu, NULL, NULL),
 | 
						|
    SPECIALPMDEF("ZCURSES_COLORS", PM_INTEGER|PM_READONLY,
 | 
						|
		 &zcurses_colorsint_gsu, NULL, NULL),
 | 
						|
    SPECIALPMDEF("ZCURSES_COLOR_PAIRS", PM_INTEGER|PM_READONLY,
 | 
						|
		 &zcurses_colorpairsint_gsu, NULL, NULL)
 | 
						|
};
 | 
						|
 | 
						|
/***************************
 | 
						|
 * Standard module interface
 | 
						|
 ***************************/
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * boot_ is executed when the module is loaded.
 | 
						|
 */
 | 
						|
 | 
						|
static struct features module_features = {
 | 
						|
    bintab, sizeof(bintab)/sizeof(*bintab),
 | 
						|
    NULL, 0,
 | 
						|
    NULL, 0,
 | 
						|
    partab, sizeof(partab)/sizeof(*partab),
 | 
						|
    0
 | 
						|
};
 | 
						|
 | 
						|
/**/
 | 
						|
int
 | 
						|
setup_(UNUSED(Module m))
 | 
						|
{
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
/**/
 | 
						|
int
 | 
						|
features_(Module m, char ***features)
 | 
						|
{
 | 
						|
    *features = featuresarray(m, &module_features);
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
/**/
 | 
						|
int
 | 
						|
enables_(Module m, int **enables)
 | 
						|
{
 | 
						|
    return handlefeatures(m, &module_features, enables);
 | 
						|
}
 | 
						|
 | 
						|
/**/
 | 
						|
int
 | 
						|
boot_(Module m)
 | 
						|
{
 | 
						|
    zcurses_windows = znewlinklist();
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
/**/
 | 
						|
int
 | 
						|
cleanup_(Module m)
 | 
						|
{
 | 
						|
    freelinklist(zcurses_windows, (FreeFunc) zcurses_free_window);
 | 
						|
    if (zcurses_colorpairs)
 | 
						|
	deletehashtable(zcurses_colorpairs);
 | 
						|
    return setfeatureenables(m, &module_features, NULL);
 | 
						|
}
 | 
						|
 | 
						|
/**/
 | 
						|
int
 | 
						|
finish_(UNUSED(Module m))
 | 
						|
{
 | 
						|
    return 0;
 | 
						|
}
 |