示例#1
0
int
main ()
{
  unsigned char input[BUFSIZ];
  unsigned char *output;
  unsigned char *str;
  int c, i = 0;

  while ((c = fgetc (stdin)) != '\n' && i < BUFSIZ)
    input[i++] = c;
  input[i] = '\0';

  printf ("input : %d bytes\n", strlen ((const char *) input));
  printf ("output: %d bytes\n", strwidth (input));

  output = (unsigned char *) gdMalloc (BUFSIZ);
  any2eucjp (output, input, BUFSIZ);
  str = output;
  while (*str != '\0')
    putchar (*(str++));
  putchar ('\n');
  gdFree (output);

  return 0;
}
示例#2
0
文件: list.c 项目: jens-na/abook-call
static void
print_list_field(int item, int line, int *x_pos, struct index_elem *e)
{
	char *s, *p;
	int width, x_start, mustfree = FALSE, len = abs(e->d.field.len);
	struct list_field f;

	get_list_field(item, e, &f);
	s = f.data;

	if(!s || !*s) {
		*x_pos += len;
		return;
	}
	
	if(f.type == FIELD_EMAILS && !opt_get_bool(BOOL_SHOW_ALL_EMAILS))
		if((p = strchr(s, ',')) != NULL) {
			s = xstrndup(s, p - s);
			mustfree = TRUE;
		}

	width = len ? bytes2width(s, len) : strwidth(s);
	x_start = *x_pos + ((e->d.field.len < 0) ? len - width : 0);
	if(width + x_start >= COLS)
		width = bytes2width(s, COLS - x_start);

	if(width)
		mvwaddnstr(list, line, x_start, s, width);

	if(mustfree)
		free(s);
		
	*x_pos += len ? len : width;
}
示例#3
0
文件: list.c 项目: hhirsch/abook
static void
print_list_line(int item, int line, int highlight)
{
	struct index_elem *cur;
	int x_pos = 1;

	if(item % 2 == 0)
		wattrset(list, COLOR_PAIR(CP_LIST_EVEN));
	else
		wattrset(list, COLOR_PAIR(CP_LIST_ODD));
	scrollok(list, FALSE);
	if(highlight)
		highlight_line(list, line);

	if(selected[item])
		mvwaddch(list, line, 0, '*' );

	for(cur = index_elements; cur; cur = cur->next)
		switch(cur->type) {
			case INDEX_TEXT:
				mvwaddstr(list, line, x_pos, cur->d.text);
				x_pos += strwidth(cur->d.text);
				break;
			case INDEX_FIELD:
				print_list_field(item, line, &x_pos, cur);
				break;
			default:
				assert(0);
		}

	scrollok(list, TRUE);
	if(highlight)
		wstandend(list);
}
示例#4
0
文件: font.c 项目: 4ad/sam
long
charwidth(XftFont *f, Rune r)
{
    
    char chars[UTFmax + 1] = {0};

    runetochar(chars, &r);
    return strwidth(f, chars);
}
示例#5
0
static window init_askstr_dialog(const char *title, const char *question,
				 const char *default_str)
{
    window win;
    dialog_data *d;
    int tw, bw, h, middle;

    if (! question)
	question= "";
    if (! default_str)
	default_str = "";

    tw = strwidth(SystemFont, G_("Cancel")) * 8;
    h = getheight(SystemFont);

    if (tw < 150) tw = 150;

    win = newwindow(title, rect(0,0,tw+30,h*9+12),
		    Titlebar | Centered | Modal);
    setbackground(win, dialog_bg());
    add_data(win);
    d = data(win);
    d->question = newlabel(question, rect(10,h,tw+4,h*2+2),
			   AlignLeft);
    if (title == PASSWORD_TITLE)
	d->text = newpassword(default_str, rect(10,h*4,tw+4,h*3/2));
    else
	d->text = newfield(default_str, rect(10,h*4,tw+4,h*3/2));

    middle = (tw+30)/2;
    bw = strwidth(SystemFont, G_("Cancel")) * 3/2;

    d->yes = newbutton(G_("OK"),
		       rect(middle-bw-10, h*7, bw, h+10), hit_button);
    setvalue(d->yes, YES);

    d->cancel = newbutton(G_("Cancel"),
			  rect(middle+10, h*7, bw, h+10), hit_button);
    setvalue(d->cancel, CANCEL);

    setkeydown(win, hit_key);

    return win;
}
示例#6
0
文件: frbox.c 项目: knusbaum/Wily
static
void
truncatebox(Frame *f, Frbox *b, int n)	/* drop last n chars; no allocation done */
{
	if(b->nrune<0 || b->nrune<n)
		berror("truncatebox");
	b->nrune -= n;
	runeindex(b->a.ptr, b->nrune)[0] = 0;
	b->wid = strwidth(f->font, (char *)b->a.ptr);
}
示例#7
0
文件: frbox.c 项目: knusbaum/Wily
static
void
chopbox(Frame *f, Frbox *b, int n)	/* drop first n chars; no allocation done */
{
	if(b->nrune<0 || b->nrune<n)
		berror("chopbox");
	strcpy((char*)b->a.ptr, (char*)runeindex(b->a.ptr, n));
	b->nrune -= n;
	b->wid = strwidth(f->font, (char *)b->a.ptr);
}
示例#8
0
文件: buttons.c 项目: Vladimir84/rcc
static void draw_radio(control c, rect r)
{
	int w;
	rect box, textrect;
	char *name;
	int style = (AlignLeft | AlignTop);
	font f;
	rgb old = currentcolour();

	/* Calculate rectangles. */
	f = gettextfont(c);
	setfont(f);
	w = strwidth(f,"W");
	if (w > r.width)  w = r.width;
	if (w > r.height) w = r.height;
	box = rect(r.x,r.y+1,w,w);
	if (w < getheight(f) - getdescent(f))
		box.y += getheight(f) - getdescent(f) - w;
	textrect = rect(r.x+w+w/2,r.y,r.width-(w+w/2),r.height);

	/* Clear the check area. */
	setlinewidth(1);
	setcolour(White);
	fillellipse(insetr(box,1));

	/* Draw the check area */
	if (isenabled(c))
		setcolour(Black);
	else
		setcolour(Grey);
	drawellipse(box);

	/* Provide 'pressed button' effect by black border. */
	if (ishighlighted(c)) {
		setlinewidth(2);
		drawellipse(box);
		setlinewidth(1);
	}

	/* Put o in circle if checked. */
	if (ischecked(c))
		fillellipse(insetr(box,3));

	name = getname(c);
	if (isenabled(c)) {
		/* if (hasfocus(c)) {
			style |= Underline;
			setlinewidth(2);
		} */
		setcolour(getforeground(c));
	}
	drawtext(textrect, style, name);

	setcolour(old);
}
示例#9
0
int strlongest(char **strs, int count)
{
	int i, max = 0;
	size_t width;

	for (i = 0; i < count; i++)
	{
		width = strwidth(strs[i]);
		if (width > max)
			max = width;
	}
	return max;
}
示例#10
0
文件: str.c 项目: DirtYiCE/uim
/*
 * str1とstr2の末尾からの共通部分文字列の幅を返す
 * compare_str_rev("a", "b") = 0
 * compare_str_rev("a", "ba") = 1
 * compare_str_rev("aあ", "baあ") = 3
 * compare_str_rev("□(0xa2a2)", "あ(0xa4a2)") = 0
 */
