Annotation of 43BSDTahoe/new/X/xterm/screen.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *     $Source: /u1/X/xterm/RCS/screen.c,v $
                      3:  *     $Header: screen.c,v 10.100 86/12/01 14:45:17 jg Rel $
                      4:  */
                      5: 
                      6: #include <X/mit-copyright.h>
                      7: 
                      8: /* Copyright    Massachusetts Institute of Technology    1984, 1985    */
                      9: 
                     10: /* screen.c */
                     11: 
                     12: #ifndef lint
                     13: static char csrg_id[] = "@(#)screen.c  1.6\t(Berkeley/CSRG)\t9/21/87";
                     14: static char sccs_id[] = "@(#)screen.c\tX10/6.6B\t12/26/86";
                     15: #endif lint
                     16: 
                     17: #include <X/Xlib.h>
                     18: #include <stdio.h>
                     19: #include <sys/ioctl.h>
                     20: #include <signal.h>
                     21: #include "scrollbar.h"
                     22: #include "ptyx.h"
                     23: #include "error.h"
                     24: 
                     25: extern char *calloc();
                     26: extern char *malloc();
                     27: extern char *realloc();
                     28: 
                     29: ScrnBuf Allocate (nrow, ncol)
                     30: /*
                     31:    allocates memory for a 2-dimensional array of chars and returns a pointer
                     32:    thereto
                     33:    each line is formed from a pair of char arrays.  The first (even) one is
                     34:    the actual character array and the second (odd) one is the attributes.
                     35:  */
                     36: register int nrow, ncol;
                     37: {
                     38:        register ScrnBuf base;
                     39: 
                     40:        if ((base = (ScrnBuf) calloc ((nrow *= 2), sizeof (char *))) == 0)
                     41:                SysError (ERROR_SCALLOC);
                     42: 
                     43:        for (nrow--; nrow >= 0; nrow--)
                     44:                if ((base [nrow] = calloc (ncol, sizeof(char))) == 0)
                     45:                        SysError (ERROR_SCALLOC2);
                     46: 
                     47:        return (base);
                     48: }
                     49: 
                     50: ScreenWrite (screen, str, flags, length)
                     51: /*
                     52:    Writes str into buf at row row and column col.  Characters are set to match
                     53:    flags.
                     54:  */
                     55: Screen *screen;
                     56: char *str;
                     57: register unsigned flags;
                     58: register int length;           /* length of string */
                     59: {
                     60:        register char *att;
                     61:        register int avail  = screen->max_col - screen->cur_col + 1;
                     62:        register char *col;
                     63: 
                     64:        if (length > avail)
                     65:            length = avail;
                     66:        if (length <= 0)
                     67:                return;
                     68: 
                     69:        col = screen->buf[avail = 2 * screen->cur_row] + screen->cur_col;
                     70:        att = screen->buf[avail + 1] + screen->cur_col;
                     71:        flags &= ATTRIBUTES;
                     72:        bcopy(str, col, length);
                     73:        while(length-- > 0)
                     74:                *att++ = flags;
                     75: }
                     76: 
                     77: ScrnInsertLine (sb, last, where, n, size)
                     78: /*
                     79:    Inserts n blank lines at sb + where, treating last as a bottom margin.
                     80:    Size is the size of each entry in sb.
                     81:    Requires: 0 <= where < where + n <= last
                     82:             n <= MAX_ROWS
                     83:  */
                     84: register ScrnBuf sb;
                     85: int last;
                     86: register int where, n, size;
                     87: {
                     88:        register int i;
                     89:        char *save [2 * MAX_ROWS];
                     90: 
                     91:        /* save n lines at bottom */
                     92:        bcopy ((char *) &sb [2 * (last -= n - 1)], (char *) save,
                     93:                2 * sizeof (char *) * n);
                     94:        
                     95:        /* clear contents of old rows */
                     96:        for (i = 2 * n - 1; i >= 0; i--)
                     97:                bzero ((char *) save [i], size);
                     98: 
                     99:        /* move down lines */
                    100:        bcopy ((char *) &sb [2 * where], (char *) &sb [2 * (where + n)],
                    101:                2 * sizeof (char *) * (last - where));
                    102: 
                    103:        /* reuse storage for new lines at where */
                    104:        bcopy ((char *)save, (char *) &sb[2 * where], 2 * sizeof(char *) * n);
                    105: }
                    106: 
                    107: 
                    108: ScrnDeleteLine (sb, last, where, n, size)
                    109: /*
                    110:    Deletes n lines at sb + where, treating last as a bottom margin.
                    111:    Size is the size of each entry in sb.
                    112:    Requires 0 <= where < where + n < = last
                    113:            n <= MAX_ROWS
                    114:  */
                    115: register ScrnBuf sb;
                    116: register int n, last, size;
                    117: int where;
                    118: {
                    119:        register int i;
                    120:        char *save [2 * MAX_ROWS];
                    121: 
                    122:        /* save n lines at where */
                    123:        bcopy ((char *) &sb[2 * where], (char *)save, 2 * sizeof(char *) * n);
                    124: 
                    125:        /* clear contents of old rows */
                    126:        for (i = 2 * n - 1 ; i >= 0 ; i--)
                    127:                bzero ((char *) save [i], size);
                    128: 
                    129:        /* move up lines */
                    130:        bcopy ((char *) &sb[2 * (where + n)], (char *) &sb[2 * where],
                    131:                2 * sizeof (char *) * ((last -= n - 1) - where));
                    132: 
                    133:        /* reuse storage for new bottom lines */
                    134:        bcopy ((char *)save, (char *) &sb[2 * last],
                    135:                2 * sizeof(char *) * n);
                    136: }
                    137: 
                    138: 
                    139: ScrnInsertChar (sb, row, col, n, size)
                    140: /*
                    141:    Inserts n blanks in sb at row, col.  Size is the size of each row.
                    142:  */
                    143: ScrnBuf sb;
                    144: int row, size;
                    145: register int col, n;
                    146: {
                    147:        register int i, j;
                    148:        register char *ptr = sb [2 * row];
                    149:        register char *att = sb [2 * row + 1];
                    150: 
                    151:        for (i = size - 1; i >= col + n; i--) {
                    152:                ptr[i] = ptr[j = i - n];
                    153:                att[i] = att[j];
                    154:        }
                    155: 
                    156:        bzero (ptr + col, n);
                    157:        bzero (att + col, n);
                    158: }
                    159: 
                    160: 
                    161: ScrnDeleteChar (sb, row, col, n, size)
                    162: /*
                    163:    Deletes n characters in sb at row, col. Size is the size of each row.
                    164:  */
                    165: ScrnBuf sb;
                    166: register int row, size;
                    167: register int n, col;
                    168: {
                    169:        register char *ptr = sb[2 * row];
                    170:        register char *att = sb[2 * row + 1];
                    171:        register nbytes = (size - n - col);
                    172: 
                    173:        bcopy (ptr + col + n, ptr + col, nbytes);
                    174:        bcopy (att + col + n, att + col, nbytes);
                    175:        bzero (ptr + size - n, n);
                    176:        bzero (att + size - n, n);
                    177: }
                    178: 
                    179: 
                    180: ScrnRefresh (screen, toprow, leftcol, nrows, ncols)
                    181: /*
                    182:    Repaints the area enclosed by the parameters.
                    183:    Requires: (toprow, leftcol), (toprow + nrows, leftcol + ncols) are
                    184:             coordinates of characters in screen;
                    185:             nrows and ncols positive.
                    186:  */
                    187: register Screen *screen;
                    188: int toprow, leftcol, nrows, ncols;
                    189: {
                    190:        int y = toprow * FontHeight(screen) + screen->border + Titlebar(screen);
                    191:        register int row;
                    192:        register int topline = screen->topline;
                    193:        int maxrow = toprow + nrows - 1;
                    194:        int scrollamt = screen->scroll_amt;
                    195:        int max = screen->max_row;
                    196:        int dostatus = 0, left, width;
                    197:        
                    198: 
                    199:        if(screen->statusline && maxrow == screen->max_row + 1) {
                    200:                dostatus++;
                    201:                maxrow--;
                    202:        }
                    203:        if(screen->cursor_col >= leftcol && screen->cursor_col <=
                    204:         (leftcol + ncols - 1) && screen->cursor_row >= toprow + topline &&
                    205:         screen->cursor_row <= maxrow + topline)
                    206:                screen->cursor_state = OFF;
                    207:     for( ; ; ) {
                    208:        for (row = toprow; row <= maxrow; y += FontHeight(screen), row++)
                    209:        {
                    210:           register char *chars;
                    211:           register char *att;
                    212:           register int col = leftcol;
                    213:           int maxcol = leftcol + ncols - 1;
                    214:           int lastind;
                    215:           int flags;
                    216:           int gxfunction;
                    217:           Font fnt;
                    218:           int x, yb, pix, n;
                    219: 
                    220:           lastind = row - scrollamt;
                    221:           if (lastind < 0 || lastind > max)
                    222:                continue;
                    223:           chars = screen->buf [2 * (lastind + topline)];
                    224:           att = screen->buf [2 * (lastind + topline) + 1];
                    225: 
                    226:           while (col <= maxcol && (att[col] & ~BOLD) == 0 &&
                    227:            (chars[col] & ~040) == 0)
                    228:                col++;
                    229: 
                    230:           while (col <= maxcol && (att[maxcol] & ~BOLD) == 0 &&
                    231:            (chars[maxcol] & ~040) == 0)
                    232:                maxcol--;
                    233: 
                    234:           if (col > maxcol) continue;
                    235: 
                    236:           flags = att[col];
                    237: 
                    238:           fnt = ActiveIcon(screen)
                    239:                 ? screen->fnt_icon
                    240:                 : (flags & BOLD)
                    241:                   ? screen->fnt_bold
                    242:                   : screen->fnt_norm;
                    243: 
                    244:           x = col * FontWidth(screen) + screen->border;
                    245:           lastind = col;
                    246: 
                    247:           for (; col <= maxcol; col++) {
                    248:                if (att[col] != flags) {
                    249:                   if (((flags & INVERSE) != 0) ^ (dostatus < 0 &&
                    250:                    screen->reversestatus))
                    251:                        XText (VWindow(screen), x, y, &chars[lastind],
                    252:                                n = col - lastind, fnt,
                    253:                                pix = screen->background, screen->foreground);
                    254:                   else
                    255:                        XText (VWindow(screen), x, y, &chars[lastind],
                    256:                                n = col - lastind, fnt,
                    257:                                pix = screen->foreground, screen->background);
                    258:                   if((flags & BOLD) && screen->enbolden)
                    259:                        XTextMask (VWindow(screen), x + 1, y, &chars[lastind],
                    260:                                n, fnt, pix);
                    261:                   if(flags & UNDERLINE) {
                    262:                        yb = y + FontHeight(screen) - 2;
                    263:                        XLine(VWindow(screen), x, yb, x + n * FontWidth(screen),
                    264:                         yb, 1, 1, pix, GXcopy, AllPlanes);
                    265:                   }
                    266: 
                    267:                   x += (col - lastind) * FontWidth(screen);
                    268: 
                    269:                   lastind = col;
                    270: 
                    271:                   flags = att[col];
                    272: 
                    273:                   fnt = ActiveIcon(screen)
                    274:                         ? screen->fnt_icon
                    275:                         : (flags & BOLD)
                    276:                           ? screen->fnt_bold
                    277:                           : screen->fnt_norm;
                    278:                }
                    279: 
                    280:                if(chars[col] == 0)
                    281:                        chars[col] = ' ';
                    282:           }
                    283: 
                    284:           if (((flags & INVERSE) != 0) ^ (dostatus < 0 &&
                    285:            screen->reversestatus))
                    286:                XText (VWindow(screen), x, y, &chars[lastind],
                    287:                 n = col - lastind, fnt, pix = screen->background,
                    288:                 screen->foreground);
                    289:           else
                    290:                XText (VWindow(screen), x, y, &chars[lastind],
                    291:                 n = col - lastind, fnt, pix = screen->foreground,
                    292:                 screen->background);
                    293:           if((flags & BOLD) && screen->enbolden)
                    294:                XTextMask (VWindow(screen), x + 1, y, &chars[lastind],
                    295:                        n, fnt, pix);
                    296:           if(flags & UNDERLINE) {
                    297:                yb = y + FontHeight(screen) - 2;
                    298:                XLine(VWindow(screen), x, yb, x + n * FontWidth(screen), yb, 1, 1,
                    299:                 pix, GXcopy, AllPlanes);
                    300:           }
                    301:        }
                    302:        if(dostatus <= 0)
                    303:                break;
                    304:        dostatus = -1;
                    305:        topline = 0;
                    306:        scrollamt = 0;
                    307:        toprow = maxrow = max = screen->max_row + 1;
                    308:        left = leftcol * FontWidth(screen) + screen->border;
                    309:        width = ncols * FontWidth(screen);
                    310:        if(leftcol == 0) {
                    311:                left--;
                    312:                width++;
                    313:        }
                    314:        if(leftcol + ncols - 1 >= screen->max_col)
                    315:                width++;
                    316:        XPixSet(VWindow(screen), left, y, width, screen->statusheight,
                    317:         screen->reversestatus ? screen->foreground : screen->background);
                    318:        if(!screen->reversestatus)
                    319:                StatusBox(screen);
                    320:        y++;
                    321:     }
                    322: }
                    323: 
                    324: ClearBufRows (screen, first, last)
                    325: /*
                    326:    Sets the rows first though last of the buffer of screen to spaces.
                    327:    Requires first <= last; first, last are rows of screen->buf.
                    328:  */
                    329: register Screen *screen;
                    330: register int first, last;
                    331: {
                    332:        first *= 2;
                    333:        last = 2 * last + 1;
                    334:        while (first <= last)
                    335:                bzero (screen->buf [first++], (screen->max_col + 1));
                    336: }
                    337: 
                    338: ScreenResize (screen, width, height, flags)
                    339: /*
                    340:    Resizes screen:
                    341:    1. If new window would have fractional characters, sets window size so as to
                    342:       discard fractional characters and returns -1.
                    343:       Minimum screen size is 1 X 1.
                    344:       Note that this causes another ExposeWindow event.
                    345:    2. Enlarges screen->buf if necessary.  New space is appended to the bottom
                    346:       and to the right
                    347:    3. Reduces  screen->buf if necessary.  Old space is removed from the bottom
                    348:       and from the right
                    349:    4. Cursor is positioned as closely to its former position as possible
                    350:    5. Sets screen->max_row and screen->max_col to reflect new size
                    351:    6. Maintains the inner border.
                    352:    7. Clears origin mode and sets scrolling region to be entire screen.
                    353:    8. Returns 0
                    354:  */
                    355: register Screen *screen;
                    356: int width, height;
                    357: unsigned *flags;
                    358: {
                    359:        register int rows, cols;
                    360:        register int index;
                    361:        register int savelines;
                    362:        register ScrnBuf sb = screen->allbuf;
                    363:        register ScrnBuf ab = screen->altbuf;
                    364:        register int x;
                    365:        register int border = 2 * screen->border;
                    366:        register int extra, i, j, k;
                    367:        register char *sl0, *sl1;       /* keep status line */
                    368:        double scale_x, scale_y;
                    369: #ifdef TIOCSWINSZ
                    370:        struct winsize ws;
                    371: #endif TIOCSWINSZ
                    372: 
                    373: 
                    374:        /* don't resize on icon exposure */
                    375:        if (ActiveIcon(screen))
                    376:                return( 0 );
                    377: 
                    378:        extra = Titlebar(screen) + screen->statusheight;
                    379:        /* round so that it is unlikely the screen will change size on  */
                    380:        /* small mouse movements.                                       */
                    381:        rows = (height + FontHeight(screen) / 2 - border - extra) /
                    382:         FontHeight(screen);
                    383:        cols = (width + FontWidth(screen) / 2 - border - screen->scrollbar) /
                    384:         FontWidth(screen);
                    385:        if (rows < 1) rows = 1;
                    386:        if (cols < 1) cols = 1;
                    387: 
                    388:        if ((width - border - screen->scrollbar) % FontWidth(screen)
                    389:         != 0 || (height - border - extra) % FontHeight(screen) != 0 ||
                    390:         rows < screen->minrows) {
                    391:                XChangeWindow (VWindow(screen),
                    392:                 cols * FontWidth(screen) + border + screen->scrollbar,
                    393:                 (rows < screen->minrows ? screen->minrows : rows) *
                    394:                 FontHeight(screen) + border + extra);
                    395:                return (-1);
                    396:        }
                    397: 
                    398:        /* change buffers if the screen has changed size */
                    399:        if (screen->max_row != rows - 1 || screen->max_col != cols - 1) {
                    400:                if(screen->cursor_state)
                    401:                        HideCursor();
                    402:                savelines = screen->sb ? screen->savelines : 0;
                    403:                j = screen->max_col + 1;
                    404:                i = cols - j;
                    405:                k = screen->max_row;
                    406:                if(ab) {
                    407:                        /* resize current lines in alternate buf */
                    408:                        for (index = x = 0; index <= k; x += 2, index++) {
                    409:                                if ((ab[x] = realloc(ab[x], cols)) == NULL)
                    410:                                        SysError(ERROR_SREALLOC);
                    411:                                if((ab[x + 1] = realloc(ab[x + 1], cols)) ==
                    412:                                 NULL)
                    413:                                        SysError (ERROR_SREALLOC2);
                    414:                                if (cols > j) {
                    415:                                        bzero (ab [x] + j, i);
                    416:                                        bzero (ab [x + 1] + j, i);
                    417:                                }
                    418:                        }
                    419:                }
                    420:                /* resize current lines */
                    421:                k += savelines + 1;     /* includes status line */
                    422:                for (index = x = 0; index <= k; x += 2, index++) {
                    423:                        if ((sb[x] = realloc(sb[x], cols)) == NULL)
                    424:                                SysError(ERROR_SREALLOC3);
                    425:                        if((sb[x + 1] = realloc(sb[x + 1], cols)) == NULL)
                    426:                                SysError (ERROR_SREALLOC4);
                    427:                        if (cols > j) {
                    428:                                bzero (sb [x] + j, i);
                    429:                                bzero (sb [x + 1] + j, i);
                    430:                        }
                    431:                }
                    432: 
                    433:                /*
                    434:                 * Adjust the number of lines, either discarding the
                    435:                 * oldest (if we're getting shorter) or padding at
                    436:                 * the "old" end with blanks (if we're getting taller.
                    437:                 *
                    438:                 * Throughout this section, i is the number of lines
                    439:                 * we need, j is the number we currently have & index
                    440:                 * is the difference.
                    441:                 */
                    442:                i = rows + savelines + 1;
                    443:                j = screen->max_row + savelines + 2;
                    444:                index = j - i;
                    445:                if (index > 0) {
                    446:                        /* we're getting shorter - free the oldest lines */
                    447:                        for (x = 0; x < 2*index; ) {
                    448:                                free (sb[x++]);
                    449:                        }
                    450:                        /* move the newer stuff into the right place */
                    451:                        k = i * 2 * sizeof(*sb);
                    452:                        bcopy (&sb[2*index], sb, k);
                    453:                        sb = (ScrnBuf) realloc (sb, k);
                    454:                        if (! sb)
                    455:                                SysError (ERROR_RESIZE2);
                    456: 
                    457:                        /* do the same thing for the alternate buf */
                    458:                        if (ab) {
                    459:                                for (x = 0; x < 2*index;) {
                    460:                                        free (ab[x++]);
                    461:                                }
                    462:                                k = (screen->max_row + 1)* sizeof(*sb);
                    463:                                bcopy (&ab[2*index], ab, k);
                    464:                                ab = (ScrnBuf) realloc (ab, k);
                    465:                                if (! ab)
                    466:                                        SysError (ERROR_RESIZE);
                    467:                        }
                    468:                }
                    469:                else if (index < 0) {
                    470:                        /* we're getting taller - add 'index' lines */
                    471:                        /* at the "old" end of the saved lines */
                    472:                        sb = (ScrnBuf) realloc (sb, i * 2 * sizeof(*sb));
                    473:                        if (! sb)
                    474:                                SysError (ERROR_RESIZE2);
                    475: 
                    476:                        /* move up the stuff we want at the new end */
                    477:                        /* of the buffer and fill the hole with blanks */
                    478:                        k = -2 * index;
                    479:                        bcopy (sb, &sb[k], j * 2 * sizeof(*sb));
                    480: 
                    481:                        for (x = 0; x < k; ) {
                    482:                                if (! (sb[x++] = calloc (cols, sizeof(**sb))))
                    483:                                        SysError(ERROR_RESIZROW3);
                    484:                        }
                    485: 
                    486:                        /* do the same thing with the alternate buffer */
                    487:                        if (ab) {
                    488:                                ab = (ScrnBuf) realloc (ab, rows*2*sizeof(*ab));
                    489:                                if (! ab)
                    490:                                        SysError (ERROR_RESIZE);
                    491: 
                    492:                                bcopy (ab, &ab[k], (screen->max_row + 1) *
                    493:                                                   2 * sizeof(*ab));
                    494:                                for (x = 0; x < k; ) {
                    495:                                        if (! (ab[x++] = calloc (cols,
                    496:                                                          sizeof(**ab))))
                    497:                                                SysError(ERROR_RESIZROW4);
                    498:                                }
                    499:                        }
                    500:                }
                    501:                screen->allbuf = sb;
                    502:                screen->buf = &sb[2 * savelines];
                    503:                screen->altbuf = ab;
                    504:        
                    505:                /* add the new lines to the old screen size & pos */
                    506:                screen->max_row -= index;
                    507:                if (! screen->instatus)
                    508:                        screen->cur_row -= index;
                    509:                else
                    510:                        screen->cur_row = screen->max_row + 1;
                    511: 
                    512:                screen->max_row = rows - 1;
                    513:                screen->max_col = cols - 1;
                    514:        
                    515:                /* adjust scrolling region */
                    516:                screen->top_marg = 0;
                    517:                screen->bot_marg = screen->max_row;
                    518:                *flags &= ~ORIGIN;
                    519:        
                    520:                if (screen->cur_row > screen->max_row)
                    521:                        screen->cur_row = screen->max_row;
                    522:                else if (screen->cur_row < 0)
                    523:                        screen->cur_row = 0;
                    524:                if (screen->cur_col > screen->max_col)
                    525:                        screen->cur_col = screen->max_col;
                    526:                else if (screen->cur_col < 0)
                    527:                        screen->cur_col = 0;
                    528:        
                    529:                screen->fullVwin.height = height - extra;
                    530:                screen->fullVwin.width = width;
                    531: 
                    532:                if (screen->active_icon)
                    533:                    SetIconSize( screen );
                    534: 
                    535:        }
                    536:        else if(FullHeight(screen) == height && FullWidth(screen) == width)
                    537:                return(0);      /* nothing has changed at all */
                    538: 
                    539:        if(screen->sb)
                    540:                ResizeScrollBar(screen->sb, width - SCROLLBARWIDTH,
                    541:                 Titlebar(screen) - 1, height - Titlebar(screen), rows);
                    542:        if(screen->title.tbar && FullWidth(screen) != width)
                    543:                VTTitleResize(width);
                    544:        
                    545:        screen->fullVwin.fullheight = height;
                    546:        screen->fullVwin.fullwidth = width;
                    547: #ifdef TIOCSWINSZ
                    548:        /* Set tty's idea of window size */
                    549:        ws.ws_row = rows;
                    550:        ws.ws_col = cols;
                    551:        ws.ws_xpixel = width;
                    552:        ws.ws_ypixel = height;
                    553:        ioctl (screen->respond, TIOCSWINSZ, &ws);
                    554: #ifdef SIGWINCH
                    555:        if(screen->pid > 1)
                    556:                killpg(getpgrp(screen->pid), SIGWINCH);
                    557: #endif SIGWINCH
                    558: #endif TIOCSWINSZ
                    559:        return (0);
                    560: }
                    561: 
                    562: 
                    563: SetIconSize( screen )
                    564:   Screen *screen;
                    565: {
                    566:        if (screen->active_icon) {
                    567:            screen->iconVwin.width = (screen->max_col + 1)
                    568:                                     * screen->iconVwin.f_width
                    569:                                     + screen->border * 2;
                    570:            screen->iconVwin.height = (screen->max_row + 1)
                    571:                                      * screen->iconVwin.f_height
                    572:                                      + screen->border * 2;
                    573:            XChangeWindow( screen->iconVwin.window,
                    574:                           screen->iconVwin.width,
                    575:                           screen->iconVwin.height );
                    576:        } else {
                    577:            IconRecalc( screen );
                    578:        }
                    579: 
                    580:        screen->iconVwin.fullwidth = screen->iconVwin.width;
                    581:        screen->iconVwin.fullheight = screen->iconVwin.height;
                    582: }

unix.superglobalmegacorp.com

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