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

📄 winctrls.c

📁 远程登陆工具软件源码 用于远程登陆unix
💻 C
📖 第 1 页 / 共 5 页
字号:
    void *data;

    base_id = *id;

    /* Start a containing box, if we have a boxname. */
    if (s->boxname && *s->boxname) {
	struct winctrl *c = snew(struct winctrl);
    	c->ctrl = NULL;
	c->base_id = base_id;
	c->num_ids = 1;
	c->data = NULL;
	memset(c->shortcuts, NO_SHORTCUT, lenof(c->shortcuts));
	winctrl_add(wc, c);
	beginbox(cp, s->boxtitle, base_id);
	base_id++;
    }

    /* Draw a title, if we have one. */
    if (!s->boxname && s->boxtitle) {
	struct winctrl *c = snew(struct winctrl);
    	c->ctrl = NULL;
	c->base_id = base_id;
	c->num_ids = 1;
	c->data = dupstr(s->boxtitle);
	memset(c->shortcuts, NO_SHORTCUT, lenof(c->shortcuts));
	winctrl_add(wc, c);
	paneltitle(cp, base_id);
	base_id++;
    }

    /* Initially we have just one column. */
    ncols = 1;
    columns[0] = *cp;		       /* structure copy */

    /* And initially, there are no pending tab-delayed controls. */
    ntabdelays = 0;

    /* Loop over each control in the controlset. */
    for (i = 0; i < s->ncontrols; i++) {
	union control *ctrl = s->ctrls[i];

	/*
	 * Generic processing that pertains to all control types.
	 * At the end of this if statement, we'll have produced
	 * `ctrl' (a pointer to the control we have to create, or
	 * think about creating, in this iteration of the loop),
	 * `pos' (a suitable ctlpos with which to position it), and
	 * `c' (a winctrl structure to receive details of the
	 * dialog IDs). Or we'll have done a `continue', if it was
	 * CTRL_COLUMNS and doesn't require any control creation at
	 * all.
	 */
	if (ctrl->generic.type == CTRL_COLUMNS) {
	    assert((ctrl->columns.ncols == 1) ^ (ncols == 1));

	    if (ncols == 1) {
		/*
		 * We're splitting into multiple columns.
		 */
		int lpercent, rpercent, lx, rx, i;

		ncols = ctrl->columns.ncols;
		assert(ncols <= lenof(columns));
		for (i = 1; i < ncols; i++)
		    columns[i] = columns[0];   /* structure copy */

		lpercent = 0;
		for (i = 0; i < ncols; i++) {
		    rpercent = lpercent + ctrl->columns.percentages[i];
		    lx = columns[i].xoff + lpercent *
			(columns[i].width + GAPBETWEEN) / 100;
		    rx = columns[i].xoff + rpercent *
			(columns[i].width + GAPBETWEEN) / 100;
		    columns[i].xoff = lx;
		    columns[i].width = rx - lx - GAPBETWEEN;
		    lpercent = rpercent;
		}
	    } else {
		/*
		 * We're recombining the various columns into one.
		 */
		int maxy = columns[0].ypos;
		int i;
		for (i = 1; i < ncols; i++)
		    if (maxy < columns[i].ypos)
			maxy = columns[i].ypos;
		ncols = 1;
		columns[0] = *cp;      /* structure copy */
		columns[0].ypos = maxy;
	    }

	    continue;
	} else if (ctrl->generic.type == CTRL_TABDELAY) {
	    int i;

	    assert(!ctrl->generic.tabdelay);
	    ctrl = ctrl->tabdelay.ctrl;

	    for (i = 0; i < ntabdelays; i++)
		if (tabdelayed[i] == ctrl)
		    break;
	    assert(i < ntabdelays);    /* we have to have found it */

	    pos = tabdelays[i];	       /* structure copy */

	    colstart = colspan = -1;   /* indicate this was tab-delayed */

	} else {
	    /*
	     * If it wasn't one of those, it's a genuine control;
	     * so we'll have to compute a position for it now, by
	     * checking its column span.
	     */
	    int col;

	    colstart = COLUMN_START(ctrl->generic.column);
	    colspan = COLUMN_SPAN(ctrl->generic.column);

	    pos = columns[colstart];   /* structure copy */
	    pos.width = columns[colstart+colspan-1].width +
		(columns[colstart+colspan-1].xoff - columns[colstart].xoff);

	    for (col = colstart; col < colstart+colspan; col++)
		if (pos.ypos < columns[col].ypos)
		    pos.ypos = columns[col].ypos;

	    /*
	     * If this control is to be tabdelayed, add it to the
	     * tabdelay list, and unset pos.hwnd to inhibit actual
	     * control creation.
	     */
	    if (ctrl->generic.tabdelay) {
		assert(ntabdelays < lenof(tabdelays));
		tabdelays[ntabdelays] = pos;   /* structure copy */
		tabdelayed[ntabdelays] = ctrl;
		ntabdelays++;
		pos.hwnd = NULL;
	    }
	}

	/* Most controls don't need anything in c->data. */
	data = NULL;

	/* And they all start off with no shortcuts registered. */
	memset(shortcuts, NO_SHORTCUT, lenof(shortcuts));
	nshortcuts = 0;

	/* Almost all controls start at base_id. */
	actual_base_id = base_id;

	/*
	 * Now we're ready to actually create the control, by
	 * switching on its type.
	 */
	switch (ctrl->generic.type) {
	  case CTRL_TEXT:
	    {
		char *wrapped, *escaped;
		int lines;
		num_ids = 1;
		wrapped = staticwrap(&pos, cp->hwnd,
				     ctrl->generic.label, &lines);
		escaped = shortcut_escape(wrapped, NO_SHORTCUT);
		statictext(&pos, escaped, lines, base_id);
		sfree(escaped);
		sfree(wrapped);
	    }
	    break;
	  case CTRL_EDITBOX:
	    num_ids = 2;	       /* static, edit */
	    escaped = shortcut_escape(ctrl->editbox.label,
				      ctrl->editbox.shortcut);
	    shortcuts[nshortcuts++] = ctrl->editbox.shortcut;
	    if (ctrl->editbox.percentwidth == 100) {
		if (ctrl->editbox.has_list)
		    combobox(&pos, escaped,
			     base_id, base_id+1);
		else
		    multiedit(&pos, ctrl->editbox.password, escaped,
			      base_id, base_id+1, 100, NULL);
	    } else {
		if (ctrl->editbox.has_list) {
		    staticcombo(&pos, escaped, base_id, base_id+1,
				ctrl->editbox.percentwidth);
		} else {
		    (ctrl->editbox.password ? staticpassedit : staticedit)
			(&pos, escaped, base_id, base_id+1,
			 ctrl->editbox.percentwidth);
		}
	    }
	    sfree(escaped);
	    break;
	  case CTRL_RADIO:
	    num_ids = ctrl->radio.nbuttons + 1;   /* label as well */
	    {
		struct radio *buttons;
		int i;

		escaped = shortcut_escape(ctrl->radio.label,
					  ctrl->radio.shortcut);
		shortcuts[nshortcuts++] = ctrl->radio.shortcut;

		buttons = snewn(ctrl->radio.nbuttons, struct radio);

		for (i = 0; i < ctrl->radio.nbuttons; i++) {
		    buttons[i].text =
			shortcut_escape(ctrl->radio.buttons[i],
					(char)(ctrl->radio.shortcuts ?
					       ctrl->radio.shortcuts[i] :
					       NO_SHORTCUT));
		    buttons[i].id = base_id + 1 + i;
		    if (ctrl->radio.shortcuts) {
			assert(nshortcuts < MAX_SHORTCUTS_PER_CTRL);
			shortcuts[nshortcuts++] = ctrl->radio.shortcuts[i];
		    }
		}

		radioline_common(&pos, escaped, base_id,
				 ctrl->radio.ncolumns,
				 buttons, ctrl->radio.nbuttons);

		for (i = 0; i < ctrl->radio.nbuttons; i++) {
		    sfree(buttons[i].text);
		}
		sfree(buttons);
		sfree(escaped);
	    }
	    break;
	  case CTRL_CHECKBOX:
	    num_ids = 1;
	    escaped = shortcut_escape(ctrl->checkbox.label,
				      ctrl->checkbox.shortcut);
	    shortcuts[nshortcuts++] = ctrl->checkbox.shortcut;
	    checkbox(&pos, escaped, base_id);
	    sfree(escaped);
	    break;
	  case CTRL_BUTTON:
	    escaped = shortcut_escape(ctrl->button.label,
				      ctrl->button.shortcut);
	    shortcuts[nshortcuts++] = ctrl->button.shortcut;
	    if (ctrl->button.iscancel)
		actual_base_id = IDCANCEL;
	    num_ids = 1;
	    button(&pos, escaped, actual_base_id, ctrl->button.isdefault);
	    sfree(escaped);
	    break;
	  case CTRL_LISTBOX:
	    num_ids = 2;
	    escaped = shortcut_escape(ctrl->listbox.label,
				      ctrl->listbox.shortcut);
	    shortcuts[nshortcuts++] = ctrl->listbox.shortcut;
	    if (ctrl->listbox.draglist) {
		data = snew(struct prefslist);
		num_ids = 4;
		prefslist(data, &pos, ctrl->listbox.height, escaped,
			  base_id, base_id+1, base_id+2, base_id+3);
		shortcuts[nshortcuts++] = 'u';   /* Up */
		shortcuts[nshortcuts++] = 'd';   /* Down */
	    } else if (ctrl->listbox.height == 0) {
		/* Drop-down list. */
		if (ctrl->listbox.percentwidth == 100) {
		    staticddlbig(&pos, escaped,
				 base_id, base_id+1);
		} else {
		    staticddl(&pos, escaped, base_id,
			      base_id+1, ctrl->listbox.percentwidth);
		}
	    } else {
		/* Ordinary list. */
		listbox(&pos, escaped, base_id, base_id+1,
			ctrl->listbox.height, ctrl->listbox.multisel);
	    }
	    if (ctrl->listbox.ncols) {
		/*
		 * This method of getting the box width is a bit of
		 * a hack; we'd do better to try to retrieve the
		 * actual width in dialog units from doctl() just
		 * before MapDialogRect. But that's going to be no
		 * fun, and this should be good enough accuracy.
		 */
		int width = cp->width * ctrl->listbox.percentwidth;
		int *tabarray;
		int i, percent;

		tabarray = snewn(ctrl->listbox.ncols-1, int);
		percent = 0;
		for (i = 0; i < ctrl->listbox.ncols-1; i++) {
		    percent += ctrl->listbox.percentages[i];
		    tabarray[i] = width * percent / 10000;
		}
		SendDlgItemMessage(cp->hwnd, base_id+1, LB_SETTABSTOPS,
				   ctrl->listbox.ncols-1, (LPARAM)tabarray);
		sfree(tabarray);
	    }
	    sfree(escaped);
	    break;
	  case CTRL_FILESELECT:
	    num_ids = 3;
	    escaped = shortcut_escape(ctrl->fileselect.label,
				      ctrl->fileselect.shortcut);
	    shortcuts[nshortcuts++] = ctrl->fileselect.shortcut;
	    editbutton(&pos, escaped, base_id, base_id+1,
		       "Bro&wse...", base_id+2);
	    shortcuts[nshortcuts++] = 'w';
	    sfree(escaped);
	    break;
	  case CTRL_FONTSELECT:
	    num_ids = 3;
	    escaped = shortcut_escape(ctrl->fontselect.label,
				      ctrl->fontselect.shortcut);
	    shortcuts[nshortcuts++] = ctrl->fontselect.shortcut;
	    statictext(&pos, escaped, 1, base_id);
	    staticbtn(&pos, "", base_id+1, "Change...", base_id+2);
	    sfree(escaped);
	    data = snew(FontSpec);
	    break;
	  default:
	    assert(!"Can't happen");
	    num_ids = 0;	       /* placate gcc */
	    break;
	}

	/*
	 * Create a `struct winctrl' for this control, and advance
	 * the dialog ID counter, if it's actually been created
	 * (and isn't tabdelayed).
	 */
	if (pos.hwnd) {
	    struct winctrl *c = snew(struct winctrl);

	    c->ctrl = ctrl;
	    c->base_id = actual_base_id;
	    c->num_ids = num_ids;
	    c->data = data;
	    memcpy(c->shortcuts, shortcuts, sizeof(shortcuts));
	    winctrl_add(wc, c);
	    winctrl_add_shortcuts(dp, c);
	    if (actual_base_id == base_id)
		base_id += num_ids;
	}

	if (colstart >= 0) {
	    /*
	     * Update the ypos in all columns crossed by this
	     * control.
	     */
	    int i;
	    for (i = colstart; i < colstart+colspan; i++)
		columns[i].ypos = pos.ypos;
	}
    }

    /*
     * We've now finished laying out the controls; so now update
     * the ctlpos and control ID that were passed in, terminate
     * any containing box, and return.
     */
    for (i = 0; i < ncols; i++)
	if (cp->ypos < columns[i].ypos)
	    cp->ypos = columns[i].ypos;
    *id = base_id;

    if (s->boxname && *s->boxname)
	endbox(cp);
}

