Annotation of uae/src/x11keys.c, revision 1.1

1.1     ! root        1:  /*
        !             2:   * UAE - The Un*x Amiga Emulator
        !             3:   *
        !             4:   * X keysym support
        !             5:   *
        !             6:   * Copyright 1995, 1996 Bernd Schmidt
        !             7:   * Copyright 1996 Ed Hanway, Andre Beck, Samuel Devulder, Bruno Coste
        !             8:   * Copyright 1998 Marcus Sundberg
        !             9:   * DGA support by Kai Kollmorgen
        !            10:   * X11/DGA merge, hotkeys and grabmouse by Marcus Sundberg
        !            11:   * Copyright 2003-2004 Richard Drummond
        !            12:   */
        !            13: 
        !            14: #include "sysconfig.h"
        !            15: #include "sysdeps.h"
        !            16: 
        !            17: #include <X11/Xlib.h>
        !            18: #include <X11/keysym.h>
        !            19: 
        !            20: #include "options.h"
        !            21: #include "inputdevice.h"
        !            22: #include "keyboard.h"
        !            23: #include "hotkeys.h"
        !            24: 
        !            25: 
        !            26: /* Decode KeySyms. This function knows about all keys that are common
        !            27:  * between different keyboard languages. */
        !            28: static int kc_decode (KeySym ks)
        !            29: {
        !            30:     switch (ks) {
        !            31:      case XK_B: case XK_b: return AK_B;
        !            32:      case XK_C: case XK_c: return AK_C;
        !            33:      case XK_D: case XK_d: return AK_D;
        !            34:      case XK_E: case XK_e: return AK_E;
        !            35:      case XK_F: case XK_f: return AK_F;
        !            36:      case XK_G: case XK_g: return AK_G;
        !            37:      case XK_H: case XK_h: return AK_H;
        !            38:      case XK_I: case XK_i: return AK_I;
        !            39:      case XK_J: case XK_j: return AK_J;
        !            40:      case XK_K: case XK_k: return AK_K;
        !            41:      case XK_L: case XK_l: return AK_L;
        !            42:      case XK_N: case XK_n: return AK_N;
        !            43:      case XK_O: case XK_o: return AK_O;
        !            44:      case XK_P: case XK_p: return AK_P;
        !            45:      case XK_R: case XK_r: return AK_R;
        !            46:      case XK_S: case XK_s: return AK_S;
        !            47:      case XK_T: case XK_t: return AK_T;
        !            48:      case XK_U: case XK_u: return AK_U;
        !            49:      case XK_V: case XK_v: return AK_V;
        !            50:      case XK_X: case XK_x: return AK_X;
        !            51: 
        !            52:      case XK_0: return AK_0;
        !            53:      case XK_1: return AK_1;
        !            54:      case XK_2: return AK_2;
        !            55:      case XK_3: return AK_3;
        !            56:      case XK_4: return AK_4;
        !            57:      case XK_5: return AK_5;
        !            58:      case XK_6: return AK_6;
        !            59:      case XK_7: return AK_7;
        !            60:      case XK_8: return AK_8;
        !            61:      case XK_9: return AK_9;
        !            62: 
        !            63:        /* You never know which Keysyms might be missing on some workstation
        !            64:         * This #ifdef should be enough. */
        !            65: #if defined(XK_KP_Prior) && defined(XK_KP_Left) && defined(XK_KP_Insert) && defined (XK_KP_End)
        !            66:      case XK_KP_0: case XK_KP_Insert: return AK_NP0;
        !            67:      case XK_KP_1: case XK_KP_End: return AK_NP1;
        !            68:      case XK_KP_2: case XK_KP_Down: return AK_NP2;
        !            69:      case XK_KP_3: case XK_KP_Next: return AK_NP3;
        !            70:      case XK_KP_4: case XK_KP_Left: return AK_NP4;
        !            71:      case XK_KP_5: case XK_KP_Begin: return AK_NP5;
        !            72:      case XK_KP_6: case XK_KP_Right: return AK_NP6;
        !            73:      case XK_KP_7: case XK_KP_Home: return AK_NP7;
        !            74:      case XK_KP_8: case XK_KP_Up: return AK_NP8;
        !            75:      case XK_KP_9: case XK_KP_Prior: return AK_NP9;
        !            76: #else
        !            77:      case XK_KP_0: return AK_NP0;
        !            78:      case XK_KP_1: return AK_NP1;
        !            79:      case XK_KP_2: return AK_NP2;
        !            80:      case XK_KP_3: return AK_NP3;
        !            81:      case XK_KP_4: return AK_NP4;
        !            82:      case XK_KP_5: return AK_NP5;
        !            83:      case XK_KP_6: return AK_NP6;
        !            84:      case XK_KP_7: return AK_NP7;
        !            85:      case XK_KP_8: return AK_NP8;
        !            86:      case XK_KP_9: return AK_NP9;
        !            87: #endif
        !            88:      case XK_KP_Divide: return AK_NPDIV;
        !            89:      case XK_KP_Multiply: return AK_NPMUL;
        !            90:      case XK_KP_Subtract: return AK_NPSUB;
        !            91:      case XK_KP_Add: return AK_NPADD;
        !            92:      case XK_KP_Decimal: return AK_NPDEL;
        !            93:      case XK_KP_Enter: return AK_ENT;
        !            94: 
        !            95:      case XK_F1: return AK_F1;
        !            96:      case XK_F2: return AK_F2;
        !            97:      case XK_F3: return AK_F3;
        !            98:      case XK_F4: return AK_F4;
        !            99:      case XK_F5: return AK_F5;
        !           100:      case XK_F6: return AK_F6;
        !           101:      case XK_F7: return AK_F7;
        !           102:      case XK_F8: return AK_F8;
        !           103:      case XK_F9: return AK_F9;
        !           104:      case XK_F10: return AK_F10;
        !           105: 
        !           106:      case XK_BackSpace: return AK_BS;
        !           107:      case XK_Delete: return AK_DEL;
        !           108:      case XK_Control_L: return AK_CTRL;
        !           109:      case XK_Control_R: return AK_RCTRL;
        !           110:      case XK_Tab: return AK_TAB;
        !           111:      case XK_Alt_L: return AK_LALT;
        !           112:      case XK_Alt_R: return AK_RALT;
        !           113:      case XK_Meta_R: case XK_Hyper_R: return AK_RAMI;
        !           114:      case XK_Meta_L: case XK_Hyper_L: return AK_LAMI;
        !           115:      case XK_Return: return AK_RET;
        !           116:      case XK_space: return AK_SPC;
        !           117:      case XK_Shift_L: return AK_LSH;
        !           118:      case XK_Shift_R: return AK_RSH;
        !           119:      case XK_Escape: return AK_ESC;
        !           120: 
        !           121:      case XK_Insert: return AK_HELP;
        !           122:      case XK_Home: return AK_NPLPAREN;
        !           123:      case XK_End: return AK_NPRPAREN;
        !           124:      case XK_Caps_Lock: return AK_CAPSLOCK;
        !           125: 
        !           126:      case XK_Up: return AK_UP;
        !           127:      case XK_Down: return AK_DN;
        !           128:      case XK_Left: return AK_LF;
        !           129:      case XK_Right: return AK_RT;
        !           130: 
        !           131: #ifdef XK_Page_Up /* These are missing occasionally */
        !           132:      case XK_Page_Up: return AK_RAMI;          /* PgUp mapped to right amiga */
        !           133:      case XK_Page_Down: return AK_LAMI;        /* PgDn mapped to left amiga */
        !           134: #endif
        !           135: 
        !           136: #ifdef XK_Super_L
        !           137:      case XK_Super_L: return AK_LAMI;
        !           138:      case XK_Super_R: return AK_RAMI;
        !           139: #endif
        !           140:      case XK_Scroll_Lock: return AKS_INHIBITSCREEN;
        !           141:      case XK_Print: return AKS_SCREENSHOT;
        !           142:     }
        !           143:     return -1;
        !           144: }
        !           145: 
        !           146: static int decode_fr (KeySym ks)
        !           147: {
        !           148:     switch(ks) {        /* FR specific */
        !           149:      case XK_A: case XK_a: return AK_Q;
        !           150:      case XK_M: case XK_m: return AK_SEMICOLON;
        !           151:      case XK_Q: case XK_q: return AK_A;
        !           152:      case XK_Y: case XK_y: return AK_Y;
        !           153:      case XK_W: case XK_w: return AK_Z;
        !           154:      case XK_Z: case XK_z: return AK_W;
        !           155: #if 0
        !           156:      case XK_bracketleft: return AK_LBRACKET;
        !           157:      case XK_bracketright: return AK_RBRACKET;
        !           158:      case XK_comma: return AK_M;
        !           159:      case XK_less: case XK_greater: return AK_LTGT;
        !           160:      case XK_period: return AK_COMMA;
        !           161:      case XK_parenright: return AK_MINUS;
        !           162:      case XK_equal: return AK_SLASH;
        !           163:      case XK_numbersign: return AK_NUMBERSIGN;
        !           164:      case XK_slash: return AK_PERIOD;
        !           165:      case XK_minus: return AK_EQUAL;
        !           166:      case XK_backslash: return AK_BACKSLASH;
        !           167: #else
        !           168:      /* not sure for this one: my X 3.3 server doesn't handle this key always
        !           169:       * correctly... But anyway, on new french keyboards, no more bracket key
        !           170:       * at this place.
        !           171:       */
        !           172:      case XK_dead_circumflex:
        !           173:      case XK_dead_diaeresis: return AK_LBRACKET;
        !           174:      case XK_dollar:
        !           175:      case XK_sterling: return AK_RBRACKET;
        !           176:      case XK_comma: case XK_question: return AK_M;
        !           177:      case XK_less: case XK_greater: return AK_LTGT;
        !           178:      case XK_semicolon: case XK_period: return AK_COMMA;
        !           179:      case XK_parenright: case XK_degree: return AK_MINUS;
        !           180:      case XK_equal: case XK_plus: return AK_SLASH;
        !           181:      case XK_numbersign: return AK_NUMBERSIGN;
        !           182:      case XK_colon: case XK_slash: return AK_PERIOD;
        !           183:      case XK_minus: case XK_6: return AK_6;
        !           184:      case XK_ugrave: case XK_percent: return AK_QUOTE;
        !           185:      /* found a spare key - I hope it deserves this place. */
        !           186:      case XK_asterisk: case XK_mu: return AK_BACKSLASH;
        !           187:      case XK_exclam: case XK_section: return AK_EQUAL;
        !           188:      case XK_twosuperior: case XK_asciitilde: return AK_BACKQUOTE;
        !           189:      case XK_Multi_key: return AK_RAMI;
        !           190:      case XK_Mode_switch: return AK_RALT;
        !           191: #endif
        !           192:     }
        !           193: 
        !           194:     return -1;
        !           195: }
        !           196: 
        !           197: static int decode_us (KeySym ks)
        !           198: {
        !           199:     switch(ks) {       /* US specific */
        !           200:      case XK_A: case XK_a: return AK_A;
        !           201:      case XK_M: case XK_m: return AK_M;
        !           202:      case XK_Q: case XK_q: return AK_Q;
        !           203:      case XK_Y: case XK_y: return AK_Y;
        !           204:      case XK_W: case XK_w: return AK_W;
        !           205:      case XK_Z: case XK_z: return AK_Z;
        !           206:      case XK_bracketleft: return AK_LBRACKET;
        !           207:      case XK_bracketright: return AK_RBRACKET;
        !           208:      case XK_comma: return AK_COMMA;
        !           209:      case XK_period: return AK_PERIOD;
        !           210:      case XK_slash: return AK_SLASH;
        !           211:      case XK_semicolon: return AK_SEMICOLON;
        !           212:      case XK_minus: return AK_MINUS;
        !           213:      case XK_equal: return AK_EQUAL;
        !           214:        /* this doesn't work: */
        !           215:      case XK_quoteright: return AK_QUOTE;
        !           216:      case XK_quoteleft: return AK_BACKQUOTE;
        !           217:      case XK_backslash: return AK_BACKSLASH;
        !           218:     }
        !           219: 
        !           220:     return -1;
        !           221: }
        !           222: 
        !           223: static int decode_de (KeySym ks)
        !           224: {
        !           225:     switch(ks) {
        !           226:        /* DE specific */
        !           227:      case XK_A: case XK_a: return AK_A;
        !           228:      case XK_M: case XK_m: return AK_M;
        !           229:      case XK_Q: case XK_q: return AK_Q;
        !           230:      case XK_W: case XK_w: return AK_W;
        !           231:      case XK_Y: case XK_y: return AK_Z;
        !           232:      case XK_Z: case XK_z: return AK_Y;
        !           233:      case XK_Odiaeresis: case XK_odiaeresis: return AK_SEMICOLON;
        !           234:      case XK_Adiaeresis: case XK_adiaeresis: return AK_QUOTE;
        !           235:      case XK_Udiaeresis: case XK_udiaeresis: return AK_LBRACKET;
        !           236:      case XK_plus: case XK_asterisk: return AK_RBRACKET;
        !           237:      case XK_comma: return AK_COMMA;
        !           238:      case XK_period: return AK_PERIOD;
        !           239:      case XK_less: case XK_greater: return AK_LTGT;
        !           240:      case XK_numbersign: return AK_NUMBERSIGN;
        !           241:      case XK_ssharp: return AK_MINUS;
        !           242:      case XK_apostrophe: return AK_EQUAL;
        !           243:      case XK_asciicircum: return AK_BACKQUOTE;
        !           244:      case XK_minus: return AK_SLASH;
        !           245:     }
        !           246: 
        !           247:     return -1;
        !           248: }
        !           249: 
        !           250: static int decode_dk (KeySym ks)
        !           251: {
        !           252:     switch(ks) {
        !           253:        /* DK specific */
        !           254:     case XK_A: case XK_a: return AK_A;
        !           255:     case XK_M: case XK_m: return AK_M;
        !           256:     case XK_Q: case XK_q: return AK_Q;
        !           257:     case XK_W: case XK_w: return AK_W;
        !           258:     case XK_Y: case XK_y: return AK_Y;
        !           259:     case XK_Z: case XK_z: return AK_Z;
        !           260:     case XK_AE: case XK_ae: return AK_SEMICOLON;
        !           261:     case XK_Ooblique: case XK_oslash: return AK_QUOTE;
        !           262:     case XK_Aring: case XK_aring: return AK_LBRACKET;
        !           263:     case XK_apostrophe: case XK_asterisk: return AK_NUMBERSIGN;
        !           264:     case XK_dead_diaeresis: case XK_dead_circumflex: return AK_RBRACKET;
        !           265:     case XK_dead_acute: case XK_dead_grave: return AK_BACKSLASH;
        !           266:     case XK_onehalf: case XK_section: return AK_BACKQUOTE;
        !           267:     case XK_comma: return AK_COMMA;
        !           268:     case XK_period: return AK_PERIOD;
        !           269:     case XK_less: case XK_greater: return AK_LTGT;
        !           270:     case XK_numbersign: return AK_NUMBERSIGN;
        !           271:     case XK_plus: return AK_MINUS;
        !           272:     case XK_asciicircum: return AK_BACKQUOTE;
        !           273:     case XK_minus: return AK_SLASH;
        !           274:     }
        !           275: 
        !           276:     return -1;
        !           277: }
        !           278: 
        !           279: static int decode_se (KeySym ks)
        !           280: {
        !           281:     switch(ks) {
        !           282:        /* SE specific */
        !           283:      case XK_A: case XK_a: return AK_A;
        !           284:      case XK_M: case XK_m: return AK_M;
        !           285:      case XK_Q: case XK_q: return AK_Q;
        !           286:      case XK_W: case XK_w: return AK_W;
        !           287:      case XK_Y: case XK_y: return AK_Y;
        !           288:      case XK_Z: case XK_z: return AK_Z;
        !           289:      case XK_Odiaeresis: case XK_odiaeresis: return AK_SEMICOLON;
        !           290:      case XK_Adiaeresis: case XK_adiaeresis: return AK_QUOTE;
        !           291:      case XK_Aring: case XK_aring: return AK_LBRACKET;
        !           292:      case XK_comma: return AK_COMMA;
        !           293:      case XK_period: return AK_PERIOD;
        !           294:      case XK_minus: return AK_SLASH;
        !           295:      case XK_less: case XK_greater: return AK_LTGT;
        !           296:      case XK_plus: case XK_question: return AK_EQUAL;
        !           297:      case XK_at: case XK_onehalf: return AK_BACKQUOTE;
        !           298:      case XK_asciitilde: case XK_asciicircum: return AK_RBRACKET;
        !           299:      case XK_backslash: case XK_bar: return AK_MINUS;
        !           300: 
        !           301:      case XK_numbersign: return AK_NUMBERSIGN;
        !           302:     }
        !           303: 
        !           304:     return -1;
        !           305:  }
        !           306: 
        !           307: static int decode_it (KeySym ks)
        !           308: {
        !           309:     switch(ks) {
        !           310:        /* IT specific */
        !           311:      case XK_A: case XK_a: return AK_A;
        !           312:      case XK_M: case XK_m: return AK_M;
        !           313:      case XK_Q: case XK_q: return AK_Q;
        !           314:      case XK_W: case XK_w: return AK_W;
        !           315:      case XK_Y: case XK_y: return AK_Y;
        !           316:      case XK_Z: case XK_z: return AK_Z;
        !           317:      case XK_Ograve: case XK_ograve: return AK_SEMICOLON;
        !           318:      case XK_Agrave: case XK_agrave: return AK_QUOTE;
        !           319:      case XK_Egrave: case XK_egrave: return AK_LBRACKET;
        !           320:      case XK_plus: case XK_asterisk: return AK_RBRACKET;
        !           321:      case XK_comma: return AK_COMMA;
        !           322:      case XK_period: return AK_PERIOD;
        !           323:      case XK_less: case XK_greater: return AK_LTGT;
        !           324:      case XK_backslash: case XK_bar: return AK_BACKQUOTE;
        !           325:      case XK_apostrophe: return AK_MINUS;
        !           326:      case XK_Igrave: case XK_igrave: return AK_EQUAL;
        !           327:      case XK_minus: return AK_SLASH;
        !           328:      case XK_numbersign: return AK_NUMBERSIGN;
        !           329:     }
        !           330: 
        !           331:     return -1;
        !           332: }
        !           333: 
        !           334: static int decode_es (KeySym ks)
        !           335: {
        !           336:     switch(ks) {
        !           337:        /* ES specific */
        !           338:      case XK_A: case XK_a: return AK_A;
        !           339:      case XK_M: case XK_m: return AK_M;
        !           340:      case XK_Q: case XK_q: return AK_Q;
        !           341:      case XK_W: case XK_w: return AK_W;
        !           342:      case XK_Y: case XK_y: return AK_Y;
        !           343:      case XK_Z: case XK_z: return AK_Z;
        !           344:      case XK_ntilde: case XK_Ntilde: return AK_SEMICOLON;
        !           345: #ifdef XK_dead_acute
        !           346:      case XK_dead_acute: case XK_dead_diaeresis: return AK_QUOTE;
        !           347:      case XK_dead_grave: case XK_dead_circumflex: return AK_LBRACKET;
        !           348: #endif
        !           349:      case XK_plus: case XK_asterisk: return AK_RBRACKET;
        !           350:      case XK_comma: return AK_COMMA;
        !           351:      case XK_period: return AK_PERIOD;
        !           352:      case XK_less: case XK_greater: return AK_LTGT;
        !           353:      case XK_backslash: case XK_bar: return AK_BACKQUOTE;
        !           354:      case XK_apostrophe: return AK_MINUS;
        !           355:      case XK_Igrave: case XK_igrave: return AK_EQUAL;
        !           356:      case XK_minus: return AK_SLASH;
        !           357:      case XK_numbersign: return AK_NUMBERSIGN;
        !           358:     }
        !           359: 
        !           360:     return -1;
        !           361: }
        !           362: 
        !           363: int xkeysym2amiga (KeySym ks)
        !           364: {
        !           365:     int as = kc_decode (ks);
        !           366: 
        !           367:     if (as == -1) {
        !           368:        switch (currprefs.keyboard_lang) {
        !           369:            case KBD_LANG_FR:
        !           370:                as = decode_fr (ks); break;
        !           371:            case KBD_LANG_US:
        !           372:                as = decode_us (ks); break;
        !           373:            case KBD_LANG_DE:
        !           374:                as = decode_de (ks); break;
        !           375:            case KBD_LANG_DK:
        !           376:                as = decode_dk (ks); break;
        !           377:            case KBD_LANG_SE:
        !           378:                as = decode_se (ks); break;
        !           379:            case KBD_LANG_IT:
        !           380:                as = decode_it (ks); break;
        !           381:            case KBD_LANG_ES:
        !           382:                as = decode_es (ks); break;
        !           383:        }
        !           384:     }
        !           385:     return as;
        !           386: }
        !           387: 
        !           388: /*
        !           389:  * Default hotkeys
        !           390:  *
        !           391:  * We need a better way of doing this. ;-)
        !           392:  */
        !           393: static struct uae_hotkeyseq x11_hotkeys[] =
        !           394: {
        !           395:     { MAKE_HOTKEYSEQ (XK_F12, XK_q, -1, -1,           INPUTEVENT_SPC_QUIT) },
        !           396:     { MAKE_HOTKEYSEQ (XK_F12, XK_r, -1, -1,           INPUTEVENT_SPC_SOFTRESET) },
        !           397:     { MAKE_HOTKEYSEQ (XK_F12, XK_Shift_L, XK_r, -1,   INPUTEVENT_SPC_HARDRESET) },
        !           398:     { MAKE_HOTKEYSEQ (XK_F12, XK_d, -1, -1,           INPUTEVENT_SPC_ENTERDEBUGGER) },
        !           399:     { MAKE_HOTKEYSEQ (XK_F12, XK_s, -1, -1,           INPUTEVENT_SPC_TOGGLEFULLSCREEN) },
        !           400:     { MAKE_HOTKEYSEQ (XK_F12, XK_g, -1, -1,           INPUTEVENT_SPC_TOGGLEMOUSEGRAB) },
        !           401:     { MAKE_HOTKEYSEQ (XK_F12, XK_i, -1, -1,           INPUTEVENT_SPC_INHIBITSCREEN) },
        !           402:     { MAKE_HOTKEYSEQ (XK_F12, XK_p, -1, -1,           INPUTEVENT_SPC_SCREENSHOT) },
        !           403:     { MAKE_HOTKEYSEQ (XK_F12, XK_a, -1, -1,           INPUTEVENT_SPC_SWITCHINTERPOL) },
        !           404:     { MAKE_HOTKEYSEQ (XK_F12, XK_KP_Add, -1, -1,      INPUTEVENT_SPC_INCREASE_REFRESHRATE) },
        !           405:     { MAKE_HOTKEYSEQ (XK_F12, XK_KP_Subtract, -1, -1, INPUTEVENT_SPC_DECREASE_REFRESHRATE) },
        !           406:     { MAKE_HOTKEYSEQ (XK_F12, XK_F1, -1, -1,         INPUTEVENT_SPC_FLOPPY0) },
        !           407:     { MAKE_HOTKEYSEQ (XK_F12, XK_F2, -1, -1,         INPUTEVENT_SPC_FLOPPY1) },
        !           408:     { MAKE_HOTKEYSEQ (XK_F12, XK_F3, -1, -1,         INPUTEVENT_SPC_FLOPPY2) },
        !           409:     { MAKE_HOTKEYSEQ (XK_F12, XK_F4, -1, -1,         INPUTEVENT_SPC_FLOPPY3) },
        !           410:     { MAKE_HOTKEYSEQ (XK_F12, XK_Shift_L, XK_F1, -1,  INPUTEVENT_SPC_EFLOPPY0) },
        !           411:     { MAKE_HOTKEYSEQ (XK_F12, XK_Shift_L, XK_F2, -1,  INPUTEVENT_SPC_EFLOPPY1) },
        !           412:     { MAKE_HOTKEYSEQ (XK_F12, XK_Shift_L, XK_F3, -1,  INPUTEVENT_SPC_EFLOPPY2) },
        !           413:     { MAKE_HOTKEYSEQ (XK_F12, XK_Shift_L, XK_F4, -1,  INPUTEVENT_SPC_EFLOPPY3) },
        !           414:     { MAKE_HOTKEYSEQ (XK_F12, XK_Return, -1, -1,      INPUTEVENT_SPC_ENTERGUI) },
        !           415:     { MAKE_HOTKEYSEQ (XK_F12, XK_f, -1, -1,           INPUTEVENT_SPC_FREEZEBUTTON) },
        !           416:     { HOTKEYS_END }
        !           417: };
        !           418: 
        !           419: struct uae_hotkeyseq *get_x11_default_hotkeys (void)
        !           420: {
        !           421:     return x11_hotkeys;
        !           422: }

unix.superglobalmegacorp.com

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