⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dialog.c

📁 远程登陆工具软件源码 用于远程登陆unix
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * dialog.c - a reasonably platform-independent mechanism for
 * describing dialog boxes.
 */

#include <assert.h>
#include <limits.h>
#include <stdarg.h>
#include <stdlib.h>

#define DEFINE_INTORPTR_FNS

#include "putty.h"
#include "dialog.h"

int ctrl_path_elements(char *path)
{
    int i = 1;
    while (*path) {
	if (*path == '/') i++;
	path++;
    }
    return i;
}

/* Return the number of matching path elements at the starts of p1 and p2,
 * or INT_MAX if the paths are identical. */
int ctrl_path_compare(char *p1, char *p2)
{
    int i = 0;
    while (*p1 || *p2) {
	if ((*p1 == '/' || *p1 == '\0') &&
	    (*p2 == '/' || *p2 == '\0'))
	    i++;		       /* a whole element matches, ooh */
	if (*p1 != *p2)
	    return i;		       /* mismatch */
	p1++, p2++;
    }
    return INT_MAX;		       /* exact match */
}

struct controlbox *ctrl_new_box(void)
{
    struct controlbox *ret = snew(struct controlbox);

    ret->nctrlsets = ret->ctrlsetsize = 0;
    ret->ctrlsets = NULL;
    ret->nfrees = ret->freesize = 0;
    ret->frees = NULL;

    return ret;
}

void ctrl_free_box(struct controlbox *b)
{
    int i;

    for (i = 0; i < b->nctrlsets; i++) {
	ctrl_free_set(b->ctrlsets[i]);
    }
    for (i = 0; i < b->nfrees; i++)
	sfree(b->frees[i]);
    sfree(b->ctrlsets);
    sfree(b->frees);
    sfree(b);
}

void ctrl_free_set(struct controlset *s)
{
    int i;

    sfree(s->pathname);
    sfree(s->boxname);
    sfree(s->boxtitle);
    for (i = 0; i < s->ncontrols; i++) {
	ctrl_free(s->ctrls[i]);
    }
    sfree(s->ctrls);
    sfree(s);
}

/*
 * Find the index of first controlset in a controlbox for a given
 * path. If that path doesn't exist, return the index where it
 * should be inserted.
 */
static int ctrl_find_set(struct controlbox *b, char *path, int start)
{
    int i, last, thisone;

    last = 0;
    for (i = 0; i < b->nctrlsets; i++) {
	thisone = ctrl_path_compare(path, b->ctrlsets[i]->pathname);
	/*
	 * If `start' is true and there exists a controlset with
	 * exactly the path we've been given, we should return the
	 * index of the first such controlset we find. Otherwise,
	 * we should return the index of the first entry in which
	 * _fewer_ path elements match than they did last time.
	 */
	if ((start && thisone == INT_MAX) || thisone < last)
	    return i;
	last = thisone;
    }
    return b->nctrlsets;	       /* insert at end */
}

/*
 * Find the index of next controlset in a controlbox for a given
 * path, or -1 if no such controlset exists. If -1 is passed as
 * input, finds the first.
 */
int ctrl_find_path(struct controlbox *b, char *path, int index)
{
    if (index < 0)
	index = ctrl_find_set(b, path, 1);
    else
	index++;

    if (index < b->nctrlsets && !strcmp(path, b->ctrlsets[index]->pathname))
	return index;
    else
	return -1;
}

/* Set up a panel title. */
struct controlset *ctrl_settitle(struct controlbox *b,
				 char *path, char *title)
{
    
    struct controlset *s = snew(struct controlset);
    int index = ctrl_find_set(b, path, 1);
    s->pathname = dupstr(path);
    s->boxname = NULL;
    s->boxtitle = dupstr(title);
    s->ncontrols = s->ctrlsize = 0;
    s->ncolumns = 0;		       /* this is a title! */
    s->ctrls = NULL;
    if (b->nctrlsets >= b->ctrlsetsize) {
	b->ctrlsetsize = b->nctrlsets + 32;
	b->ctrlsets = sresize(b->ctrlsets, b->ctrlsetsize,struct controlset *);
    }
    if (index < b->nctrlsets)
	memmove(&b->ctrlsets[index+1], &b->ctrlsets[index],
		(b->nctrlsets-index) * sizeof(*b->ctrlsets));
    b->ctrlsets[index] = s;
    b->nctrlsets++;
    return s;
}

