1 1.20 dholland /* $NetBSD: fancy.c,v 1.20 2024/11/29 21:48:44 dholland Exp $ */ 2 1.3 cgd 3 1.1 cgd /* 4 1.3 cgd * Copyright (c) 1980, 1993 5 1.3 cgd * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * Redistribution and use in source and binary forms, with or without 8 1.1 cgd * modification, are permitted provided that the following conditions 9 1.1 cgd * are met: 10 1.1 cgd * 1. Redistributions of source code must retain the above copyright 11 1.1 cgd * notice, this list of conditions and the following disclaimer. 12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 cgd * notice, this list of conditions and the following disclaimer in the 14 1.1 cgd * documentation and/or other materials provided with the distribution. 15 1.11 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 cgd * may be used to endorse or promote products derived from this software 17 1.1 cgd * without specific prior written permission. 18 1.1 cgd * 19 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 cgd * SUCH DAMAGE. 30 1.1 cgd */ 31 1.1 cgd 32 1.5 lukem #include <sys/cdefs.h> 33 1.1 cgd #ifndef lint 34 1.3 cgd #if 0 35 1.3 cgd static char sccsid[] = "@(#)fancy.c 8.1 (Berkeley) 5/31/93"; 36 1.3 cgd #else 37 1.20 dholland __RCSID("$NetBSD: fancy.c,v 1.20 2024/11/29 21:48:44 dholland Exp $"); 38 1.3 cgd #endif 39 1.1 cgd #endif /* not lint */ 40 1.1 cgd 41 1.1 cgd #include "back.h" 42 1.5 lukem 43 1.14 dholland static void bsect(int, int, int, int); 44 1.14 dholland static void fixpos(int, int, int, int, int); 45 1.14 dholland static void fixcol(int, int, int, int, int); 46 1.14 dholland static void newline(void); 47 1.14 dholland 48 1.14 dholland /* 49 1.14 dholland * These need to be declared so they come out as commons, because 50 1.14 dholland * termcap might or might not define some of them. Our termcap defines 51 1.14 dholland * PC, BC, and UP only. This is gross. 52 1.14 dholland * 53 1.14 dholland * XXX: rewrite this crap using curses. 54 1.14 dholland */ 55 1.16 mrg #if 0 56 1.5 lukem char PC; /* padding character */ 57 1.5 lukem char *BC; /* backspace sequence */ 58 1.16 mrg #endif 59 1.19 rillig static char *CD; /* clear to end of screen sequence */ 60 1.19 rillig static char *CE; /* clear to end of line sequence */ 61 1.19 rillig static char *CL; /* clear screen sequence */ 62 1.19 rillig static char *CM; /* cursor movement instructions */ 63 1.19 rillig static char *HO; /* home cursor sequence */ 64 1.19 rillig static char *MC; /* column cursor movement map */ 65 1.19 rillig static char *ML; /* row cursor movement map */ 66 1.19 rillig static char *ND; /* forward cursor sequence */ 67 1.16 mrg #if 0 68 1.5 lukem char *UP; /* up cursor sequence */ 69 1.16 mrg #endif 70 1.5 lukem 71 1.14 dholland static int lHO; /* length of HO */ 72 1.14 dholland static int lBC; /* length of BC */ 73 1.14 dholland static int lND; /* length of ND */ 74 1.14 dholland static int lUP; /* length of UP */ 75 1.14 dholland static int CO; /* number of columns */ 76 1.14 dholland static int LI; /* number of lines */ 77 1.14 dholland static int *linect; /* array of lengths of lines on screen (the 78 1.5 lukem * actual screen is not stored) */ 79 1.5 lukem 80 1.5 lukem /* two letter codes */ 81 1.14 dholland static char tcap[] = "bccdceclcmhomcmlndup"; 82 1.5 lukem /* corresponding strings */ 83 1.14 dholland static char **tstr[] = {&BC, &CD, &CE, &CL, &CM, &HO, &MC, &ML, &ND, &UP}; 84 1.5 lukem 85 1.14 dholland static char tbuf[1024]; /* buffer for decoded termcap entries */ 86 1.5 lukem 87 1.17 rillig static int oldb[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88 1.14 dholland 0, 0, 0, 0, 0, 0}; 89 1.5 lukem 90 1.14 dholland static int oldr; 91 1.14 dholland static int oldw; 92 1.5 lukem /* "real" cursor positions, so it knows when to reposition. These are -1 if 93 1.5 lukem * curr and curc are accurate */ 94 1.14 dholland static int realr; 95 1.14 dholland static int realc; 96 1.1 cgd 97 1.5 lukem void 98 1.13 jmc fboard(void) 99 1.5 lukem { 100 1.5 lukem int i, j, l; 101 1.1 cgd 102 1.5 lukem curmove(0, 0); /* do top line */ 103 1.1 cgd for (i = 0; i < 53; i++) 104 1.5 lukem fancyc('_'); 105 1.1 cgd 106 1.18 andvar curmove(15, 0); /* do bottom line */ 107 1.1 cgd for (i = 0; i < 53; i++) 108 1.5 lukem fancyc('_'); 109 1.1 cgd 110 1.5 lukem l = 1; /* do vertical lines */ 111 1.5 lukem for (i = 52; i > -1; i -= 28) { 112 1.5 lukem curmove((l == 1 ? 1 : 15), i); 113 1.5 lukem fancyc('|'); 114 1.5 lukem for (j = 0; j < 14; j++) { 115 1.5 lukem curmove(curr + l, curc - 1); 116 1.5 lukem fancyc('|'); 117 1.1 cgd } 118 1.1 cgd if (i == 24) 119 1.1 cgd i += 32; 120 1.5 lukem l = -l; /* alternate directions */ 121 1.1 cgd } 122 1.1 cgd 123 1.5 lukem curmove(2, 1); /* label positions 13-18 */ 124 1.5 lukem for (i = 13; i < 18; i++) { 125 1.5 lukem fancyc('1'); 126 1.5 lukem fancyc((i % 10) + '0'); 127 1.5 lukem curmove(curr, curc + 2); 128 1.5 lukem } 129 1.5 lukem fancyc('1'); 130 1.5 lukem fancyc('8'); 131 1.5 lukem 132 1.5 lukem curmove(2, 29); /* label positions 19-24 */ 133 1.5 lukem fancyc('1'); 134 1.5 lukem fancyc('9'); 135 1.5 lukem for (i = 20; i < 25; i++) { 136 1.5 lukem curmove(curr, curc + 2); 137 1.5 lukem fancyc('2'); 138 1.5 lukem fancyc((i % 10) + '0'); 139 1.5 lukem } 140 1.5 lukem 141 1.5 lukem curmove(14, 1); /* label positions 12-7 */ 142 1.5 lukem fancyc('1'); 143 1.5 lukem fancyc('2'); 144 1.5 lukem for (i = 11; i > 6; i--) { 145 1.5 lukem curmove(curr, curc + 2); 146 1.5 lukem fancyc(i > 9 ? '1' : ' '); 147 1.5 lukem fancyc((i % 10) + '0'); 148 1.1 cgd } 149 1.1 cgd 150 1.5 lukem curmove(14, 30); /* label positions 6-1 */ 151 1.5 lukem fancyc('6'); 152 1.1 cgd for (i = 5; i > 0; i--) { 153 1.5 lukem curmove(curr, curc + 3); 154 1.5 lukem fancyc(i + '0'); 155 1.1 cgd } 156 1.1 cgd 157 1.5 lukem for (i = 12; i > 6; i--)/* print positions 12-7 */ 158 1.1 cgd if (board[i]) 159 1.5 lukem bsect(board[i], 13, 1 + 4 * (12 - i), -1); 160 1.1 cgd 161 1.5 lukem if (board[0]) /* print red men on bar */ 162 1.5 lukem bsect(board[0], 13, 25, -1); 163 1.1 cgd 164 1.5 lukem for (i = 6; i > 0; i--) /* print positions 6-1 */ 165 1.1 cgd if (board[i]) 166 1.5 lukem bsect(board[i], 13, 29 + 4 * (6 - i), -1); 167 1.1 cgd 168 1.5 lukem l = (off[1] < 0 ? off[1] + 15 : off[1]); /* print white's home */ 169 1.5 lukem bsect(l, 3, 54, 1); 170 1.1 cgd 171 1.5 lukem curmove(8, 25); /* print the word BAR */ 172 1.5 lukem fancyc('B'); 173 1.5 lukem fancyc('A'); 174 1.5 lukem fancyc('R'); 175 1.1 cgd 176 1.5 lukem for (i = 13; i < 19; i++) /* print positions 13-18 */ 177 1.1 cgd if (board[i]) 178 1.5 lukem bsect(board[i], 3, 1 + 4 * (i - 13), 1); 179 1.1 cgd 180 1.5 lukem if (board[25]) /* print white's men on bar */ 181 1.5 lukem bsect(board[25], 3, 25, 1); 182 1.1 cgd 183 1.5 lukem for (i = 19; i < 25; i++) /* print positions 19-24 */ 184 1.1 cgd if (board[i]) 185 1.5 lukem bsect(board[i], 3, 29 + 4 * (i - 19), 1); 186 1.1 cgd 187 1.5 lukem l = (off[0] < 0 ? off[0] + 15 : off[0]); /* print red's home */ 188 1.5 lukem bsect(-l, 13, 54, -1); 189 1.1 cgd 190 1.5 lukem for (i = 0; i < 26; i++)/* save board position for refresh later */ 191 1.1 cgd oldb[i] = board[i]; 192 1.5 lukem oldr = (off[1] < 0 ? off[1] + 15 : off[1]); 193 1.5 lukem oldw = -(off[0] < 0 ? off[0] + 15 : off[0]); 194 1.1 cgd } 195 1.1 cgd /* 196 1.1 cgd * bsect (b,rpos,cpos,cnext) 197 1.1 cgd * Print the contents of a board position. "b" has the value of the 198 1.1 cgd * position, "rpos" is the row to start printing, "cpos" is the column to 199 1.1 cgd * start printing, and "cnext" is positive if the position starts at the top 200 1.1 cgd * and negative if it starts at the bottom. The value of "cpos" is checked 201 1.1 cgd * to see if the position is a player's home, since those are printed 202 1.1 cgd * differently. 203 1.1 cgd */ 204 1.14 dholland static void 205 1.13 jmc bsect(int b, int rpos, int cpos, int cnext) 206 1.5 lukem { 207 1.5 lukem int j; /* index */ 208 1.5 lukem int n; /* number of men on position */ 209 1.5 lukem int bct; /* counter */ 210 1.5 lukem int k; /* index */ 211 1.5 lukem char pc; /* color of men on position */ 212 1.5 lukem 213 1.5 lukem bct = 0; 214 1.5 lukem n = abs(b); /* initialize n and pc */ 215 1.5 lukem pc = (b > 0 ? 'r' : 'w'); 216 1.1 cgd 217 1.5 lukem if (n < 6 && cpos < 54) /* position cursor at start */ 218 1.5 lukem curmove(rpos, cpos + 1); 219 1.5 lukem else 220 1.5 lukem curmove(rpos, cpos); 221 1.1 cgd 222 1.5 lukem for (j = 0; j < 5; j++) { /* print position row by row */ 223 1.1 cgd 224 1.5 lukem for (k = 0; k < 15; k += 5) /* print men */ 225 1.5 lukem if (n > j + k) 226 1.5 lukem fancyc(pc); 227 1.1 cgd 228 1.5 lukem if (j < 4) { /* figure how far to back up for next row */ 229 1.5 lukem if (n < 6) { /* stop if none left */ 230 1.5 lukem if (j + 1 == n) 231 1.1 cgd break; 232 1.5 lukem bct = 1; /* single column */ 233 1.5 lukem } else { 234 1.5 lukem if (n < 11) { /* two columns */ 235 1.5 lukem if (cpos == 54) { /* home pos */ 236 1.5 lukem if (j + 5 >= n) 237 1.1 cgd bct = 1; 238 1.1 cgd else 239 1.1 cgd bct = 2; 240 1.1 cgd } 241 1.5 lukem if (cpos < 54) { /* not home */ 242 1.5 lukem if (j + 6 >= n) 243 1.1 cgd bct = 1; 244 1.1 cgd else 245 1.1 cgd bct = 2; 246 1.1 cgd } 247 1.5 lukem } else { /* three columns */ 248 1.5 lukem if (j + 10 >= n) 249 1.1 cgd bct = 2; 250 1.1 cgd else 251 1.1 cgd bct = 3; 252 1.1 cgd } 253 1.1 cgd } 254 1.17 rillig /* reposition cursor */ 255 1.13 jmc curmove(curr + cnext, curc - bct); 256 1.1 cgd } 257 1.1 cgd } 258 1.1 cgd } 259 1.1 cgd 260 1.5 lukem void 261 1.13 jmc refresh(void) 262 1.5 lukem { 263 1.5 lukem int i, r, c; 264 1.5 lukem 265 1.5 lukem r = curr; /* save current position */ 266 1.1 cgd c = curc; 267 1.1 cgd 268 1.5 lukem for (i = 12; i > 6; i--)/* fix positions 12-7 */ 269 1.5 lukem if (board[i] != oldb[i]) { 270 1.5 lukem fixpos(oldb[i], board[i], 13, 1 + (12 - i) * 4, -1); 271 1.1 cgd oldb[i] = board[i]; 272 1.1 cgd } 273 1.5 lukem if (board[0] != oldb[0]) { /* fix red men on bar */ 274 1.5 lukem fixpos(oldb[0], board[0], 13, 25, -1); 275 1.1 cgd oldb[0] = board[0]; 276 1.1 cgd } 277 1.5 lukem for (i = 6; i > 0; i--) /* fix positions 6-1 */ 278 1.5 lukem if (board[i] != oldb[i]) { 279 1.5 lukem fixpos(oldb[i], board[i], 13, 29 + (6 - i) * 4, -1); 280 1.1 cgd oldb[i] = board[i]; 281 1.1 cgd } 282 1.5 lukem i = -(off[0] < 0 ? off[0] + 15 : off[0]); /* fix white's home */ 283 1.5 lukem if (oldw != i) { 284 1.5 lukem fixpos(oldw, i, 13, 54, -1); 285 1.1 cgd oldw = i; 286 1.1 cgd } 287 1.5 lukem for (i = 13; i < 19; i++) /* fix positions 13-18 */ 288 1.5 lukem if (board[i] != oldb[i]) { 289 1.5 lukem fixpos(oldb[i], board[i], 3, 1 + (i - 13) * 4, 1); 290 1.1 cgd oldb[i] = board[i]; 291 1.1 cgd } 292 1.5 lukem if (board[25] != oldb[25]) { /* fix white men on bar */ 293 1.5 lukem fixpos(oldb[25], board[25], 3, 25, 1); 294 1.1 cgd oldb[25] = board[25]; 295 1.1 cgd } 296 1.5 lukem for (i = 19; i < 25; i++) /* fix positions 19-24 */ 297 1.5 lukem if (board[i] != oldb[i]) { 298 1.5 lukem fixpos(oldb[i], board[i], 3, 29 + (i - 19) * 4, 1); 299 1.1 cgd oldb[i] = board[i]; 300 1.1 cgd } 301 1.5 lukem i = (off[1] < 0 ? off[1] + 15 : off[1]); /* fix red's home */ 302 1.5 lukem if (oldr != i) { 303 1.5 lukem fixpos(oldr, i, 3, 54, 1); 304 1.1 cgd oldr = i; 305 1.1 cgd } 306 1.5 lukem curmove(r, c); /* return to saved position */ 307 1.1 cgd newpos(); 308 1.1 cgd buflush(); 309 1.1 cgd } 310 1.1 cgd 311 1.14 dholland static void 312 1.13 jmc fixpos(int cur, int new, int r, int c, int inc) 313 1.1 cgd { 314 1.5 lukem int o, n, nv; 315 1.5 lukem int ov, nc; 316 1.5 lukem char col; 317 1.1 cgd 318 1.5 lukem nc = 0; 319 1.13 jmc if (cur * new >= 0) { 320 1.13 jmc ov = abs(cur); 321 1.1 cgd nv = abs(new); 322 1.13 jmc col = (cur + new > 0 ? 'r' : 'w'); 323 1.5 lukem o = (ov - 1) / 5; 324 1.5 lukem n = (nv - 1) / 5; 325 1.5 lukem if (o == n) { 326 1.1 cgd if (o == 2) 327 1.5 lukem nc = c + 2; 328 1.1 cgd if (o == 1) 329 1.5 lukem nc = c < 54 ? c : c + 1; 330 1.1 cgd if (o == 0) 331 1.5 lukem nc = c < 54 ? c + 1 : c; 332 1.1 cgd if (ov > nv) 333 1.17 rillig fixcol(r + inc * (nv - n * 5), nc, 334 1.13 jmc abs(ov - nv), ' ', inc); 335 1.1 cgd else 336 1.17 rillig fixcol(r + inc * (ov - o * 5), nc, 337 1.13 jmc abs(ov - nv), col, inc); 338 1.1 cgd return; 339 1.5 lukem } else { 340 1.5 lukem if (c < 54) { 341 1.5 lukem if (o + n == 1) { 342 1.5 lukem if (n) { 343 1.17 rillig fixcol(r, c, abs(nv - 5), col, 344 1.13 jmc inc); 345 1.1 cgd if (ov != 5) 346 1.17 rillig fixcol(r + inc * ov, 347 1.13 jmc c + 1, abs(ov - 5), 348 1.13 jmc col, inc); 349 1.5 lukem } else { 350 1.17 rillig fixcol(r, c, abs(ov - 5), ' ', 351 1.13 jmc inc); 352 1.1 cgd if (nv != 5) 353 1.17 rillig fixcol(r + inc * nv, 354 1.13 jmc c + 1, abs(nv - 5), 355 1.13 jmc ' ', inc); 356 1.1 cgd } 357 1.1 cgd return; 358 1.1 cgd } 359 1.5 lukem if (n == 2) { 360 1.1 cgd if (ov != 10) 361 1.5 lukem fixcol(r + inc * (ov - 5), c, 362 1.5 lukem abs(ov - 10), col, inc); 363 1.17 rillig fixcol(r, c + 2, abs(nv - 10), col, 364 1.13 jmc inc); 365 1.5 lukem } else { 366 1.1 cgd if (nv != 10) 367 1.5 lukem fixcol(r + inc * (nv - 5), c, 368 1.5 lukem abs(nv - 10), ' ', inc); 369 1.17 rillig fixcol(r, c + 2, abs(ov - 10), ' ', 370 1.13 jmc inc); 371 1.1 cgd } 372 1.1 cgd return; 373 1.1 cgd } 374 1.5 lukem if (n > o) { 375 1.17 rillig fixcol(r + inc * (ov % 5), c + o, 376 1.13 jmc abs(5 * n - ov), col, inc); 377 1.5 lukem if (nv != 5 * n) 378 1.17 rillig fixcol(r, c + n, abs(5 * n - nv), 379 1.13 jmc col, inc); 380 1.5 lukem } else { 381 1.17 rillig fixcol(r + inc * (nv % 5), c + n, 382 1.13 jmc abs(5 * n - nv), ' ', inc); 383 1.5 lukem if (ov != 5 * o) 384 1.17 rillig fixcol(r, c + o, abs(5 * o - ov), 385 1.13 jmc ' ', inc); 386 1.1 cgd } 387 1.1 cgd return; 388 1.1 cgd } 389 1.1 cgd } 390 1.1 cgd nv = abs(new); 391 1.5 lukem fixcol(r, c + 1, nv, new > 0 ? 'r' : 'w', inc); 392 1.13 jmc if (abs(cur) <= abs(new)) 393 1.1 cgd return; 394 1.13 jmc fixcol(r + inc * new, c + 1, abs(cur + new), ' ', inc); 395 1.1 cgd } 396 1.1 cgd 397 1.14 dholland static void 398 1.13 jmc fixcol(int r, int c, int l, int ch, int inc) 399 1.1 cgd { 400 1.5 lukem int i; 401 1.1 cgd 402 1.5 lukem curmove(r, c); 403 1.5 lukem fancyc(ch); 404 1.5 lukem for (i = 1; i < l; i++) { 405 1.5 lukem curmove(curr + inc, curc - 1); 406 1.5 lukem fancyc(ch); 407 1.1 cgd } 408 1.1 cgd } 409 1.1 cgd 410 1.5 lukem void 411 1.13 jmc curmove(int r, int c) 412 1.1 cgd { 413 1.1 cgd if (curr == r && curc == c) 414 1.1 cgd return; 415 1.5 lukem if (realr == -1) { 416 1.1 cgd realr = curr; 417 1.1 cgd realc = curc; 418 1.1 cgd } 419 1.1 cgd curr = r; 420 1.1 cgd curc = c; 421 1.1 cgd } 422 1.1 cgd 423 1.5 lukem void 424 1.13 jmc newpos(void) 425 1.5 lukem { 426 1.5 lukem int r; /* destination row */ 427 1.5 lukem int c; /* destination column */ 428 1.5 lukem int mode = -1; /* mode of movement */ 429 1.1 cgd 430 1.13 jmc int ccount = 1000; /* character count */ 431 1.5 lukem int i; /* index */ 432 1.5 lukem int n; /* temporary variable */ 433 1.5 lukem char *m; /* string containing CM movement */ 434 1.1 cgd 435 1.1 cgd 436 1.5 lukem m = NULL; 437 1.5 lukem if (realr == -1) /* see if already there */ 438 1.1 cgd return; 439 1.1 cgd 440 1.5 lukem r = curr; /* set current and dest. positions */ 441 1.1 cgd c = curc; 442 1.1 cgd curr = realr; 443 1.1 cgd curc = realc; 444 1.1 cgd 445 1.5 lukem /* double check position */ 446 1.5 lukem if (curr == r && curc == c) { 447 1.1 cgd realr = realc = -1; 448 1.1 cgd return; 449 1.1 cgd } 450 1.5 lukem if (CM) { /* try CM to get there */ 451 1.1 cgd mode = 0; 452 1.5 lukem m = (char *) tgoto(CM, c, r); 453 1.19 rillig ccount = (int)strlen(m); 454 1.1 cgd } 455 1.5 lukem /* try HO and local movement */ 456 1.13 jmc if (HO && (n = r + c * lND + lHO) < ccount) { 457 1.1 cgd mode = 1; 458 1.13 jmc ccount = n; 459 1.1 cgd } 460 1.5 lukem /* try various LF combinations */ 461 1.5 lukem if (r >= curr) { 462 1.5 lukem /* CR, LF, and ND */ 463 1.13 jmc if ((n = (r - curr) + c * lND + 1) < ccount) { 464 1.1 cgd mode = 2; 465 1.13 jmc ccount = n; 466 1.1 cgd } 467 1.5 lukem /* LF, ND */ 468 1.13 jmc if (c >= curc && (n = (r - curr) + (c - curc) * lND) < ccount) { 469 1.1 cgd mode = 3; 470 1.13 jmc ccount = n; 471 1.1 cgd } 472 1.5 lukem /* LF, BS */ 473 1.13 jmc if (c < curc && (n = (r - curr) + (curc - c) * lBC) < ccount) { 474 1.1 cgd mode = 4; 475 1.13 jmc ccount = n; 476 1.1 cgd } 477 1.1 cgd } 478 1.5 lukem /* try corresponding UP combinations */ 479 1.5 lukem if (r < curr) { 480 1.5 lukem /* CR, UP, and ND */ 481 1.13 jmc if ((n = (curr - r) * lUP + c * lND + 1) < ccount) { 482 1.1 cgd mode = 5; 483 1.13 jmc ccount = n; 484 1.1 cgd } 485 1.5 lukem /* UP and ND */ 486 1.17 rillig if (c >= curc && 487 1.13 jmc (n = (curr - r) * lUP + (c - curc) * lND) < ccount) { 488 1.1 cgd mode = 6; 489 1.13 jmc ccount = n; 490 1.1 cgd } 491 1.5 lukem /* UP and BS */ 492 1.17 rillig if (c < curc && 493 1.13 jmc (n = (curr - r) * lUP + (curc - c) * lBC) < ccount) { 494 1.1 cgd mode = 7; 495 1.13 jmc ccount = n; 496 1.1 cgd } 497 1.1 cgd } 498 1.5 lukem /* space over */ 499 1.13 jmc if (curr == r && c > curc && linect[r] < curc && c - curc < ccount) 500 1.1 cgd mode = 8; 501 1.1 cgd 502 1.5 lukem switch (mode) { 503 1.1 cgd 504 1.5 lukem case -1: /* error! */ 505 1.5 lukem write(2, "\r\nInternal cursor error.\r\n", 26); 506 1.5 lukem getout(0); 507 1.19 rillig /* NOTREACHED */ 508 1.5 lukem 509 1.5 lukem /* direct cursor motion */ 510 1.5 lukem case 0: 511 1.5 lukem tputs(m, abs(curr - r), addbuf); 512 1.1 cgd break; 513 1.1 cgd 514 1.5 lukem /* relative to "home" */ 515 1.5 lukem case 1: 516 1.5 lukem tputs(HO, r, addbuf); 517 1.1 cgd for (i = 0; i < r; i++) 518 1.5 lukem addbuf('\012'); 519 1.1 cgd for (i = 0; i < c; i++) 520 1.5 lukem tputs(ND, 1, addbuf); 521 1.1 cgd break; 522 1.1 cgd 523 1.5 lukem /* CR and down and over */ 524 1.5 lukem case 2: 525 1.5 lukem addbuf('\015'); 526 1.5 lukem for (i = 0; i < r - curr; i++) 527 1.5 lukem addbuf('\012'); 528 1.1 cgd for (i = 0; i < c; i++) 529 1.5 lukem tputs(ND, 1, addbuf); 530 1.1 cgd break; 531 1.5 lukem 532 1.5 lukem /* down and over */ 533 1.5 lukem case 3: 534 1.5 lukem for (i = 0; i < r - curr; i++) 535 1.5 lukem addbuf('\012'); 536 1.5 lukem for (i = 0; i < c - curc; i++) 537 1.5 lukem tputs(ND, 1, addbuf); 538 1.1 cgd break; 539 1.5 lukem 540 1.5 lukem /* down and back */ 541 1.5 lukem case 4: 542 1.5 lukem for (i = 0; i < r - curr; i++) 543 1.5 lukem addbuf('\012'); 544 1.5 lukem for (i = 0; i < curc - c; i++) 545 1.5 lukem addbuf('\010'); 546 1.1 cgd break; 547 1.5 lukem 548 1.5 lukem /* CR and up and over */ 549 1.5 lukem case 5: 550 1.5 lukem addbuf('\015'); 551 1.5 lukem for (i = 0; i < curr - r; i++) 552 1.5 lukem tputs(UP, 1, addbuf); 553 1.1 cgd for (i = 0; i < c; i++) 554 1.5 lukem tputs(ND, 1, addbuf); 555 1.1 cgd break; 556 1.5 lukem 557 1.5 lukem /* up and over */ 558 1.5 lukem case 6: 559 1.5 lukem for (i = 0; i < curr - r; i++) 560 1.5 lukem tputs(UP, 1, addbuf); 561 1.5 lukem for (i = 0; i < c - curc; i++) 562 1.5 lukem tputs(ND, 1, addbuf); 563 1.1 cgd break; 564 1.5 lukem 565 1.5 lukem /* up and back */ 566 1.5 lukem case 7: 567 1.5 lukem for (i = 0; i < curr - r; i++) 568 1.5 lukem tputs(UP, 1, addbuf); 569 1.5 lukem for (i = 0; i < curc - c; i++) { 570 1.1 cgd if (BC) 571 1.5 lukem tputs(BC, 1, addbuf); 572 1.1 cgd else 573 1.5 lukem addbuf('\010'); 574 1.1 cgd } 575 1.1 cgd break; 576 1.1 cgd 577 1.5 lukem /* safe space */ 578 1.5 lukem case 8: 579 1.5 lukem for (i = 0; i < c - curc; i++) 580 1.5 lukem addbuf(' '); 581 1.1 cgd } 582 1.1 cgd 583 1.5 lukem /* fix positions */ 584 1.1 cgd curr = r; 585 1.1 cgd curc = c; 586 1.1 cgd realr = -1; 587 1.1 cgd realc = -1; 588 1.1 cgd } 589 1.1 cgd 590 1.5 lukem void 591 1.13 jmc clear(void) 592 1.5 lukem { 593 1.5 lukem int i; 594 1.5 lukem 595 1.5 lukem /* double space if can't clear */ 596 1.20 dholland if (CL == NULL) { 597 1.5 lukem writel("\n\n"); 598 1.1 cgd return; 599 1.1 cgd } 600 1.5 lukem curr = curc = 0; /* fix position markers */ 601 1.1 cgd realr = realc = -1; 602 1.5 lukem for (i = 0; i < 24; i++)/* clear line counts */ 603 1.1 cgd linect[i] = -1; 604 1.5 lukem buffnum = -1; /* ignore leftover buffer contents */ 605 1.5 lukem tputs(CL, CO, addbuf); /* put CL in buffer */ 606 1.1 cgd } 607 1.5 lukem 608 1.5 lukem void 609 1.13 jmc fancyc(int c) 610 1.1 cgd { 611 1.5 lukem int sp; /* counts spaces in a tab */ 612 1.1 cgd 613 1.5 lukem if (c == '\007') { /* bells go in blindly */ 614 1.5 lukem addbuf(c); 615 1.1 cgd return; 616 1.1 cgd } 617 1.12 simonb /* process tabs, use spaces if the tab should be erasing things, 618 1.5 lukem * otherwise use cursor movement routines. Note this does not use 619 1.5 lukem * hardware tabs at all. */ 620 1.5 lukem if (c == '\t') { 621 1.5 lukem sp = (curc + 8) & (~7); /* compute spaces */ 622 1.5 lukem /* check line length */ 623 1.5 lukem if (linect[curr] >= curc || sp < 4) { 624 1.1 cgd for (; sp > curc; sp--) 625 1.5 lukem addbuf(' '); 626 1.5 lukem curc = sp; /* fix curc */ 627 1.1 cgd } else 628 1.5 lukem curmove(curr, sp); 629 1.1 cgd return; 630 1.1 cgd } 631 1.5 lukem /* do newline be calling newline */ 632 1.5 lukem if (c == '\n') { 633 1.1 cgd newline(); 634 1.1 cgd return; 635 1.1 cgd } 636 1.5 lukem /* ignore any other control chars */ 637 1.1 cgd if (c < ' ') 638 1.1 cgd return; 639 1.1 cgd 640 1.5 lukem /* if an erasing space or non-space, just add it to buffer. Otherwise 641 1.5 lukem * use cursor movement routine, so that multiple spaces will be 642 1.5 lukem * grouped together */ 643 1.5 lukem if (c > ' ' || linect[curr] >= curc) { 644 1.5 lukem newpos(); /* make sure position correct */ 645 1.5 lukem addbuf(c); /* add character to buffer */ 646 1.5 lukem /* fix line length */ 647 1.1 cgd if (c == ' ' && linect[curr] == curc) 648 1.1 cgd linect[curr]--; 649 1.5 lukem else 650 1.5 lukem if (linect[curr] < curc) 651 1.5 lukem linect[curr] = curc; 652 1.5 lukem curc++; /* fix curc */ 653 1.1 cgd } else 654 1.5 lukem /* use cursor movement routine */ 655 1.5 lukem curmove(curr, curc + 1); 656 1.1 cgd } 657 1.1 cgd 658 1.5 lukem void 659 1.13 jmc clend(void) 660 1.5 lukem { 661 1.5 lukem int i; 662 1.1 cgd 663 1.5 lukem if (CD) { 664 1.5 lukem tputs(CD, CO - curr, addbuf); 665 1.1 cgd for (i = curr; i < LI; i++) 666 1.1 cgd linect[i] = -1; 667 1.1 cgd return; 668 1.1 cgd } 669 1.5 lukem curmove(i = curr, 0); 670 1.1 cgd cline(); 671 1.5 lukem while (curr < LI - 1) { 672 1.5 lukem curmove(curr + 1, 0); 673 1.1 cgd if (linect[curr] > -1) 674 1.5 lukem cline(); 675 1.1 cgd } 676 1.5 lukem curmove(i, 0); 677 1.1 cgd } 678 1.1 cgd 679 1.5 lukem void 680 1.13 jmc cline(void) 681 1.5 lukem { 682 1.5 lukem int c; 683 1.1 cgd 684 1.1 cgd if (curc > linect[curr]) 685 1.1 cgd return; 686 1.5 lukem newpos(); 687 1.5 lukem if (CE) { 688 1.5 lukem tputs(CE, 1, addbuf); 689 1.5 lukem linect[curr] = curc - 1; 690 1.5 lukem } else { 691 1.5 lukem c = curc - 1; 692 1.5 lukem while (linect[curr] > c) { 693 1.5 lukem addbuf(' '); 694 1.1 cgd curc++; 695 1.1 cgd linect[curr]--; 696 1.1 cgd } 697 1.5 lukem curmove(curr, c + 1); 698 1.1 cgd } 699 1.1 cgd } 700 1.1 cgd 701 1.14 dholland static void 702 1.13 jmc newline(void) 703 1.5 lukem { 704 1.1 cgd cline(); 705 1.5 lukem if (curr == LI - 1) 706 1.5 lukem curmove(begscr, 0); 707 1.1 cgd else 708 1.5 lukem curmove(curr + 1, 0); 709 1.1 cgd } 710 1.1 cgd 711 1.5 lukem int 712 1.13 jmc getcaps(const char *s) 713 1.1 cgd { 714 1.5 lukem char *code; /* two letter code */ 715 1.5 lukem char ***cap; /* pointer to cap string */ 716 1.5 lukem char *bufp; /* pointer to cap buffer */ 717 1.5 lukem char tentry[1024]; /* temporary uncoded caps buffer */ 718 1.1 cgd 719 1.9 hubertf tgetent(tentry, s); /* get uncoded termcap entry */ 720 1.1 cgd 721 1.5 lukem LI = tgetnum("li"); /* get number of lines */ 722 1.1 cgd if (LI == -1) 723 1.1 cgd LI = 12; 724 1.5 lukem CO = tgetnum("co"); /* get number of columns */ 725 1.1 cgd if (CO == -1) 726 1.1 cgd CO = 65; 727 1.1 cgd 728 1.5 lukem bufp = tbuf; /* get padding character */ 729 1.5 lukem tgetstr("pc", &bufp); 730 1.1 cgd if (bufp != tbuf) 731 1.1 cgd PC = *tbuf; 732 1.1 cgd else 733 1.1 cgd PC = 0; 734 1.1 cgd 735 1.5 lukem bufp = tbuf; /* get string entries */ 736 1.1 cgd cap = tstr; 737 1.1 cgd for (code = tcap; *code; code += 2) 738 1.5 lukem **cap++ = (char *) tgetstr(code, &bufp); 739 1.1 cgd 740 1.5 lukem /* get pertinent lengths */ 741 1.1 cgd if (HO) 742 1.19 rillig lHO = (int)strlen(HO); 743 1.1 cgd if (BC) 744 1.19 rillig lBC = (int)strlen(BC); 745 1.1 cgd else 746 1.1 cgd lBC = 1; 747 1.1 cgd if (UP) 748 1.19 rillig lUP = (int)strlen(UP); 749 1.1 cgd if (ND) 750 1.19 rillig lND = (int)strlen(ND); 751 1.20 dholland if (LI < 24 || CO < 72 || !(CL && UP && ND)) { 752 1.20 dholland /* force CL to null because this is what's tested in clear() */ 753 1.20 dholland CL = NULL; 754 1.1 cgd return (0); 755 1.20 dholland } 756 1.5 lukem linect = (int *) calloc(LI + 1, sizeof(int)); 757 1.10 hubertf if (linect == NULL) { 758 1.10 hubertf write(2, "\r\nOut of memory!\r\n", 18); 759 1.10 hubertf getout(0); 760 1.10 hubertf } 761 1.1 cgd return (1); 762 1.1 cgd } 763