1: #ifdef sun 2: /* 3: * The Sun X drivers are a product of Sun Microsystems, Inc. and are provided 4: * for unrestricted use provided that this legend is included on all tape 5: * media and as a part of the software program in whole or part. Users 6: * may copy or modify these drivers without charge, but are not authorized 7: * to license or distribute them to anyone else except as part of a product or 8: * program developed by the user. 9: * 10: * THE SUN X DRIVERS ARE PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND 11: * INCLUDING THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A 12: * PARTICULAR PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE 13: * PRACTICE. 14: * 15: * The Sun X Drivers are provided with no support and without any obligation 16: * on the part of Sun Microsystems, Inc. to assist in their use, correction, 17: * modification or enhancement. 18: * 19: * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20: * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THE SUN X 21: * DRIVERS OR ANY PART THEREOF. 22: * 23: * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24: * or profits or other special, indirect and consequential damages, even if 25: * Sun has been advised of the possibility of such damages. 26: * 27: * Sun Microsystems, Inc. 28: * 2550 Garcia Avenue 29: * Mountain View, California 94043 30: */ 31: 32: #ifndef lint 33: static char sccsid[] = "@(#)text.c 2.1 86/01/28 Copyright 1986 Sun Micro"; 34: #endif 35: 36: /*- 37: * Copyright (c) 1986 by Sun Microsystems, Inc. 38: */ 39: 40: /* 41: * ToDo: 42: * Color 43: */ 44: 45: #include "Xsun.h" 46: #ifndef stdin 47: #include <stdio.h> 48: #endif 49: #include <pixrect/memreg.h> 50: #include <pixrect/cg2reg.h> 51: 52: /* I've put in some rather ugly hacks, in the name of performance. The 53: global variables private_* are really extra parameters to the batchrop 54: routines. I did this, rather than adding parameters, because I wanted to 55: do the least violence to the "official" specs of batchrop -- this way X 56: will vaguely work on displays that don't use one of the tuned batchrops. 57: JAG */ 58: 59: int private_fgcolor, private_bgcolor, private_czmask; 60: 61: extern struct pixrect *PixRect; 62: 63: PrintText(string, strlen, font, fore, back, charpad, spacepad, dstx, dsty, 64: clips, clipcount, func, zmask) 65: register unsigned char *string; 66: FONT *font; 67: int strlen, fore, back, charpad, spacepad, dstx, dsty; 68: CLIP *clips; 69: int clipcount, zmask; 70: int func; 71: { 72: extern CURSOR *CurrentCursor; 73: extern CursorDisplayed; 74: int cleft, ctop, cwidth, cheight; 75: int op; 76: extern char FBMap[]; 77: #define CHUNK 400 78: unsigned char *limit = string + (strlen < CHUNK ? strlen : CHUNK); 79: register w = 0; 80: static struct pr_prpos bat[CHUNK]; 81: int bsize = 0; 82: int lheight; 83: int sbot, sright; 84: 85: private_czmask = zmask; 86: private_fgcolor = fore; 87: private_bgcolor = back; 88: if (fore & 1) 89: func += 0x20; 90: if (back & 1) 91: func += 0x10; 92: func = FBMap[func]; 93: #ifdef notdef 94: op = SUN_FROM_X_OP(func) /* | PIX_COLOR(fore) */ ; 95: #else 96: op = SUN_FROM_X_OP(func) | PIX_COLOR(fore); 97: #endif 98: { 99: register struct pixfont *pf = (struct pixfont *) font->data; 100: register struct pr_prpos *p = bat; 101: lheight = pf->pf_defaultsize.y; 102: if (charpad == 0 && spacepad == 0) 103: while (string < limit) { 104: register struct pixchar *pc = &(pf->pf_char[*string++]); 105: if (pc == 0 || pc->pc_pr == NULL) 106: continue; 107: p->pr = pc->pc_pr; 108: p->pos.x = pc->pc_adv.x; 109: w += p->pos.x; 110: p++; 111: bsize++; 112: } 113: else { 114: struct pixchar *space = &pf->pf_char[font->space]; 115: while (string < limit) { 116: register struct pixchar *pc = &(pf->pf_char[*string++]); 117: if (pc == 0 || pc->pc_pr == NULL) 118: continue; 119: p->pr = pc->pc_pr; 120: p->pos.x = pc->pc_adv.x + charpad; 121: if (pc == space) 122: p->pos.x += spacepad; 123: w += p->pos.x; 124: p++; 125: bsize++; 126: } 127: } 128: } 129: sbot = dsty + lheight; 130: sright = dstx + w; 131: if (CursorDisplayed) { 132: extern DEVICE *CurrentDevice; 133: register vsCursor *ms = CurrentDevice->mouse; 134: register CURSOR *cs = CurrentCursor; 135: if (ms->y < sbot && ms->x < sright 136: && ms->y + cs->height > dsty 137: && ms->x + cs->width > dstx) 138: DisplayCursor(NULL); 139: } 140: do { 141: GetNextClip(clips, cleft, ctop, cwidth, cheight); 142: if (dsty >= ctop && sbot <= ctop + cheight 143: && dstx >= cleft && sright <= cleft + cwidth) 144: pr_batchrop(PixRect, dstx - bat[0].pos.x, dsty, 145: op | PIX_DONTCLIP, bat, bsize); 146: else { 147: struct pixrect *region; 148: if (dsty > ctop + cheight) 149: continue; 150: if (dsty + lheight <= ctop) 151: continue; 152: region = pr_region(PixRect, cleft, ctop, cwidth, cheight); 153: pr_batchrop(region, dstx - cleft - bat[0].pos.x, 154: dsty - ctop, 155: op, bat, bsize); 156: pr_destroy(region); 157: } 158: } while (--clipcount > 0); 159: if (!CursorDisplayed) 160: DisplayCursor(CurrentCursor); 161: } 162: 163: PrintTextMask(string, strlen, font, srcpix, charpad, spacepad, dstx, dsty, 164: clips, clipcount, func, zmask) 165: unsigned char *string; 166: FONT *font; 167: int strlen, srcpix, charpad, spacepad, dstx, dsty; 168: CLIP *clips; 169: int clipcount, zmask; 170: register int func; 171: { 172: extern CURSOR *CurrentCursor; 173: extern CursorDisplayed; 174: int cleft, ctop, cwidth, cheight; 175: int op; 176: extern char SSMap[]; 177: #define CHUNK 400 178: unsigned char *limit = string + (strlen < CHUNK ? strlen : CHUNK); 179: register w = 0; 180: static struct pr_prpos bat[CHUNK]; 181: int bsize = 0; 182: int lheight; 183: int sbot, sright; 184: 185: 186: SetZmask(PixRect, &zmask); 187: private_bgcolor = -1; 188: private_fgcolor = srcpix; 189: if (PixRect->pr_depth == 1) { 190: if ((srcpix & 1) == 0) 191: func += 0x10; 192: op = SUN_FROM_X_OP(SSMap[func]) & PIX_SRC | PIX_NOT(PIX_SRC) & PIX_DST; 193: } 194: else 195: op = SUN_FROM_X_OP(func); 196: if (PixRect->pr_depth > 1) 197: op |= PIX_COLOR(srcpix); 198: { 199: register struct pixfont *pf = (struct pixfont *) font->data; 200: register struct pr_prpos *p = bat; 201: lheight = pf->pf_defaultsize.y; 202: if (charpad == 0 && spacepad == 0) 203: while (string < limit) { 204: register struct pixchar *pc = &(pf->pf_char[*string++]); 205: if (pc == 0) 206: continue; 207: p->pr = pc->pc_pr; 208: p->pos.x = pc->pc_adv.x; 209: w += p->pos.x; 210: p++; 211: bsize++; 212: } 213: else { 214: struct pixchar *space = &pf->pf_char[font->space]; 215: while (string < limit) { 216: register struct pixchar *pc = &(pf->pf_char[*string++]); 217: if (pc == 0) 218: continue; 219: p->pr = pc->pc_pr; 220: p->pos.x = pc->pc_adv.x + charpad; 221: if (pc == space) 222: p->pos.x += spacepad; 223: w += p->pos.x; 224: p++; 225: bsize++; 226: } 227: } 228: } 229: sbot = dsty + lheight; 230: sright = dstx + w; 231: if (CursorDisplayed) { 232: extern DEVICE *CurrentDevice; 233: register vsCursor *ms = CurrentDevice->mouse; 234: register CURSOR *cs = CurrentCursor; 235: if (ms->y < sbot && ms->x < sright 236: && ms->y + cs->height > dsty 237: && ms->x + cs->width > dstx) 238: DisplayCursor(NULL); 239: } 240: do { 241: GetNextClip(clips, cleft, ctop, cwidth, cheight); 242: if (dsty >= ctop && sbot <= ctop + cheight 243: && dstx >= cleft && sright <= cleft + cwidth) 244: pr_batchrop(PixRect, dstx - bat[0].pos.x, dsty, 245: op | PIX_DONTCLIP, bat, bsize); 246: else { 247: struct pixrect *region; 248: if (dsty > ctop + cheight) 249: continue; 250: if (dsty + lheight <= ctop) 251: continue; 252: region = pr_region(PixRect, cleft, ctop, cwidth, cheight); 253: pr_batchrop(region, dstx - cleft - bat[0].pos.x, 254: dsty - ctop, 255: op, bat, bsize); 256: pr_destroy(region); 257: } 258: } while (--clipcount > 0); 259: if (!CursorDisplayed) 260: DisplayCursor(CurrentCursor); 261: { 262: static allmask = -1; 263: SetZmask(PixRect, &allmask); 264: } 265: } 266: 267: 268: /* 269: * Copyright (c) 1983 by Sun Microsystems, Inc. 270: */ 271: 272: /* 273: * Memory batchrop 274: */ 275: 276: 277: extern char pr_reversedst[]; 278: extern struct pixrectops mem_ops; 279: 280: 281: 282: #define MEMBATCH(IfClip, IfMask, op, IfReverse) \ 283: for (; --count >= 0; src++) { \ 284: dst.pos.x += src->pos.x; \ 285: dp = dp0 + (((dskew = xoff0 + dst.pos.x) >> 3) & ~1); \ 286: dskew &= 0xF; \ 287: spr = src->pr; \ 288: sizex = spr->pr_size.x; \ 289: sizey = spr->pr_size.y; \ 290: sprd = mpr_d(spr); \ 291: if (sprd->md_linebytes != 2) \ 292: goto hard; \ 293: sp = (u_short *) sprd->md_image; \ 294: IfClip( if (dst.pos.x + sizex > limx) \ 295: goto hard; \ 296: if (dst.pos.y + sizey > limy) \ 297: sizey = limy - dst.pos.y; \ 298: if (dst.pos.x < 0) \ 299: goto hard; \ 300: if (dst.pos.y < 0) { \ 301: sizey += dst.pos.y; \ 302: sp -= dst.pos.y; \ 303: dp -= pr_product(dst.pos.y, vert); \ 304: } \ 305: if (sizex <= 0) \ 306: continue; \ 307: ,) \ 308: if (--sizey>=0) \ 309: if (dskew + sizex <= 16) { \ 310: IfMask( register short mask; \ 311: mask = 0x8000; \ 312: sizex -= 1; \ 313: mask >>= sizex; \ 314: ((unsigned short) mask) >>= dskew; \ 315: IfReverse(mask = ~mask;,),) \ 316: do { \ 317: IfMask(*(u_short *) dp IfReverse(&,|)= mask;,) \ 318: *(u_short *) dp op (*sp++ >> dskew); \ 319: dp += vert; \ 320: } while (--sizey != -1); \ 321: } \ 322: else { \ 323: IfMask( register long mask; \ 324: mask = 0x80000000; \ 325: sizex -= 1; \ 326: mask >>= sizex; \ 327: ((unsigned long) mask) >>= dskew; \ 328: IfReverse(mask = ~mask;,),) \ 329: dskew = 16 - dskew; \ 330: do { \ 331: IfMask(*(u_int *) dp IfReverse(&,|)= mask;,) \ 332: *(u_int *) dp op (*sp++ << dskew); \ 333: dp += vert; \ 334: } while (--sizey != -1); \ 335: } \ 336: } 337: 338: #define MTRUE(a,b) a 339: #define MFALSE(a,b) b 340: 341: #define ClippedOp(mask,op,revmask) \ 342: if(clip) MEMBATCH(MTRUE,mask,op,revmask) \ 343: else MEMBATCH(MFALSE,mask,op,revmask) 344: 345: mem_batchrop(dst, op, src, count) 346: struct pr_prpos dst; 347: int op; 348: struct pr_prpos *src; 349: short count; 350: { 351: register u_short *sp; 352: register char *dp; 353: char *dp0; 354: register char *handy; 355: register short sizex, sizey; 356: register vert, dskew; 357: int dskew0, xoff0; 358: int errors = 0; 359: int clip, limx, limy; 360: int oppassed = op; 361: 362: /* 363: * Preliminaries: get pixrect data and image pointers; decide whether 364: * clipping. If not clipping, normalize op, else compute limits for 365: * cursors for later comparisons. 366: */ 367: 368: clip = 0; 369: if (!(op & PIX_DONTCLIP)) { 370: clip = 1; 371: limx = dst.pr->pr_size.x; 372: limy = dst.pr->pr_size.y; 373: } 374: op = (op >> 1) & 0xf; /* Kill dontclip, just keep useful */ 375: /* 376: * If destination is reverse video, invert function. FIXME: we dont 377: * deal with a reverse video source. Admittedly its unlikely that 378: * anyone will call batchrop with a device pixrect as source (since we 379: * copy the whole pixrect), but this is a bug. 380: */ 381: if (mpr_d(dst.pr)->md_flags & MP_REVERSEVIDEO) 382: op = pr_reversedst[op]; 383: 384: vert = mpr_d(dst.pr)->md_linebytes; 385: #define dprd ((struct mpr_data *)handy) 386: dprd = mpr_d(dst.pr); 387: xoff0 = dprd->md_offset.x; 388: dp0 = (char *) ((int) dprd->md_image 389: + pr_product(dprd->md_linebytes, 390: dst.pos.y + dprd->md_offset.y)); 391: #undef dprd 392: restart: 393: #define spr ((struct pixrect *)handy) 394: #define sprd ((struct mpr_data *)handy) 395: switch (op) { 396: case (PIX_SRC ^ PIX_DST) >> 1: 397: ClippedOp(MFALSE, ^=, MTRUE); 398: break; 399: case PIX_SRC >> 1: 400: ClippedOp(MTRUE, |=, MTRUE); 401: break; 402: case PIX_NOT(PIX_SRC) >> 1: 403: ClippedOp(MTRUE, ^=, MFALSE); 404: break; 405: case (PIX_SRC | PIX_DST) >> 1: 406: ClippedOp(MFALSE, |=, MTRUE); 407: break; 408: case (PIX_NOT(PIX_SRC) & PIX_DST) >> 1: 409: ClippedOp(MFALSE, &=~, MTRUE); 410: break; 411: default: 412: for (; --count >= 0; src++) { 413: dst.pos.x += src->pos.x; 414: errors |= mem_rop(dst.pr, dst.pos, src->pr->pr_size, 415: oppassed, src->pr, 0, 0); 416: } 417: } 418: return errors; 419: hard: 420: if (dst.pos.x + sizex <= 0) 421: /* 422: * Completely clipped on left... 423: */ 424: ; 425: else { 426: errors |= mem_rop(dst.pr, dst.pos, src->pr->pr_size, 427: oppassed, src->pr, 0, 0); 428: } 429: src++; 430: goto restart; 431: } 432: 433: /* 434: * cg2batch.c: Sun2 Color batchrop 435: */ 436: 437: extern struct pixrectops mem_ops; 438: 439: 440: extern short mrc_lmasktable[]; 441: extern short mrc_rmasktable[]; 442: 443: #define resolution unused, 0 444: 445: cg2_batchrop(dst, op, src, count) 446: struct pr_prpos dst; 447: int op; 448: struct pr_prpos *src; 449: register int count; 450: { 451: register short sizey; 452: register int tem, w, prime, linebytes; 453: register short *bx, *leftx, *ma; 454: register struct memropc *ropregs; 455: short sizex; 456: int clip; 457: struct pixrect *pr; 458: short *ma_homey; 459: short homex, homey, limx, limy, dstx, dsty, by; 460: 461: struct cg2fb *fb; 462: struct mpr_data *md; 463: int oppassed = op; 464: int errors = 0; 465: short color; 466: 467: if (count <= 0) 468: return (0); 469: 470: /* 471: * Preliminaries: get pixrect data and frame buffer pointers; decide 472: * whether clipping. If not clipping, normalize op, else compute 473: * limits for cursors for later comparisons. 474: */ 475: #define dbd ((struct cg2pr *)leftx) 476: dbd = cg2_d(dst.pr); 477: homex = dbd->cgpr_offset.x; 478: homey = dbd->cgpr_offset.y; 479: #define FB ((struct cg2fb *)leftx) 480: FB = dbd->cgpr_va; 481: fb = FB; 482: #undef dbd 483: ropregs = &FB->ropcontrol[CG2_ALLROP].ropregs; 484: if (op & PIX_DONTCLIP) { 485: op &= ~PIX_DONTCLIP; 486: clip = 0; 487: } 488: else { 489: clip = 1; 490: limx = homex + dst.pr->pr_size.x; 491: limy = homey + dst.pr->pr_size.y; 492: } 493: dstx = homex + dst.pos.x; 494: dsty = homey + dst.pos.y; 495: if (private_bgcolor < 0) { 496: FB->ppmask.reg = private_fgcolor; /* set colored text */ 497: ropregs->mrc_pattern = -1; 498: FB->ppmask.reg = ~private_fgcolor; 499: ropregs->mrc_pattern = 0; 500: FB->ppmask.reg = private_czmask; 501: switch (op & 0x1E) { 502: case PIX_SRC ^ PIX_DST: 503: ropregs->mrc_op = CG_SRC & (CG_MASK ^ CG_DEST) | ~CG_SRC & CG_DEST; 504: break; 505: case PIX_NOT(PIX_DST): 506: ropregs->mrc_op = CG_SRC & (~CG_DEST) | ~CG_SRC & CG_DEST; 507: break; 508: default: 509: ropregs->mrc_op = CG_SRC & CG_MASK | ~CG_SRC & CG_DEST; 510: break; 511: } 512: } 513: else { 514: FB->ppmask.reg = private_fgcolor & private_bgcolor; 515: ropregs->mrc_op = ~0; 516: FB->ppmask.reg = ~(private_fgcolor | private_bgcolor); 517: ropregs->mrc_op = 0; 518: FB->ppmask.reg = private_fgcolor & ~private_bgcolor; 519: ropregs->mrc_op = CG_SRC; 520: FB->ppmask.reg = ~private_fgcolor & private_bgcolor; 521: ropregs->mrc_op = ~CG_SRC; 522: FB->ppmask.reg = private_czmask; 523: } 524: FB->status.reg.ropmode = PWWWRD; 525: linebytes = cg2_linebytes(FB, PWWWRD); 526: #undef FB 527: 528: for (; --count >= 0; src++) { 529: /* 530: * Update destination x and y by pre-advance amount. If no pixrect 531: * for this, then skip to next. 532: */ 533: dstx += src->pos.x; 534: pr = src->pr; 535: if (pr == 0) 536: continue; 537: sizex = pr->pr_size.x; 538: sizey = pr->pr_size.y; 539: md = mpr_d(pr); 540: ma = md->md_image; 541: 542: /* 543: * Grab sizes and address of image. If clipping (rare case 544: * hopefully) compare cursors against limits. 545: */ 546: by = dsty; 547: tem = 0; 548: if (clip) { 549: if (dstx + sizex > limx) 550: sizex = limx - dstx; 551: if (dsty + sizey > limy) 552: sizey = limy - dsty; 553: if (dsty < homey) { /* works if pr_depth = 1! */ 554: tem = homey - dsty; 555: by += tem; 556: ma += pr_product(tem, (md->md_linebytes >> 1)); 557: sizey -= tem; 558: tem = 0; 559: } 560: if (dstx < homex) { 561: tem = homex - dstx; 562: ma += tem >> 4; 563: sizex -= tem; 564: } 565: if (sizex <= 0) 566: continue; 567: } 568: 569: /* 570: * Hard case: characters greater than 16 wide. 571: */ 572: ma_homey = ma; 573: 574: /* set the ROP chip word width and opcount */ 575: 576: w = cg2_prskew(dstx); /* source skew is 0 */ 577: ropregs->mrc_shift = (w & 0xF) | (1 << 8); 578: prime = !w; 579: w = (sizex + w + (tem & 0xF) - 1) >> 4; 580: ropregs->mrc_width = w; 581: ropregs->mrc_opcount = w; 582: 583: /* set the ROP chip end masks */ 584: 585: ropregs->mrc_mask1 = 586: mrc_lmasktable[(tem += dstx) & 0xf]; 587: ropregs->mrc_mask2 = 588: mrc_rmasktable[(sizex + tem - 1) & 0xf]; 589: 590: leftx = cg2_ropwordaddr(fb, 0, tem, by); 591: tem = md->md_linebytes; 592: if (--sizey >= 0) 593: if (w) { 594: w++; 595: do { 596: register short i = w; 597: ma = ma_homey; 598: bx = leftx; 599: if (prime) 600: ropregs->mrc_source1 = *ma++; 601: while (i--) 602: *bx++ = *ma++; 603: (char *) ma_homey += tem; 604: (char *) leftx += linebytes; 605: } while (--sizey != -1); 606: } 607: else { 608: bx = leftx; 609: ma = ma_homey; 610: if (prime) { 611: ma++; 612: do { 613: ma--; 614: ropregs->mrc_source1 = *ma++; 615: *bx = *ma; 616: (char *) ma += tem; 617: (char *) bx += linebytes; 618: } while (--sizey != -1); 619: } 620: else 621: do { 622: *bx = *ma; 623: (char *) ma += tem; 624: (char *) bx += linebytes; 625: } while (--sizey != -1); 626: } 627: } 628: 629: return (errors); 630: } 631: 632: #endif sun