int compare_str_rev(char *str1, char *str2)
{
  int i;
  int len1;
  int len2;
  int width1;
  int width2;

  assert(str1 != NULL && str2 != NULL);

  len1 = strlen(str1);
  len2 = strlen(str2);

  for (i = 1; i <= min(len1, len2); i++) {
    if (str1[len1 - i] != str2[len2 - i]) {
      break;
    }
  }

  width1 = strwidth(str1) - byte2width2((char *)str1, len1 - i + 1);
  width2 = strwidth(str2) - byte2width2((char *)str2, len2 - i + 1);
  return (width1 == width2) ? width1 : 0;
}
示例#11
0
文件: utils.cpp 项目: 2ion/newsbeuter
size_t utils::strwidth_stfl(const std::string& str) {
	size_t reduce_count = 0;
	size_t len = str.length();
	if (len > 1) {
		for (size_t idx=0;idx<len-1;++idx) {
			if (str[idx] == '<' && str[idx+1] != '>') {
				reduce_count += 3;
				idx += 3;
			}
		}
	}

	return strwidth(str) - reduce_count;
}
示例#12
0
文件: drawtext.c 项目: Bgods/r-source
static const char *draw_text_centered(char *line, rect r, int line_height,
				      int underline, const char *s)
{
    char *k;
    int w;
    point p;
    int width, height;
    font f;

    f = current->fnt;

    for(p=pt(r.x,r.y); (p.y<=r.y+r.height) && (s); p.y+=line_height)
    {
	s = get_next_line(line, r.width, s);

	for (k=line; *k!='\0'; k++)
	    continue;
	for (--k; (k>=line) && isspace(*k); k--)
	    *k = '\0';
	for(k=line; (*k!='\0') && isspace(*k); k++)
	    continue;

	w = strwidth(current->fnt, k);
	p.x = r.x + (r.width-w)/2;

	drawstr(p, k);

	if (underline) {
	    width = strwidth(f, k);
	    height = p.y+getheight(f)-getdescent(f)+2;
	    drawline(pt(p.x+1, height), pt(p.x+width-1, height));
	}
    }

    return s;
}
示例#13
0
void	movemenubar(MenuBar *mb)
{
    int	i, tx = MENUXENDGAP-9, totaltwidth = 0;
    int	xsize, ysize, width;

    getorigin(&mb->xorg, &mb->yorg);
    getsize(&xsize, &ysize);
    mb->xmin = mb->xorg;
    mb->xmax = mb->xorg+xsize-1;
    mb->ymin = mb->yorg+ysize-MENUBARHEIGHT;
    mb->ymax = mb->yorg+ysize-1;

    width = mb->xmax - mb->xmin + 1;

    font(PULLDOWNFONT);	/* for correct strwidths */
    for (i = 0; i < mb->count; i++)
        totaltwidth += strwidth(mb->pds[i]->title) + 2*MENUXENDGAP;

    for (i = 0; i < mb->count; i++) {
	if (mb->pds[i]->title)
	    mb->pds[i]->twidth = strwidth(mb->pds[i]->title);
        if ((mb->pds[i]->title) && (!strcmp(mb->pds[i]->title,"Help")))
           mb->pds[i]->txorg = mb->xmax-MENUXENDGAP-mb->pds[i]->twidth-MENUXGAP;
        else
           mb->pds[i]->txorg = mb->xmin + tx;
        mb->pds[i]->xorg = mb->pds[i]->txorg;
	mb->pds[i]->yorg = mb->ymin-TITLESEP;
	mb->pds[i]->orglocked = 1;
	mb->pds[i]->mb = mb;

	if (totaltwidth > width)
            tx += (width-2*MENUXENDGAP)/mb->count-2;
        else
            tx += mb->pds[i]->twidth+24;
    } 
}
示例#14
0
文件: str.c 项目: DirtYiCE/uim
static int byte2width2(char *str, int n)
{
  int width;
  int str_byte;
  char save_char;
  char *save_str;
  wchar_t *wcstr;
  int nr_wchars;
  
  assert(str != NULL);

  if (n <= 0) {
    return 0;
  }

  str_byte = strlen(str);
  if (str_byte == 0) {
    return 0;
  }

  if (n > str_byte) {
    n = str_byte;
  }

  wcstr = uim_malloc(sizeof(wchar_t) * str_byte);

  save_str = str;

  save_char = str[n];
  str[n] = '\0';
  nr_wchars = mbsrtowcs(wcstr, (const char **)&str, str_byte, NULL);
  save_str[n] = save_char;

  if ((size_t)nr_wchars != (size_t)(-1)) {
    width = wcswidth(wcstr, nr_wchars);
  } else {
    mbsrtowcs(wcstr, (const char **)&str, 1, NULL);
    /* strを最後まで変換するとNULLになる */
    assert(str != NULL);
    save_char = str[0];
    str[0] = '\0';
    width = strwidth(save_str);
    str[0] = save_char;
  }
  free(wcstr);
  assert(width >= 0);
  return width;
}
示例#15
0
文件: menuhit.c 项目: pocket7878/sam
void
menupaint(Menu *menu, Rectangle textr, int off, int nitemdrawn)
{
    int i;
    Point pt;
    Rectangle r;
    char *item;

    r = inset(textr, Border-Margin);
    bitblt(&screen, r.min, &screen, r, 0);
    pt = Pt(textr.min.x+textr.max.x, textr.min.y);
    for(i = 0; i<nitemdrawn; i++, pt.y += fontheight()+Vspacing){
        item = menu->item? menu->item[i+off] : (*menu->gen)(i+off);
        string(&screen,
            Pt((pt.x-strwidth(font, item))/2, pt.y),
            font, item, S);
    }
}
示例#16
0
文件: escseq.c 项目: NgoHuy/uim
/*
 * strを端末に出力する
 * 画面の右端を越えてはいけない
 * エスケープシーケンスは含まない
 * 下線、反転はattrで指定
 */
void put_uim_str(const char *str, int attr)
{
  if (str[0] == '\0') {
    return;
  }
  if (s_escseq_buf != NULL) {
    free(s_escseq_buf);
    s_escseq_buf = NULL;
  }

  s_attr_uim.standout = attr & UPreeditAttr_Reverse;
  s_attr_uim.underline = attr & UPreeditAttr_UnderLine;
  change_attr(&s_attr, &s_attr_uim);

  s_cursor.col += strwidth(str);
  assert(s_cursor.col <= g_win->ws_col || g_opt.no_report_cursor);
  write(g_win_out, str, strlen(str));
  debug(("<put_uim_str \"%s\">", str));
}
示例#17
0
void	drawparttl(TextList *tl,int item)
{
    int	xmin = tl->xmin+8, xmax = tl->xmax-8-SLIDERWIDTH;
    int	ymin = 
		tl->ymin+5+(tl->listheight - item + tl->top - 1)*TEXTHEIGHT;
    int 	ymax = ymin + TEXTHEIGHT - 3;
    char        **s;

    if (!getvisibletl(tl) || !getitemvisibletl(tl,item))
	return;

    s = &tl->strs[item];
    drawsetup();

    uifrontbuffer(1);

    uiLtGray();
    	uirectfi(xmin-1, ymin-1, xmax+1, ymax+1);

    font(TEXTLISTFONT);
    pushviewport();
    scrmask(xmin-1, xmax+1, ymin-1, ymax+1);
    if (s) {
        xmax = xmin + 7 + strwidth(*s);
        if (item == tl->selecteditem) {
    	    uiWhite();
            	uirectfi(xmin, ymin, xmax, ymax);
        }
        if (item == tl->locateditem) {
    	    uiWhite();
            	uirecti(xmin-1, ymin-1, xmax+1, ymax+1);
            	uirecti(xmin, ymin, xmax, ymax);
        }
    	uiBlack();
            uicmov2i(xmin+4, ymin + 5);
            uicharstr(*s);
    }
    popviewport();

    uifrontbuffer(0);

    drawrestore();
}
示例#18
0
文件: ui.c 项目: jens-na/abook-call
/* Same as statusline_addstr(), but hilight "<str>" sequences if the terminal
 * supports it */
static void
statusline_addhlstr(const char *str)
{
#if defined(A_BOLD) && defined(A_NORMAL) && defined(A_DIM)
    const char *p = str, *start = str;
    char *tmp;
    int pos = 0;

    while(1) {
        if(!*p || strchr("<>", *p)) {
            if(p - start > 0) {
                wattrset(bottom, (*p == '>') ? A_BOLD : A_NORMAL);
                tmp = xstrndup(start, p - start);
                mvwaddstr(bottom, 1, pos, tmp);
                pos += strwidth(tmp);
                free(tmp);
            }
            if(*p) {
                start = p + 1;

                /* show tag markers */
                wattrset(bottom, A_DIM);
                mvwaddch(bottom, 1, pos++, *p);
            }
        }

        if(!*p) {
            wattrset(bottom, A_NORMAL);
            break;
        }

        p++;
    }
#else
    mvwaddstr(bottom, 1, 0, str);
#endif

    refresh();
    wrefresh(bottom);
}
示例#19
0
int
strtruncate (char *what, size_t maxsize)
{
    size_t pos;
    int k;
    char *p;
    wchar_t c;

    if (strwidth(what) <= maxsize)
        return 0;

    /*  Replace end of string with ellipsis "..."; as the last character
     *  may have a double width, stops 4 characters before the end
     */
    pos = 0;
    for (p = what; (k = mbtowc (&c, p, MB_LEN_MAX)) > 0 && pos < maxsize-5; p += k)
        pos += wcwidth (c);

    for (k=0; k < 3; k++, p++)
        *p = '.';
    *p = '\0';
    return 1;
}  
示例#20
0
文件: menuhit.c 项目: pocket7878/sam
int
menuhit(int but, Mouse *m, Menu *menu)
{
    int i, nitem, nitemdrawn, maxwid, lasti, off, noff, wid, screenitem;
    bool scrolling;
    Rectangle r, menur, sc, textr, scrollr;
    Bitmap *b;
    Point pt;
    char *item;
    extern unsigned int cursor;
    unsigned int oldcursor = cursor;

    cursorswitch(ArrowCursor);
    sc = screen.clipr;
    clipr(&screen, screen.r);
    maxwid = 0;
    for(nitem = 0;
        (item = menu->item? menu->item[nitem] : (*menu->gen)(nitem));
        nitem++){
        i = strwidth(font, item);
        if(i > maxwid)
            maxwid = i;
    }
    if(menu->lasthit<0 || menu->lasthit>=nitem)
        menu->lasthit = 0;
    screenitem = (Dy(screen.r)-10)/(fontheight()+Vspacing);
    if(nitem>Maxunscroll || nitem>screenitem){
        scrolling = true;
        nitemdrawn = Nscroll;
        if(nitemdrawn > screenitem)
            nitemdrawn = screenitem;
        wid = maxwid + Gap + Scrollwid;
        off = menu->lasthit - nitemdrawn/2;
        if(off < 0)
            off = 0;
        if(off > nitem-nitemdrawn)
            off = nitem-nitemdrawn;
        lasti = menu->lasthit-off;
    }else{
        scrolling = false;
        nitemdrawn = nitem;
        wid = maxwid;
        off = 0;
        lasti = menu->lasthit;
    }
    r = inset(Rect(0, 0, wid, nitemdrawn*(fontheight()+Vspacing)), -Margin);
    r = rsubp(r, Pt(wid/2, lasti*(fontheight()+Vspacing)+fontheight()/2));
    r = raddp(r, m->xy);
    pt = Pt(0, 0);
    if(r.max.x>screen.r.max.x)
        pt.x = screen.r.max.x-r.max.x;
    if(r.max.y>screen.r.max.y)
        pt.y = screen.r.max.y-r.max.y;
    if(r.min.x<screen.r.min.x)
        pt.x = screen.r.min.x-r.min.x;
    if(r.min.y<screen.r.min.y)
        pt.y = screen.r.min.y-r.min.y;
    menur = raddp(r, pt);
    textr.max.x = menur.max.x-Margin;
    textr.min.x = textr.max.x-maxwid;
    textr.min.y = menur.min.y+Margin;
    textr.max.y = textr.min.y + nitemdrawn*(fontheight()+Vspacing);
    if(scrolling){
        scrollr = inset(menur, Border);
        scrollr.max.x = scrollr.min.x+Scrollwid;
    }else
        scrollr = Rect(0, 0, 0, 0);

    b = balloc(menur, screen.ldepth);
    if(b == 0)
        b = &screen;
    bitblt(b, menur.min, &screen, menur, S);
    bitblt(&screen, menur.min, &screen, menur, 0);
    border(&screen, menur, Blackborder, F, _bgpixel);
    r = menurect(textr, lasti);
    cursorset(divpt(add(r.min, r.max), 2));
    menupaint(menu, textr, off, nitemdrawn);
    if(scrolling)
        menuscrollpaint(scrollr, off, nitem, nitemdrawn);
    r = menurect(textr, lasti);
    cursorset(divpt(add(r.min, r.max), 2));
    menupaint(menu, textr, off, nitemdrawn);
    if(scrolling)
        menuscrollpaint(scrollr, off, nitem, nitemdrawn);
    while(m->buttons & (1<<(but-1))){
        lasti = menuscan(but, m, textr, lasti);
        if(lasti >= 0)
            break;
        while(!ptinrect(m->xy, textr) && (m->buttons & (1<<(but-1)))){
            if(scrolling && ptinrect(m->xy, scrollr)){
                noff = ((m->xy.y-scrollr.min.y)*nitem)/Dy(scrollr);
                noff -= nitemdrawn/2;
                if(noff < 0)
                    noff = 0;
                if(noff > nitem-nitemdrawn)
                    noff = nitem-nitemdrawn;
                if(noff != off){
                    off = noff;
                    menupaint(menu, textr, off, nitemdrawn);
                    menuscrollpaint(scrollr, off, nitem, nitemdrawn);
                }
            }
            *m = emouse();
        }
    }
    bitblt(&screen, menur.min, b, menur, S);
    if(b != &screen)
        bfree(b);
    clipr(&screen, sc);
    if(lasti >= 0){
        menu->lasthit = lasti+off;
        return cursorswitch(oldcursor), menu->lasthit;
    }
    cursorswitch(oldcursor);
    return -1;
}
示例#21
0
ptrdiff_t
doprnt (char *buffer, ptrdiff_t bufsize, const char *format,
	const char *format_end, va_list ap)
{
  const char *fmt = format;	/* Pointer into format string.  */
  char *bufptr = buffer;	/* Pointer into output buffer.  */

  /* Use this for sprintf unless we need something really big.  */
  char tembuf[DBL_MAX_10_EXP + 100];

  /* Size of sprintf_buffer.  */
  ptrdiff_t size_allocated = sizeof (tembuf);

  /* Buffer to use for sprintf.  Either tembuf or same as BIG_BUFFER.  */
  char *sprintf_buffer = tembuf;

  /* Buffer we have got with malloc.  */
  char *big_buffer = NULL;

  enum text_quoting_style quoting_style = text_quoting_style ();
  ptrdiff_t tem = -1;
  char *string;
  char fixed_buffer[20];	/* Default buffer for small formatting. */
  char *fmtcpy;
  int minlen;
  char charbuf[MAX_MULTIBYTE_LENGTH + 1];	/* Used for %c.  */
  USE_SAFE_ALLOCA;

  if (format_end == 0)
    format_end = format + strlen (format);

  fmtcpy = (format_end - format < sizeof (fixed_buffer) - 1
	    ? fixed_buffer
	    : SAFE_ALLOCA (format_end - format + 1));

  bufsize--;

  /* Loop until end of format string or buffer full. */
  while (fmt < format_end && bufsize > 0)
    {
      char const *fmt0 = fmt;
      char fmtchar = *fmt++;
      if (fmtchar == '%')
	{
	  ptrdiff_t size_bound = 0;
	  ptrdiff_t width;  /* Columns occupied by STRING on display.  */
	  enum {
	    pDlen = sizeof pD - 1,
	    pIlen = sizeof pI - 1,
	    pMlen = sizeof pMd - 2
	  };
	  enum {
	    no_modifier, long_modifier, pD_modifier, pI_modifier, pM_modifier
	  } length_modifier = no_modifier;
	  static char const modifier_len[] = { 0, 1, pDlen, pIlen, pMlen };
	  int maxmlen = max (max (1, pDlen), max (pIlen, pMlen));
	  int mlen;

	  /* Copy this one %-spec into fmtcpy.  */
	  string = fmtcpy;
	  *string++ = '%';
	  while (fmt < format_end)
	    {
	      *string++ = *fmt;
	      if ('0' <= *fmt && *fmt <= '9')
		{
		  /* Get an idea of how much space we might need.
		     This might be a field width or a precision; e.g.
		     %1.1000f and %1000.1f both might need 1000+ bytes.
		     Parse the width or precision, checking for overflow.  */
		  ptrdiff_t n = *fmt - '0';
		  while (fmt + 1 < format_end
			 && '0' <= fmt[1] && fmt[1] <= '9')
		    {
		      /* Avoid ptrdiff_t, size_t, and int overflow, as
			 many sprintfs mishandle widths greater than INT_MAX.
			 This test is simple but slightly conservative: e.g.,
			 (INT_MAX - INT_MAX % 10) is reported as an overflow
			 even when it's not.  */
		      if (n >= min (INT_MAX, min (PTRDIFF_MAX, SIZE_MAX)) / 10)
			error ("Format width or precision too large");
		      n = n * 10 + fmt[1] - '0';
		      *string++ = *++fmt;
		    }

		  if (size_bound < n)
		    size_bound = n;
		}
	      else if (! (*fmt == '-' || *fmt == ' ' || *fmt == '.'
			  || *fmt == '+'))
		break;
	      fmt++;
	    }

	  /* Check for the length modifiers in textual length order, so
	     that longer modifiers override shorter ones.  */
	  for (mlen = 1; mlen <= maxmlen; mlen++)
	    {
	      if (format_end - fmt < mlen)
		break;
	      if (mlen == 1 && *fmt == 'l')
		length_modifier = long_modifier;
	      if (mlen == pDlen && memcmp (fmt, pD, pDlen) == 0)
		length_modifier = pD_modifier;
	      if (mlen == pIlen && memcmp (fmt, pI, pIlen) == 0)
		length_modifier = pI_modifier;
	      if (mlen == pMlen && memcmp (fmt, pMd, pMlen) == 0)
		length_modifier = pM_modifier;
	    }

	  mlen = modifier_len[length_modifier];
	  memcpy (string, fmt + 1, mlen);
	  string += mlen;
	  fmt += mlen;
	  *string = 0;

	  /* Make the size bound large enough to handle floating point formats
	     with large numbers.  */
	  if (size_bound > min (PTRDIFF_MAX, SIZE_MAX) - DBL_MAX_10_EXP - 50)
	    error ("Format width or precision too large");
	  size_bound += DBL_MAX_10_EXP + 50;

	  /* Make sure we have that much.  */
	  if (size_bound > size_allocated)
	    {
	      if (big_buffer)
		xfree (big_buffer);
	      big_buffer = xmalloc (size_bound);
	      sprintf_buffer = big_buffer;
	      size_allocated = size_bound;
	    }
	  minlen = 0;
	  switch (*fmt++)
	    {
	    default:
	      error ("Invalid format operation %s", fmtcpy);

/*	    case 'b': */
	    case 'l':
	    case 'd':
	      switch (length_modifier)
		{
		case no_modifier:
		  {
		    int v = va_arg (ap, int);
		    tem = sprintf (sprintf_buffer, fmtcpy, v);
		  }
		  break;
		case long_modifier:
		  {
		    long v = va_arg (ap, long);
		    tem = sprintf (sprintf_buffer, fmtcpy, v);
		  }
		  break;
		case pD_modifier:
		signed_pD_modifier:
		  {
		    ptrdiff_t v = va_arg (ap, ptrdiff_t);
		    tem = sprintf (sprintf_buffer, fmtcpy, v);
		  }
		  break;
		case pI_modifier:
		  {
		    EMACS_INT v = va_arg (ap, EMACS_INT);
		    tem = sprintf (sprintf_buffer, fmtcpy, v);
		  }
		  break;
		case pM_modifier:
		  {
		    intmax_t v = va_arg (ap, intmax_t);
		    tem = sprintf (sprintf_buffer, fmtcpy, v);
		  }
		  break;
		}
	      /* Now copy into final output, truncating as necessary.  */
	      string = sprintf_buffer;
	      goto doit;

	    case 'o':
	    case 'x':
	      switch (length_modifier)
		{
		case no_modifier:
		  {
		    unsigned v = va_arg (ap, unsigned);
		    tem = sprintf (sprintf_buffer, fmtcpy, v);
		  }
		  break;
		case long_modifier:
		  {
		    unsigned long v = va_arg (ap, unsigned long);
		    tem = sprintf (sprintf_buffer, fmtcpy, v);
		  }
		  break;
		case pD_modifier:
		  goto signed_pD_modifier;
		case pI_modifier:
		  {
		    EMACS_UINT v = va_arg (ap, EMACS_UINT);
		    tem = sprintf (sprintf_buffer, fmtcpy, v);
		  }
		  break;
		case pM_modifier:
		  {
		    uintmax_t v = va_arg (ap, uintmax_t);
		    tem = sprintf (sprintf_buffer, fmtcpy, v);
		  }
		  break;
		}
	      /* Now copy into final output, truncating as necessary.  */
	      string = sprintf_buffer;
	      goto doit;

	    case 'f':
	    case 'e':
	    case 'g':
	      {
		double d = va_arg (ap, double);
		tem = sprintf (sprintf_buffer, fmtcpy, d);
		/* Now copy into final output, truncating as necessary.  */
		string = sprintf_buffer;
		goto doit;
	      }

	    case 'S':
	      string[-1] = 's';
	    case 's':
	      if (fmtcpy[1] != 's')
		minlen = atoi (&fmtcpy[1]);
	      string = va_arg (ap, char *);
	      tem = strlen (string);
	      if (STRING_BYTES_BOUND < tem)
		error ("String for %%s or %%S format is too long");
	      width = strwidth (string, tem);
	      goto doit1;

	      /* Copy string into final output, truncating if no room.  */
	    doit:
	      eassert (0 <= tem);
	      /* Coming here means STRING contains ASCII only.  */
	      if (STRING_BYTES_BOUND < tem)
		error ("Format width or precision too large");
	      width = tem;
	    doit1:
	      /* We have already calculated:
		 TEM -- length of STRING,
		 WIDTH -- columns occupied by STRING when displayed, and
		 MINLEN -- minimum columns of the output.  */
	      if (minlen > 0)
		{
		  while (minlen > width && bufsize > 0)
		    {
		      *bufptr++ = ' ';
		      bufsize--;
		      minlen--;
		    }
		  minlen = 0;
		}
	      if (tem > bufsize)
		{
		  /* Truncate the string at character boundary.  */
		  tem = bufsize;
		  do
		    {
		      tem--;
		      if (CHAR_HEAD_P (string[tem]))
			{
			  if (BYTES_BY_CHAR_HEAD (string[tem]) <= bufsize - tem)
			    tem = bufsize;
			  break;
			}
		    }
		  while (tem != 0);

		  memcpy (bufptr, string, tem);
		  bufptr[tem] = 0;
		  /* Trigger exit from the loop, but make sure we
		     return to the caller a value which will indicate
		     that the buffer was too small.  */
		  bufptr += bufsize;
		  bufsize = 0;
		  continue;
		}
	      memcpy (bufptr, string, tem);
	      bufptr += tem;
	      bufsize -= tem;
	      if (minlen < 0)
		{
		  while (minlen < - width && bufsize > 0)
		    {
		      *bufptr++ = ' ';
		      bufsize--;
		      minlen++;
		    }
		  minlen = 0;
		}
	      continue;

	    case 'c':
	      {
		int chr = va_arg (ap, int);
		tem = CHAR_STRING (chr, (unsigned char *) charbuf);
		string = charbuf;
		string[tem] = 0;
		width = strwidth (string, tem);
		if (fmtcpy[1] != 'c')
		  minlen = atoi (&fmtcpy[1]);
		goto doit1;
	      }

	    case '%':
	      fmt--;    /* Drop thru and this % will be treated as normal */
	    }
	}

      char const *src;
      ptrdiff_t srclen;
      if (quoting_style == CURVE_QUOTING_STYLE && fmtchar == '`')
	src = uLSQM, srclen = sizeof uLSQM - 1;
      else if (quoting_style == CURVE_QUOTING_STYLE && fmtchar == '\'')
	src = uRSQM, srclen = sizeof uRSQM - 1;
      else if (quoting_style == STRAIGHT_QUOTING_STYLE && fmtchar == '`')
	src = "'", srclen = 1;
      else
	{
	  while (fmt < format_end && !CHAR_HEAD_P (*fmt))
	    fmt++;
	  src = fmt0, srclen = fmt - fmt0;
	}

      if (bufsize < srclen)
	{
	  /* Truncate, but return value that will signal to caller
	     that the buffer was too small.  */
	  do
	    *bufptr++ = '\0';
	  while (--bufsize != 0);
	}
      else
	{
	  do
	    *bufptr++ = *src++;
	  while (--srclen != 0);
	}
    }
示例#22
0
uint16_t picaso4d::integerwidth(int n) {
	char buffer[16];
	itoa(n, buffer, 10);
	return strwidth(buffer);
}
示例#23
0
文件: drawtext.c 项目: Bgods/r-source
static const char *get_next_line(char *line, int width, const char *s)
{
    const char *t; char  *k;
    int	word_width, line_width;
    int	sp, tab, nl;

    line_width  = 0;

    for (t=s, k=line; *t!='\0'; line=k, s=t)
    {
	for (nl=tab=sp=0; (*t!='\0') && isspace(*t) && !nl; t++)
	{
#if COMPRESS_WHITESPACE
	    if (*t == '\n') nl++;
	    else if (*t == '\t') tab++;
	    else sp++;
#else
	    if (*t == '\n') nl++;
	    else if (*t == '\t') { /* expand tabs */
		for (tab=4; tab; tab--)
		    *k++ = ' ';
	    }
	    else
		*k++ = *t;
#endif
	}

	s = t;

	if (nl)	{ *k++ = '\n'; break; }
	else if (tab)	{ *k++ = ' '; *k++ = ' '; }
	else if (sp)	{ *k++ = ' ';  }

	/* fetch the next word to draw */

	for (*k='\0'; (*t!='\0') && !isspace(*t); *k='\0') {
	    if (*t == '-') {
		*k++ = *t++;
		*k = '\0';
		break;
	    }
	    *k++ = *t++;
	}

	/* determine where the word should be drawn */

	while (((word_width = strwidth(current->fnt,line)) > width)
	       && (k>line))
	{
	    *(--k) = '\0';
	    --t;
	}

	if (word_width > (width - line_width)) {
	    k = line;
	    break;
	} else
	    line_width += word_width;
    }

    *k = '\0';

    return (*s == '\0') ? NULL : s;
}
示例#24
0
文件: doprnt.c 项目: oscarfv/emacs
int
doprnt (char *buffer, register int bufsize, const char *format,
        const char *format_end, va_list ap)
{
    const char *fmt = format;	/* Pointer into format string */
    register char *bufptr = buffer; /* Pointer into output buffer.. */

    /* Use this for sprintf unless we need something really big.  */
    char tembuf[DBL_MAX_10_EXP + 100];

    /* Size of sprintf_buffer.  */
    unsigned size_allocated = sizeof (tembuf);

    /* Buffer to use for sprintf.  Either tembuf or same as BIG_BUFFER.  */
    char *sprintf_buffer = tembuf;

    /* Buffer we have got with malloc.  */
    char *big_buffer = 0;

    register int tem;
    unsigned char *string;
    char fixed_buffer[20];	/* Default buffer for small formatting. */
    char *fmtcpy;
    int minlen;
    unsigned char charbuf[MAX_MULTIBYTE_LENGTH + 1];	/* Used for %c.  */

    if (format_end == 0)
        format_end = format + strlen (format);

    if ((format_end - format + 1) < sizeof (fixed_buffer))
        fmtcpy = fixed_buffer;
    else
        fmtcpy = (char *) alloca (format_end - format + 1);

    bufsize--;

    /* Loop until end of format string or buffer full. */
    while (fmt != format_end && bufsize > 0)
    {
        if (*fmt == '%')	/* Check for a '%' character */
        {
            unsigned size_bound = 0;
            int width;		/* Columns occupied by STRING.  */

            fmt++;
            /* Copy this one %-spec into fmtcpy.  */
            string = (unsigned char *) fmtcpy;
            *string++ = '%';
            while (1)
            {
                *string++ = *fmt;
                if ('0' <= *fmt && *fmt <= '9')
                {
                    /* Get an idea of how much space we might need.
                       This might be a field width or a precision; e.g.
                       %1.1000f and %1000.1f both might need 1000+ bytes.
                       Parse the width or precision, checking for overflow.  */
                    unsigned n = *fmt - '0';
                    while ('0' <= fmt[1] && fmt[1] <= '9')
                    {
                        if (n * 10 + fmt[1] - '0' < n)
                            error ("Format width or precision too large");
                        n = n * 10 + fmt[1] - '0';
                        *string++ = *++fmt;
                    }

                    if (size_bound < n)
                        size_bound = n;
                }
                else if (*fmt == '-' || *fmt == ' ' || *fmt == '.' || *fmt == '+')
                    ;
                else
                    break;
                fmt++;
            }
            *string = 0;

            /* Make the size bound large enough to handle floating point formats
               with large numbers.  */
            if (size_bound + DBL_MAX_10_EXP + 50 < size_bound)
                error ("Format width or precision too large");
            size_bound += DBL_MAX_10_EXP + 50;

            /* Make sure we have that much.  */
            if (size_bound > size_allocated)
            {
                if (big_buffer)
                    big_buffer = (char *) xrealloc (big_buffer, size_bound);
                else
                    big_buffer = (char *) xmalloc (size_bound);
                sprintf_buffer = big_buffer;
                size_allocated = size_bound;
            }
            minlen = 0;
            switch (*fmt++)
            {
            default:
                error ("Invalid format operation %%%c", fmt[-1]);

            /*	    case 'b': */
            case 'd':
            case 'o':
            case 'x':
                if (sizeof (int) == sizeof (EMACS_INT))
                    ;
                else if (sizeof (long) == sizeof (EMACS_INT))
                    /* Insert an `l' the right place.  */
                    string[1] = string[0],
                                string[0] = string[-1],
                                            string[-1] = 'l',
                                                         string++;
                else
                    abort ();
                sprintf (sprintf_buffer, fmtcpy, va_arg(ap, char *));
                /* Now copy into final output, truncating as nec.  */
                string = (unsigned char *) sprintf_buffer;
                goto doit;

            case 'f':
            case 'e':
            case 'g':
            {
                double d = va_arg(ap, double);
                sprintf (sprintf_buffer, fmtcpy, d);
                /* Now copy into final output, truncating as nec.  */
                string = (unsigned char *) sprintf_buffer;
                goto doit;
            }

            case 'S':
                string[-1] = 's';
            case 's':
                if (fmtcpy[1] != 's')
                    minlen = atoi (&fmtcpy[1]);
                string = va_arg(ap, unsigned char *);
                tem = strlen (string);
                width = strwidth (string, tem);
                goto doit1;

                /* Copy string into final output, truncating if no room.  */
doit:
                /* Coming here means STRING contains ASCII only.  */
                width = tem = strlen (string);
doit1:
                /* We have already calculated:
                TEM -- length of STRING,
                 WIDTH -- columns occupied by STRING when displayed, and
                 MINLEN -- minimum columns of the output.  */
                if (minlen > 0)
                {
                    while (minlen > width && bufsize > 0)
                    {
                        *bufptr++ = ' ';
                        bufsize--;
                        minlen--;
                    }
                    minlen = 0;
                }
                if (tem > bufsize)
                {
                    /* Truncate the string at character boundary.  */
                    tem = bufsize;
                    while (!CHAR_HEAD_P (string[tem - 1])) tem--;
                    memcpy (bufptr, string, tem);
                    /* We must calculate WIDTH again.  */
                    width = strwidth (bufptr, tem);
                }
                else
                    memcpy (bufptr, string, tem);
                bufptr += tem;
                bufsize -= tem;
                if (minlen < 0)
                {
                    while (minlen < - width && bufsize > 0)
                    {
                        *bufptr++ = ' ';
                        bufsize--;
                        minlen++;
                    }
                    minlen = 0;
                }
                continue;

            case 'c':
            {
                /* Sometimes for %c we pass a char, which would widen
                   to int.  Sometimes we pass XFASTINT() or XINT()
                   values, which would be EMACS_INT.  Let's hope that
                   both are passed the same way, otherwise we'll need
                   to rewrite callers.  */
                EMACS_INT chr = va_arg(ap, EMACS_INT);
                tem = CHAR_STRING ((int) chr, charbuf);
                string = charbuf;
                string[tem] = 0;
                width = strwidth (string, tem);
                if (fmtcpy[1] != 'c')
                    minlen = atoi (&fmtcpy[1]);
                goto doit1;
            }

            case '%':
                fmt--;    /* Drop thru and this % will be treated as normal */
            }
        }

        {
            /* Just some character; Copy it if the whole multi-byte form
               fit in the buffer.  */
            char *save_bufptr = bufptr;

            do {
                *bufptr++ = *fmt++;
            }
            while (--bufsize > 0 && !CHAR_HEAD_P (*fmt));
            if (!CHAR_HEAD_P (*fmt))
            {
                bufptr = save_bufptr;
                break;
            }
        }
    };
示例#25
0
/*
 * Display a dialog box with a list of options that can be turned on or off
 */
int
dialog_checklist(unsigned char *title, unsigned char *prompt, int height, int width,
		 int list_height, int cnt, void *it, unsigned char *result)
{
    int i, j, x, y, cur_x, cur_y, old_x, old_y, box_x, box_y, key = 0, button,
	choice, l, k, scroll, max_choice, item_no = 0, *status;
    int redraw_menu = FALSE, cursor_reset = FALSE;
    int rval = 0, onlist = 1, ok_space, cancel_space;
    char okButton, cancelButton;
    WINDOW *dialog, *list;
    unsigned char **items = NULL;
    dialogMenuItem *ditems;
    int list_width, check_x, item_x;

    /* Allocate space for storing item on/off status */
    if ((status = alloca(sizeof(int) * abs(cnt))) == NULL) {
	endwin();
	fprintf(stderr, "\nCan't allocate memory in dialog_checklist().\n");
	exit(-1);
    }
    
draw:
    choice = scroll = button = 0;
    /* Previous calling syntax, e.g. just a list of strings? */
    if (cnt >= 0) {
	items = it;
	ditems = NULL;
	item_no = cnt;
	/* Initializes status */
	for (i = 0; i < item_no; i++)
	    status[i] = !strcasecmp(items[i*3 + 2], "on");
    }
    /* It's the new specification format - fake the rest of the code out */
    else {
	item_no = abs(cnt);
	ditems = it;
	if (!items)
	    items = (unsigned char **)alloca((item_no * 3) * sizeof(unsigned char *));
	
	/* Initializes status */
	for (i = 0; i < item_no; i++) {
	    status[i] = ditems[i].checked ? ditems[i].checked(&ditems[i]) : FALSE;
	    items[i*3] = ditems[i].prompt;
	    items[i*3 + 1] = ditems[i].title;
	    items[i*3 + 2] = status[i] ? "on" : "off";
	}
    }
    max_choice = MIN(list_height, item_no);
    
    check_x = 0;
    item_x = 0;
    /* Find length of longest item in order to center checklist */
    for (i = 0; i < item_no; i++) {
	l = strlen(items[i*3]);
	for (j = 0; j < item_no; j++) {
	    k = strlen(items[j*3 + 1]);
	    check_x = MAX(check_x, l + k + 6);
	}
	item_x = MAX(item_x, l);
    }
    if (height < 0)
	height = strheight(prompt)+list_height+4+2;
    if (width < 0) {
	i = strwidth(prompt);
	j = ((title != NULL) ? strwidth(title) : 0);
	width = MAX(i,j);
	width = MAX(width,check_x+4)+4;
    }
    width = MAX(width,24);
    
    if (width > COLS)
	width = COLS;
    if (height > LINES)
	height = LINES;
    /* center dialog box on screen */
    x = (COLS - width)/2;
    y = (LINES - height)/2;

#ifdef HAVE_NCURSES
    if (use_shadow)
	draw_shadow(stdscr, y, x, height, width);
#endif
    dialog = newwin(height, width, y, x);
    if (dialog == NULL) {
	endwin();
	fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width, y, x);
	return -1;
    }
    keypad(dialog, TRUE);
    
    draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
    wattrset(dialog, border_attr);
    wmove(dialog, height-3, 0);
    waddch(dialog, ACS_LTEE);
    for (i = 0; i < width-2; i++)
	waddch(dialog, ACS_HLINE);
    wattrset(dialog, dialog_attr);
    waddch(dialog, ACS_RTEE);
    wmove(dialog, height-2, 1);
    for (i = 0; i < width-2; i++)
	waddch(dialog, ' ');
    
    if (title != NULL) {
	wattrset(dialog, title_attr);
	wmove(dialog, 0, (width - strlen(title))/2 - 1);
	waddch(dialog, ' ');
	waddstr(dialog, title);
	waddch(dialog, ' ');
    }
    wattrset(dialog, dialog_attr);
    wmove(dialog, 1, 2);
    print_autowrap(dialog, prompt, height - 1, width - 2, width, 1, 2, TRUE, FALSE);
    
    list_width = width - 6;
    getyx(dialog, cur_y, cur_x);
    box_y = cur_y + 1;
    box_x = (width - list_width) / 2 - 1;
    
    /* create new window for the list */
    list = subwin(dialog, list_height, list_width, y + box_y + 1, x + box_x + 1);
    if (list == NULL) {
	delwin(dialog);
	endwin();
	fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", list_height, list_width,
		y + box_y + 1, x + box_x + 1);
	return -1;
    }
    keypad(list, TRUE);
    
    /* draw a box around the list items */
    draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, menubox_border_attr, menubox_attr);
    
    check_x = (list_width - check_x) / 2;
    item_x = check_x + item_x + 6;
    
    /* Print the list */
    for (i = 0; i < max_choice; i++)
	print_item(list, items[i * 3], items[i * 3 + 1], status[i], i, i == choice, DREF(ditems, i), list_width, item_x, check_x);
    wnoutrefresh(list);
    print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
    
    display_helpline(dialog, height - 1, width);
    
    x = width / 2 - 11;
    y = height - 2;
    /* Is this a fancy new style argument string where we get to override
     * the buttons, or an old style one where they're fixed?
     */
    if (ditems && result) {
	cancelButton = toupper(ditems[CANCEL_BUTTON].prompt[0]);
	print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : FALSE);
	okButton = toupper(ditems[OK_BUTTON].prompt[0]);
	print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : TRUE);
    }
    else {
	cancelButton = 'C';
	print_button(dialog, "Cancel", y, x + 14, FALSE);
	okButton = 'O';
	print_button(dialog, "  OK  ", y, x, TRUE);
    }
    wnoutrefresh(dialog);
    wmove(list, choice, check_x+1);
    wrefresh(list);

    /*
     *	XXX Black magic voodoo that allows printing to the checklist
     *	window. For some reason, if this "refresh" code is not in
     *	place, printing to the window from the selected callback
     *	prints "behind" the checklist window. There is probably a
     *	better way to do this.
     */
    draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, menubox_border_attr, menubox_attr);

    for (i = 0; i < max_choice; i++)
	print_item(list, items[i * 3], items[i * 3 + 1], status[i], i, i == choice, DREF(ditems, i), list_width, item_x, check_x);
    print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);

    wmove(list, choice, check_x+1);
    wnoutrefresh(dialog);
    wrefresh(list);
    /* XXX Black magic XXX */
    
    while (key != ESC) {
	key = wgetch(dialog);
	
	/* Shortcut to OK? */
	if (toupper(key) == okButton) {
	    if (ditems) {
		if (result && ditems[OK_BUTTON].fire) {
		    int st;
		    WINDOW *save;

		    save = dupwin(newscr);
		    st = ditems[OK_BUTTON].fire(&ditems[OK_BUTTON]);
		    if (st & DITEM_RESTORE) {
			touchwin(save);
			wrefresh(save);
		    }
		    delwin(save);
		}
	    }
	    else if (result) {
		*result = '\0';
		for (i = 0; i < item_no; i++) {
		    if (status[i]) {
			strcat(result, items[i*3]);
			strcat(result, "\n");
		    }
		}
	    }
	    rval = 0;
	    key = ESC;	/* Lemme out! */
	    break;
	}

	/* Shortcut to cancel? */
	if (toupper(key) == cancelButton) {
	    if (ditems && result && ditems[CANCEL_BUTTON].fire) {
		int st;
		WINDOW *save;

		save = dupwin(newscr);
		st = ditems[CANCEL_BUTTON].fire(&ditems[CANCEL_BUTTON]);
		if (st & DITEM_RESTORE) {
		    touchwin(save);
		    wrefresh(save);
		    wmove(dialog, cur_y, cur_x);
		}
		delwin(save);
	    }
	    rval = 1;
	    key = ESC;	/* I gotta go! */
	    break;
	}
	
	/* Check if key pressed matches first character of any item tag in list */
	for (i = 0; i < max_choice; i++)
	    if (key != ' ' && key < 0x100 && toupper(key) == toupper(items[(scroll+i)*3][0]))
		break;

	if (i < max_choice || (key >= '1' && key <= MIN('9', '0'+max_choice)) ||
	    KEY_IS_UP(key) || KEY_IS_DOWN(key) || ((key == ' ' || key == '\n' ||
	    key == '\r') && onlist)) {

	    /* if moving from buttons to the list, reset and redraw buttons */
	    if (!onlist) {
		onlist = 1;
		button = 0;

	        if (ditems && result) {
		    print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button);
		    print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button);
		}
		else {
		    print_button(dialog, "Cancel", y, x + 14, button);
		    print_button(dialog, "  OK  ", y, x, !button);
		}
		wmove(list, choice, check_x+1);
		wnoutrefresh(dialog);
		wrefresh(list);
	    }

	    if (key >= '1' && key <= MIN('9', '0'+max_choice))
		i = key - '1';
	    
	    else if (KEY_IS_UP(key)) {
		if (!choice) {
		    if (scroll) {
			/* Scroll list down */
			getyx(dialog, cur_y, cur_x);    /* Save cursor position */
			if (list_height > 1) {
			    /* De-highlight current first item before scrolling down */
			    print_item(list, items[scroll * 3], items[scroll * 3 + 1], status[scroll], 0,
				       FALSE, DREF(ditems, scroll), list_width, item_x, check_x);
			    scrollok(list, TRUE);
			    wscrl(list, -1);
			    scrollok(list, FALSE);
			}
			scroll--;
			print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0,
				   TRUE, DREF(ditems, scroll), list_width, item_x, check_x);
			print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
			wmove(list, choice, check_x+1);
			wnoutrefresh(dialog);
			wrefresh(list);
		    }
		    continue;    /* wait for another key press */
		}
		else
		    i = choice - 1;
	    }
	    else if (KEY_IS_DOWN(key)) {
		if (choice == max_choice - 1) {
		    if (scroll + choice < item_no - 1) {
			/* Scroll list up */
			getyx(dialog, cur_y, cur_x);    /* Save cursor position */
			if (list_height > 1) {
			    /* De-highlight current last item before scrolling up */
			    print_item(list, items[(scroll + max_choice - 1) * 3],
				       items[(scroll + max_choice - 1) * 3 + 1],
				       status[scroll + max_choice - 1], max_choice - 1,
				       FALSE, DREF(ditems, scroll + max_choice - 1), list_width, item_x, check_x);
			    scrollok(list, TRUE);
			    scroll(list);
			    scrollok(list, FALSE);
			}
			scroll++;
			print_item(list, items[(scroll + max_choice - 1) * 3],
				   items[(scroll + max_choice - 1) * 3 + 1],
				   status[scroll + max_choice - 1], max_choice - 1, TRUE,
				   DREF(ditems, scroll + max_choice - 1), list_width, item_x, check_x);
			print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
			wmove(list, choice, check_x+1);
			wnoutrefresh(dialog);
			wrefresh(list);
		    }
		    continue;    /* wait for another key press */
		}
		else
		    i = choice + 1;
	    }
	    else if ((key == ' ' || key == '\n' || key == '\r') && onlist) {    /* Toggle item status */
		char lbra = 0, rbra = 0, mark = 0;

		getyx(list, old_y, old_x);    /* Save cursor position */
		
		if (ditems) {
		    if (ditems[scroll + choice].fire) {
			int st;
			WINDOW *save;

			save = dupwin(newscr);
			st = ditems[scroll + choice].fire(&ditems[scroll + choice]);	/* Call "fire" action */
			if (st & DITEM_RESTORE) {
			    touchwin(save);
			    wrefresh(save);
			}
			delwin(save);
			if (st & DITEM_REDRAW) {
			    wclear(list);
			    for (i = 0; i < item_no; i++)
				status[i] = ditems[i].checked ? ditems[i].checked(&ditems[i]) : FALSE;
			    for (i = 0; i < max_choice; i++) {
				print_item(list, items[(scroll + i) * 3], items[(scroll + i) * 3 + 1],
					   status[scroll + i], i, i == choice, DREF(ditems, scroll + i), list_width, item_x, check_x);
			    }
			    wnoutrefresh(list);
			    print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4,
					 cur_x, cur_y);
			    wrefresh(dialog);
			}
			if (st & DITEM_LEAVE_MENU) {
			    /* Allow a fire action to take us out of the menu */
			    key = ESC;
			    rval = 0;
			    break;
			}
			else if (st & DITEM_RECREATE) {
			    delwin(list);
			    delwin(dialog);
			    dialog_clear();
			    goto draw;
			}
		    }
		    status[scroll + choice] = ditems[scroll + choice].checked ?
			ditems[scroll + choice].checked(&ditems[scroll + choice]) : FALSE;
		    lbra = ditems[scroll + choice].lbra;
		    rbra = ditems[scroll + choice].rbra;
		    mark = ditems[scroll + choice].mark;
		}
		else
		    status[scroll + choice] = !status[scroll + choice];
		wmove(list, choice, check_x);
		wattrset(list, check_selected_attr);
		if (!lbra)
		    lbra = '[';
		if (!rbra)
		    rbra = ']';
		if (!mark)
		    mark = 'X';
		wprintw(list, "%c%c%c", lbra, status[scroll + choice] ? mark : ' ', rbra);
		wmove(list, old_y, old_x);  /* Restore cursor to previous position */
		wrefresh(list);
		continue;    /* wait for another key press */
	    }
	    
	    if (i != choice) {
		/* De-highlight current item */
		getyx(dialog, cur_y, cur_x);    /* Save cursor position */
		print_item(list, items[(scroll + choice) * 3], items[(scroll + choice) * 3 + 1],
			   status[scroll + choice], choice, FALSE, DREF(ditems, scroll + choice), list_width, item_x, check_x);
		
		/* Highlight new item */
		choice = i;
		print_item(list, items[(scroll + choice) * 3], items[(scroll + choice) * 3 + 1], status[scroll + choice], choice, TRUE, DREF(ditems, scroll + choice), list_width, item_x, check_x);
		wmove(list, choice, check_x+1);	  /* Restore cursor to previous position */
		wrefresh(list);
	    }
	    continue;    /* wait for another key press */
	}
	
	switch (key) {
	case KEY_PPAGE:	/* can we go up? */
	    if (scroll > height - 4)
		scroll -= (height-4);
	    else
		scroll = 0;
	    redraw_menu = TRUE;
	    if (!onlist) {
		onlist = 1;
		button = 0;
	    }
	    break;
	    
	case KEY_NPAGE:      /* can we go down a full page? */
	    if (scroll + list_height >= item_no-1 - list_height) {
		scroll = item_no - list_height;
		if (scroll < 0)
		    scroll = 0;
	    }
	    else
		scroll += list_height;
	    redraw_menu = TRUE;
	    if (!onlist) {
 		onlist = 1;
		button = 0;
	    }
	    break;
	    
	case KEY_HOME:      /* go to the top */
	    scroll = 0;
	    choice = 0;
	    redraw_menu = TRUE;
	    cursor_reset = TRUE;
	    onlist = 1;
	    break;
	    
	case KEY_END:      /* Go to the bottom */
	    scroll = item_no - list_height;
	    if (scroll < 0)
		scroll = 0;
	    choice = max_choice - 1;
	    redraw_menu = TRUE;
	    cursor_reset = TRUE;
	    onlist = 1;
	    break;
	    
	case TAB:
	case KEY_BTAB:
	    /* move to next component */
	    if (onlist) {       /* on list, next is ok button */
		onlist = 0;
		if (ditems && result) {
		    print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button);
		    print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button);
		    ok_space = 1;
		    cancel_space = strlen(ditems[OK_BUTTON].prompt) + 6;
		}
		else {
		    print_button(dialog, "Cancel", y, x + 14, button);
		    print_button(dialog, "  OK  ", y, x, !button);
		    ok_space = 3;
		    cancel_space = 15;
		}
		if (button)
		    wmove(dialog, y, x + cancel_space);
		else
		    wmove(dialog, y, x + ok_space);
		wrefresh(dialog);
		break;
	    }
	    else if (button) {     /* on cancel button, next is list */
		button = 0;
		onlist = 1;
		redraw_menu = TRUE;
		break; 
	    }
	    /* on ok button, next is cancel button, same as left/right case */

	case KEY_LEFT:
	case KEY_RIGHT:
	    onlist = 0;
	    button = !button;
	    if (ditems && result) {
		print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button);
		print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ?  ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button);
		ok_space = 1;
		cancel_space = strlen(ditems[OK_BUTTON].prompt) + 6;
	    }
	    else {
		print_button(dialog, "Cancel", y, x + 14, button);
		print_button(dialog, "  OK  ", y, x, !button);
		ok_space = 3;
		cancel_space = 15;
	    }
	    if (button)
		wmove(dialog, y, x + cancel_space);
	    else
		wmove(dialog, y, x + ok_space);
	    wrefresh(dialog);
	    break;

	case ' ':
	case '\n':
	case '\r':
	    if (!onlist) {
		if (ditems) {
		    if (result && ditems[button ? CANCEL_BUTTON : OK_BUTTON].fire) {
			int st;
			WINDOW *save = dupwin(newscr);

			st = ditems[button ? CANCEL_BUTTON : OK_BUTTON].fire(&ditems[button ? CANCEL_BUTTON : OK_BUTTON]);
			if (st & DITEM_RESTORE) {
			    touchwin(save);
			    wrefresh(save);
			}
			delwin(save);
			if (st == DITEM_FAILURE)
			continue;
		    }
		}
		else if (result) {
		    *result = '\0';
		    for (i = 0; i < item_no; i++) {
			if (status[i]) {
			    strcat(result, items[i*3]);
			    strcat(result, "\n");
			}
		    }
		}
		rval = button;
		key = ESC;	/* Bail out! */
		break;
	    }
	    
	    /* Let me outta here! */
	case ESC:
	    rval = -1;
	    break;
	    
	    /* Help! */
	case KEY_F(1):
	case '?':
	    display_helpfile();
	    break;
	}
	
	if (redraw_menu) {
	    getyx(list, old_y, old_x);
	    wclear(list);

    	    /*
	     * Re-draw a box around the list items.  It is required
	     * if amount of list items is smaller than height of listbox.
	     * Otherwise un-redrawn field will be filled with default
	     * screen attributes instead of dialog attributes.
	     */
	    draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, menubox_border_attr, menubox_attr);

	    for (i = 0; i < max_choice; i++)
		print_item(list, items[(scroll + i) * 3], items[(scroll + i) * 3 + 1], status[scroll + i], i, i == choice, DREF(ditems, scroll + i), list_width, item_x, check_x);
	    print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);

	    /* redraw buttons to fix highlighting */
	    if (ditems && result) {
		print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button);
		print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button);
	    }
	    else {
		print_button(dialog, "Cancel", y, x + 14, button);
		print_button(dialog, "  OK  ", y, x, !button);
	    }
	    wnoutrefresh(dialog);
	    if (cursor_reset) {
		wmove(list, choice, check_x+1);
		cursor_reset = FALSE;
	    }
	    else {
		wmove(list, old_y, old_x);
	    }
	    wrefresh(list);
	    redraw_menu = FALSE;
	}
    }
    delwin(list);
    delwin(dialog);
    return rval;
}
static void 
_dxf_DRAW_GNOMON (tdmInteractor I, void *udata, float rot[4][4], int draw)
{
  /*
   *  draw == 1 to draw gnomon, draw == 0 to undraw.  This is done with
   *  two separate calls in order to support explicit erasure of edges for
   *  some implementations.  A draw is always preceded by an undraw and
   *  the pair of invocations is atomic.
   *
   *  Computations are done in normalized screen coordinates in order to
   *  render arrow heads correctly.
   */

  DEFDATA(I,tdmRotateData) ;
  DEFPORT(I_PORT_HANDLE) ;
  int dummy = 0 ;
  float origin[2] ;
  float xaxis[2],  yaxis[2],  zaxis[2] ;
  float xlabel[2], ylabel[2], zlabel[2] ;

  ENTRY(("_dxf_DRAW_GNOMON (0x%x, 0x%x, 0x%x, %d)",I, udata, rot, draw));

  if (PDATA(font) == -1)
    {
      /* font width for axes labels in normalized coordinates */
      font(0) ;
      PDATA(font) = 0 ;
      PDATA(swidth) = (float)strwidth("Z")/(float)GNOMONRADIUS ;

      /* 1 pixel in normalized coordinates */
      PDATA(nudge) = 1.0/(float)GNOMONRADIUS ;
    }
  else
      font(PDATA(font)) ;
  
  if (draw)
    {
      lmcolor(LMC_COLOR) ;
      cpack(0xffffffff) ;
      linewidth(1) ;
    }
  else
    {
      if (PDATA(redrawmode) != tdmViewEchoMode)
	{
	  /*
	   *  In tdmViewEchoMode (DX's Execute On Change), we are drawing
	   *  the gnomon echo on top of a background image that is redrawn
	   *  with every frame of a direct interaction.
	   *
	   *  If we're not in that mode, the background image is static
	   *  while the gnomon echo rotates in front of it, so erasing the
	   *  gnomon means we have to repair damage to the background.  We
	   *  do this by blitting a portion of the static image to the
	   *  back buffer, drawing the gnomon over that, then blitting the
	   *  combined results back to the front buffer.
	   */
	  
	  /* force graphics output into back buffer */
	  frontbuffer(FALSE) ;
	  backbuffer(TRUE) ;
	  
	  /* erase gnomon background */
	  lrectwrite (PDATA(illx), PDATA(illy),
		      PDATA(iurx), PDATA(iury), PDATA(background)) ;
	}

#ifndef NOSHADOW      
      /* draw wide black lines to ensure visibility against background */
      lmcolor(LMC_COLOR) ;
      cpack(0x0) ;
      linewidth(2) ;
#else
      EXIT(("No shadow"));
      return ;
#endif
    }

  origin[0] = 0 ;
  origin[1] = 0 ;

  xaxis[0] = 0.7 * rot[0][0] ; xaxis[1] = 0.7 * rot[0][1] ;
  yaxis[0] = 0.7 * rot[1][0] ; yaxis[1] = 0.7 * rot[1][1] ;
  zaxis[0] = 0.7 * rot[2][0] ; zaxis[1] = 0.7 * rot[2][1] ;

  xlabel[0] = 0.8 * rot[0][0] ; xlabel[1] = 0.8 * rot[0][1] ;
  ylabel[0] = 0.8 * rot[1][0] ; ylabel[1] = 0.8 * rot[1][1] ;
  zlabel[0] = 0.8 * rot[2][0] ; zlabel[1] = 0.8 * rot[2][1] ;

  pushmatrix() ;
  loadmatrix(identity) ;
  bgnline() ; v2f(origin) ; v2f(xaxis) ; endline() ;
  _dxf_DRAW_ARROWHEAD(PORT_CTX, xaxis[0], xaxis[1]) ;

  bgnline() ; v2f(origin) ; v2f(yaxis) ; endline() ;
  _dxf_DRAW_ARROWHEAD(PORT_CTX, yaxis[0], yaxis[1]) ;

  bgnline() ; v2f(origin) ; v2f(zaxis) ; endline() ;
  _dxf_DRAW_ARROWHEAD(PORT_CTX, zaxis[0], zaxis[1]) ;
  
  if (xlabel[0] <= 0) xlabel[0] -= PDATA(swidth) ;
  if (xlabel[1] <= 0) xlabel[1] -= PDATA(swidth) ;
  
  if (ylabel[0] <= 0) ylabel[0] -= PDATA(swidth) ;
  if (ylabel[1] <= 0) ylabel[1] -= PDATA(swidth) ;
  
  if (zlabel[0] <= 0) zlabel[0] -= PDATA(swidth) ;
  if (zlabel[1] <= 0) zlabel[1] -= PDATA(swidth) ;

#ifndef NOSHADOW  
  if (!draw)
    {
      /* offset text slightly for shadow */
      xlabel[0] += PDATA(nudge) ; xlabel[1] -= PDATA(nudge) ;
      ylabel[0] += PDATA(nudge) ; ylabel[1] -= PDATA(nudge) ;
      zlabel[0] += PDATA(nudge) ; zlabel[1] -= PDATA(nudge) ;
    }
#endif

  font(0) ;
  cmov2 (xlabel[0], xlabel[1]) ;
  charstr ("X") ;
  cmov2 (ylabel[0], ylabel[1]) ;
  charstr ("Y") ;
  cmov2 (zlabel[0], zlabel[1]) ;
  charstr ("Z") ;

  popmatrix() ;

  if (draw && PDATA(redrawmode) != tdmViewEchoMode)
    {
      /* copy rendered gnomon from back buffer to front buffer */
      readsource(SRC_BACK) ;
      frontbuffer(TRUE) ;
      backbuffer(FALSE) ;
      rectcopy (PDATA(illx), PDATA(illy), PDATA(iurx), PDATA(iury),
		PDATA(illx), PDATA(illy)) ;

      /* restore original buffer config from current tdmFrontBufferDraw */
      _dxf_BUFFER_RESTORE_CONFIG
	  (PORT_CTX, dummy, PDATA(buffermode), tdmFrontBufferDraw) ;
    }

  EXIT((""));
}