Annotation of 43BSD/contrib/X/Xlib/Xtextlib.c, revision 1.1

1.1     ! root        1: /* $Header: Xtextlib.c,v 10.4 86/02/01 15:42:32 tony Rel $ */
        !             2: /* Library of routines for creating a simple text output window.
        !             3:  *
        !             4:  * Routines in the library are:
        !             5:  *
        !             6:  *     TextCreate              Creates a new instance of a text window
        !             7:  *     TextDestroy             Destroys the window
        !             8:  *     TextClear               Clears a text window
        !             9:  *     TextRedisplay           Redisplays the window
        !            10:  *     TextEvent               Handles exposure and unmapping events
        !            11:  *     TextPutString           Displays a string in a text window
        !            12:  *     TextPutChar             Displays a character in a text window
        !            13:  *     TextPrintf              Does a printf in a text window
        !            14:  *
        !            15:  * All these routines pass around a pointer to a TextWindow data structure:
        !            16:  *
        !            17:  * typedef struct _TextWindow {
        !            18:  *     Window w;               Window to use
        !            19:  *     FontInfo *font;         Font to use for text
        !            20:  *     short num_lines;        Number of lines in the window
        !            21:  *     short num_chars;        The length of each line
        !            22:  *     short mapped;           Whether or not the window is mapped
        !            23:  *     short height;           Height of window in pixels
        !            24:  *     short width;            Width of window in pixels
        !            25:  *     short first_line;       The index of the first line
        !            26:  *     char **lines;           Ptr to array of text lines
        !            27:  *     short *line_length;     Ptr to array of line lengths (in pixels)
        !            28:  *     short *line_chars;      Ptr to array of line lengths in chars
        !            29:  *     short last_line;        Which line is the last
        !            30:  *     short last_char;        Length of the last line
        !            31:  *     short next_x;           X-coord for next character
        !            32:  *     short next_y;           Y-coord for next character
        !            33:  *     unsigned int eventmask; List of events we're interested in
        !            34:  *     char *scroll_history;   Ptr to list of scroll amounts
        !            35:  *     short scroll_count;     Number of outstanding scrolls
        !            36:  *     short scroll_start;     Where in the history the history starts
        !            37:  *     short old_scrolls;      Number of ignorable outstanding scrolls
        !            38:  *     short fastscroll;       Whether or not to use fast scrolling
        !            39:  * } TextWindow; 
        !            40:  *
        !            41:  * Applications should not modify anything in this data structure, obviously!
        !            42:  * They may, however, have reason to get information out of it. (Such as the
        !            43:  * window id for mapping).
        !            44:  *
        !            45:  * Information about the first line of the window is stored in the array
        !            46:  * entries subscripted by [first_line]; the arrays wrap back up at the end.
        !            47:  * Last_char should always be the same as line_chars[last_line]. 
        !            48:  * Similarly, next_x should always be the same as line_length[last_line];
        !            49:  *
        !            50:  * The only complicated thing about these procedures is the way they keep
        !            51:  * track of scrolling.  When a scroll is done, X sends ExposeRegions for
        !            52:  * every region that needs to be patched up and then an ExposeCopy event.
        !            53:  * The ExposeCopy comes even if there were no regions.  The only problem
        !            54:  * is that more scrolls may have been done in the meantime.  So we keep a
        !            55:  * history of how much cumulative scrolling has been done in the
        !            56:  * scroll_history list.  scroll_start tells which one to start with, and
        !            57:  * scroll_count tells how many there are (they wrap around).  The list is
        !            58:  * num_lines long since anything that's scrolled away longer ago than that
        !            59:  * has scrolled off the screen.  The old_scrolls field gets set whenever the
        !            60:  * screen is fully updated for some reason or other; it means that that
        !            61:  * many ExposeCopy events can be completely ignored since the screen has
        !            62:  * been fully updated.
        !            63:  */
        !            64: 
        !            65: #include <stdio.h>
        !            66: #include "Xlib.h"
        !            67: #include "Xtext.h"
        !            68: 
        !            69: #ifndef TRUE
        !            70: #define TRUE 1
        !            71: #define FALSE 0
        !            72: #endif
        !            73: 
        !            74: /* Define the width of the left margin */
        !            75: 
        !            76: #define mar_width 2
        !            77: 
        !            78: char *calloc(), *malloc(), *realloc();
        !            79: 
        !            80: /* The following variable is sometimes set by TextPutString to temporarily
        !            81:    disable screen updating. */
        !            82: 
        !            83: static int dont_update = FALSE;
        !            84: 
        !            85: /* TextCreate creates a new window which will use the
        !            86:  * specified font.  The window is height lines high and width
        !            87:  * characters wide.  Note that since a variable-width font may be
        !            88:  * used, the width is calculated using the average width of the font.
        !            89:  * Colors are used as specified.
        !            90:  */
        !            91: 
        !            92: TextWindow *TextCreate (width, height, x, y, parent, fontname,
        !            93:                bwidth, fgpixel, bgpixel, bordercolor, fastscroll)
        !            94:        int height, width, x, y, bwidth, fastscroll;
        !            95:        Window parent;
        !            96:        char *fontname;
        !            97:        int fgpixel, bgpixel;
        !            98:        Pixmap bordercolor;
        !            99: {
        !           100:        register TextWindow *t;
        !           101:        register int i;
        !           102:        register FontInfo *f;
        !           103:        Window XCreateWindow();
        !           104:        Pixmap bgpixmap;
        !           105: 
        !           106:        if ((t = (TextWindow *) malloc(sizeof(TextWindow))) ==
        !           107:                NULL) return NULL;
        !           108: 
        !           109:        if ((f = t->font = XOpenFont(fontname)) == NULL) {
        !           110:            TextDestroy(t);
        !           111:            return NULL;
        !           112:        }
        !           113: 
        !           114:        t->fgpixel = fgpixel;
        !           115:        t->bgpixel = bgpixel;
        !           116: 
        !           117:        if ((bgpixmap = XMakeTile(bgpixel)) == NULL) {
        !           118:            TextDestroy(t);
        !           119:            return NULL;
        !           120:        }
        !           121: 
        !           122:        t->width = width * f->width + mar_width;
        !           123:        t->height = height * f->height;
        !           124: 
        !           125:        t->w = XCreateWindow (parent, x, y, t->width, t->height,
        !           126:                bwidth, bordercolor, bgpixmap);
        !           127:        if (t->w == NULL) {
        !           128:            TextDestroy(t);
        !           129:            XFreePixmap(bgpixmap);
        !           130:            return NULL;
        !           131:        }
        !           132: 
        !           133:        XFreePixmap(bgpixmap);
        !           134: 
        !           135:        t->eventmask = ExposeRegion | ExposeCopy | UnmapWindow;
        !           136:        /* (ExposeRegion automatically selects ExposeWindow) */
        !           137: 
        !           138:        XSelectInput (t->w, t->eventmask);
        !           139: 
        !           140:        XSetResizeHint (t->w, mar_width, 0, f->width, f->height);
        !           141:        t->fastscroll = fastscroll;
        !           142:        t->mapped = FALSE;
        !           143:        t->num_lines = height;
        !           144:        t->num_chars = width;
        !           145: 
        !           146:        t->first_line = 0;
        !           147: 
        !           148:        if ((t->lines = (char **)
        !           149:                calloc (height, sizeof (char *))) == NULL) {
        !           150:            TextDestroy(t);
        !           151:            return NULL;
        !           152:        }
        !           153: 
        !           154:        if ((t->line_length = (short *)
        !           155:                calloc (height, sizeof (short))) == NULL) {
        !           156:            TextDestroy(t);
        !           157:            return NULL;
        !           158:        }
        !           159: 
        !           160:        if ((t->line_chars = (short *)
        !           161:                calloc (height, sizeof (short))) == NULL) {
        !           162:            TextDestroy(t);
        !           163:            return NULL;
        !           164:        }
        !           165: 
        !           166:        for (i = 0; i < height; i++) {
        !           167:            if ((t->lines[i] = (char *)
        !           168:                    calloc (width+1, sizeof (char))) == NULL) {
        !           169:                TextDestroy(t);
        !           170:                return NULL;
        !           171:            }
        !           172:        }
        !           173: 
        !           174:        if ((t->scroll_history = calloc(height, sizeof (char))) == NULL) {
        !           175:            TextDestroy(t);
        !           176:            return NULL;
        !           177:        }
        !           178: 
        !           179:        t->scroll_count = t->scroll_start = t->old_scrolls = 0;
        !           180:        TextClear(t);
        !           181:        return t;
        !           182: }
        !           183: 
        !           184: /* Free all the storage associated with a textwindow */
        !           185: 
        !           186: TextDestroy(t)
        !           187:        register TextWindow *t;
        !           188: {
        !           189:        register int i;
        !           190: 
        !           191:        /* Free things in the order we allocated them.  If something doesn't
        !           192:           exist, don't free it!) */
        !           193: 
        !           194:        if (t->font) {
        !           195:            if (t->font->fixedwidth == 0) free(t->font->widths);
        !           196:            free(t->font);
        !           197:        }
        !           198: 
        !           199:        if (t->w) XDestroyWindow(t->w);
        !           200: 
        !           201:        if (t->lines) {
        !           202:            for (i = 0; i < t->num_lines; i++) {
        !           203:                if (t->lines[i]) free(t->lines[i]);
        !           204:            }
        !           205:            free(t->lines);
        !           206:        }
        !           207: 
        !           208:        if (t->line_length) free (t->line_length);
        !           209:        if (t->line_chars) free (t->line_chars);
        !           210:        if (t->scroll_history) free (t->scroll_history);
        !           211: 
        !           212:        /* And finally the data structure itself! */
        !           213: 
        !           214:        free (t);
        !           215: }
        !           216: 
        !           217: /* Clear out a text window and redisplay */
        !           218: 
        !           219: TextClear(t)
        !           220:        register TextWindow *t;
        !           221: {
        !           222:        register int i;
        !           223: 
        !           224:        for (i = 0; i < t->num_lines; i++) {
        !           225:            t->lines[i][0] = '\0';
        !           226:            t->line_chars[i] = 0;
        !           227:            t->line_length[i] = mar_width;      /* Allow a left margin */
        !           228:        }
        !           229:        t->last_line = 0;
        !           230:        t->last_char = 0;
        !           231:        t->next_x = mar_width;          /* Allow a left margin */
        !           232:        t->next_y = 0;
        !           233:        t->first_line = 0;
        !           234: 
        !           235:        TextRedisplay(t);
        !           236: }
        !           237: 
        !           238: /* Redisplays a text window */
        !           239: 
        !           240: TextRedisplay (t)
        !           241:        register TextWindow *t;
        !           242: {
        !           243:        if (!t->mapped) return;
        !           244: 
        !           245:        /* Clear the border area */
        !           246: 
        !           247:        XPixSet(t->w, 0, 0, mar_width, t->height, t->bgpixel);
        !           248: 
        !           249:        Redisplay_lines(t, 0, t->num_lines - 1);
        !           250: 
        !           251:        /* Any outstanding copies from scrolls can now be ignored */
        !           252: 
        !           253:        t->old_scrolls = t->scroll_count;
        !           254:        t->scroll_count = t->scroll_start = 0;
        !           255: }
        !           256: 
        !           257: Redisplay_lines(t, start, finish)
        !           258:        register TextWindow *t;
        !           259:        int start, finish;
        !           260: {
        !           261:        register int i, j, y, height = t->font->height, x, width;
        !           262: 
        !           263:        if (finish < 0) return;
        !           264:        if (start < 0) start = 0;
        !           265: 
        !           266:        y = start * height;
        !           267:        j = start + t->first_line;
        !           268: 
        !           269:        for (i = start; i <= finish; i++) {
        !           270:            if (j >= t->num_lines) j = 0;
        !           271: 
        !           272:            if (t->line_chars[j]) {
        !           273:                XText (t->w, mar_width, y, t->lines[j], t->line_chars[j],
        !           274:                        t->font->id, t->fgpixel, t->bgpixel);
        !           275:            }
        !           276: 
        !           277:            x = t->line_length[j];
        !           278:            width = t->width - x;
        !           279: 
        !           280:            if (width > 0) XPixSet(t->w, x, y, width, height, t->bgpixel);
        !           281:            y += height;
        !           282:            j++;
        !           283:        }
        !           284: }
        !           285: 
        !           286: /* Handles an event.  If it's not an event it knows how to deal with,
        !           287:    returns TRUE, otherwise FALSE. */
        !           288: 
        !           289: int TextEvent(t, e)
        !           290:        register TextWindow *t;
        !           291:        XEvent *e;
        !           292: {
        !           293:        XExposeEvent *ee = (XExposeEvent *) e;
        !           294:        int offset;
        !           295: 
        !           296:        switch (e->type) {
        !           297:            case ExposeWindow:
        !           298:                if (ee->height != t->height || ee->width != t->width) {
        !           299:                    Change_text_window_size(t, ee->height / t->font->height,
        !           300:                            ee->width / t->font->width);
        !           301:                }
        !           302:                t->mapped = TRUE;
        !           303:                TextRedisplay(t);
        !           304:                break;
        !           305: 
        !           306:            case ExposeRegion:
        !           307:                /* If there have been more scrolls than there are lines,
        !           308:                   this stuff has already scrolled off! */
        !           309: 
        !           310:                if (t->scroll_count > t->num_lines) return FALSE;
        !           311: 
        !           312:                /* If this is for an old scroll, ignore it */
        !           313: 
        !           314:                if (ee->detail == ExposeCopy && t->old_scrolls) return FALSE;
        !           315: 
        !           316:                if (t->scroll_count > 0) {
        !           317:                    offset = t->scroll_history[t->scroll_start];
        !           318:                } else offset = 0;
        !           319:                Redisplay_lines(t, ee->y / t->font->height - offset,
        !           320:                        (ee->y + ee->height - 1) / t->font->height - offset);
        !           321:                break;
        !           322: 
        !           323:            case UnmapWindow:
        !           324:                t->mapped = FALSE;
        !           325:                break;
        !           326: 
        !           327:            case ExposeCopy:    /* We've finished the events for one scroll */
        !           328:                /* If there are old scrolls, just decrement the count and
        !           329:                   return */
        !           330: 
        !           331:                if (t->old_scrolls) {
        !           332:                    t->old_scrolls--;
        !           333:                    return FALSE;
        !           334:                }
        !           335:                t->scroll_count--;
        !           336:                if (t->scroll_count < t->num_lines) {
        !           337:                    t->scroll_start++;
        !           338:                    if (t->scroll_start >= t->num_lines) t->scroll_start = 0;
        !           339:                }
        !           340:                break;
        !           341: 
        !           342:            default:
        !           343:                return TRUE;
        !           344:        }
        !           345:        return FALSE;
        !           346: }
        !           347: 
        !           348: Change_text_window_size (t, new_h, new_w)
        !           349:        register TextWindow *t;
        !           350:        register int new_h, new_w;
        !           351: {
        !           352:        register int i;
        !           353:        register char *curline;
        !           354: 
        !           355:        Normalize(t);           /* Rearrange lines so that first_line = 0 */
        !           356: 
        !           357:        /* First free up any now extraneous lines */
        !           358: 
        !           359:        for (i = new_h; i < t->num_lines; i++) free(t->lines[i]);
        !           360: 
        !           361:        if ((t->lines = (char **)
        !           362:                realloc(t->lines, new_h * sizeof (char *))) == NULL) {
        !           363:            return;
        !           364:        }
        !           365: 
        !           366:        if ((t->line_length = (short *)
        !           367:                realloc(t->line_length, new_h * sizeof (short))) == NULL) {
        !           368:            return;
        !           369:        }
        !           370: 
        !           371:        if ((t->line_chars = (short *)
        !           372:                realloc(t->line_chars, new_h * sizeof (short))) == NULL) {
        !           373:            return;
        !           374:        }
        !           375: 
        !           376:        if ((t->scroll_history = realloc(t->scroll_history, new_h)) == NULL) {
        !           377:            return;
        !           378:        }
        !           379: 
        !           380:        for (i = 0; i < new_h; i++) {
        !           381:            if (i < t->num_lines) {
        !           382:                if ((curline = t->lines[i] =
        !           383:                        realloc(t->lines[i], new_w + 1)) == NULL) {
        !           384:                    return;
        !           385:                }
        !           386: 
        !           387:                if (t->line_chars[i] > new_w) {
        !           388:                    t->line_chars[i] = new_w;
        !           389:                    curline[new_w] = '\0';      /* Truncate the line */
        !           390:                    t->line_length[i] = mar_width +
        !           391:                            XStringWidth (curline, t->font, 0, 0);
        !           392:                }
        !           393:            } else {
        !           394:                if ((t->lines[i] = malloc(new_w+1)) == NULL) {
        !           395:                    return;
        !           396:                }
        !           397:                t->lines[i][0] = '\0';
        !           398:                t->line_chars[i] = 0;
        !           399:                t->line_length[i] = mar_width;
        !           400:            }
        !           401:        }
        !           402: 
        !           403:        if (t->last_line >= new_h) {
        !           404:            t->last_line = new_h - 1;
        !           405:            t->last_char = t->line_chars[t->last_line];
        !           406:            t->next_x = t->line_length[t->last_line];
        !           407:            t->next_y = t->last_line * t->font->height;
        !           408: 
        !           409:        } else if (t->last_char > new_w) {
        !           410:            t->last_char = t->line_chars[t->last_line];
        !           411:            t->next_x = t->line_length[t->last_line];
        !           412:        }
        !           413: 
        !           414:        t->num_lines = new_h;
        !           415:        t->num_chars = new_w;
        !           416:        t->height = new_h * t->font->height;
        !           417:        t->width = new_w * t->font->width + mar_width;
        !           418: }
        !           419: 
        !           420: /* Routine to re-arrange the lines in a window structure so that first_line
        !           421:    is equal to 0. */
        !           422: 
        !           423: Normalize(t)
        !           424:        register TextWindow *t;
        !           425: {
        !           426:        if (t->first_line == 0) return;
        !           427: 
        !           428:        t->last_line -= t->first_line;
        !           429:        if (t->last_line < 0) t->last_line += t->num_lines;
        !           430: 
        !           431:        Spin_lines(t, 0, t->num_lines-1, t->first_line);
        !           432: 
        !           433:        t->first_line = 0;
        !           434: }
        !           435: 
        !           436: /* Spin lines rotates the m through n lines of the arrays
        !           437:    forward offset places.  For example, 012345 spun forward 2 is 234501.
        !           438:    It's straightforward to spin the first part of the arrays; and we
        !           439:    call Spin_lines recursively to do the last offset elements */
        !           440: 
        !           441: /* Actually, it's tail-recursive, so I just use a loop.  But I can
        !           442:    pretend, can't I? */
        !           443: 
        !           444: Spin_lines(t, m, n, offset)
        !           445:        register TextWindow *t;
        !           446:        int m, n;
        !           447:        register int offset;
        !           448: {
        !           449:        register int i;
        !           450:        register int temp;              /* Temporaries */
        !           451:        register char *tempc;
        !           452: 
        !           453:        while (1) {
        !           454:            if (offset == 0 || offset > n-m) return;
        !           455: 
        !           456:            for (i = m; i <= n-offset; i++) {
        !           457:                temp = t->line_length[i];
        !           458:                t->line_length[i] = t->line_length[offset+i];
        !           459:                t->line_length[offset+i] = temp;
        !           460: 
        !           461:                temp = t->line_chars[i];
        !           462:                t->line_chars[i] = t->line_chars[offset+i];
        !           463:                t->line_chars[offset+i] = temp;
        !           464: 
        !           465:                tempc = t->lines[i];
        !           466:                t->lines[i] = t->lines[offset+i];
        !           467:                t->lines[offset+i] = tempc;
        !           468:            }
        !           469: 
        !           470: /*         Spin_lines(t, n-offset+1, n, offset - ((n-m+1) % offset)); */
        !           471: 
        !           472:            temp = m;
        !           473:            m = n - offset + 1;
        !           474:            offset -= (n - temp + 1) % offset;
        !           475:        }
        !           476: }
        !           477: 
        !           478: /* Routine to put a string in a text window.  If fastscroll is
        !           479:    set in the TextWindow structure, a single block scroll is done instead
        !           480:    of scrolling at each newline. */
        !           481: 
        !           482: #define verybig 10000  /* Amount to scroll if we should refresh instead */
        !           483: 
        !           484: TextPutString (t, str)
        !           485:        register TextWindow *t;
        !           486:        register char *str;
        !           487: {
        !           488:        register char *ch = str;
        !           489:        register char oldch;
        !           490:        int jump = t->fastscroll;       /* Whether to do jump scrolling */
        !           491:        int newlines, scroll;
        !           492: 
        !           493:        if (jump) jump = Count_lines (t, str, &newlines, &scroll);
        !           494: 
        !           495:        while (1) {
        !           496:            while (*ch != '\0' && *ch != '\n') ch++;
        !           497:            if (ch != str) {
        !           498:                oldch = *ch;
        !           499:                *ch = '\0';
        !           500:                Do_text_string (t, str);
        !           501:                *ch = oldch;
        !           502:            }
        !           503:            if (*ch == '\0') break;
        !           504:            if (jump && newlines == scroll) {
        !           505:                Clear_lines (t, newlines);
        !           506:                dont_update = TRUE;     /* Stop updating now */
        !           507:            }
        !           508:            newlines--;
        !           509:            TextPutChar (t, *ch);
        !           510:            str = ++ch;
        !           511:        }
        !           512:        if (t->mapped && jump) {
        !           513:            if (scroll != verybig) Scroll_text_window (t, scroll);
        !           514:            else TextRedisplay (t);
        !           515:        }
        !           516:        dont_update = FALSE;
        !           517: }
        !           518: 
        !           519: /* Count the number of lines in str, calculate how much scrolling
        !           520:    will be needed, and return whether this amount is positive */
        !           521: 
        !           522: int Count_lines (t, str, newlines, scroll)
        !           523:        register TextWindow *t;
        !           524:        register char *str;
        !           525:        int *newlines, *scroll;
        !           526: {
        !           527:        register int num_lines = 0;
        !           528:        register int lines_left, height = t->num_lines;
        !           529: 
        !           530:        *scroll = 0;
        !           531: 
        !           532:        while (*str) {
        !           533:            if (*str++ == '\n') num_lines++;
        !           534:        }
        !           535: 
        !           536:        *newlines = num_lines;
        !           537: 
        !           538:        if (num_lines <= 1) return FALSE;    /* Don't bother jump scrolling */
        !           539: 
        !           540:        /* Would this fill the screen? */
        !           541: 
        !           542:        if (num_lines >= height) {
        !           543:            *scroll = verybig;
        !           544:            return TRUE;
        !           545:        }
        !           546: 
        !           547:        /* Calculate the number of lines left in the window */
        !           548: 
        !           549:        lines_left = height - (t->last_line - t->first_line + 1);
        !           550:        if (lines_left >= height) lines_left -= height;
        !           551: 
        !           552:        /* Figure out how many lines to scroll */
        !           553: 
        !           554:        num_lines -= lines_left;
        !           555: 
        !           556:        if (num_lines <= 0) return FALSE;       /* Enough room already */
        !           557: 
        !           558:        *scroll = num_lines;
        !           559:        return TRUE;
        !           560: }
        !           561: 
        !           562: /* Clear a number of lines in the window data structure */
        !           563: 
        !           564: Clear_lines (t, scroll)
        !           565:        register TextWindow *t;
        !           566:        register int scroll;
        !           567: {
        !           568:        register int i, start = t->first_line;
        !           569:        register int height = t->num_lines;
        !           570: 
        !           571:        /* If this would fill the screen, clear it instead */
        !           572: 
        !           573:        if (scroll >= t->height ) {
        !           574:            TextClear (t);
        !           575:            return;
        !           576:        }
        !           577: 
        !           578:        /* Shift the contents */
        !           579: 
        !           580:        t->first_line += scroll;
        !           581:        if (t->first_line >= height) t->first_line -= height;
        !           582: 
        !           583:        /* Now clear the blank lines */
        !           584: 
        !           585:        for (i = 0; i < scroll; i++) {
        !           586:            t->lines[start][0] = '\0';
        !           587:            t->line_chars[start] = 0;
        !           588:            t->line_length[start] = mar_width;  /* Allow a left margin */
        !           589:            start++;
        !           590:            if (start >= height) start = 0;
        !           591:        }
        !           592: }
        !           593: 
        !           594: /* Store the characters of a string in the window and update the screen,
        !           595:    but only if dont_update isn't set */
        !           596: 
        !           597: Do_text_string (t, str)
        !           598:        register TextWindow *t;
        !           599:        char *str;
        !           600: {
        !           601:        register char *ch = str;
        !           602:        register char *curline = t->lines[t->last_line];
        !           603:        register int curchar = t->last_char;
        !           604:        register int x = t->next_x;
        !           605:        register FontInfo *f = t->font;
        !           606:        int start_x = t->next_x, start = curchar,
        !           607:                minch = f->firstchar, maxch = f->lastchar;
        !           608: 
        !           609:        /* First store the characters in the line */
        !           610: 
        !           611:        while (*ch != '\0' && curchar < t->num_chars) {
        !           612:            curline[curchar] = *ch;
        !           613:            if (*ch >= minch && *ch <= maxch) {
        !           614:                x += f->fixedwidth ? f->width : f->widths[*ch - minch];
        !           615:            }
        !           616:            curchar++;
        !           617:            ch++;
        !           618:        }
        !           619: 
        !           620:        curline[curchar] = '\0';
        !           621:        t->line_chars[t->last_line] = t->last_char = curchar;
        !           622:        t->line_length[t->last_line] = t->next_x = x;
        !           623: 
        !           624:        if (dont_update || !t->mapped) return;
        !           625: 
        !           626:        /* And then update the screen */
        !           627: 
        !           628:        if (start < t->num_chars) {
        !           629:            XText (t->w, start_x, t->next_y, str, curchar-start,
        !           630:                    f->id, t->fgpixel, t->bgpixel);
        !           631:        }
        !           632: }
        !           633: 
        !           634: /* Textputchar displays a character in the text window.  It
        !           635:  * responds to \n as a special character and just displays anything else.
        !           636:  */
        !           637: 
        !           638: TextPutChar (t, ch)
        !           639:        register TextWindow *t;
        !           640:        char ch;
        !           641: {
        !           642:        register int i, height = t->num_lines;
        !           643:        register char *curline = t->lines[t->last_line];
        !           644:        register FontInfo *f = t->font;
        !           645:        
        !           646:        switch (ch) {
        !           647:            case '\0':          /* NULL */
        !           648:                break;
        !           649: 
        !           650:            case '\n':          /* newline */
        !           651:                if (t->last_line == t->first_line - 1 ||
        !           652:                        (t->last_line == height - 1 && t->first_line == 0)) {
        !           653: 
        !           654:                    /* The screen is full...clear out the first line */
        !           655: 
        !           656:                    t->lines[t->first_line][0] = '\0';
        !           657:                    t->line_chars[t->first_line] = 0;
        !           658:                    t->line_length[t->first_line] = mar_width;
        !           659: 
        !           660:                    t->first_line++;                    /* And advance it */
        !           661:                    if (t->first_line == height) t->first_line = 0;
        !           662: 
        !           663:                    if (!dont_update && t->mapped) Scroll_text_window (t, 1);
        !           664: 
        !           665:                } else if (!dont_update) t->next_y += f->height;
        !           666: 
        !           667:                t->last_line++;
        !           668:                if (t->last_line == height) t->last_line = 0;
        !           669: 
        !           670:                t->last_char = 0;
        !           671:                t->next_x = mar_width;
        !           672:                break;
        !           673: 
        !           674:            default:            /* Just insert the character */
        !           675:                t->last_char++;
        !           676:                t->line_chars[t->last_line]++;
        !           677:                if (t->last_char > t->num_chars) break;
        !           678: 
        !           679:                curline[t->last_char] = ch;
        !           680:                curline[t->last_char+1] = '\0';
        !           681: 
        !           682:                if (!dont_update && t->mapped) {
        !           683:                    XText(t->w, t->next_x, t->next_y, &ch, 1,
        !           684:                            f->id, t->fgpixel, t->bgpixel);
        !           685:                }
        !           686:                if (ch <= f->firstchar && ch >= f->lastchar) {
        !           687:                    t->line_length[t->last_line] = t->next_x +=
        !           688:                            (f->fixedwidth ? f->width :
        !           689:                                             f->widths[ch - f->lastchar]);
        !           690:                }
        !           691:                break;
        !           692:        }
        !           693: }
        !           694: 
        !           695: /* This procedure moves the contents of a text window up n lines.
        !           696:  */
        !           697: 
        !           698: Scroll_text_window (t, n)
        !           699:        register TextWindow *t;
        !           700:        register int n;
        !           701: {
        !           702:        register int i, y, x, width, j;
        !           703:        int height = t->font->height;
        !           704:        int scrollsize = n * height;
        !           705: 
        !           706:        /* First shift up the contents */
        !           707: 
        !           708:        XMoveArea(t->w, 0, scrollsize, 0, 0, t->width, t->height-scrollsize);
        !           709: 
        !           710:        /* Now redisplay the bottom n lines */
        !           711: 
        !           712:        y = height * (t->num_lines - n);
        !           713:        i = t->first_line - n;
        !           714:        if (i < 0) i += t->num_lines;
        !           715: 
        !           716:        for (j = 0; j < n; j++) {
        !           717:            if (t->line_chars[i]) {
        !           718:                XText (t->w, mar_width, y, t->lines[i], t->line_chars[i],
        !           719:                        t->font->id, t->fgpixel, t->bgpixel);
        !           720:            }
        !           721:            x = t->line_length[i];
        !           722:            width = t->width - x;
        !           723: 
        !           724:            if (width > 0) XPixSet(t->w, x, y, width, height, t->bgpixel);
        !           725:            y += height;
        !           726:            i++;
        !           727:            if (i == t->num_lines) i = 0;
        !           728:        }
        !           729: 
        !           730:        /* Add the current scroll to all values in the scroll history,
        !           731:           then add a new entry at the end (the history wraps!) */
        !           732: 
        !           733:        i = t->scroll_start;
        !           734: 
        !           735:        for (j = 0; j < t->scroll_count; j++) {
        !           736:            t->scroll_history[i] += n;
        !           737:            i++;
        !           738:            if (i >= t->num_lines) i = 0;
        !           739:        }
        !           740:        t->scroll_count++;
        !           741:        t->scroll_history[i] = n;
        !           742: 
        !           743:        if (t->scroll_count > t->num_lines) t->scroll_start++; /* trash one */
        !           744: }
        !           745: 
        !           746: #define TEXT_BUFSIZE 2048
        !           747: 
        !           748: TextPrintf(t, format, args)
        !           749:        TextWindow *t;
        !           750:        char *format;
        !           751: {
        !           752:        char buffer[TEXT_BUFSIZE+1];
        !           753:        struct _iobuf _strbuf;
        !           754: 
        !           755:        _strbuf._flag = _IOWRT+_IOSTRG;
        !           756:        _strbuf._ptr = buffer;
        !           757:        _strbuf._cnt = TEXT_BUFSIZE;
        !           758:        _doprnt(format, &args, &_strbuf);
        !           759:        _strbuf._cnt++;     /* Be sure there's room for the \0 */
        !           760:        putc('\0', &_strbuf);
        !           761:        TextPutString(t, buffer);
        !           762: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.