📄 winio.c
字号:
char *col = out+strlen(BOLD); int bf=0; while (*s!=0 && (end==NULL || s<end)) { if (*s == '\e') { if (!strncmp(s, BOLD, strlen(BOLD))) { bf = 1; s += strlen(BOLD); } else if (!strncmp(s, WHITE, strlen(WHITE))) { bf = 0; col[0] = 0; s += strlen(WHITE); } else if (s[3] == 'm') { strncpy(col, s, 4); col[4] = 0; s += 4; } else { strncpy(col, s, 5); col[5] = 0; s += 5; } } else { s++; } } if (bf) { return out; } else { return col; }}/* calculate the "printable" length of a string, not including any escape sequences */int esc_getlength(char *s) { int len = 0; while (*s) { if (*s == '\e' && s[3] == 'm') { s+=4; } else if (*s == '\e') { s+=5; } else { s++; len++; } } return len;}/* NOTE: the scroll log is the biggest memory hog in nap, as it can grow to thousands of lines. Therefore some special care was taken to allocate no more room for each line than necessary. In addition, we limit the size of the scroll to scrollsize. *//* add a line to the "scroll" list of the main screen */void addscroll(WINDOW *win, char *buf){ scroll_t *cur, *new; char *p, *q; char *linebreak, *linebreak1=NULL; int scrollsize; /* len: length of the current line to append to, or -1 if the last character was '\n' and a line has not yet been created. Note len>=0 implies mscrollend != NULL */ static int len = -1; static int size, asize; /* real size and allocated size of current line, if len != -1. */ /* process each character or espace sequence from buf */ for (p=buf; *p!=0; p++) { if (*p == '\r') { /* ignore - concession to MSDOS? */ continue; } /* create a new logical line if there is no current line (previous character was '\n'). */ if (len==-1) { /* create a new empty line */ cur = (scroll_t *)malloc(sizeof(scroll_t)); cur->lastlog = lastlogflag; cur->chan = recent; cur->own = NULL; asize = 256; cur->line = (char *)malloc(asize); cur->line[0] = 0; /* attach to scroll */ dlist_append(mscroll, mscrollend, cur); mscrollsize++; /* initialize local state for appending to this line */ len = 0; size = 0; } cur = mscrollend; /* make sure at least 5 more characters fit in current line */ if (size+5+1 > asize) { asize += 256; cur->line = (char *)realloc(cur->line, asize); } if (*p == '\n') { /* mark this line ended - next printable character will start a new (logical and physical) line */ q = esc_getcolor(cur->line, NULL); if (q[0] != 0) { strcat(cur->line, WHITE); size += strlen(WHITE); } len = -1; /* free some memory by allocating a fixed size for this line */ q = strdup(cur->line); free(cur->line); cur->line = q; continue; } else if (*p == '\e') { /* escape sequence - copy to current line without counting its length towards the total */ if (p[3] == 'm') { strncat(cur->line, p, 4); size += 4; p += 3; } else { strncat(cur->line, p, 5); size += 5; p += 4; } continue; } else { /* printable character - copy it to current line */ if (*p!=' ' && len >= COLS-1) { /* the character will not fit. Find a good place to break line */ linebreak = strrchr(cur->line, ' '); if (linebreak - cur->line < COLS/2 || linebreak - cur->line < 40) { linebreak = NULL; } if (linebreak) { linebreak1 = linebreak + 1; while (linebreak > cur->line && linebreak[-1]==' ') { linebreak--; } } /* create continuation line */ new = (scroll_t *)malloc(sizeof(scroll_t)); new->lastlog = lastlogflag; new->chan = recent; new->own = cur->own ? cur->own : cur; asize = 256; new->line = (char *)malloc(asize); new->line[0] = 0; /* copy over stuff from old line to new one */ q = esc_getcolor(cur->line, linebreak); strcat(new->line, q); strcat(new->line, LINEINDENT); if (linebreak) { strcat(new->line, linebreak1); } len = esc_getlength(new->line); size = strlen(new->line); /* truncate old line if necessary */ if (linebreak) { *linebreak = 0; } /* re-allocate old line using smallest amount of space */ q = strdup(cur->line); free(cur->line); cur->line = q; /* attach new line to scroll */ dlist_append(mscroll, mscrollend, new); mscrollsize++; cur = new; } /* character fits; append it */ strncat(cur->line, p, 1); len++; } } scrollsize = nvar_default("scrollsize", SCROLLSIZE); while (scrollsize > 0 && mscrollsize > scrollsize) { /* limit the size of mscroll */ do { dlist_unlink_first(mscroll, mscrollend, cur); mscrollsize--; free(cur->line); free(cur); } while (mscroll && mscroll->own); }}/* clear the main scroll */void clearscroll(void) { scroll_t *elt; dlist_forall_unlink(elt, mscroll, mscrollend) { free(elt->line); free(elt); } mscrollsize = 0; scur = NULL; dscr(wchan);} /* scroll to bottom */void scrollbottom(void) { scur = NULL; dscr(wchan);}void dscr(WINDOW *win){ scroll_t *cur; int i, j, k, m, at=0, t, c; unsigned char bf = 0, uf = 0, gf = 0; char ebuf[6]; int col; /* column */ werase(win); wmove(win, 0, 0); if (scur == NULL) cur = mscrollend; else cur = scur; if (cur == NULL) return; i = win->_maxy-1; if (cur->chan && (wmode && cur->chan != curchan)) i++; while (i >= 0) { if (cur->prev == NULL) break; cur = cur->prev; if (cur->chan && (wmode && cur->chan != curchan)) continue; i--; } c = win->_maxy; for (j=0,i=0; i<=c; cur=cur->next) { if (cur == NULL) break; if (cur->chan && (wmode && cur->chan != curchan)) continue; if (!cur->own) { bf = 0; uf = 0; gf = 0; } wmove(win, j, 0); col = 0; for (k=0; cur->line[k] && col < COLS; k++) { if (cur->line[k] == '\e' && cur->line[k+1] == '[' && isdigit(cur->line[k+2])) { for (m=0; cur->line[k] && cur->line[k]!='m'; m++, k++) ebuf[m] = cur->line[k]; ebuf[m] = 'm'; ebuf[m+1] = '\0'; t = doesc(win, ebuf); if (t == COLOR_PAIR(CPW)) at = 0; else at |= t; } else if (cur->line[k] == 2) { if (!bf) { at |= doesc(win, BOLD); bf = 1; } else { at &= ~doesc(win, BOLD); bf = 0; } } else if (cur->line[k] == 31) { if (!uf) { at |= doesc(win, UNDERLINE); uf = 1; } else { at &= ~doesc(win, UNDERLINE); uf = 0; } } else if (cur->line[k] == 7) { if (!gf && i == c) beep(); gf = 1; } else if (cur->line[k] == 15) uf = bf = at = 0; else { waddch(win, cur->line[k]|at); col++; } } i++; j++; } scur = cur ? cur->prev : NULL;}void dscroll(WINDOW *win, int n){ int i; scroll_t *cur; if (scur == NULL) cur = mscrollend; else cur = scur; if (!cur) return; if (n > 0) { i = n; if (cur->chan && (wmode && cur->chan != curchan)) i++; while (i > 0) { if (cur->prev == NULL) break; cur = cur->prev; if (cur->chan && (wmode && cur->chan != curchan)) continue; i--; } } else if (n < 0) { i = n; if (cur->chan && (wmode && cur->chan != curchan)) i--; while (i < 0) { if (cur->next == NULL) { cur = NULL; break; } cur = cur->next; if (cur->chan && (wmode && cur->chan != curchan)) continue; i++; } } else return; scur = cur; dscr(win); drw(win);}int doesc(WINDOW *win, const char *in){ int i; for (i=0;;i++) { if (!colortab[i].in) return(0); if (!strcmp(colortab[i].in, in)) break; } if (colortab[i].c) return(COLOR_PAIR(colortab[i].pair)); else return(colortab[i].pair);}int input(WINDOW *win, sock_t *m){ chtype ebuf = 0; sock_t *t; int g; int j, s, n; char *msg; char *command; cmds_t *elt; t = findsock("server"); s = t ? t->fd : -1; ebuf = wgetch(winput); if (ebuf == '\e') { /* ESC */ ebuf = wgetch(winput); if (ebuf == ERR) { return(1); } else { ebuf+=128; } } switch (ebuf) { case '\n': /* Newline */ case '\r': /* Return */ /* enter the current line (cbuf) in the command history, unless it is a repetition of the previous command, or unless it is empty. */ if (*cbuf && (!cmdlend || strcmp(cbuf, cmdlend->cmd))) { elt = (cmds_t *)malloc(sizeof(cmds_t)); elt->cmd = strdup(cbuf); elt->prev = cmdlend; elt->next = NULL; if (cmdlend) { cmdlend->next=elt; } else { cmdl=elt; } cmdlend=elt; cmdlsize++; /* make sure command history does not get too long */ if (cmdlsize > BACKLOG) { elt = cmdl->next; free(cmdl->cmd); free(cmdl); cmdl = elt; cmdl->prev = NULL; cmdlsize--; } } /* remember command from cbuf for execution below */ command = strdup(cbuf); /* get ready for new input (we do this before the command is executed, because the command might cause a switch to another screen) */ ccmd = NULL; cbuf[0]=0; curx = 0; curr = 0; indraw(); ebuf = 0; if (*command == 0 || !strcmp(command, "/")) { /* do nothing, just print an empty line to give visual feedback */ wp(win, "\n"); drw(win); } else if (*command == '/') { lpbrk = 0; /* clear previous loop interrupt request */ n = parseout(s, command+1, win); indraw(); /* necessary because command could have been "/query" etc */ dstatus(); } else if (!curchan) { wp(win, "%s* You are not on a channel. Commands start with \"/\".%s\n", RED, WHITE); drw(win); } else if (curchan->q == 1) { msg = fixquotes(strdup(command)); sendpack(s, NAP_TELL, "%s %s", curchan->nm, msg); recent = curchan; wp(win, "%s* --> (%s%s%s)%s %s\n", GREEN, WHITE, curchan->nm, GREEN, WHITE, msg); drw(win); free(msg); recent = NULL; } else if (curchan->q == 2) { ssock(ircsock, "PRIVMSG %s :%s\n", curchan->nm, command); recent = curchan; wp(win, "%s<%s%s%s>%s %s\n", BRIGHT(MAGENTA), WHITE, mnick, BRIGHT(MAGENTA), WHITE, command); drw(win); recent = NULL; } else { msg = fixquotes(strdup(command)); if (sendpack(s, NAP_SAY, "%s %s", curchan->nm, msg) == -1) { delsock(s); /* s is the server, or -1 if no server */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -