1 /* $OpenBSD: hack.topl.c,v 1.4 2001/01/28 23:41:46 niklas Exp $ */ 2 3 /* 4 * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. 5 */ 6 7 #ifndef lint 8 static char rcsid[] = "$OpenBSD: hack.topl.c,v 1.4 2001/01/28 23:41:46 niklas Exp $"; 9 #endif /* not lint */ 10 11 #include "hack.h" 12 #include <stdio.h> 13 extern char *eos(); 14 extern int CO; 15 16 char toplines[BUFSZ]; 17 xchar tlx, tly; /* set by pline; used by addtopl */ 18 19 struct topl { 20 struct topl *next_topl; 21 char *topl_text; 22 } *old_toplines, *last_redone_topl; 23 #define OTLMAX 20 /* max nr of old toplines remembered */ 24 25 doredotopl(){ 26 if(last_redone_topl) 27 last_redone_topl = last_redone_topl->next_topl; 28 if(!last_redone_topl) 29 last_redone_topl = old_toplines; 30 if(last_redone_topl){ 31 (void) strcpy(toplines, last_redone_topl->topl_text); 32 } 33 redotoplin(); 34 return(0); 35 } 36 37 redotoplin() { 38 home(); 39 if(strchr(toplines, '\n')) cl_end(); 40 putstr(toplines); 41 cl_end(); 42 tlx = curx; 43 tly = cury; 44 flags.toplin = 1; 45 if(tly > 1) 46 more(); 47 } 48 49 remember_topl() { 50 register struct topl *tl; 51 register int cnt = OTLMAX; 52 if(last_redone_topl && 53 !strcmp(toplines, last_redone_topl->topl_text)) return; 54 if(old_toplines && 55 !strcmp(toplines, old_toplines->topl_text)) return; 56 last_redone_topl = 0; 57 tl = (struct topl *) 58 alloc((unsigned)(strlen(toplines) + sizeof(struct topl) + 1)); 59 tl->next_topl = old_toplines; 60 tl->topl_text = (char *)(tl + 1); 61 (void) strcpy(tl->topl_text, toplines); 62 old_toplines = tl; 63 while(cnt && tl){ 64 cnt--; 65 tl = tl->next_topl; 66 } 67 if(tl && tl->next_topl){ 68 free((char *) tl->next_topl); 69 tl->next_topl = 0; 70 } 71 } 72 73 addtopl(s) char *s; { 74 curs(tlx,tly); 75 if(tlx + strlen(s) > CO) putsym('\n'); 76 putstr(s); 77 tlx = curx; 78 tly = cury; 79 flags.toplin = 1; 80 } 81 82 xmore(s) 83 char *s; /* allowed chars besides space/return */ 84 { 85 if(flags.toplin) { 86 curs(tlx, tly); 87 if(tlx + 8 > CO) putsym('\n'), tly++; 88 } 89 90 if(flags.standout) 91 standoutbeg(); 92 putstr("--More--"); 93 if(flags.standout) 94 standoutend(); 95 96 xwaitforspace(s); 97 if(flags.toplin && tly > 1) { 98 home(); 99 cl_end(); 100 docorner(1, tly-1); 101 } 102 flags.toplin = 0; 103 } 104 105 more(){ 106 xmore(""); 107 } 108 109 cmore(s) 110 register char *s; 111 { 112 xmore(s); 113 } 114 115 clrlin(){ 116 if(flags.toplin) { 117 home(); 118 cl_end(); 119 if(tly > 1) docorner(1, tly-1); 120 remember_topl(); 121 } 122 flags.toplin = 0; 123 } 124 125 /*VARARGS1*/ 126 pline(line,arg1,arg2,arg3,arg4,arg5,arg6) 127 register char *line,*arg1,*arg2,*arg3,*arg4,*arg5,*arg6; 128 { 129 char pbuf[BUFSZ]; 130 register char *bp = pbuf, *tl; 131 register int n,n0; 132 133 if(!line || !*line) return; 134 if(!strchr(line, '%')) (void) strcpy(pbuf,line); else 135 (void) sprintf(pbuf,line,arg1,arg2,arg3,arg4,arg5,arg6); 136 if(flags.toplin == 1 && !strcmp(pbuf, toplines)) return; 137 nscr(); /* %% */ 138 139 /* If there is room on the line, print message on same line */ 140 /* But messages like "You die..." deserve their own line */ 141 n0 = strlen(bp); 142 if(flags.toplin == 1 && tly == 1 && 143 n0 + strlen(toplines) + 3 < CO-8 && /* leave room for --More-- */ 144 strncmp(bp, "You ", 4)) { 145 (void) strcat(toplines, " "); 146 (void) strcat(toplines, bp); 147 tlx += 2; 148 addtopl(bp); 149 return; 150 } 151 if(flags.toplin == 1) more(); 152 remember_topl(); 153 toplines[0] = 0; 154 while(n0){ 155 if(n0 >= CO){ 156 /* look for appropriate cut point */ 157 n0 = 0; 158 for(n = 0; n < CO; n++) if(bp[n] == ' ') 159 n0 = n; 160 if(!n0) for(n = 0; n < CO-1; n++) 161 if(!letter(bp[n])) n0 = n; 162 if(!n0) n0 = CO-2; 163 } 164 (void) strncpy((tl = eos(toplines)), bp, n0); 165 tl[n0] = '\0'; 166 bp += n0; 167 168 /* remove trailing spaces, but leave one */ 169 while(n0 > 1 && tl[n0-1] == ' ' && tl[n0-2] == ' ') 170 tl[--n0] = 0; 171 172 n0 = strlen(bp); 173 if(n0 && tl[0]) (void) strcat(tl, "\n"); 174 } 175 redotoplin(); 176 } 177 178 putsym(c) char c; { 179 switch(c) { 180 case '\b': 181 backsp(); 182 return; 183 case '\n': 184 curx = 1; 185 cury++; 186 if(cury > tly) tly = cury; 187 break; 188 default: 189 if(curx == CO) 190 putsym('\n'); /* 1 <= curx <= CO; avoid CO */ 191 else 192 curx++; 193 } 194 (void) putchar(c); 195 } 196 197 putstr(s) register char *s; { 198 while(*s) putsym(*s++); 199 } 200