static void winctrl_set_focus(union control *ctrl, struct dlgparam *dp,
			      int has_focus)
{
    if (has_focus) {
	if (dp->focused)
	    dp->lastfocused = dp->focused;
	dp->focused = ctrl;
    } else if (!has_focus && dp->focused == ctrl) {
	dp->lastfocused = dp->focused;
	dp->focused = NULL;
    }
}

union control *dlg_last_focused(union control *ctrl, void *dlg)
{
    struct dlgparam *dp = (struct dlgparam *)dlg;
    return dp->focused == ctrl ? dp->lastfocused : dp->focused;
}

/*
 * The dialog-box procedure calls this function to handle Windows
 * messages on a control we manage.
 */
int winctrl_handle_command(struct dlgparam *dp, UINT msg,
			   WPARAM wParam, LPARAM lParam)
{
    struct winctrl *c;
    union control *ctrl;
    int i, id, ret;
    static UINT draglistmsg = WM_NULL;

    /*
     * Filter out pointless window messages. Our interest is in
     * WM_COMMAND and the drag list message, and nothing else.
     */
    if (draglistmsg == WM_NULL)
	draglistmsg = RegisterWindowMessage (DRAGLISTMSGSTRING);

    if (msg != draglistmsg && msg != WM_COMMAND && msg != WM_DRAWITEM)
	return 0;

    /*
     * Look up the control ID in our data.
     */
    c = NULL;
    for (i = 0; i < dp->nctrltrees; i++) {
	c = winctrl_findbyid(dp->controltrees[i], LOWORD(wParam));
	if (c)
	    break;
    }
    if (!c)
	return 0;		       /* we have nothing to do */

    if (msg == WM_DRAWITEM) {
	/*
	 * Owner-draw request for a panel title.
	 */
	LPDRAWITEMSTRUCT di = (LPDRAWITEMSTRUCT) lParam;
	HDC hdc = di->hDC;
	RECT r = di->rcItem;
	SIZE s;

	SetMapMode(hdc, MM_TEXT);      /* ensure logical units == pixels */

	GetTextExtentPoint32(hdc, (char *)c->data,
				 strlen((char *)c->data), &s);
	DrawEdge(hdc, &r, EDGE_ETCHED, BF_ADJUST | BF_RECT);
	TextOut(hdc,
		r.left + (r.right-r.left-s.cx)/2,
		r.top + (r.bottom-r.top-s.cy)/2,
		(char *)c->data, strlen((char *)c->data));

	return TRUE;
    }

    ctrl = c->ctrl;
    id = LOWORD(wParam) - c->base_id;

⌨️ 快捷键说明

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