/* Output char with attribute */ static void Putchar(int ch) { if ((_cursvar.cursrow < LINES) || (_cursvar.curscol < COLS)) { newattr(ch); putchar(ch); } }
static void clrupdate(WINDOW *scr) { register int *src; register int *dst; register int i; register int j; WINDOW *w; w = curscr; if (scr != w) { /* copy scr to curscr */ for (i = 0; i < LINES; i++) { src = scr->_line[i]; dst = w->_line[i]; for (j = 0; j < COLS; j++) *dst++ = *src++; } /* for */ } /* if */ newattr(scr->_attrs); clrscr(); scr->_clear = FALSE; for (i = 0; i < LINES; i++) { /* update physical screen */ src = w->_line[i]; j = 0; while (j < COLS) { if (*src != (' ' | ATR_NRM)) { gotoxy(i, j); while (j < COLS && (*src != (' ' | ATR_NRM))) { Putchar(*src++); j++; } } else { src++; j++; } } /* for */ } /* for */ fflush(stdout); } /* clrupdate */
// We've just seen a '<'. Gather up stuff to closing '>' (if buffer // ends before then, return -1). // If it's a tag, look up the name, gather the attributes, and return // the appropriate token. // Else it's either just plain data or some kind of ignorable stuff: // return Data or Comment as appropriate. // If it's not a Comment, put it in a[*pai] and bump *pai. static int gettag(TokenSource* ts, int starti, Token* a, int* pai) { int rbra; int ans; Attr* al; int nexti; int c; int ti; int afnd; int attid; int quote; Rune* val; int nv; int i; int tag; Token* tok; Rune buf[BIGBUFSIZE]; rbra = 0; nexti = ts->i; tok = &a[*pai]; tok->tag = Notfound; tok->text = nil; tok->attr = nil; tok->starti = starti; c = getchar(ts); if(c == '/') { rbra = RBRA; c = getchar(ts); } if(c < 0) goto eob_done; if(c >= 256 || !isalpha(c)) { // not a tag if(c == '!') { ans = comment(ts); if(ans != -1) return ans; goto eob_done; } else { backup(ts, nexti); tok->tag = Data; tok->text = _Strdup(L"<"); (*pai)++; return Data; } } // c starts a tagname buf[0] = c; i = 1; while(1) { c = getchar(ts); if(c < 0) goto eob_done; if(!ISNAMCHAR(c)) break; // if name is bigger than buf it won't be found anyway... if(i < BIGBUFSIZE) buf[i++] = c; } if(_lookup(tagtable, Numtags, buf, i, &tag)) tok->tag = tag + rbra; else tok->text = _Strndup(buf, i); // for warning print, in build // attribute gathering loop al = nil; while(1) { // look for "ws name" or "ws name ws = ws val" (ws=whitespace) // skip whitespace attrloop_continue: while(c < 256 && isspace(c)) { c = getchar(ts); if(c < 0) goto eob_done; } if(c == '>') goto attrloop_done; if(c == '<') { if(warn) fprint(2, "warning: unclosed tag\n"); ungetchar(ts, c); goto attrloop_done; } if(c >= 256 || !isalpha(c)) { if(warn) fprint(2, "warning: expected attribute name\n"); // skipt to next attribute name while(1) { c = getchar(ts); if(c < 0) goto eob_done; if(c < 256 && isalpha(c)) goto attrloop_continue; if(c == '<') { if(warn) fprint(2, "warning: unclosed tag\n"); ungetchar(ts, 60); goto attrloop_done; } if(c == '>') goto attrloop_done; } } // gather attribute name buf[0] = c; i = 1; while(1) { c = getchar(ts); if(c < 0) goto eob_done; if(!ISNAMCHAR(c)) break; if(i < BIGBUFSIZE-1) buf[i++] = c; } afnd = _lookup(attrtable, Numattrs, buf, i, &attid); if(warn && !afnd) { buf[i] = 0; fprint(2, "warning: unknown attribute name %S\n", buf); } // skip whitespace while(c < 256 && isspace(c)) { c = getchar(ts); if(c < 0) goto eob_done; } if(c != '=') { if(afnd) al = newattr(attid, nil, al); goto attrloop_continue; } //# c is '=' here; skip whitespace while(1) { c = getchar(ts); if(c < 0) goto eob_done; if(c >= 256 || !isspace(c)) break; } quote = 0; if(c == '\'' || c == '"') { quote = c; c = getchar(ts); if(c < 0) goto eob_done; } val = nil; nv = 0; while(1) { valloop_continue: if(c < 0) goto eob_done; if(c == '>') { if(quote) { // c might be part of string (though not good style) // but if line ends before close quote, assume // there was an unmatched quote ti = ts->i; while(1) { c = getchar(ts); if(c < 0) goto eob_done; if(c == quote) { backup(ts, ti); buf[nv++] = '>'; if(nv == BIGBUFSIZE-1) { val = buftostr(val, buf, nv); nv = 0; } c = getchar(ts); goto valloop_continue; } if(c == '\n') { if(warn) fprint(2, "warning: apparent unmatched quote\n"); backup(ts, ti); c = '>'; goto valloop_done; } } } else goto valloop_done; } if(quote) { if(c == quote) { c = getchar(ts); if(c < 0) goto eob_done; goto valloop_done; } if(c == '\r') { c = getchar(ts); goto valloop_continue; } if(c == '\t' || c == '\n') c = ' '; } else { if(c < 256 && isspace(c)) goto valloop_done; } if(c == '&') { c = ampersand(ts); if(c == -1) goto eob_done; } buf[nv++] = c; if(nv == BIGBUFSIZE-1) { val = buftostr(val, buf, nv); nv = 0; } c = getchar(ts); } valloop_done: if(afnd) { val = buftostr(val, buf, nv); al = newattr(attid, val, al); } } attrloop_done: tok->attr = al; (*pai)++; return tok->tag; eob_done: if(warn) fprint(2, "warning: incomplete tag at end of page\n"); backup(ts, nexti); tok->tag = Data; tok->text = _Strdup(L"<"); return Data; }