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; }
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; }
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); }
long charwidth(XftFont *f, Rune r) { char chars[UTFmax + 1] = {0}; runetochar(chars, &r); return strwidth(f, chars); }
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; }
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); }
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); }
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); }
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; }
/* * 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; }
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; }
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; }
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; } }
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; }
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); } }
/* * 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)); }
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(); }
/* 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); }
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; }
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; }
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); } }
uint16_t picaso4d::integerwidth(int n) { char buffer[16]; itoa(n, buffer, 10); return strwidth(buffer); }
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; }
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; } } };
/* * 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(("")); }