/* * scroll -- * Scroll the window up a line. */ int scroll(WINDOW *win) { register int oy, ox; #ifdef DEBUG __CTRACE("scroll: (%0.2o)\n", win); #endif if (!(win->flags & __SCROLLOK)) return (ERR); getyx(win, oy, ox); wmove(win, 0, 0); wdeleteln(win); wmove(win, oy, ox); if (win == curscr) { putchar('\n'); if (!NONL) win->curx = 0; #ifdef DEBUG __CTRACE("scroll: win == curscr\n"); #endif } return (OK); }
/* * Restore the WINCH handler. */ void __restore_winchhandler(void) { #ifdef DEBUG __CTRACE(__CTRACE_MISC, "__restore_winchhandler: %d\n", winch_set); #endif if (winch_set > 0) { struct sigaction cwsa; sigaction(SIGWINCH, NULL, &cwsa); if (cwsa.sa_handler == owsa.sa_handler) { sigaction(SIGWINCH, &owsa, NULL); winch_set = 0; } else { /* * We're now using the programs WINCH handler, * so don't restore the previous one. */ winch_set = -1; #ifdef DEBUG __CTRACE(__CTRACE_MISC, "cwsa.sa_handler = %p\n", cwsa.sa_handler); #endif } } }
/* * waddch -- * Add the character to the current position in the given window. * */ int waddch(WINDOW *win, chtype ch) { #ifdef HAVE_WCHAR cchar_t cc; #else __LDATA buf; #endif #ifdef HAVE_WCHAR __cursesi_chtype_to_cchar(ch, &cc); #else buf.ch = (wchar_t) ch & __CHARTEXT; buf.attr = (attr_t) ch & __ATTRIBUTES; #endif #ifdef DEBUG #ifdef HAVE_WCHAR __CTRACE(__CTRACE_INPUT, "addch: %d : 0x%x (adding char as wide char)\n", cc.vals[0], cc.attributes); #else __CTRACE(__CTRACE_INPUT, "addch: %d : 0x%x\n", buf.ch, buf.attr); #endif #endif #ifdef HAVE_WCHAR return (wadd_wch(win, &cc)); #else return (__waddch(win, &buf)); #endif }
int __touchline(WINDOW *win, int y, int sx, int ex, int force) { #ifdef DEBUG __CTRACE("touchline: (%0.2o, %d, %d, %d, %d)\n", win, y, sx, ex, force); __CTRACE("touchline: first = %d, last = %d\n", *win->lines[y]->firstchp, *win->lines[y]->lastchp); #endif if (force) win->lines[y]->flags |= __FORCEPAINT; sx += win->ch_off; ex += win->ch_off; if (!(win->lines[y]->flags & __ISDIRTY)) { win->lines[y]->flags |= __ISDIRTY; *win->lines[y]->firstchp = sx; *win->lines[y]->lastchp = ex; } else { if (*win->lines[y]->firstchp > sx) *win->lines[y]->firstchp = sx; if (*win->lines[y]->lastchp < ex) *win->lines[y]->lastchp = ex; } #ifdef DEBUG __CTRACE("touchline: first = %d, last = %d\n", *win->lines[y]->firstchp, *win->lines[y]->lastchp); #endif return (OK); }
/* * touchoverlap -- * Touch, on win2, the part that overlaps with win1. */ int touchoverlap(WINDOW *win1, WINDOW *win2) { int y, endy, endx, starty, startx; #ifdef DEBUG __CTRACE(__CTRACE_WINDOW, "touchoverlap: (%p, %p);\n", win1, win2); #endif starty = max(win1->begy, win2->begy); startx = max(win1->begx, win2->begx); endy = min(win1->maxy + win1->begy, win2->maxy + win2->begy); endx = min(win1->maxx + win1->begx, win2->maxx + win2->begx); #ifdef DEBUG __CTRACE(__CTRACE_WINDOW, "touchoverlap: from (%d,%d) to (%d,%d)\n", starty, startx, endy, endx); __CTRACE(__CTRACE_WINDOW, "touchoverlap: win1 (%d,%d) to (%d,%d)\n", win1->begy, win1->begx, win1->begy + win1->maxy, win1->begx + win1->maxx); __CTRACE(__CTRACE_WINDOW, "touchoverlap: win2 (%d,%d) to (%d,%d)\n", win2->begy, win2->begx, win2->begy + win2->maxy, win2->begx + win2->maxx); #endif if (starty >= endy || startx >= endx) return (OK); starty -= win2->begy; startx -= win2->begx; endy -= win2->begy; endx -= win2->begx; for (--endx, y = starty; y < endy; y++) __touchline(win2, y, startx, endx); return (OK); }
/* * initscr -- * Initialize the current and standard screen. */ WINDOW * initscr() { register char *sp; #ifdef DEBUG __CTRACE("initscr\n"); #endif __echoit = 1; __pfast = __rawmode = __noqch = 0; if (gettmode() == ERR) return (NULL); /* * If My_term is set, or can't find a terminal in the environment, * use Def_term. */ if (My_term || (sp = getenv("TERM")) == NULL) sp = Def_term; if (setterm(sp) == ERR) return (NULL); /* Need either homing or cursor motion for refreshes */ if (!HO && !CM) return (NULL); if (curscr != NULL) delwin(curscr); if ((curscr = newwin(LINES, COLS, 0, 0)) == ERR) return (NULL); clearok(curscr, 1); if (stdscr != NULL) delwin(stdscr); if ((stdscr = newwin(LINES, COLS, 0, 0)) == ERR) { delwin(curscr); return (NULL); } __set_stophandler(); #ifdef DEBUG __CTRACE("initscr: LINES = %d, COLS = %d\n", LINES, COLS); #endif __startwin(); return (stdscr); }
/* * wredrawln -- * Mark count lines starting at start as corrupted. Implemented using * wtouchln(). */ int wredrawln(WINDOW *win, int start, int count) { #ifdef DEBUG __CTRACE(__CTRACE_LINE, "wredrawln: (%p, %d, %d)\n", win, start, count); #endif return wtouchln(win, start, count, 1); }
/* * wtouchln -- * If changed is 1 then touch n lines starting at line. If changed * is 0 then mark the lines as unchanged. */ int wtouchln(WINDOW *win, int line, int n, int changed) { int y; __LINE *wlp; #ifdef DEBUG __CTRACE(__CTRACE_LINE, "wtouchln: (%p) %d, %d, %d\n", win, line, n, changed); #endif if (line + n > win->maxy) line = win->maxy - n; for (y = line; y < line + n; y++) { if (changed == 1) __touchline(win, y, 0, (int) win->maxx - 1); else { wlp = win->alines[y]; if (*wlp->firstchp >= win->ch_off && *wlp->firstchp < win->maxx + win->ch_off) *wlp->firstchp = win->maxx + win->ch_off; if (*wlp->lastchp >= win->ch_off && *wlp->lastchp < win->maxx + win->ch_off) *wlp->lastchp = win->ch_off; wlp->flags &= ~__ISDIRTY; } } return OK; }
/* * wbkgd -- * Set new background and new background attributes. */ int wbkgd(WINDOW *win, chtype ch) { int y, x; #ifdef DEBUG __CTRACE(__CTRACE_ATTR, "wbkgd: (%p), '%s', %08x\n", win, unctrl(ch & +__CHARTEXT), ch & __ATTRIBUTES); #endif /* Background attributes (check colour). */ if (__using_color && !(ch & __COLOR)) ch |= __default_color; win->battr = (attr_t) ch & __ATTRIBUTES; wbkgdset(win, ch); for (y = 0; y < win->maxy; y++) for (x = 0; x < win->maxx; x++) { /* Copy character if space */ if (ch & A_CHARTEXT && win->alines[y]->line[x].ch == ' ') win->alines[y]->line[x].ch = ch & __CHARTEXT; /* Merge attributes */ if (win->alines[y]->line[x].attr & __ALTCHARSET) win->alines[y]->line[x].attr = (ch & __ATTRIBUTES) | __ALTCHARSET; else win->alines[y]->line[x].attr = ch & __ATTRIBUTES; #ifdef HAVE_WCHAR SET_WCOL(win->alines[y]->line[x], 1); #endif } __touchwin(win); return(OK); }
int wbkgrnd(WINDOW *win, const cchar_t *wch) { #ifndef HAVE_WCHAR return ERR; #else /* int y, x, i; */ attr_t battr; /* nschar_t *np, *tnp, *pnp; */ #ifdef DEBUG __CTRACE(__CTRACE_ATTR, "wbkgrnd: (%p), '%s', %x\n", win, (const char *) wunctrl(wch), wch->attributes); #endif /* ignore multi-column characters */ if ( !wch->elements || wcwidth( wch->vals[ 0 ]) > 1 ) return ERR; /* Background attributes (check colour). */ battr = wch->attributes & WA_ATTRIBUTES; if (__using_color && !( battr & __COLOR)) battr |= __default_color; win->battr = battr; wbkgrndset(win, wch); __touchwin(win); return OK; #endif /* HAVE_WCHAR */ }
/* * waddnstr -- * Add a string (at most n characters) to the given window * starting at (_cury, _curx). If n is negative, add the * entire string. */ int waddnstr(WINDOW *win, const char *s, int n) { size_t len; const char *p; #ifdef DEBUG __CTRACE(__CTRACE_INPUT, "ADDNSTR: win %p, length %d\n", win, n); #endif /* * behavior changed from traditional BSD curses, for better XCURSES * conformance. * * BSD curses: if (n > 0) then "at most n", else "len = strlen(s)" * ncurses: if (n >= 0) then "at most n", else "len = strlen(s)" * XCURSES: if (n != -1) then "at most n", else "len = strlen(s)" * */ if (n >= 0) for (p = s, len = 0; n-- && *p++; ++len); else len = strlen(s); return(waddbytes(win, s, (int) len)); }
/* * winsertln -- * Do an insert-line on the window, leaving (cury, curx) unchanged. */ int winsertln(WINDOW *win) { register int y, i; register __LINE *temp; #ifdef DEBUG __CTRACE("insertln: (%0.2o)\n", win); #endif if (win->orig == NULL) temp = win->lines[win->maxy - 1]; for (y = win->maxy - 1; y > (int) win->cury; --y) { win->lines[y]->flags &= ~__ISPASTEOL; win->lines[y - 1]->flags &= ~__ISPASTEOL; if (win->orig == NULL) win->lines[y] = win->lines[y - 1]; else (void)memcpy(win->lines[y]->line, win->lines[y - 1]->line, win->maxx * __LDATASIZE); __touchline(win, y, 0, win->maxx - 1, 0); } if (win->orig == NULL) win->lines[y] = temp; else temp = win->lines[y]; for(i = 0; i < win->maxx; i++) { temp->line[i].ch = ' '; temp->line[i].attr = 0; } __touchline(win, y, 0, win->maxx - 1, 0); if (win->orig == NULL) __id_subwins(win); return (OK); }
/* * __unget -- * Do the work for ungetch() and unget_wch(); */ int __unget(wint_t c) { wchar_t *p; int len; #ifdef DEBUG __CTRACE(__CTRACE_INPUT, "__unget(%x)\n", c); #endif if (_cursesi_screen->unget_pos >= _cursesi_screen->unget_len) { len = _cursesi_screen->unget_len + 32; if ((p = realloc(_cursesi_screen->unget_list, sizeof(wchar_t) * len)) == NULL) { /* Can't realloc(), so just lose the oldest entry */ memmove(_cursesi_screen->unget_list, _cursesi_screen->unget_list + sizeof(wchar_t), _cursesi_screen->unget_len - 1); _cursesi_screen->unget_list[_cursesi_screen->unget_len - 1] = c; _cursesi_screen->unget_pos = _cursesi_screen->unget_len; return OK; } else { _cursesi_screen->unget_pos = _cursesi_screen->unget_len; _cursesi_screen->unget_len = len; _cursesi_screen->unget_list = p; } } _cursesi_screen->unget_list[_cursesi_screen->unget_pos] = c; _cursesi_screen->unget_pos++; return OK; }
/* * resizeterm -- * Resize the terminal window, resizing the dependent windows. */ int resizeterm(int nlines, int ncols) { WINDOW *win; struct __winlist *list; #ifdef DEBUG __CTRACE(__CTRACE_WINDOW, "resizeterm: (%d, %d)\n", nlines, ncols); #endif if (__resizeterm(curscr, nlines, ncols) == ERR) return ERR; if (__resizeterm(__virtscr, nlines, ncols) == ERR) return ERR; if (__resizeterm(stdscr, nlines, ncols) == ERR) return ERR; LINES = nlines; COLS = ncols; /* tweak the flags now that we have updated the LINES and COLS */ for (list = _cursesi_screen->winlistp; list != NULL; list = list->nextp) { win = list->winp; if (!(win->flags & __ISPAD)) __swflags(win); } wrefresh(curscr); return OK; }
int __timeout(int delay) { #ifdef DEBUG __CTRACE(__CTRACE_MISC, "__timeout()\n"); #endif /* Check if we need to restart ... */ if (_cursesi_screen->endwin) __restartwin(); if (_cursesi_screen->notty == TRUE) return OK; _cursesi_screen->ovmin = _cursesi_screen->cbreakt.c_cc[VMIN]; _cursesi_screen->ovtime = _cursesi_screen->cbreakt.c_cc[VTIME]; _cursesi_screen->rawt.c_cc[VMIN] = 0; _cursesi_screen->rawt.c_cc[VTIME] = delay; _cursesi_screen->cbreakt.c_cc[VMIN] = 0; _cursesi_screen->cbreakt.c_cc[VTIME] = delay; _cursesi_screen->baset.c_cc[VMIN] = 0; _cursesi_screen->baset.c_cc[VTIME] = delay; if (tcsetattr(fileno(_cursesi_screen->infd), __tcaction ? TCSASOFT | TCSANOW : TCSANOW, _cursesi_screen->curt)) { __restore_termios(); return ERR; } return OK; }
int nonl(void) { #ifdef DEBUG __CTRACE(__CTRACE_MISC, "nonl()\n"); #endif /* Check if we need to restart ... */ if (_cursesi_screen->endwin) __restartwin(); if (_cursesi_screen->notty == TRUE) return OK; _cursesi_screen->rawt.c_iflag &= ~ICRNL; _cursesi_screen->rawt.c_oflag &= ~ONLCR; _cursesi_screen->cbreakt.c_iflag &= ~ICRNL; _cursesi_screen->cbreakt.c_oflag &= ~ONLCR; _cursesi_screen->baset.c_iflag &= ~ICRNL; _cursesi_screen->baset.c_oflag &= ~ONLCR; _cursesi_screen->nl = 0; __pfast = 1; return (tcsetattr(fileno(_cursesi_screen->infd), __tcaction ? TCSASOFT | TCSADRAIN : TCSADRAIN, _cursesi_screen->curt) ? ERR : OK); }
int __nodelay(void) { #ifdef DEBUG __CTRACE(__CTRACE_MISC, "__nodelay()\n"); #endif /* Check if we need to restart ... */ if (_cursesi_screen->endwin) __restartwin(); if (_cursesi_screen->notty == TRUE) return OK; _cursesi_screen->rawt.c_cc[VMIN] = 0; _cursesi_screen->rawt.c_cc[VTIME] = 0; _cursesi_screen->cbreakt.c_cc[VMIN] = 0; _cursesi_screen->cbreakt.c_cc[VTIME] = 0; _cursesi_screen->baset.c_cc[VMIN] = 0; _cursesi_screen->baset.c_cc[VTIME] = 0; if (tcsetattr(fileno(_cursesi_screen->infd), TCSASOFT | TCSANOW, _cursesi_screen->curt)) { __restore_termios(); return ERR; } return OK; }
/* * nocbreak -- * Disable cbreak mode */ int nocbreak(void) { #ifdef DEBUG __CTRACE(__CTRACE_MISC, "nocbreak()\n"); #endif /* Check if we need to restart ... */ if (_cursesi_screen->endwin) __restartwin(); __rawmode = 0; if (_cursesi_screen->notty == TRUE) return OK; /* if we were in halfdelay mode then nuke the timeout */ if ((_cursesi_screen->half_delay == TRUE) && (__notimeout() == ERR)) return ERR; _cursesi_screen->half_delay = FALSE; _cursesi_screen->curt = _cursesi_screen->useraw ? &_cursesi_screen->rawt : &_cursesi_screen->baset; return (tcsetattr(fileno(_cursesi_screen->infd), __tcaction ? TCSASOFT | TCSADRAIN : TCSADRAIN, _cursesi_screen->curt) ? ERR : OK); }
/* * Delete the given key symbol from the key mappings for the screen. * */ void delete_key_sequence(keymap_t *current, int key_type) { key_entry_t *key; int i; /* * we need to iterate over all the keys as there may be * multiple instances of the leaf symbol. */ for (i = 0; i < MAX_CHAR; i++) { if (current->mapping[i] < 0) continue; /* no mapping for the key, next! */ key = current->key[current->mapping[i]]; if (key->type == KEYMAP_MULTI) { /* have not found the leaf, recurse down */ delete_key_sequence(key->value.next, key_type); /* if we deleted the last key in the map, free */ if (key->value.next->count == 0) _cursesi_free_keymap(key->value.next); } else if ((key->type == KEYMAP_LEAF) && (key->value.symbol == key_type)) { #ifdef DEBUG __CTRACE(__CTRACE_INPUT, "delete_key_sequence: found keysym %d, deleting\n", key_type); #endif key->enable = FALSE; } } }
/* * waddnstr -- * Add a string (at most n characters) to the given window * starting at (_cury, _curx). If n is negative, add the * entire string. */ int waddnstr(WINDOW *win, const char *s, int n) { size_t len; const char *p; #ifdef DEBUG __CTRACE(__CTRACE_INPUT, "ADDNSTR: win %p, length %d\n", win, n); #endif /* * behavior changed from traditional BSD curses, for better XCURSES * conformance. * * BSD curses: if (n > 0) then "at most n", else "len = strlen(s)" * ncurses: if (n >= 0) then "at most n", else "len = strlen(s)" * XCURSES: if (n != -1) then "at most n", else "len = strlen(s)" * * Also SUSv2 says these functions do not wrap nor change the * cursor position. */ if (n >= 0) for (p = s, len = 0; n-- && *p++; ++len); else len = strlen(s); if (len > (win->maxx - win->curx)) len = win->maxx - win->curx; return(waddbytes(win, s, (int) len)); }
/* * flash * Flash the terminal screen */ int flash(void) { if (flash_screen != NULL) { #ifdef DEBUG __CTRACE(__CTRACE_MISC, "flash: vb\n"); #endif tputs(flash_screen, 0, __cputchar); } else if (bell != NULL) { #ifdef DEBUG __CTRACE(__CTRACE_MISC, "flash: bl\n"); #endif tputs(bell, 0, __cputchar); } return (1); }
/* * redrawwin -- * Mark entire window as corrupted. Implemented using wtouchln(). */ int redrawwin(WINDOW *win) { #ifdef DEBUG __CTRACE(__CTRACE_LINE, "redrawwin: (%p)\n", win); #endif return wtouchln(win, 0, win->maxy, 1); }
int endwin(void) { #ifdef DEBUG __CTRACE(__CTRACE_MISC, "endwin\n"); #endif return __stopwin(); }
/* * Init_getch - initialise all the pointers & structures needed to make * getch work in keypad mode. * */ void __init_getch(SCREEN *screen) { char entry[1024], *p; const char *s; int i; size_t limit, l; #ifdef DEBUG int k, length; #endif /* init the inkey state variable */ state = INKEY_NORM; /* init the base keymap */ screen->base_keymap = new_keymap(); /* key input buffer pointers */ start = end = working = 0; /* now do the terminfo snarfing ... */ for (i = 0; i < num_tcs; i++) { p = entry; limit = 1023; s = screen->term->strs[tc[i].code]; if (s == NULL) continue; l = strlen(s) + 1; if (limit < l) continue; strlcpy(p, s, limit); p += l; limit -= l; #ifdef DEBUG __CTRACE(__CTRACE_INIT, "Processing terminfo entry %d, sequence ", tc[i].code); length = (int) strlen(entry); for (k = 0; k <= length -1; k++) __CTRACE(__CTRACE_INIT, "%s", unctrl(entry[k])); __CTRACE(__CTRACE_INIT, "\n"); #endif add_key_sequence(screen, entry, tc[i].symbol); } }
/* * untouchwin -- * Make it look like the window has not been changed. */ int untouchwin(WINDOW *win) { #ifdef DEBUG __CTRACE(__CTRACE_LINE, "untouchwin: (%p)\n", win); #endif return wtouchln(win, 0, win->maxy, 0); }
/* * waddchnstr -- * Add a string (at most n characters) to the given window * starting at (_cury, _curx) until the end of line is reached or * n characters have been added. If n is negative, add as much * of the string that will fit on the current line. SUSv2 says * that the addchnstr family does not wrap and strings are truncated * to the RHS of the window. */ int waddchnstr(WINDOW *win, const chtype *chstr, int n) { size_t len; const chtype *chp; attr_t attr; char *ocp, *cp, *start; int i, ret, ox, oy; #ifdef DEBUG __CTRACE(__CTRACE_INPUT, "waddchnstr: win = %p, chstr = %p, n = %d\n", win, chstr, n); #endif if (n >= 0) for (chp = chstr, len = 0; n-- && *chp++; ++len); else for (chp = chstr, len = 0; *chp++; ++len); /* check if string is too long for current location */ if (len > (win->maxx - win->curx)) len = win->maxx - win->curx; if ((ocp = malloc(len + 1)) == NULL) return ERR; chp = chstr; cp = ocp; start = ocp; i = 0; attr = (*chp) & __ATTRIBUTES; ox = win->curx; oy = win->cury; while (len) { *cp = (*chp) & __CHARTEXT; cp++; chp++; i++; len--; if (((*chp) & __ATTRIBUTES) != attr) { *cp = '\0'; if (_cursesi_waddbytes(win, start, i, attr, 0) == ERR) { free(ocp); return ERR; } attr = (*chp) & __ATTRIBUTES; start = cp; i = 0; } } *cp = '\0'; ret = _cursesi_waddbytes(win, start, i, attr, 0); free(ocp); wmove(win, oy, ox); return ret; }
/* * Restore the TSTP handler. */ void __restore_stophandler(void) { #ifdef DEBUG __CTRACE(__CTRACE_MISC, "__restore_stophandler: %d\n", tstp_set); #endif if (tstp_set) { (void) signal(SIGTSTP, otstpfn); tstp_set = 0; } }
/* * Set the TSTP handler. */ void __set_stophandler(void) { #ifdef DEBUG __CTRACE(__CTRACE_MISC, "__set_stophandler: %d\n", tstp_set); #endif if (!tstp_set) { otstpfn = signal(SIGTSTP, __stop_signal_handler); tstp_set = 1; } }
/* * wunderend -- * Exit underscore mode. */ int wunderend(WINDOW *win) { if (exit_underline_mode != NULL) { #ifdef DEBUG __CTRACE(__CTRACE_ATTR, "wunderend\n"); #endif win->wattr &= ~__UNDERSCORE; } return 1; }
WINDOW * __newwin(SCREEN *screen, int nlines, int ncols, int by, int bx, int ispad) { WINDOW *win; __LINE *lp; int i, j; int maxy, maxx; __LDATA *sp; if (by < 0 || bx < 0) return (NULL); maxy = nlines > 0 ? nlines : LINES - by + nlines; maxx = ncols > 0 ? ncols : COLS - bx + ncols; if ((win = __makenew(screen, maxy, maxx, by, bx, 0, ispad)) == NULL) return (NULL); win->bch = ' '; if (__using_color) win->battr = __default_color; else win->battr = 0; win->nextp = win; win->ch_off = 0; win->orig = NULL; win->reqy = nlines; win->reqx = ncols; #ifdef DEBUG __CTRACE(__CTRACE_WINDOW, "newwin: win->ch_off = %d\n", win->ch_off); #endif for (i = 0; i < maxy; i++) { lp = win->alines[i]; if (ispad) lp->flags = __ISDIRTY; else lp->flags = 0; for (sp = lp->line, j = 0; j < maxx; j++, sp++) { sp->attr = 0; #ifndef HAVE_WCHAR sp->ch = win->bch; #else sp->ch = ( wchar_t )btowc(( int ) win->bch ); sp->nsp = NULL; SET_WCOL( *sp, 1 ); #endif /* HAVE_WCHAR */ } lp->hash = __hash((char *)(void *)lp->line, (size_t) (ncols * __LDATASIZE)); } return (win); }