/* Retrieve a pointer to a controlset, creating it if absent. */
struct controlset *ctrl_getset(struct controlbox *b,
			       char *path, char *name, char *boxtitle)
{
    struct controlset *s;
    int index = ctrl_find_set(b, path, 1);
    while (index < b->nctrlsets &&
	   !strcmp(b->ctrlsets[index]->pathname, path)) {
	if (b->ctrlsets[index]->boxname &&
	    !strcmp(b->ctrlsets[index]->boxname, name))
	    return b->ctrlsets[index];
	index++;
    }
    s = snew(struct controlset);
    s->pathname = dupstr(path);
    s->boxname = dupstr(name);
    s->boxtitle = boxtitle ? dupstr(boxtitle) : NULL;
    s->ncolumns = 1;
    s->ncontrols = s->ctrlsize = 0;
    s->ctrls = NULL;
    if (b->nctrlsets >= b->ctrlsetsize) {
	b->ctrlsetsize = b->nctrlsets + 32;
	b->ctrlsets = sresize(b->ctrlsets, b->ctrlsetsize,struct controlset *);
    }
    if (index < b->nctrlsets)
	memmove(&b->ctrlsets[index+1], &b->ctrlsets[index],
		(b->nctrlsets-index) * sizeof(*b->ctrlsets));
    b->ctrlsets[index] = s;
    b->nctrlsets++;
    return s;
}

/* Allocate some private data in a controlbox. */
void *ctrl_alloc(struct controlbox *b, size_t size)
{
    void *p;
    /*
     * This is an internal allocation routine, so it's allowed to
     * use smalloc directly.
     */
    p = smalloc(size);
    if (b->nfrees >= b->freesize) {
	b->freesize = b->nfrees + 32;
	b->frees = sresize(b->frees, b->freesize, void *);
    }
    b->frees[b->nfrees++] = p;
    return p;
}

static union control *ctrl_new(struct controlset *s, int type,
			       intorptr helpctx, handler_fn handler,
			       intorptr context)
{
    union control *c = snew(union control);
    if (s->ncontrols >= s->ctrlsize) {
	s->ctrlsize = s->ncontrols + 32;
	s->ctrls = sresize(s->ctrls, s->ctrlsize, union control *);
    }
    s->ctrls[s->ncontrols++] = c;
    /*
     * Fill in the standard fields.
     */
    c->generic.type = type;
    c->generic.tabdelay = 0;
    c->generic.column = COLUMN_FIELD(0, s->ncolumns);
    c->generic.helpctx = helpctx;
    c->generic.handler = handler;
    c->generic.context = context;
    c->generic.label = NULL;
    return c;
}

/* `ncolumns' is followed by that many percentages, as integers. */
union control *ctrl_columns(struct controlset *s, int ncolumns, ...)
{
    union control *c = ctrl_new(s, CTRL_COLUMNS, P(NULL), NULL, P(NULL));
    assert(s->ncolumns == 1 || ncolumns == 1);
    c->columns.ncols = ncolumns;
    s->ncolumns = ncolumns;
    if (ncolumns == 1) {
	c->columns.percentages = NULL;
    } else {
	va_list ap;
	int i;
	c->columns.percentages = snewn(ncolumns, int);
	va_start(ap, ncolumns);
	for (i = 0; i < ncolumns; i++)
	    c->columns.percentages[i] = va_arg(ap, int);
	va_end(ap);
    }
    return c;
}

union control *ctrl_editbox(struct controlset *s, char *label, char shortcut,
			    int percentage,
			    intorptr helpctx, handler_fn handler,
			    intorptr context, intorptr context2)
{
    union control *c = ctrl_new(s, CTRL_EDITBOX, helpctx, handler, context);
    c->editbox.label = label ? dupstr(label) : NULL;
    c->editbox.shortcut = shortcut;
    c->editbox.percentwidth = percentage;
    c->editbox.password = 0;
    c->editbox.has_list = 0;
    c->editbox.context2 = context2;
    return c;
}

union control *ctrl_combobox(struct controlset *s, char *label, char shortcut,
			     int percentage,
			     intorptr helpctx, handler_fn handler,
			     intorptr context, intorptr context2)
{
    union control *c = ctrl_new(s, CTRL_EDITBOX, helpctx, handler, context);
    c->editbox.label = label ? dupstr(label) : NULL;
    c->editbox.shortcut = shortcut;
    c->editbox.percentwidth = percentage;
    c->editbox.password = 0;
    c->editbox.has_list = 1;
    c->editbox.context2 = context2;
    return c;
}

/*
 * `ncolumns' is followed by (alternately) radio button titles and
 * intorptrs, until a NULL in place of a title string is seen. Each
 * title is expected to be followed by a shortcut _iff_ `shortcut'
 * is NO_SHORTCUT.
 */
union control *ctrl_radiobuttons(struct controlset *s, char *label,
				 char shortcut, int ncolumns, intorptr helpctx,
				 handler_fn handler, intorptr context, ...)
{
    va_list ap;
    int i;
    union control *c = ctrl_new(s, CTRL_RADIO, helpctx, handler, context);
    c->radio.label = label ? dupstr(label) : NULL;
    c->radio.shortcut = shortcut;
    c->radio.ncolumns = ncolumns;
    /*
     * Initial pass along variable argument list to count the
     * buttons.
     */
    va_start(ap, context);
    i = 0;
    while (va_arg(ap, char *) != NULL) {
	i++;
	if (c->radio.shortcut == NO_SHORTCUT)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -