|
|
1.1 ! root 1: /* ! 2: * This program is in public domain; written by Dave G. Conroy. ! 3: * This file contains the main driving routine, and some keyboard processing ! 4: * code, for the MicroEMACS screen editor. ! 5: * Modified by W. L. Sheldon for use with the COHERENT Operating System - ! 6: * VT100 terminal key bindings. ! 7: */ ! 8: ! 9: #include <stdio.h> ! 10: #include "ed.h" ! 11: ! 12: #if VMS ! 13: #include <ssdef.h> ! 14: #define GOOD (SS$_NORMAL) ! 15: #define BAD (SS$_ABORT) ! 16: #endif ! 17: ! 18: #ifndef GOOD ! 19: #define GOOD 0 ! 20: #define BAD 1 ! 21: #endif ! 22: ! 23: int currow; /* Working cursor row */ ! 24: int curcol; /* Working cursor column */ ! 25: int curgoal; /* Goal column */ ! 26: BUFFER *curbp; /* Current buffer */ ! 27: WINDOW *curwp; /* Current window */ ! 28: BUFFER *bheadp; /* BUFFER listhead */ ! 29: WINDOW *wheadp; /* WINDOW listhead */ ! 30: BUFFER *blistp; /* Buffer list BUFFER */ ! 31: #if LIBHELP ! 32: BUFFER *helpbp; /* Help buffer */ ! 33: #endif ! 34: BUFFER *errbp; /* Error file BUFFER */ ! 35: uchar pat[NPAT]; /* Pattern */ ! 36: ! 37: uchar errfile[NFILEN]; /* Error file name */ ! 38: ! 39: #if LIBHELP ! 40: uchar *helpfile=0; /* Help file name ptr. */ ! 41: uchar *helpindex=0; /* Help index file name ptr. */ ! 42: uchar hfname[NFILEN]; /* Help file name place */ ! 43: uchar hiname[NFILEN]; /* Help index file name place */ ! 44: #endif ! 45: extern char *strcpy(); /* copy string */ ! 46: extern char *getenv(); ! 47: ! 48: /* ! 49: * File-name list for command line... ! 50: */ ! 51: uchar *cfiles[NCFILES]; /* Command line specified files */ ! 52: int cfilecnt; /* File count... */ ! 53: ! 54: /* ! 55: * Command line switch flags... ! 56: */ ! 57: unsigned int runswitch; ! 58: ! 59: #if LK201 ! 60: /* ! 61: * Mapping table for all of the funny keys with the numeric parameters ! 62: * on the LK201. ! 63: * Indexed by the code, which is between 0 (unused) and 34 (F20). ! 64: * An entry of 0 means no mapping. The map goes to command keys. ! 65: * If I had a "special" bit, I could use the code in the escape sequence ! 66: * as a key code, and return (for example) "do" as SPECIAL + 29. ! 67: * Then the dispatch would be done by the default keymap. This is probably a ! 68: * better way to go. ! 69: */ ! 70: short lkmap[] = { ! 71: #if EXKEYS ! 72: 0, ! 73: FN18, /* 1 Find */ ! 74: FN19, /* 2 Insert here */ ! 75: FN1A, /* 3 Remove */ ! 76: FN1B, /* 4 Select */ ! 77: FN1C, /* 5 Previous screen */ ! 78: FN1D, /* 6 Next screen */ ! 79: 0, ! 80: 0, ! 81: 0, ! 82: FN17, /* 10 Compose */ ! 83: 0, ! 84: FN3, /* 12 Print screen */ ! 85: 0, ! 86: FN4, /* 14 F4 */ ! 87: 0, ! 88: 0, ! 89: FN6, /* 17 F6 */ ! 90: FN7, /* 18 F7 */ ! 91: FN8, /* 19 F8 */ ! 92: FN9, /* 20 F9 */ ! 93: FNA, /* 21 F10 */ ! 94: 0, ! 95: 0, ! 96: 0, ! 97: 0, ! 98: FNE, /* 26 F14 */ ! 99: 0, ! 100: FN15, /* 28 Help */ ! 101: FN16, /* 29 Do C-X E */ ! 102: 0, ! 103: FN11, /* 31 F17 C-X P */ ! 104: FN12, /* 32 F18 C-X N */ ! 105: FN13, /* 33 F19 C-X Z */ ! 106: FN14 /* 34 F20 C-X C-Z */ ! 107: #else ! 108: 0, ! 109: OBND|CTRL|'S', /* 1 Find */ ! 110: OBND|CTRL|'Y', /* 2 Insert here */ ! 111: OBND|CTRL|'W', /* 3 Remove */ ! 112: OBND|CTRL|'@', /* 4 Select */ ! 113: OBND|META|'V', /* 5 Previous screen */ ! 114: OBND|CTRL|'V', /* 6 Next screen */ ! 115: 0, ! 116: 0, ! 117: 0, ! 118: 0, /* 10 Compose */ ! 119: 0, ! 120: 0, /* 12 Print screen */ ! 121: 0, ! 122: 0, /* 14 F4 */ ! 123: 0, ! 124: 0, ! 125: 0, /* 17 F6 */ ! 126: 0, /* 18 F7 */ ! 127: 0, /* 19 F8 */ ! 128: 0, /* 20 F9 */ ! 129: 0, /* 21 F10 */ ! 130: 0, ! 131: 0, ! 132: 0, ! 133: 0, ! 134: 0, /* 26 F14 */ ! 135: 0, ! 136: 0, /* 28 Help */ ! 137: OBND|PFX1|'E', /* 29 Do C-X E */ ! 138: 0, ! 139: OBND|PFX1|'P', /* 31 F17 C-X P */ ! 140: OBND|PFX1|'N', /* 32 F18 C-X N */ ! 141: OBND|PFX1|'Z', /* 33 F19 C-X Z */ ! 142: OBND|PFX1|CTRL|'Z' /* 34 F20 C-X C-Z */ ! 143: #endif ! 144: }; ! 145: #endif ! 146: ! 147: main(argc, argv) ! 148: uchar *argv[]; ! 149: { ! 150: register int c; ! 151: register int f; ! 152: register int n; ! 153: uchar bname[NBUFN]; ! 154: ! 155: #if MSDOS ! 156: setkeys(); ! 157: #endif ! 158: #if IBM ! 159: vidnit(); ! 160: #endif ! 161: for (c = 0; c < MAXREB; c++) /* nothing in the new table */ ! 162: bind.table[c].k_synonym = bind.table[c].k_code = -1; ! 163: runswitch = 0; /* Initialize the switches */ ! 164: bind.ffold = FALSE; /* initialize the fold flg */ ! 165: bind.bracket = 1; /* initialize bracket mode */ ! 166: bind.pfx1 = CTRL|'X'; /* initialize prefix keys */ ! 167: bind.pfx2 = bind.pfx3 = -1; ! 168: bind.repeat = CTRL|'U'; ! 169: argproc(argc, argv); /* Parse the arg list */ ! 170: #if GEM ! 171: if (runswitch & CF_GRABMEM) /* Get largest chunk of */ ! 172: grabmem(0, 0); /* memory (ST only) */ ! 173: #endif ! 174: #if _I386 ! 175: { ! 176: /* ! 177: * Speed up processing on 80386 for small files. ! 178: */ ! 179: char *junk; ! 180: ! 181: if (NULL != (junk = malloc(128L * 1024L))) ! 182: free(junk); ! 183: } ! 184: #endif ! 185: topen(); /* Force the length setup */ ! 186: strcpy(bname, "main"); /* Work out the name of */ ! 187: if (cfilecnt > 0) /* the default buffer. */ ! 188: makename(bname, cfiles[0]); /* Make a buffer name */ ! 189: edinit(bname); /* Buffers, windows. */ ! 190: vtinit(); /* Displays. */ ! 191: if (cfilecnt > 0) { /* If there are files */ ! 192: update(); /* You have to update */ ! 193: readin(cfiles[0]); /* in case "[New file]" */ ! 194: } ! 195: if (cfilecnt > 1) { /* If more than one */ ! 196: n = (term.t_nrow - cfilecnt - 1) / cfilecnt; ! 197: for (c = 1; c < cfilecnt ; c++) { /* For all other files... */ ! 198: splitwind(0,0); /* Split this window... */ ! 199: if ((f=curwp->w_ntrows-n) != 0) ! 200: shrinkwind(0,f); /* Even out the windows */ ! 201: nextwind(0,0); /* Go on to the next one */ ! 202: visitfile(cfiles[c]); /* Read in that file */ ! 203: } ! 204: } ! 205: if ((runswitch & CF_ERROR) != 0) { ! 206: splitwind(0,0); /* Split this window */ ! 207: f = curwp->w_ntrows - ERRLINES; /* Make error window small */ ! 208: if (f > 0) ! 209: shrinkwind(0,f); ! 210: readerr(); ! 211: nextwind(); ! 212: mlerase(); ! 213: update(); ! 214: nexterr(0,1); ! 215: update(); ! 216: } ! 217: lastflag = 0; /* Fake last flags. */ ! 218: if (NULL != bind.macs[MAXMAC]) /* initialization macro */ ! 219: doMac(bind.macs + MAXMAC, FALSE, 1); ! 220: ! 221: for (;;) { ! 222: update(); /* Fix up the screen */ ! 223: c = getbind(0); /* Get a key */ ! 224: if (mpresf != FALSE) { /* If a message there */ ! 225: mlerase(); /* get rid of it... */ ! 226: update(); /* Fix screen */ ! 227: if (c == ' ') /* ITS EMACS does this */ ! 228: continue; /* (eat a space) */ ! 229: } ! 230: f = FALSE; ! 231: n = 1; ! 232: if (c == bind.repeat) { /* ^U, start argument */ ! 233: int ctmp; ! 234: ! 235: f = TRUE; /* We have a count */ ! 236: n = getnum("Arg", 4, &ctmp); /* get the count */ ! 237: c = ctmp; /* And get the last chr */ ! 238: } ! 239: if (kbdmip != NULL) { /* Save macro strokes. */ ! 240: if (kbdmip > (kbdm + ((NKBDM - 3)/2))) { ! 241: ctrlg(FALSE, 0); ! 242: continue; ! 243: } ! 244: if (f != FALSE) { ! 245: *kbdmip++ = bind.repeat; ! 246: *kbdmip++ = n; ! 247: } ! 248: *kbdmip++ = c; ! 249: } ! 250: bracketoff(); ! 251: execute(c, f, n); /* Do it. */ ! 252: } ! 253: } ! 254: ! 255: /* ! 256: * Initialize all of the buffers and windows. ! 257: * The buffer name is passed down as an argument, because the main routine may ! 258: * have been told to read in a file by default, and we want the buffer name to ! 259: * be right. ! 260: */ ! 261: edinit(bname) ! 262: uchar bname[]; ! 263: { ! 264: register BUFFER *bp; ! 265: register WINDOW *wp; ! 266: ! 267: bp = bfind(bname, TRUE, 0); /* First buffer */ ! 268: blistp = bfind("[List]", TRUE, BFTEMP); /* Buffer list buffer */ ! 269: #if LIBHELP ! 270: helpbp = bfind("[Help]", TRUE, BFTEMP|BFHELP); /* Help buffer */ ! 271: #endif ! 272: wp = (WINDOW *) malloc(sizeof(WINDOW)); /* First window */ ! 273: if (bp==NULL || wp==NULL || blistp==NULL) ! 274: abort(); ! 275: curbp = bp; /* Make this current */ ! 276: wheadp = wp; ! 277: curwp = wp; ! 278: wp->w_wndp = NULL; /* Initialize window */ ! 279: wp->w_bufp = bp; ! 280: bp->b_nwnd = 1; /* Displayed. */ ! 281: wp->w_linep = bp->b_linep; ! 282: wp->w_dotp = bp->b_linep; ! 283: wp->w_doto = 0; ! 284: wp->w_markp = NULL; ! 285: wp->w_marko = 0; ! 286: wp->w_toprow = 0; ! 287: wp->w_ntrows = term.t_nrow-1; /* "-1" for mode line. */ ! 288: wp->w_force = 0; ! 289: wp->w_flag = WFMODE|WFHARD; /* Full. */ ! 290: } ! 291: ! 292: ! 293: /* ! 294: * Read in a key. Do the standard keyboard preprocessing. ! 295: * Convert the keys to the internal character set. On the LK201, which lacks ! 296: * a reasonable ESC key, make the grave accent a meta key too; this is a fairly ! 297: * common customization around Digital. Also read and decode the arrow keys, ! 298: * and other special keys. This is done in Rainbow mode; does this work on all ! 299: * the terminals with LK201 keyboards? ! 300: */ ! 301: getkey() ! 302: { ! 303: register int c; ! 304: #if LK201 ! 305: register int n; ! 306: for (;;) { ! 307: if ((c = tgetc()) == AGRAVE) /* Alternate M- prefix. */ ! 308: return (META | getCtl()); ! 309: if (c == METACH) { /* M-, or special key. */ ! 310: if ((c = tgetc()) == '[') { /* Arrows and extras. */ ! 311: switch (c = tgetc()) { ! 312: case 'A': ! 313: return (OBND | CTRL | 'P'); ! 314: case 'B': ! 315: return (OBND | CTRL | 'N'); ! 316: case 'C': ! 317: return (OBND | CTRL | 'F'); ! 318: case 'D': ! 319: return (OBND | CTRL | 'B'); ! 320: } ! 321: if (c >= '0' && c <= '9') { ! 322: n = 0; ! 323: do { ! 324: n = 10*n + c - '0'; ! 325: } ! 326: while ((c = tgetc()) >= '0' && c <= '9'); ! 327: if (c == '~' && n <= 34 && (c = lkmap[n])) ! 328: return (c); ! 329: } ! 330: continue; ! 331: } ! 332: if (c == 'O') { ! 333: switch (tgetc()) { ! 334: case 'P': /* PF1 => M-X (Future) */ ! 335: return (OBND | META | 'X'); ! 336: case 'Q': /* PF2 => C-Q */ ! 337: return (OBND | CTRL | 'Q'); ! 338: case 'R': /* PF3 => C-S */ ! 339: return (OBND | CTRL | 'S'); ! 340: case 'S': /* PF4 => C-R */ ! 341: return (OBND | CTRL | 'R'); ! 342: } ! 343: continue; ! 344: } ! 345: return (META | toCtl(c)); ! 346: } ! 347: break; ! 348: } ! 349: #else ! 350: #if VT100 ! 351: for (;;) { ! 352: if ((c = tgetc()) == METACH) { /* Apply M- prefix */ ! 353: if ((c = tgetc()) == '[') { /* Arrow keys. */ ! 354: switch (tgetc()) { ! 355: case 'A': ! 356: return (OBND | CTRL | 'P'); ! 357: case 'B': ! 358: return (OBND | CTRL | 'N'); ! 359: case 'C': ! 360: return (OBND | CTRL | 'F'); ! 361: case 'D': ! 362: return (OBND | CTRL | 'B'); ! 363: case 'P': ! 364: return (OBND | CTRL | 'D'); /* DEL key */ ! 365: case 'H': ! 366: return (OBND | CTRL | 'A'); /* HOME key */ ! 367: case '1': ! 368: switch (tgetc()) { ! 369: case 'x': ! 370: return (OBND | META | '?'); /* F1 help C/ASM word */ ! 371: case 'y': ! 372: return (OBND | PFX1 | '2'); /* Alt-F1 open 2nd window */ ! 373: } ! 374: case '2': ! 375: switch (tgetc()) { ! 376: case '4': ! 377: if ((tgetc()) == 'H') ! 378: return (OBND | CTRL | 'E'); /* END key */ ! 379: case 'x': ! 380: return (OBND | PFX1 | CTRL | 'V'); /* new file F2 */ ! 381: } ! 382: case 'V': ! 383: return (OBND | META | 'V'); /* PGUP key */ ! 384: case 'U': ! 385: return (OBND | CTRL | 'V'); /* PGDN key */ ! 386: case '3': ! 387: switch (tgetc()) { ! 388: case 'x': ! 389: return (OBND | META | 'S'); /* F3 search forward */ ! 390: case 'y': ! 391: return (OBND | META | '/'); /* ALT-F3 cont search */ ! 392: } ! 393: case '4': ! 394: tgetc(); ! 395: return (OBND | META | 'R'); /* F4 search backward */ ! 396: case '5': ! 397: tgetc(); ! 398: return (OBND | META | '%'); /* F5 search & replace */ ! 399: case '6': ! 400: tgetc(); ! 401: return (OBND | PFX1 | 'N'); /* F6 next window */ ! 402: case '8': ! 403: tgetc(); ! 404: return (OBND | CTRL | 'Z'); /* F8 save/exit */ ! 405: case '0': ! 406: switch (tgetc()) { ! 407: case 'x': ! 408: return (OBND | PFX1 | '1'); /* F10 close other wndws */ ! 409: case 'y': ! 410: return (OBND | META | 'J'); ! 411: } ! 412: } ! 413: continue; ! 414: } ! 415: if (c == 'O') { /* function keys */ ! 416: switch (tgetc()) { ! 417: case 'P': /* PF1 => M-X (Future) */ ! 418: return (OBND | META | 'X'); ! 419: case 'Q': /* PF2 => C-Q */ ! 420: return (OBND | CTRL | 'Q'); ! 421: case 'R': /* PF3 => C-S */ ! 422: return (OBND | CTRL | 'S'); ! 423: case 'S': /* PF4 => C-R */ ! 424: return (OBND | CTRL | 'R'); ! 425: } ! 426: continue; ! 427: } ! 428: return (META | toCtl(c)); ! 429: } ! 430: break; ! 431: } ! 432: #else ! 433: if ((c = tgetc()) == METACH) /* Apply M- prefix */ ! 434: return (META | getCtl()); ! 435: #endif ! 436: #endif ! 437: if (c == 0x0D && bind.autoindent) ! 438: return (OBND | CTRL | 'J'); ! 439: if (c >= 0x00 && c <= 0x1F) /* C0 control -> C- */ ! 440: return (CTRL | '@' | c); ! 441: return (c); ! 442: } ! 443: ! 444: /* ! 445: * Apply control modifications to a key ! 446: */ ! 447: toCtl(c) ! 448: register int c; ! 449: { ! 450: if (c>='a' && c<='z') /* Force to upper */ ! 451: return (c - 0x20); ! 452: if (c>=0x00 && c<=0x1F) /* C0 control -> C- */ ! 453: return (c | CTRL | '@'); ! 454: return (c); ! 455: } ! 456: ! 457: getCtl() ! 458: { ! 459: return (toCtl(tgetc())); ! 460: } ! 461: ! 462: /* ! 463: * Fancy quit command, as implemented by Norm. ! 464: * If the current buffer has changed do a write current buffer and exit emacs, ! 465: * otherwise simply exit. ! 466: */ ! 467: quickexit(f, n) ! 468: { ! 469: if ((curbp->b_flag&BFCHG) != 0 /* Changed. */ ! 470: && (curbp->b_flag&(BFTEMP|BFERROR|BFNOWRT)) == 0) ! 471: /* Real and not R/O... */ ! 472: filesave(f, n); ! 473: quit(f, n); /* conditionally quit */ ! 474: } ! 475: ! 476: /* ! 477: * Quit command. If an argument, always quit. Otherwise confirm ! 478: * if a buffer has been changed and not written out. ! 479: * Normally bound to "C-X C-C". ! 480: */ ! 481: quit(f, n) ! 482: { ! 483: register int s = FALSE; ! 484: ! 485: if (f != FALSE /* Argument forces it. */ ! 486: || anycb() == FALSE /* All buffers clean. */ ! 487: || (s=mlyesno("Quit")) == TRUE) { /* User says it's OK. */ ! 488: vttidy(); ! 489: #if MSDOS ! 490: resetkeys(); ! 491: #endif ! 492: if (f != FALSE || s != FALSE) ! 493: exit(BAD); ! 494: else ! 495: exit(GOOD); ! 496: } ! 497: #if MSDOS ! 498: setkeys(); ! 499: #endif ! 500: return (s); ! 501: } ! 502: ! 503: /* ! 504: * Get binding char. Turn prefix chars into or'ed bits. ! 505: */ ! 506: getbind(bound) ! 507: register int bound; ! 508: { ! 509: register int c; ! 510: ! 511: if (((c = getkey()) == bind.pfx1) && !(bound & PFX1)) ! 512: return (PFX1 | toCtl(getbind(bound | PFX1))); ! 513: if ((c == bind.pfx2) && !(bound & PFX2)) ! 514: return (PFX2 | toCtl(getbind(bound | PFX2))); ! 515: if ((c == bind.pfx3) && !(bound & PFX3)) ! 516: return (PFX3 | toCtl(getbind(bound | PFX3))); ! 517: return (c); ! 518: } ! 519: ! 520: /* ! 521: * Abort. ! 522: * Beep the beeper. ! 523: * Kill off any keyboard macro, ! 524: * etc., that is in progress. ! 525: * Sometimes called as a routine, ! 526: * to do general aborting of ! 527: * stuff. ! 528: */ ! 529: ctrlg(f, n) ! 530: { ! 531: tbeep(); ! 532: if (kbdmip != NULL) { ! 533: if (NULL != kbdm) { ! 534: free(kbdm); ! 535: kbdm = NULL; ! 536: } ! 537: kbdmip = NULL; ! 538: } ! 539: return (ABORT); ! 540: } ! 541: ! 542: #if MSDOS ! 543: setkeys() /* redefine cursor keys */ ! 544: /* so that they make */ ! 545: /* sense to microEMACS */ ! 546: /* as described in IBM */ ! 547: /* DOS tech. reference */ ! 548: /* manual */ ! 549: { ! 550: #if !IBM ! 551: static uchar *ctlseq[] = { ! 552: "\033[0;72;16p", /* up = <ctrl-p> */ ! 553: "\033[0;77;6p", /* right = <ctrl-f> */ ! 554: "\033[0;75;2p", /* left = <ctrl-b> */ ! 555: "\033[0;80;14p", /* down = <ctrl-n> */ ! 556: "\033[0;81;22p", /* pg dn = <ctrl-v> */ ! 557: "\033[0;73;27;86p", /* pg up = <esc>V */ ! 558: "\033[0;71;27;60p", /* home = <esc>< */ ! 559: "\033[0;79;27;62p", /* end = <esc>> */ ! 560: "\033[0;83;127p", /* del = del */ ! 561: "\033[0;3;27;46p", /* <ctrl-@> = <exc>. */ ! 562: NULL ! 563: }; ! 564: register uchar **ctlp; ! 565: ! 566: for (ctlp = ctlseq; NULL != *ctlp; ctlp++) ! 567: mlwrite(*ctlp); ! 568: #endif ! 569: } ! 570: ! 571: ! 572: ! 573: resetkeys() /* redefine cursor keys */ ! 574: /* to default values */ ! 575: { ! 576: #if !IBM ! 577: static uchar *ctlseq[] = { ! 578: "\033[0;72;0;72p", ! 579: "\033[0;77;0;77p", ! 580: "\033[0;75;0;75p", ! 581: "\033[0;80;0;80p", ! 582: "\033[0;81;0;81p", ! 583: "\033[0;73;0;73p", ! 584: "\033[0;71;0;71p", ! 585: "\033[0;79;0;79p", ! 586: "\033[0;83;0;83p", ! 587: "\033[0;3;0;3p", ! 588: NULL ! 589: }; ! 590: register uchar **ctlp; ! 591: ! 592: for (ctlp = ctlseq; NULL != *ctlp; ctlp++) ! 593: mlwrite(*ctlp); ! 594: #endif ! 595: } ! 596: #endif ! 597: ! 598: argproc(argc, argv) ! 599: int argc; ! 600: uchar **argv; ! 601: { ! 602: int i; ! 603: uchar *flexn; ! 604: extern uchar *flexName(); ! 605: uchar *ptr; ! 606: ! 607: if (!bind.tabsiz && ! 608: (NULL == (ptr = getenv("TABSIZ")) || ! 609: !(bind.tabsiz = atoi(ptr)))) ! 610: bind.tabsiz = 8; ! 611: cfilecnt = 0; ! 612: flexn = NULL; ! 613: for (i = 1; i < argc; i++) { ! 614: ptr = argv[i]; /* Get this argument... */ ! 615: if (*ptr == '-') { /* Is this a switch? */ ! 616: switch (ptr[1]) { ! 617: case 'd': ! 618: runswitch |= CF_DEBUG; ! 619: break; ! 620: case 'e': ! 621: runswitch |= CF_ERROR; ! 622: if (ptr[2] == 0) { ! 623: if (++i == argc) { ! 624: runswitch &= ~CF_ERROR; ! 625: continue; ! 626: } ! 627: strcpy(errfile, argv[i]); ! 628: } ! 629: else { ! 630: strcpy(errfile, &ptr[2]); ! 631: } ! 632: break; ! 633: case 'f': ! 634: if (ptr[2] == 0) { ! 635: if (++i == argc) ! 636: continue; ! 637: flexn = argv[i]; ! 638: } ! 639: else ! 640: flexn = ptr + 1; ! 641: break; ! 642: #if LIBHELP ! 643: case 'h': /* Alternate help */ ! 644: if (ptr[2] == 0) { ! 645: if (++i == argc) { ! 646: continue; ! 647: } ! 648: strcpy(hfname, argv[i]); ! 649: } ! 650: else { ! 651: strcpy(hfname, &ptr[2]); ! 652: } ! 653: strcpy(hiname, hfname); ! 654: #if GEM || MSDOS ! 655: strcat(hfname, ".hlp"); ! 656: #endif ! 657: strcat(hiname, ".idx"); ! 658: helpfile = hfname; ! 659: helpindex = hiname; ! 660: break; ! 661: #endif ! 662: case 'w': ! 663: runswitch |= CF_WARN; ! 664: break; ! 665: #if NATIVE && GEM ! 666: case 'l': /* long screen */ ! 667: runswitch |= CF_LONGSCR; ! 668: break; ! 669: case 't': /* very long screen */ ! 670: runswitch |= CF_VLONG; ! 671: break; ! 672: #endif ! 673: #if GEM ! 674: case 'x': /* grab all memory */ ! 675: runswitch |= CF_GRABMEM; ! 676: break; ! 677: #endif ! 678: default: ! 679: break; ! 680: } ! 681: /* Process this switch */ ! 682: } ! 683: else { /* Otherwise... */ ! 684: if (cfilecnt >= NCFILES) ! 685: continue; ! 686: cfiles[cfilecnt++] = ptr; /* This is a file. */ ! 687: #if GEM ! 688: fixname(cfiles[cfilecnt-1]); ! 689: #endif ! 690: } ! 691: } ! 692: if (NULL == flexn) ! 693: loadBup(flexName(), TRUE); ! 694: else ! 695: loadBup(flexn, ABORT); ! 696: } ! 697: ! 698: #if EXKEYS ! 699: /* ! 700: * Do nothing. ("Dead") ! 701: */ ! 702: ignore() ! 703: { ! 704: return TRUE; ! 705: } ! 706: #endif ! 707: ! 708: /* ! 709: * Get a numeric argument... ! 710: */ ! 711: getnum(prompt, n, lastc) ! 712: register uchar *prompt; ! 713: register int n; ! 714: register int *lastc; ! 715: { ! 716: register int mflag = 0; ! 717: register int c; ! 718: ! 719: mflag = 0; /* that can be discarded. */ ! 720: mlwrite("%s: %d", prompt, n); ! 721: while ((c = getbind(0)) >='0' && c<='9' ! 722: || c==bind.repeat || c=='-'){ ! 723: if (c == bind.repeat) ! 724: n = n*4; ! 725: /* ! 726: * If dash, and start of argument string, set arg. ! 727: * to -1. Otherwise, insert it. ! 728: */ ! 729: else if (c == '-') { ! 730: if (mflag) ! 731: break; ! 732: n = 0; ! 733: mflag = -1; ! 734: } ! 735: /* ! 736: * If first digit entered, replace previous argument ! 737: * with digit and set sign. Otherwise, append to arg. ! 738: */ ! 739: else { ! 740: if (!mflag) { ! 741: n = 0; ! 742: mflag = 1; ! 743: } ! 744: n = 10*n + c - '0'; ! 745: } ! 746: mlwrite("%s: %d", prompt, (mflag >=0) ? n : (n ? -n : -1)); ! 747: } ! 748: *lastc = c; /* Return the terminal char. */ ! 749: /* ! 750: * Make arguments preceded by a minus sign negative and change ! 751: * the special argument "^U -" to an effective "^U -1". ! 752: */ ! 753: if (mflag == -1) { ! 754: if (n == 0) ! 755: n++; ! 756: n = -n; ! 757: } ! 758: return n; ! 759: } ! 760: ! 761: #if GEM ! 762: /* ! 763: * The following routine gets around a problem with GEMDOS Malloc(), ! 764: * it forces a single, very large Malloc() so very large files can ! 765: * be read. ! 766: * It is available only on the Atari ST, and is bound to M-+ ! 767: * it can also be specified using the -x switch ! 768: */ ! 769: #include <osbind.h> ! 770: ! 771: grabmem(f, n) ! 772: int f, n; ! 773: { ! 774: extern char *lmalloc(); ! 775: register char *p = NULL; ! 776: register long t; ! 777: ! 778: t = Malloc(-1L); /* How big is free memory? */ ! 779: while (p == NULL) { /* Until we have a block */ ! 780: t -= 4096L; /* shrink the block */ ! 781: if (t < 2048) { /* if too small, tell user */ ! 782: mlwrite( "[Cannot allocate memory]" ); ! 783: return 1; /* and fail */ ! 784: } ! 785: p = lmalloc(t); /* Try to get this chunk */ ! 786: } /* loop until success or fail */ ! 787: free(p); /* return chunk to arena */ ! 788: mlwrite( "[Allocated %ld bytes]", t ); /* tell user how much */ ! 789: return 0; /* and return success */ ! 790: } ! 791: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.