page@swan.ulowell.edu (Bob Page) (12/02/88)
Submitted-by: u211344@hnykun11.bitnet (Olaf 'Rhialto' Seibert) Posting-number: Volume 2, Issue 68 Archive-name: fun/nethack.a1 [The Amiga additional files plus the diffs, when applied to the original nethack source, should produce an Amiga executable version of nethack. ..Bob] # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # amigaDos.c # amigaMenu.c # amigaTTY.c # amigaTermcap.c # amigaUnix.c # amigaWindow.c # This archive created: Thu Dec 1 17:50:06 1988 cat << \SHAR_EOF > amigaDos.c /* SCCS Id: @(#)amigaDos.c msdos.c - Amiga version 2.3 88/07/24 /* An assortment of MSDOS functions. */ #include <stdio.h> #include "hack.h" #undef TRUE #undef FALSE #undef COUNT #include <libraries/dos.h> extern char Initialized; struct FileLock *Lock(), *CurrentDir(); /* Cheating - BCPL pointers */ struct FileHandle *Open(); /* Cheating - BCPL pointer */ long Read(), Write(), IoErr(), AvailMem(); void *malloc(); char *rindex(), *index(); int Enable_Abort = 0; /* for stdio package */ /* Initial path, so we can find NetHack.cnf */ char PATH[PATHLEN] = "Ram:;df0:;NetHack:"; void flushout() { (void) fflush(stdout); } getuid() { return 1; } /* * Actually make up a process id. * Makes sure one can mess less with saved levels... */ int getpid() { static short pid; while (pid == 0) { struct DateStamp dateStamp; pid = rnd(30000); pid += DateStamp(&dateStamp); /* More or less random */ pid ^= (short) (dateStamp.ds_Days >> 16) ^ (short) (dateStamp.ds_Days) ^ (short) (dateStamp.ds_Minute) + (short) (dateStamp.ds_Tick); pid %= 30000; } return pid; } char * getlogin() { return ((char *) NULL); } int abs(x) int x; { return x < 0? -x: x; } #ifdef REDO tgetch() { char ch, popch(); if (!(ch = popch())) { ch = WindowGetchar(); } return ((ch == '\r') ? '\n' : ch); } #else /* REDO /**/ tgetch() { char ch; ch = WindowGetchar(); return ((ch == '\r') ? '\n' : ch); } #endif /* REDO /**/ #ifdef DGK # include <ctype.h> # include <fcntl.h> # define Sprintf (void) sprintf # ifdef SHELL dosh() { pline("No mysterious force prevented you from using multitasking."); return 0; } # endif /* SHELL */ /* construct the string file.level */ void name_file(file, level) char *file; int level; { char *tf; if (tf = rindex(file, '.')) Sprintf(tf+1, "%d", level); } #define ID_DOS1_DISK 'DOS\1' /* * This routine uses an approximation of the free bytes on a disk. * How large a file you can actually write depends on the number of * extension blocks you need for it. * An iterative approach is used that (hopefully) mimics the AmigaDOG * (yuck, tripos) block allocation sequence used when a file grows. */ long freediskspace(path) char *path; { register long freeBytes = 0; register struct InfoData *infoData; /* Remember... longword aligned */ char fileName[32]; /* * Find a valid path on the device of which we want the free space. * If there is a colon in the name, it is an absolute path * and all up to the colon is everything we need. * Remember slashes in a volume name are allowed! * If there is no colon, it is relative to the current directory, * so must be on the current device, so "" is enough... */ { register char *colon; strncpy(fileName, path, sizeof(fileName)-1); fileName[31] = 0; if (colon = index(fileName, ':')) colon[1] = '\0'; else fileName[0] = '\0'; } if (infoData = malloc(sizeof(*infoData))) { struct FileLock *fileLock; /* Cheating */ if (fileLock = Lock(fileName, SHARED_LOCK)) { if (Info(fileLock, infoData)) { /* We got a kind of DOS volume, since we can Lock it. */ /* Calculate number of blocks available for new file */ /* Kludge for the ever-full VOID: (oops RAM:) device */ if (infoData->id_UnitNumber == -1 && infoData->id_NumBlocks == infoData->id_NumBlocksUsed) { freeBytes = AvailMem(0L) - 48*1024; /* Just a stupid guess at the */ /* Ram-Handler overhead per block: */ freeBytes -= freeBytes/16; } else { /* Normal kind of DOS file system device/volume */ register long fileBlocks; register long extensionPointers; freeBytes = infoData->id_NumBlocks - infoData->id_NumBlocksUsed - 1; /* for file header */ if (infoData->id_DiskType == ID_DOS_DISK) /* BytesPerBlock is 488 on floppies */ extensionPointers = (infoData->id_BytesPerBlock-200)/4; else /* Presumably it is 512 on ID_DOS1_DISK. */ extensionPointers = (infoData->id_BytesPerBlock-224)/4; /* Number of blocks left to simulate */ fileBlocks = freeBytes; /* Need another extension block? */ while (fileBlocks > extensionPointers) { /* Get an extension block. One block less free. */ freeBytes--; fileBlocks--; /* to accomodate 72 extra data blocks */ fileBlocks -= extensionPointers; } freeBytes *= infoData->id_BytesPerBlock; } if (freeBytes < 0) freeBytes = 0; } UnLock(fileLock); } free(infoData); } return freeBytes; } long filesize(file) char *file; { register struct FileLock *fileLock; register struct FileInfoBlock *fileInfoBlock; register long size = 0; if (fileInfoBlock = malloc(sizeof(*fileInfoBlock))) { if (fileLock = Lock(file, SHARED_LOCK)) { if (Examine(fileLock, fileInfoBlock)) { size = fileInfoBlock->fib_Size; } UnLock(fileLock); } free(fileInfoBlock); } return size; } /* * On the Amiga, looking if a specific file exists is much faster * than sequentially reading a directory. */ void eraseall(path, files) char *path, *files; { char buf[FILENAME]; short i; struct FileLock *fileLock, *dirLock; if (dirLock = Lock(path)) { dirLock = CurrentDir(dirLock); strcpy(buf, files); for (i = 0; i < MAXLEVEL; i++) { name_file(buf, i); if (fileLock = Lock(buf, SHARED_LOCK)) { UnLock(fileLock); DeleteFile(buf); } } UnLock(CurrentDir(dirLock)); } } /* This size makes that most files can be copied with two Read()/Write()s */ #define COPYSIZE 4096 char *CopyFile(from, to) char *from, *to; { register struct FileHandle *fromFile, *toFile; register char *buffer; register long size; char *error = NULL; if (buffer = malloc(COPYSIZE)) { if (fromFile = Open(from, MODE_OLDFILE)) { if (toFile = Open(to, MODE_NEWFILE)) { while (size = Read(fromFile, buffer, (long)COPYSIZE)) { if (size != Write(toFile, buffer, size)) { error = "Write error"; break; } } Close(toFile); } else /* Can't open destination file */ error = "Cannot open destination"; Close(fromFile); } else /* Cannot open source file. Should not happen. */ error = "Huh?? Cannot open source??"; free(buffer); return error; } else /* Cannot obtain buffer for copying */ return "No Memory !"; } void copybones(mode) int mode; { struct FileLock *fileLock; char from[FILENAME], to[FILENAME]; char *frompath, *topath, *status; short i; extern int saveprompt; if (!ramdisk) return; frompath = (mode != TOPERM) ? permbones : levels; topath = (mode == TOPERM) ? permbones : levels; /* Remove any bones files in `to' directory. */ eraseall(topath, allbones); /* Copy `from' to `to' */ strcpy(from, frompath); strcat(from, allbones); strcpy(to, topath); strcat(to, allbones); for (i = 1; i < MAXLEVEL; i++) { name_file(from, i); name_file(to, i); if (fileLock = Lock(from, SHARED_LOCK)) { UnLock(fileLock); if (status = CopyFile(from, to)) goto failed; } } /* * The last file got there. Remove the ramdisk bones files. */ if (mode == TOPERM) eraseall(frompath, allbones); return; /* Last file didn't get there. */ failed: msmsg("Cannot copy `%s' to `%s'\n(%s)\n", from, to, status); if (mode == TOPERM) { msmsg("Bones will be left in `%s'\n", *frompath ? frompath : hackdir); return; } else { /* Remove all bones files on the RAMdisk */ eraseall(levels, allbones); playwoRAMdisk(); } } playwoRAMdisk() { msmsg("Do you wish to play without a RAMdisk (y/n) ? "); /* Set ramdisk false *before* exit'ing (because msexit calls * copybones) */ ramdisk = FALSE; if (getchar() != 'y') { settty("Be seeing you ...\n"); exit(0); } set_lock_and_bones(); return; } saveDiskPrompt(start) { extern int saveprompt; char buf[BUFSIZ], *bp; struct FileLock *fileLock; if (saveprompt) { /* Don't prompt if you can find the save file */ if (fileLock = Lock(SAVEF, SHARED_LOCK)) { UnLock(fileLock); return 1; } remember_topl(); home(); cl_end(); msmsg("If save file is on a SAVE disk, put that disk in now.\n"); cl_end(); msmsg("File name (default `%s'%s) ? ", SAVEF, start ? "" : ", <Esc> cancels save"); getlin(buf); home(); cl_end(); curs(1, 2); cl_end(); if (!start && *buf == '\033') return 0; /* Strip any whitespace. Also, if nothing was entered except * whitespace, do not change the value of SAVEF. */ for (bp = buf; *bp; bp++) if (!isspace(*bp)) { strncpy(SAVEF, bp, PATHLEN); break; } } return 1; } /* Return 1 if the record file was found */ static boolean record_exists() { FILE *file; if (file = fopenp(RECORD, "r")) { fclose(file); return TRUE; } return FALSE; } /* Prompt for game disk, then check for record file. */ void gameDiskPrompt() { extern int saveprompt; if (record_exists()) return; if (saveprompt) { (void) putchar('\n'); getreturn("when the GAME disk has been put in"); } if (!record_exists()) { msmsg("\n\nWARNING: can't find record file `%s'!\n", RECORD); msmsg("If the GAME disk is not in, put it in now.\n"); getreturn("to continue"); } } /* Read configuration */ void read_config_file() { char tmp_ramdisk[PATHLEN], tmp_levels[PATHLEN]; char buf[BUFSZ], *bufp; FILE *fp, *fopenp(); extern char plname[]; extern int saveprompt; tmp_ramdisk[0] = 0; tmp_levels[0] = 0; if ((fp = fopenp(configfile, "r")) == NULL) { msmsg("Warning: no configuration file!\n"); getreturn("to continue"); return; } while (fgets(buf, BUFSZ, fp)) { if (*buf == '#') continue; /* remove trailing whitespace */ bufp = index(buf, '\n'); while (bufp > buf && isspace(*bufp)) bufp--; if (bufp == buf) continue; /* skip all-blank lines */ else *(bufp + 1) = 0; /* 0 terminate line */ /* find the '=' */ if (!(bufp = index(buf, '='))) { msmsg("Bad option line: '%s'\n", buf); getreturn("to continue"); continue; } /* skip whitespace between '=' and value */ while (isspace(*++bufp)) ; /* Go through possible variables */ if (!strncmp(buf, "HACKDIR", 4)) { strncpy(hackdir, bufp, PATHLEN); } else if (!strncmp(buf, "RAMDISK", 3)) { strncpy(tmp_ramdisk, bufp, PATHLEN); } else if (!strncmp(buf, "LEVELS", 4)) { strncpy(tmp_levels, bufp, PATHLEN); } else if (!strncmp(buf, "OPTIONS", 4)) { parseoptions(bufp, TRUE); if (plname[0]) /* If a name was given */ plnamesuffix(); /* set the character class */ } else if (!strncmp(buf, "SAVE", 4)) { char *ptr; if (ptr = index(bufp, ';')) { *ptr = '\0'; if (*(ptr+1) == 'n' || *(ptr+1) == 'N') saveprompt = FALSE; } (void) strncpy(SAVEF, bufp, PATHLEN); append_slash(SAVEF); #ifdef GRAPHICS } else if (!strncmp(buf, "GRAPHICS", 4)) { unsigned int translate[MAXPCHARS]; int i; if ((i = sscanf(bufp, "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d", &translate[ 0], &translate[ 1], &translate[ 2], &translate[ 3], &translate[ 4], &translate[ 5], &translate[ 6], &translate[ 7], &translate[ 8], &translate[ 9], &translate[10], &translate[11], &translate[12], &translate[13], &translate[14], &translate[15], &translate[16], &translate[17])) < 0) { msmsg ("Syntax error in GRAPHICS\n"); getreturn("to continue"); } /* Yuck! Worked only with low-byte first!!! */ /* * You could have problems here if you configure FOUNTAINS, SPIDERS or NEWCLASS * in or out and forget to change the tail entries in your graphics string. */ #define SETPCHAR(f, n) showsyms.f = (i > n) ? translate[n] : defsyms.f SETPCHAR(stone, 0); SETPCHAR(vwall, 1); SETPCHAR(hwall, 2); SETPCHAR(tlcorn, 3); SETPCHAR(trcorn, 4); SETPCHAR(blcorn, 5); SETPCHAR(brcorn, 6); SETPCHAR(door, 7); SETPCHAR(room, 8); SETPCHAR(corr, 9); SETPCHAR(upstair, 10); SETPCHAR(dnstair, 11); SETPCHAR(trap, 12); #ifdef FOUNTAINS SETPCHAR(pool, 13); SETPCHAR(fountain, 14); #endif #ifdef NEWCLASS SETPCHAR(throne, 15); #endif #ifdef SPIDERS SETPCHAR(web, 16); #endif #ifdef SINKS SETPCHAR(sink, 17); #endif #undef SETPCHAR #endif /* GRAPHICS */ } else if (!strncmp(buf, "PATH", 4)) { strncpy(PATH, bufp, PATHLEN); } else { msmsg("Bad option line: '%s'\n", buf); getreturn("to continue"); } } fclose(fp); strcpy(permbones, tmp_levels); if (tmp_ramdisk[0]) { strcpy(levels, tmp_ramdisk); if (strcmpi(permbones, levels)) /* if not identical */ ramdisk = TRUE; } else strcpy(levels, tmp_levels); strcpy(bones, levels); } /* Set names for bones[] and lock[] */ void set_lock_and_bones() { if (!ramdisk) { strcpy(levels, permbones); strcpy(bones, permbones); } append_slash(permbones); append_slash(levels); append_slash(bones); strcat(bones, allbones); strcpy(lock, levels); strcat(lock, alllevels); } /* * Add a slash to any name not ending in / or :. There must * be room for the /. */ void append_slash(name) char *name; { char *ptr; if (!*name) return; ptr = name + (strlen(name) - 1); if (*ptr != '/' && *ptr != ':') { *++ptr = '/'; *++ptr = '\0'; } } void getreturn(str) char *str; { int ch; msmsg("Hit <RETURN> %s.", str); while ((ch = getchar()) != '\n') ; } void msmsg(fmt, a1, a2, a3) char *fmt; long a1, a2, a3; { printf(fmt, a1, a2, a3); (void) fflush(stdout); } /* Follow the PATH, trying to fopen the file. */ #define PATHSEP ';' #undef fopen FILE * fopenp(name, mode) register char *name, *mode; { char buf[BUFSIZ], *bp, *pp, lastch; FILE *fp; register struct FileLock *theLock; /* Try the default directory first. Then look along PATH. */ strcpy(buf, name); if (theLock = Lock(buf, SHARED_LOCK)) { UnLock(theLock); if (fp = fopen(buf, mode)) return fp; } pp = PATH; while (pp && *pp) { bp = buf; while (*pp && *pp != PATHSEP) lastch = *bp++ = *pp++; if (lastch != ':' && lastch != '/' && bp != buf) *bp++ = '/'; strcpy(bp, name); if (theLock = Lock(buf, SHARED_LOCK)) { UnLock(theLock); if (fp = fopen(buf, mode)) return fp; } if (*pp) pp++; } return NULL; } #endif /* DGK */ #ifdef CHDIR /* * A not general-purpose directory changing routine. * Assumes you want to return to the original directory eventually, * by chdir()ing to orgdir. * Assumes -1 is not a valid lock, since 0 is valid. */ #define NO_LOCK ((struct FileLock *) -1) char orgdir[1]; static struct FileLock *OrgDirLock = NO_LOCK; chdir(dir) char *dir; { if (dir == orgdir) { /* We want to go back to where we came from. */ if (OrgDirLock != NO_LOCK) { UnLock(CurrentDir(OrgDirLock)); OrgDirLock = NO_LOCK; } } else { /* * Go to some new place. If still at the original * directory, save the FileLock. */ struct FileLock *newDir; if (newDir = Lock(dir, SHARED_LOCK)) { if (OrgDirLock == NO_LOCK) { OrgDirLock = CurrentDir(newDir); } else { UnLock(CurrentDir(newDir)); } } else { return -1; /* Failed */ } } /* CurrentDir always succeeds if you have a lock */ return 0; } #endif /* Chdir back to original directory */ #undef exit void msexit(code) { #ifdef CHDIR extern char orgdir[]; #endif #ifdef DGK (void) fflush(stdout); if (ramdisk) copybones(TOPERM); #endif #ifdef CHDIR chdir(orgdir); /* chdir, not chdirx */ #endif /* Never know when exit is called... */ if (Initialized && (curx != 1 || cury != 1)) getret(); CleanUp(); exit(code); } /* * Strcmp while ignoring case. Not general-purpose, so static. */ static int strcmpi(a, b) register char *a, *b; { while (tolower(*a) == tolower(*b)) { if (!*a) /* *a == *b, so at end of both strings */ return 0; /* equal. */ a++; b++; } return 1; } /* * cmpmem - used to compare two struct symbols, in lev.c */ cmpmem(a, b, size) register unsigned char *a, *b; register int size; { while (size--) { if (*a++ != *b++) return 1; /* not equal */ } return 0; /* equal */ } SHAR_EOF cat << \SHAR_EOF > amigaMenu.c /* * amigaMenu.c (C) Copyright 1988 by Olaf Seibert (KosmoSoft) * * Originally by John Toebes. */ #define TEXT(nam,str) \ static struct IntuiText nam = {0,1,JAM2,0,0,NULL,(UBYTE *)str,NULL} /* Commands */ TEXT(T_HELP, "? display help"); TEXT(T_o, "O set options"); TEXT(T_SHELL, "! AMIGADOS commands"); TEXT(T_v, "v version number"); TEXT(T_CR, "^R redraw screen"); TEXT(T_CP, "^P repeat last message"); TEXT(T_Q, "Q quit game"); TEXT(T_S, "S save the game"); /* Inventory */ TEXT(T_i, "i inventory"); TEXT(T_p, "p pay your bill"); TEXT(T_d, "d drop an object"); TEXT(T_D, "D Drop several things"); TEXT(T_COMMA, ", Pickup an object"); TEXT(T_SLASH, "/ identify something"); TEXT(T_c, "c call class of objects"); TEXT(T_C, "C Christen a monster"); /* Actions */ TEXT(T_a, "a apply/use something"); TEXT(T_e, "e eat something"); TEXT(T_q, "q quaff a potion"); TEXT(T_r, "r read a scroll"); TEXT(T_t, "t throw/shoot weapon"); TEXT(T_z, "z zap a wand"); /* Preparations */ TEXT(T_w, "w wield a weapon"); TEXT(T_P, "P Put on ring"); TEXT(T_R, "R Remove ring"); TEXT(T_T, "T Take off armor"); TEXT(T_W, "W Wear armor"); TEXT(T_WPN, ") current weapon"); TEXT(T_ARMOR, "[ current armor"); TEXT(T_RING, "= current rings"); /* Movement */ TEXT(T_E, "E Engrave msg on floor"); TEXT(T_s, "s search"); TEXT(T_UP, "< Go up stairs"); TEXT(T_DOWN, "> Go down stairs"); TEXT(T_WAIT, ". wait a moment"); TEXT(T_CT, "^T Teleport"); #define IFLAGS ITEMENABLED|ITEMTEXT|HIGHCOMP #define IDATA(cmd,str,off) 0,off,WDT,9,IFLAGS,0,(APTR)&str,NULL,cmd,NULL,NULL /* Commands */ #undef WDT #define WDT 184 static struct MenuItem cmdsub[] = { { &cmdsub[1], IDATA('?', T_HELP, 0) }, /* display help */ { &cmdsub[2], IDATA('O', T_o, 10) }, /* set options */ { &cmdsub[3], IDATA('!', T_SHELL, 20) }, /* AMIGADOS commands */ { &cmdsub[4], IDATA('v', T_v, 30) }, /* version number */ { &cmdsub[5], IDATA(022, T_CR, 40) }, /*R redraw screen */ { &cmdsub[6], IDATA(024 ,T_CP, 50) }, /*P repeat last message */ { &cmdsub[7], IDATA('Q', T_Q, 60) }, /* quit game */ { NULL, IDATA('S', T_S, 70) } /* save the game */ }; /* Inventory */ #undef WDT #define WDT 200 static struct MenuItem invsub[] = { { &invsub[1], IDATA('i', T_i, 0) }, /* inventory */ { &invsub[2], IDATA('p', T_p, 10) }, /* pay your bill */ { &invsub[3], IDATA('d', T_d, 20) }, /* drop an object */ { &invsub[4], IDATA('D', T_D, 30) }, /* Drop several things */ { &invsub[5], IDATA(',', T_COMMA, 40) }, /* Pickup an object */ { &invsub[6], IDATA('/', T_SLASH, 50) }, /* identify something */ { &invsub[7], IDATA('c', T_c, 60) }, /* call a class of objects */ { NULL, IDATA('C', T_C, 70) } /* Christen a monster */ }; /* Actions */ #undef WDT #define WDT 184 static struct MenuItem actsub[] = { { &actsub[1], IDATA('a', T_a, 0) }, /* apply/use something */ { &actsub[2], IDATA('e', T_e, 10) }, /* eat something */ { &actsub[3], IDATA('q', T_q, 20) }, /* quaff a potion */ { &actsub[4], IDATA('r', T_r, 30) }, /* read a scroll */ { &actsub[5], IDATA('t', T_t, 40) }, /* throw/shoot weapon */ { NULL, IDATA('z', T_z, 50) } /* zap a wand */ }; /* Preparations */ #undef WDT #define WDT 144 static struct MenuItem armsub[] = { { &armsub[1], IDATA('w', T_w, 0) }, /* wield a weapon */ { &armsub[2], IDATA('P', T_P, 10) }, /* Put on ring */ { &armsub[3], IDATA('R', T_R, 20) }, /* Remove ring */ { &armsub[4], IDATA('T', T_T, 30) }, /* Take off armor */ { &armsub[5], IDATA('W', T_W, 40) }, /* Wear armor */ { &armsub[6], IDATA(')', T_WPN, 50) }, /* current weapon */ { &armsub[7], IDATA('[', T_ARMOR, 60) }, /* current armor */ { NULL, IDATA('=', T_RING, 70) } /* current rings */ }; /* Movement */ #undef WDT #define WDT 192 static struct MenuItem movsub[] = { { &movsub[1], IDATA('E', T_E, 0) }, /* Engrave msg on floor */ { &movsub[2], IDATA('s', T_s, 10) }, /* search */ { &movsub[3], IDATA('<', T_UP, 20) }, /* Go up stairs */ { &movsub[4], IDATA('>', T_DOWN, 30) }, /* Go down stairs */ { &movsub[5], IDATA('.', T_WAIT, 40) }, /* wait a moment */ { NULL, IDATA(024, T_CT, 50) } /*T Teleport */ }; /* Menustrip */ /* Width = #letters * 8 + 8 */ struct Menu HackMenu[] = { { &HackMenu[1], 10,0, 72,0,MENUENABLED,"Commands", &cmdsub[0] }, /*8*/ { &HackMenu[2], 82,0, 80,0,MENUENABLED,"Inventory", &invsub[0] }, /*9*/ { &HackMenu[3],162,0, 64,0,MENUENABLED,"Actions", &actsub[0] }, /*7*/ { &HackMenu[4],226,0,104,0,MENUENABLED,"Preparations", &armsub[0] }, /*12*/ { NULL, 330,0, 72,0,MENUENABLED,"Movement", &movsub[0] } /*8*/ }; SHAR_EOF cat << \SHAR_EOF > amigaTTY.c /* SCCS Id: @(#)amigaTTY.c 2.3 88/07/25 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* tty.c - (Amiga) version */ #include <stdio.h> #include "hack.h" #include "func_tab.h" extern int Enable_Abort; static char erase_char, kill_char; /* * Get initial state of terminal, set ospeed (for termcap routines) * and switch off tab expansion if necessary. * Called by startup() in termcap.c and after returning from ! or ^Z */ gettty() { erase_char = 127; /* DEL */ kill_char = 21; /* cntl-U */ flags.cbreak = TRUE; Enable_Abort = 0; curx = 1; cury = 1; } /* reset terminal to original state */ settty(s) char *s; { end_screen(); if (s) { printf(s); curx = FAR; /* For msexit(): don't exit immediately */ } (void) fflush(stdout); /* Do not close the screen, that is done in msexit() */ } /* fatal error */ /*VARARGS1*/ error(s,x,y) char *s; { end_screen(); putchar('\n'); printf(s,x,y); putchar('\n'); abort(1); } /* * Read a line closed with '\n' into the array char bufp[BUFSZ]. * (The '\n' is not stored. The string is closed with a '\0'.) * Reading can be interrupted by an escape ('\033') - now the * resulting string is "\033". */ getlin(bufp) register char *bufp; { register char *obufp = bufp; register int c; flags.toplin = 2; /* nonempty, no --More-- required */ for(;;) { (void) fflush(stdout); if((c = getchar()) == EOF) { *bufp = 0; return; } if(c == '\033') { *obufp = c; obufp[1] = 0; return; } if(c == erase_char || c == '\b') { if(bufp != obufp) { bufp--; putstr("\b \b"); /* putsym converts \b */ } else bell(); } else if(c == '\n') { *bufp = 0; return; } else if(' ' <= c && c < '\177') { /* avoid isprint() - some people don't have it ' ' is not always a printing char */ *bufp = c; bufp[1] = 0; putstr(bufp); if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO) bufp++; } else if(c == kill_char || c == '\177') { /* Robert Viduya */ /* this test last - @ might be the kill_char */ while(bufp != obufp) { bufp--; putstr("\b \b"); } } else bell(); } } getret() { cgetret(""); } cgetret(s) register char *s; { putsym('\n'); if(flags.standout) standoutbeg(); putstr("Hit "); putstr(flags.cbreak ? "space" : "return"); putstr(" to continue: "); if(flags.standout) standoutend(); xwaitforspace(s); } char morc; /* tell the outside world what char he used */ xwaitforspace(s) register char *s; /* chars allowed besides space or return */ { register int c; morc = 0; while((c = readchar()) != '\n') { if(flags.cbreak) { if(c == ' ') break; if(s && index(s,c)) { morc = c; break; } bell(); } } } static int last_multi; char * parse() { static char inline[COLNO]; register foo; flags.move = 1; if(!Invisible) curs_on_u(); else home(); multi = 0; #ifdef DGK while((foo = readchar()) >= '0' && foo <= '9') { multi = 10*multi+foo-'0'; if (multi < 0 || multi > LARGEST_INT) multi = LARGEST_INT; if (multi > 9) { remember_topl(); home(); cl_end(); printf("Count: %d", multi); } last_multi = multi; } # ifdef REDO if (foo == DOAGAIN || in_doagain) multi = last_multi; else { savech(0); /* reset input queue */ savech(foo); } # endif #else /* DGK */ while((foo = readchar()) >= '0' && foo <= '9') multi = 10*multi+foo-'0'; #endif /* DGK */ if(multi) { multi--; save_cm = inline; } inline[0] = foo; inline[1] = 0; if(foo == 'g' || foo == 'G'){ inline[1] = getchar(); #ifdef REDO savech(inline[1]); #endif inline[2] = 0; } if(foo == 'm' || foo == 'M'){ inline[1] = getchar(); #ifdef REDO savech(inline[1]); #endif inline[2] = 0; } clrlin(); return(inline); } char readchar() { register int sym; (void) fflush(stdout); sym = getchar(); if(flags.toplin == 1) flags.toplin = 2; return((char) sym); } #ifdef COM_COMPL /* Read in an extended command - doing command line completion for * when enough character have been entered to make a unique command. * This is just a modified getlin(). -jsb */ get_ext_cmd(bufp) register char *bufp; { register char *obufp = bufp; register int c; int com_index, index; flags.toplin = 2; /* nonempty, no --More-- required */ for(;;) { (void) fflush(stdout); if((c = readchar()) == EOF) { *bufp = 0; return; } if(c == '\033') { *obufp = c; obufp[1] = 0; return; } if(c == erase_char || c == '\b') { if(bufp != obufp) { bufp--; putstr("\b \b"); /* putsym converts \b */ } else bell(); } else if(c == '\n') { *bufp = 0; return; } else if(' ' <= c && c < '\177') { /* avoid isprint() - some people don't have it ' ' is not always a printing char */ *bufp = c; bufp[1] = 0; index = 0; com_index = -1; while(extcmdlist[index].ef_txt != (char *) 0){ if(!strncmp(obufp, extcmdlist[index].ef_txt, strlen(obufp))) if(com_index == -1) /* No matches yet*/ com_index = index; else /* More than 1 match */ com_index = -2; index++; } if(com_index >= 0){ strcpy(obufp, extcmdlist[com_index].ef_txt); /* finish print our string */ putstr(bufp); bufp = obufp; /* reset it */ if(strlen(obufp) < BUFSIZ-1 && strlen(obufp) < COLNO) /* set bufp at the end of our * string */ bufp += strlen(obufp); } else { putstr(bufp); if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO) bufp++; } } else if(c == kill_char || c == '\177') { /* Robert Viduya */ /* this test last - @ might be the kill_char */ while(bufp != obufp) { bufp--; putstr("\b \b"); } } else bell(); } } #endif COM_COMPL SHAR_EOF cat << \SHAR_EOF > amigaTermcap.c /* SCCS Id: @(#)termcap.c 2.1 87/10/19 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ #include <stdio.h> #include <ctype.h> /* for isdigit() */ #include "hack.h" /* for ROWNO, COLNO, *HI, *HE */ #define xputc(c) WindowPutchar(c) #define xputs(s) WindowFPuts(s) extern char *getenv(); extern long *alloc(); static char HO[] = "\x9BH"; /* Home */ static char CL[] = "\x1Bc"; /* Clear */ static char CE[] = "\x9BK"; /* Erase end of line */ static char UP[] = "\x0B"; /* Cursor up */ static char CM[] = "\x9B%d;%dH"; /* used with function tgoto() */ static char ND[] = "\x9BC"; /* Cursor right */ static char XD[] = "\x9BB"; /* Cursor down */ static char BC[] = "\x08"; /* Cursor left */ #ifdef MSDOSCOLOR /* creps@silver.bacs.indiana.edu */ static char SO[] = "\x9B33m"; /* Standout: Color #3 (red) */ static char SE[] = "\x9B0m"; #else static char SO[] = "\x9B7m"; /* Inverse video */ static char SE[] = "\x9B0m"; #endif char *CD = "\x9BJ"; /* char *CD; tested in pri.c: docorner() */ /* #if defined(DGK) || defined(SORTING) */ #ifdef DGK # define XXX #endif #ifdef SORTING # define XXX #endif #ifdef XXX # ifdef MSDOSCOLOR char *HI_OBJ = "\x9B31;42m"; /* White on Black */ char *HI_MON = "\x9B33;42m"; /* Orange on black */ char *HI = "\x9B1m"; /* Bold (hilight) */ char *HE = "\x9B0m"; /* Plain */ # else char *HI_OBJ = ""; char *HI_MON = ""; char *HI = "\x9B4m"; /* Underline */ char *HE = "\x9B0m"; /* Plain */ # endif #endif #undef XXX int CO = COLNO; int LI = ROWNO; /* used in pri.c and whatis.c */ static char tgotobuf[20]; #define tgoto(fmt, x, y) (sprintf(tgotobuf, fmt, y+1, x+1), tgotobuf) startup() { (void) Initialize(); /* This opens screen, window, console, &c */ } start_screen() { } end_screen() { clear_screen(); } /* Cursor movements */ extern xchar curx, cury; #ifdef TERMCAP curs(x, y) register int x, y; /* not xchar: perhaps xchar is unsigned and curx-x would be unsigned as well */ { if (y == cury && x == curx) return; if(!ND && (curx != x || x <= 3)) { /* Extremely primitive */ cmov(x, y); /* bunker!wtm */ return; } if(abs(cury-y) <= 3 && abs(curx-x) <= 3) nocmov(x, y); else if((x <= 3 && abs(cury-y)<= 3) || (!CM && x<abs(curx-x))) { (void) putchar('\r'); curx = 1; nocmov(x, y); } else if(!CM) { nocmov(x, y); } else cmov(x, y); } nocmov(x, y) { if (cury > y) { if(UP) { while (cury > y) { /* Go up. */ xputs(UP); cury--; } } else if(CM) { cmov(x, y); } else if(HO) { home(); curs(x, y); } /* else impossible("..."); */ } else if (cury < y) { if(XD) { while(cury < y) { xputs(XD); cury++; } } else if(CM) { cmov(x, y); } else { while(cury < y) { xputc('\n'); curx = 1; cury++; } } } if (curx < x) { /* Go to the right. */ if(!ND) cmov(x, y); else /* bah */ /* should instead print what is there already */ while (curx < x) { xputs(ND); curx++; } } else if (curx > x) { while (curx > x) { /* Go to the left. */ xputs(BC); curx--; } } } cmov(x, y) register x, y; { xputs(tgoto(CM, x-1, y-1)); cury = y; curx = x; } #else /* !TERMCAP */ curs(x, y) register x, y; { if (x != curx || y != cury) { xputs(tgoto(CM, x-1, y-1)); cury = y; curx = x; } } #endif /* TERMCAP */ #ifndef xputc xputc(c) char c; { (void) putchar(c, stdout); } #endif #ifndef xputs xputs(s) char *s; { WindowFPuts(s); } #endif cl_end() { #ifdef TERMCAP if(CE) xputs(CE); else { /* no-CE fix - free after Harold Rynes */ /* this looks terrible, especially on a slow terminal but is better than nothing */ register cx = curx, cy = cury; while(curx < COLNO) { xputc(' '); curx++; } curs(cx, cy); } #else xputs(CE); #endif } clear_screen() { xputs(CL); home(); } home() { #ifdef TERMCAP if(HO) xputs(HO); else if(CM) xputs(tgoto(CM, 0, 0)); else curs(1, 1); /* using UP ... */ #else xputs(HO); #endif curx = cury = 1; } standoutbeg() { #ifdef TERMCAP if(SO) #endif xputs(SO); } standoutend() { #ifdef TERMCAP if(SE) #endif xputs(SE); } backsp() { xputs(BC); curx--; } bell() { #ifdef DGKMOD if (flags.silent) return; #endif /* DGKMOD /**/ (void) putchar('\007'); /* curx does not change */ (void) fflush(stdout); } delay_output() { /* delay 50 ms - could also use a 'nap'-system call */ Delay(2L); } cl_eos() /* free after Robert Viduya */ { /* must only be called with curx = 1 */ #ifdef TERMCAP if(CD) xputs(CD); else { register int cx = curx, cy = cury; while(cury <= LI-2) { cl_end(); xputc('\n'); curx = 1; cury++; } cl_end(); curs(cx, cy); } #else xputs(CD); #endif } SHAR_EOF cat << \SHAR_EOF > amigaUnix.c /* SCCS Id: @(#)pcunix.c 1.4 87/08/08 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* unix.c - version 1.0.3 */ /* This file collects some Unix dependencies; pager.c contains some more */ /* * The time is used for: * - seed for rand() * - year on tombstone and yymmdd in record file * - phase of the moon (various monsters react to NEW_MOON or FULL_MOON) * - night and midnight (the undead are dangerous at midnight) * - determination of what files are "very old" */ #include <stdio.h> /* mainly for NULL */ #include "hack.h" /* mainly for index() which depends on BSD */ #include <time.h> #include <stat.h> extern time_t time(); static struct stat buf, hbuf; setrandom() { (void) srand((int) time ((time_t *) 0)); } struct tm * getlt() { time_t date; struct tm *localtime(); (void) time(&date); return(localtime(&date)); } getyear() { return(1900 + getlt()->tm_year); } char * getdate() { static char datestr[7]; register struct tm *lt = getlt(); (void) sprintf(datestr, "%2d%2d%2d", lt->tm_year, lt->tm_mon + 1, lt->tm_mday); if(datestr[2] == ' ') datestr[2] = '0'; if(datestr[4] == ' ') datestr[4] = '0'; return(datestr); } phase_of_the_moon() /* 0-7, with 0: new, 4: full */ { /* moon period: 29.5306 days */ /* year: 365.2422 days */ register struct tm *lt = getlt(); register int epact, diy, golden; diy = lt->tm_yday; golden = (lt->tm_year % 19) + 1; epact = (11 * golden + 18) % 30; if ((epact == 25 && golden > 11) || epact == 24) epact++; return( (((((diy + epact) * 6) + 11) % 177) / 22) & 7 ); } night() { register int hour = getlt()->tm_hour; return(hour < 6 || hour > 21); } midnight() { return(getlt()->tm_hour == 0); } gethdate(name) char *name; { /* old version - for people short of space */ /* /* register char *np; /* if(stat(name, &hbuf)) /* error("Cannot get status of %s.", /* (np = rindex(name, '/')) ? np+1 : name); /* /* version using PATH from: seismo!gregc@ucsf-cgl.ARPA (Greg Couch) */ /* * The problem with #include <sys/param.h> is that this include file * does not exist on all systems, and moreover, that it sometimes includes * <sys/types.h> again, so that the compiler sees these typedefs twice. */ #define MAXPATHLEN 80 extern char PATH[]; /* In amigaDOS.c */ register char *np, *path; char filename[MAXPATHLEN+1]; if (index(name, '/') != NULL || (path = PATH) == NULL) path = ""; for (;;) { if ((np = index(path, ':')) == NULL) np = path + strlen(path); /* point to end str */ if (np - path <= 1) /* %% */ (void) strcpy(filename, name); else { (void) strncpy(filename, path, np - path); filename[np - path] = '/'; (void) strcpy(filename + (np - path) + 1, name); } if (stat(filename, &hbuf) == 0) return; if (*np == '\0') path = ""; path = np + 1; } error("Cannot get status of %s.", (np = rindex(name, '/')) ? np+1 : name); } uptodate(fd) { #ifndef AMIGA /* Amiga has no fstat */ if(fstat(fd, &buf)) { pline("Cannot get status of saved level? "); return(0); } if(buf.st_mtime < hbuf.st_mtime) { pline("Saved level is out of date. "); return(0); } #endif return(1); } regularize(s) /* normalize file name - we don't like :'s or /'s */ register char *s; { register char *lp; while((lp = index(s, ':')) || (lp = index(s, '/'))) *lp = '_'; } SHAR_EOF cat << \SHAR_EOF > amigaWindow.c /* * amigaWindow.c (C) Copyright 1988 by Olaf Seibert (KosmoSoft) */ /* * Here is some very Amiga specific stuff, dealing with * screens, windows and menus. */ #include "config.h" #define HACKFONT #undef TRUE #undef FALSE #undef COUNT #include <exec/types.h> #include <exec/alerts.h> #include <exec/io.h> #include <exec/devices.h> #include <devices/console.h> #include <intuition/intuition.h> #include <libraries/dosextens.h> #include "amigaMenu.c" /* First, external declarations... */ struct Library *OpenLibrary(); struct Screen *OpenScreen(); struct Window *OpenWindow(); struct TextFont *OpenDiskFont(); struct IntuiMessage *GetMsg(); struct MenuItem *ItemAddress(); struct Process *FindTask(); /* Cheating */ long DeadKeyConvert(), OpenDevice(), CloseDevice(); extern struct Library *IconBase; /* Now our own variables */ struct Library *IntuitionBase; struct Screen *HackScreen; struct Window *HackWindow; struct Window *pr_WindowPtr; struct IOStdReq ConsoleIO; char Initialized = FALSE; #ifdef HACKFONT struct Library *GfxBase; struct Library *DiskfontBase; #endif struct Device *ConsoleDevice; #define CSI '\x9b' #define NO_CHAR -1 #define RAWHELP 0x5F /* Rawkey code of the HELP key */ /* * It is assumed that all multiple-character outputs are * at most CONBUFFER characters each. */ #define CONBUFFER BUFSZ /* 512 */ static char ConsoleBuffer[CONBUFFER]; static unsigned short Buffered; #define KBDBUFFER 10 static unsigned char KbdBuffer[KBDBUFFER]; static unsigned char KbdBuffered; #define BufferQueueChar(ch) (KbdBuffer[KbdBuffered++] = ch) /* * It seems Intuition won't OpenDiskFont our diskFont, so we get the * closest match, which is of course topaz/8. (and if not, it is still * an 8-pixel font, so everything still looks ok) */ struct TextAttr Hack80 = { #ifdef HACKFONT (UBYTE *) "NetHack:Hack.font", #else (UBYTE *) "topaz.font", #endif TOPAZ_EIGHTY, FS_NORMAL, FPF_DISKFONT }; #ifdef HACKFONT struct TextFont *HackFont; #endif #define BARHEIGHT 11 #define WINDOWHEIGHT 192 #define WIDTH 640 #define DEPTH 2 struct NewScreen NewHackScreen = { 0, 0, WIDTH, BARHEIGHT + WINDOWHEIGHT, DEPTH, 0, 1, /* DetailPen, BlockPen */ HIRES, CUSTOMSCREEN, &Hack80, /* Font */ (UBYTE *) "NetHack 2.3 - Ported by Olaf Seibert (KosmoSoft)", NULL, /* Gadgets */ NULL, /* CustomBitmap */ }; struct NewWindow NewHackWindow = { /* left, top, width, height, detailpen, blockpen */ 0, BARHEIGHT, WIDTH, WINDOWHEIGHT, -1, -1, RAWKEY | MENUPICK /* | MOUSEBUTTONS | GADGETDOWN */ , BORDERLESS | BACKDROP | ACTIVATE, NULL, NULL, NULL, NULL, NULL, -1,-1,-1,-1, CUSTOMSCREEN }; static int BufferGetchar() { register unsigned char *from, *to; register int c; register short i; if (KbdBuffered) { c = KbdBuffer[0]; KbdBuffered--; to = KbdBuffer; from = to + 1; /* Move the remaining characters */ for (i = KbdBuffered; i > 0; i--) { *to++ = *from++; } return c; } return NO_CHAR; } /* * This should remind you remotely of DeadKeyConvert, * but we are cheating a bit. * We want complete control over the numeric keypad, and no * dead keys... (they are assumed to be on Alted keys) * Also assumed is that the IntuiMessage is of type RAWKEY. * For some reason, IECODE_UP_PREFIX events seem to be lost when they * occur while our console window is inactive. This is particulary * troublesome with qualifier keys... Is this because I never * RawKeyConvert those events??? */ int ConvertKey(message) register struct IntuiMessage *message; { static struct InputEvent theEvent; static char numpad[] = "bjnh.lyku"; static char ctrl_numpad[] = "\x02\x0A\x0E\x08.\x0C\x19\x0B\x15"; static char shift_numpad[] = "BJNH.LYKU"; unsigned char buffer[1]; register char length; register ULONG qualifier = message->Qualifier; char numeric_pad, shift, control, alt; control = (qualifier & IEQUALIFIER_CONTROL) != 0; shift = (qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) != 0; /* * Shortcut for HELP and arrow keys... I suppose this is allowed... * the defines are in intuition/intuition.h, and the keys * don't serve 'text' input, normally. * Also, parsing their escape sequences is such a mess... */ switch (message->Code) { case RAWHELP: length = '?'; goto no_arrow; case CURSORLEFT: length = 'h'; goto arrow; case CURSORDOWN: length = 'j'; goto arrow; case CURSORUP: length = 'k'; goto arrow; case CURSORRIGHT: length = 'l'; arrow: if (control) length &= 0x1F; /* ToControl... */ else if (shift) length &= 0x5F; /* ToUpper... */ no_arrow: BufferQueueChar(length); return; } #ifdef BETA if (!ConsoleDevice) { /* Should never happen */ abort(AG_IOError | AO_ConsoleDev); return; } #endif numeric_pad = (qualifier & IEQUALIFIER_NUMERICPAD) != 0; if (alt = (qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT)) != 0) /* Don't want dead keys... */ qualifier &= ~(IEQUALIFIER_LALT | IEQUALIFIER_RALT); theEvent.ie_Class = IECLASS_RAWKEY; theEvent.ie_Code = message->Code; theEvent.ie_Qualifier = numeric_pad ? IEQUALIFIER_NUMERICPAD : qualifier; theEvent.ie_EventAddress = (APTR) *(message->IAddress); length = RawKeyConvert(&theEvent, buffer, (long) sizeof(buffer), NULL); if (length == 1) { /* Plain ASCII character */ length = buffer[0]; if (numeric_pad && length >= '1' && length <= '9') { length -= '1'; if (control) { length = ctrl_numpad[length]; } else if (shift) { length = shift_numpad[length]; } else { length = numpad[length]; } } BufferQueueChar(length); } /* else shift, ctrl, alt, amiga, F-key, shift-tab, etc */ } /* * Process an incoming IntuiMessage. * It would certainly look nicer if this could be done using a * PA_SOFTINT message port, but we cannot call RawKeyConvert() * during a software interrupt. * Anyway, kbhit() is called often enough, and usually gets * ahead of input demands, when the user types ahead. */ static char ProcessMessage(message) register struct IntuiMessage *message; { switch(message->Class) { case MENUPICK: { USHORT thismenu; struct MenuItem *item = NULL; thismenu = message->Code; while (thismenu != MENUNULL) { item = ItemAddress(&HackMenu, (ULONG) thismenu); if (KbdBuffered < KBDBUFFER) BufferQueueChar(item->Command); /* Unused: No COMMSEQ */ thismenu = item->NextSelect; } } break; case RAWKEY: if (!(message->Code & IECODE_UP_PREFIX)) ConvertKey(message); /* May queue multiple characters */ break; /* but doesn't do that yet */ #if 0 case CLOSEWINDOW: BufferQueueChar('Q'); break; #endif #if 0 case GADGETDOWN: BufferQueueChar( ((struct Gadget *)message->IAddress)->GadgetID ); break; #endif } ReplyMsg(message); } /* * Get all incoming messages and fill up the keyboard buffer, * thus allowing Intuition to (maybe) free up the IntuiMessages. * Return when no more messages left, or keyboard buffer half full. * We need to do this since there is no one-to-one correspondence * between characters and incoming messages. */ int kbhit() { register struct IntuiMessage *message; while( (KbdBuffered < KBDBUFFER / 2) && (message = GetMsg(HackWindow->UserPort)) ) ProcessMessage(message); return KbdBuffered; } /* * Get a character from the keyboard buffer, waiting if * not available. */ int WindowGetchar() { while ( !kbhit() ) { Wait( 1L << HackWindow->UserPort->mp_SigBit ); } return BufferGetchar(); } /* * Flush the output waiting in the console output buffer. */ void WindowFlush() { #ifdef BETA if (!ConsoleDevice) { /* Should never happen */ abort(AG_IOError | AO_ConsoleDev); return; } #endif if (Buffered) { ConsoleIO.io_Command = CMD_WRITE; ConsoleIO.io_Data = (APTR)ConsoleBuffer; ConsoleIO.io_Length = Buffered; DoIO(&ConsoleIO); Buffered = 0; } } /* * Queue a single character for output to the console screen. */ int WindowPutchar(c) char c; { if (Buffered >= CONBUFFER) WindowFlush(); ConsoleBuffer[Buffered++] = c; } /* * Queue an entire string for output to the console screen, * flushing the existing characters first, if necessary. * Do not append a newline. */ void WindowFPuts(string) char *string; { register int len = _BUILTIN_strlen(string); if (len + Buffered >= CONBUFFER) WindowFlush(); _BUILTIN_strcpy(ConsoleBuffer + Buffered, string); Buffered += len; } /* * Queue an entire string for output to the console screen, * flushing the existing characters first, if necessary. * Append a newline. */ void WindowPuts(string) char *string; { WindowFPuts(string); WindowPutchar('\n'); } /* * Queue a formatted string for output to the console screen, * flushing the existing characters first, if necessary. */ void WindowPrintf(fmt, args, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) char *fmt; long args, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9; { #ifdef AZTEC_C /* Efficient but not portable */ format(WindowPutchar, fmt, &args); #else WindowFlush(); /* Don't know if all will fit */ # ifdef __STDC__ /* Cheap and portable way */ vsprintf(ConsoleBuffer, fmt, &args); # else /* Expensive... */ sprintf(ConsoleBuffer, fmt, args, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); # endif ConsoleIO.io_Command = CMD_WRITE; ConsoleIO.io_Data = (APTR)ConsoleBuffer; ConsoleIO.io_Length = -1; DoIO(&ConsoleIO); #endif } void CleanUp() { struct IntuiMessage *msg; /* Clean up resources */ if (ConsoleIO.io_Device) { CloseDevice(&ConsoleIO); ConsoleDevice = NULL; } if (HackWindow) { FindTask(NULL)->pr_WindowPtr = (APTR) pr_WindowPtr; ClearMenuStrip(HackWindow); Forbid(); while (msg = GetMsg(HackWindow->UserPort)) ReplyMsg(msg); CloseWindow(HackWindow); Permit(); HackWindow = NULL; } if (HackScreen) { CloseScreen(HackScreen); HackScreen = NULL; } /* if (IconBase) { CloseLibrary(IconBase); IconBase = NULL; } */ #ifdef HACKFONT if (HackFont) { CloseFont(HackFont); HackFont = NULL; } if (DiskfontBase) { CloseLibrary(DiskfontBase); DiskfontBase = NULL; } if (GfxBase) { CloseLibrary(GfxBase); GfxBase = NULL; } #endif if (IntuitionBase) { CloseLibrary(IntuitionBase); IntuitionBase = NULL; } Initialized = FALSE; } void abort(rc) long rc; { #ifdef CHDIR extern char orgdir[]; chdir(orgdir); #endif if (Initialized && ConsoleDevice) { printf("\n\nAbort with alert code %08lx...\n", rc); getret(); } else Alert(rc, 0L); CleanUp(); #undef exit exit(rc); } /* Used by library routines, and the debugger */ void _abort() { abort(-10L); } /* * Open everything we need. */ void Initialize() { if (Initialized) return; if ( (IntuitionBase = OpenLibrary("intuition.library", LIBRARY_VERSION)) == NULL) abort(AG_OpenLib | AO_Intuition); #ifdef HACKFONT if ( (GfxBase = OpenLibrary("graphics.library",LIBRARY_VERSION)) == NULL) abort(AG_OpenLib | AO_GraphicsLib); /* * Force our own font to be loaded, if possible. * If we can open diskfont.library, but not our font, we can close * the diskfont.library again since it just wastes memory. * Even if we can open the font, we don't need the diskfont.library * anymore, since CloseFont is a graphics.library function. */ if (DiskfontBase = OpenLibrary("diskfont.library", LIBRARY_VERSION)) { HackFont = OpenDiskFont(&Hack80); CloseLibrary(DiskfontBase); DiskfontBase = NULL; } #endif /* if ( (IconBase = OpenLibrary("icon.library",LIBRARY_VERSION)) == NULL) abort(AG_OpenLib | AO_IconLib); */ /* * Now Intuition is supposed to use our HackFont for the screen, * since we have a corresponding TextAttr, but it *doesn't*. * So, we need to do a SetFont() a bit later on. */ if ( (HackScreen = OpenScreen(&NewHackScreen)) == NULL) abort(AN_OpenScreen & ~AT_DeadEnd); NewHackWindow.Screen = HackScreen; if ( (HackWindow = OpenWindow(&NewHackWindow)) == NULL) abort(AN_OpenWindow & ~AT_DeadEnd); SetMenuStrip(HackWindow,&HackMenu); { register struct Process *myProcess = FindTask(NULL); pr_WindowPtr = (struct Window *)myProcess->pr_WindowPtr; myProcess->pr_WindowPtr = (APTR) HackWindow; } #ifdef HACKFONT if (HackFont) SetFont(HackWindow->RPort, HackFont); #endif ConsoleIO.io_Data = (APTR) HackWindow; ConsoleIO.io_Length = sizeof(*HackWindow); if (OpenDevice("console.device",0L , &ConsoleIO, 0L) != 0) abort(AG_OpenDev | AO_ConsoleDev); ConsoleDevice = ConsoleIO.io_Device; Buffered = 0; KbdBuffered = 0; /* set CRMOD on */ WindowFPuts("\x9B20h"); Initialized = TRUE; } SHAR_EOF # End of shell archive exit 0 -- Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page Have five nice days.