///////////////////////////////////////////////////////////////////////////// // // hefile emucall handler // sint32 EMU_CALL psx_emucall( void *state, uint8 *ram_native, uint32 ram_size, sint32 type, sint32 emufd, sint32 ofs, sint32 arg1, sint32 arg2 ) { if(type == 0) { if(PSXSTATE->console_callback) { sint32 i; for(i = 0; i < arg1; i++) { char c = ram_native[ofs & (ram_size-1)]; ofs++; if(c == 'H') { PSXSTATE->console_enable = 1; } if(PSXSTATE->console_enable) { (PSXSTATE->console_callback)(PSXSTATE->console_context, c); } } } return arg1; } if(!(HAVE_VFS)) return -5; switch(type) { case 3: return vopen (VFSSTATE, ram_native, ram_size, ofs); case 4: return vclose(VFSSTATE, emufd); case 5: return vread (VFSSTATE, ram_native, ram_size, emufd, ofs, arg1); case 6: return -13; // EACCES permission denied case 7: return vlseek(VFSSTATE, emufd, arg1, arg2); default: return -5; } }
VSP::VSP(char *fname) { VFILE *f = vopen(fname); if (!f) err("VSP::VSP() - couldn't find VSP file %s", fname); LoadVSP(f); vclose(f); }
corona::Image* load_image_from_packfile(const char* filename) { VFILE* vf = vopen(filename); if (!vf) { err("loadimage: couldn't load image %s; couldnt find a file or a vfile", filename); } int l = filesize(vf); std::auto_ptr<char> buffer(new char[l]); vread(buffer.get(), l, vf); vclose(vf); std::auto_ptr<corona::File> memfile(corona::CreateMemoryFile(buffer.get(), l)); return corona::OpenImage(memfile.get(), corona::FF_AUTODETECT, corona::PF_DONTCARE); }
/* OPEN, LOCK, UNLOCK */ void ivopen() { int obj_cnt, item; for (item = 1, obj_cnt = 0; item < MAXOBJ; item++) { if ((g.place[item] == g.loc) && (hinged(item))) { object = item; obj_cnt++; } } if (obj_cnt != 1) needobj(); else if (verb == LOCK) vlock(); else if (verb == UNLOCK) vunlock(); else if (verb == SHUT) vclose(); else vopen(); }
void vappend(int ch, int cnt, int indent) { register int i; register char *gcursor; bool escape; int repcnt; short oldhold = hold; /* * Before a move in hardopen when the line is dirty * or we are in the middle of the printed representation, * we retype the line to the left of the cursor so the * insert looks clean. */ if (ch != 'o' && state == HARDOPEN && (rubble || !ateopr())) { rubble = 1; wcursor = cursor; vmove(); } vaifirst = indent == 0; /* * Handle replace character by (eventually) * limiting the number of input characters allowed * in the vgetline routine. */ if (ch == 'r') repcnt = 2; else repcnt = 0; /* * If an autoindent is specified, then * generate a mixture of blanks to tabs to implement * it and place the cursor after the indent. * Text read by the vgetline routine will be placed in genbuf, * so the indent is generated there. */ if (value(AUTOINDENT) && indent != 0) { gcursor = genindent(indent); *gcursor = 0; vgotoCL(qcolumn(cursor - 1, genbuf)); } else { gcursor = genbuf; *gcursor = 0; if (ch == 'o') vfixcurs(); } /* * Prepare for undo. Pointers delimit inserted portion of line. */ vUA1 = vUA2 = cursor; /* * If we are not in a repeated command and a ^@ comes in * then this means the previous inserted text. * If there is none or it was too long to be saved, * then beep() and also arrange to undo any damage done * so far (e.g. if we are a change.) */ if ((vglobp && *vglobp == 0) || peekbr()) { if ((INS[0] & (OVERBUF|TRIM)) == OVERBUF) { beep(); if (!splitw) ungetkey('u'); doomed = 0; hold = oldhold; return; } /* * Unread input from INS. * An escape will be generated at end of string. * Hold off n^^2 type update on dumb terminals. */ vglobp = INS; hold |= HOLDQIK; } else if (vglobp == 0) /* * Not a repeated command, get * a new inserted text for repeat. */ INS[0] = 0; /* * For wrapmargin to hack away second space after a '.' * when the first space caused a line break we keep * track that this happened in gobblebl, which says * to gobble up a blank silently. */ gobblebl = 0; /* * Text gathering loop. * New text goes into genbuf starting at gcursor. * cursor preserves place in linebuf where text will eventually go. */ if (*cursor == 0 || state == CRTOPEN) hold |= HOLDROL; for (;;) { if (ch == 'r' && repcnt == 0) escape = 0; else { gcursor = vgetline(repcnt, gcursor, &escape); /* * After an append, stick information * about the ^D's and ^^D's and 0^D's in * the repeated text buffer so repeated * inserts of stuff indented with ^D as backtab's * can work. */ if (HADUP) addtext("^"); else if (HADZERO) addtext("0"); while (CDCNT > 0) addtext("\204"), CDCNT--; if (gobbled) addtext(" "); addtext(ogcursor); } repcnt = 0; /* * Smash the generated and preexisting indents together * and generate one cleanly made out of tabs and spaces * if we are using autoindent. */ if (!vaifirst && value(AUTOINDENT)) { i = fixindent(indent); if (!HADUP) indent = i; gcursor = strend(genbuf); } /* * Limit the repetition count based on maximum * possible line length; do output implied * by further count (> 1) and cons up the new line * in linebuf. */ cnt = vmaxrep(ch, cnt); CP(gcursor + 1, cursor); do { CP(cursor, genbuf); if (cnt > 1) { int oldhold = hold; Outchar = vinschar; hold |= HOLDQIK; ex_printf("%s", genbuf); hold = oldhold; Outchar = vputchar; } cursor += gcursor - genbuf; } while (--cnt > 0); endim(); vUA2 = cursor; if (escape != '\n') CP(cursor, gcursor + 1); /* * If doomed characters remain, clobber them, * and reopen the line to get the display exact. */ if (state != HARDOPEN) { DEPTH(vcline) = 0; if (doomed > 0) { register int cind = cindent(); physdc(cind, cind + doomed); doomed = 0; } i = vreopen(LINE(vcline), lineDOT(), vcline); } /* * All done unless we are continuing on to another line. */ if (escape != '\n') break; /* * Set up for the new line. * First save the current line, then construct a new * first image for the continuation line consisting * of any new autoindent plus the pushed ahead text. */ killU(); addtext(gobblebl ? " " : "\n"); vsave(); cnt = 1; if (value(AUTOINDENT)) { #ifdef LISP if (value(LISP)) indent = lindent(dot + 1); else #endif if (!HADUP && vaifirst) indent = whitecnt(linebuf); vaifirst = 0; strcLIN(vpastwh(gcursor + 1)); gcursor = genindent(indent); *gcursor = 0; if (gcursor + strlen(linebuf) > &genbuf[LBSIZE - 2]) gcursor = genbuf; CP(gcursor, linebuf); } else { CP(genbuf, gcursor + 1); gcursor = genbuf; } /* * If we started out as a single line operation and are now * turning into a multi-line change, then we had better yank * out dot before it changes so that undo will work * correctly later. */ if (vundkind == VCHNG) { vremote(1, (void (*)(int))yank, 0); undap1--; } /* * Now do the append of the new line in the buffer, * and update the display. If slowopen * we don't do very much. */ vdoappend(genbuf); vundkind = VMANYINS; vcline++; if (state != VISUAL) vshow(dot, NOLINE); else { i += LINE(vcline - 1); vopen(dot, i); if (value(SLOWOPEN)) vscrap(); else vsync1(LINE(vcline)); } strcLIN(gcursor); *gcursor = 0; cursor = linebuf; vgotoCL(qcolumn(cursor - 1, genbuf)); } /* * All done with insertion, position the cursor * and sync the screen. */ hold = oldhold; if (cursor > linebuf) cursor--; if (state != HARDOPEN) vsyncCL(); else if (cursor > linebuf) back1(); doomed = 0; wcursor = cursor; vmove(); }
//--- //setup garlick to use vfile void *Garlick_vf_open(const char *fname) { return vopen(fname); }
/* Routine to process a transitive verb */ trverb() { switch(verb){ case CALM: case WALK: case QUIT: case SCORE: case FOO: case BRIEF: case SUSPEND: case HOURS: case LOG: actspk(verb); break; case TAKE: vtake(); break; case DROP: vdrop(); break; case OPEN: case LOCK: vopen(); break; case SAY: vsay(); break; case NOTHING: rspeak(54); break; case ON: von(); break; case OFF: voff(); break; case WAVE: vwave(); break; case KILL: vkill(); break; case POUR: vpour(); break; case EAT: veat(); break; case DRINK: vdrink(); break; case RUB: if (object != LAMP) rspeak(76); else actspk(RUB); break; case THROW: vthrow(); break; case FEED: vfeed(); break; case FIND: case INVENTORY: vfind(); break; case FILL: vfill(); break; case READ: vread(); break; case BLAST: vblast(); break; case BREAK: vbreak(); break; case WAKE: vwake(); break; default: printf("This verb is not implemented yet.\n"); } }
/* * Fully cleanup the screen, leaving no @ lines except at end when * line after last won't completely fit. The routine vsync is * more conservative and much less work on dumb terminals. */ void vredraw(register int p) { register int l; register line *tp; char temp[LBSIZE]; bool anydl = 0; short oldhold = hold; #ifdef ADEBUG if (trace) tfixnl(), fprintf(trace, "vredraw(%d)\n", p), tvliny(); #endif if (holdupd) { holdupd = 3; return; } if (state == HARDOPEN || splitw) return; if (p < 0 /* || p > WECHO */) error(catgets(catd, 1, 221, "Internal error: vredraw")); /* * Trim the ragged edges (lines which are off the screen but * not yet logically discarded), save the current line, and * search for first logical line affected by the redraw. */ vscrap(); CP(temp, linebuf); l = 0; tp = dot - vcline; if (vcnt == 0) LINE(0) = WTOP; while (l < vcnt && LINE(l) < p) l++, tp++; /* * We hold off echo area clearing during the redraw in deference * to a final clear of the echo area at the end if appropriate. */ heldech = 0; hold |= HOLDECH; for (; l < vcnt && Peekkey != ATTN; l++) { if (l == vcline) strcLIN(temp); else getline(*tp); /* * Delete junk between displayed lines. */ if (LINE(l) != LINE(l + 1) && LINE(l) != p) { if (anydl == 0 && DB && CD) { hold = oldhold; vclrech(0); anydl = 1; hold |= HOLDECH; heldech = 0; } vdellin(p, LINE(l) - p, l); } /* * If line image is not know to be up to date, then * redisplay it; else just skip onward. */ LINE(l) = p; if (FLAGS(l) & VDIRT) { DEPTH(l) = vdepth(); if (l != vcline && p + DEPTH(l) - 1 > WBOT) { vscrap(); break; } FLAGS(l) &= ~VDIRT; vreopen(p, lineno(tp), l); p = LINE(l) + DEPTH(l); } else p += DEPTH(l); tp++; } /* * That takes care of lines which were already partially displayed. * Now try to fill the rest of the screen with text. */ if (state == VISUAL && p <= WBOT) { int ovcline = vcline; vcline = l; for (; tp <= dol && Peekkey != ATTN; tp++) { getline(*tp); if (p + vdepth() - 1 > WBOT) break; vopen(tp, p); p += DEPTH(vcline); vcline++; } vcline = ovcline; } /* * Thats all the text we can get on. * Now rest of lines (if any) get either a ~ if they * are past end of file, or an @ if the next line won't fit. */ for (; p <= WBOT && Peekkey != ATTN; p++) vclrlin(p, tp); strcLIN(temp); hold = oldhold; if (heldech) vclrech(0); #ifdef ADEBUG if (trace) tvliny(); #endif }
/* * Open new lines. * * Tricky thing here is slowopen. This causes display updating * to be held off so that 300 baud dumb terminals don't lose badly. * This also suppressed counts, which otherwise say how many blank * space to open up. Counts are also suppressed on intelligent terminals. * Actually counts are obsoleted, since if your terminal is slow * you are better off with slowopen. */ void voOpen ( int c, /* mjm: char --> int */ register int cnt ) { register int ind = 0, i; short oldhold = hold; #ifdef SIGWINCH sigset_t set, oset; #endif if (value(SLOWOPEN) || value(REDRAW) && AL && DL) cnt = 1; #ifdef SIGWINCH sigemptyset(&set); sigaddset(&set, SIGWINCH); sigprocmask(SIG_BLOCK, &set, &oset); #endif vsave(); setLAST(); if (value(AUTOINDENT)) ind = whitecnt(linebuf); if (c == 'O') { vcline--; dot--; if (dot > zero) getDOT(); } if (value(AUTOINDENT)) { #ifdef LISPCODE if (value(LISP)) ind = lindent(dot + 1); #endif } killU(); prepapp(); if (FIXUNDO) vundkind = VMANY; if (state != VISUAL) c = WBOT + 1; else { c = vcline < 0 ? WTOP - cnt : LINE(vcline) + DEPTH(vcline); if (c < ZERO) c = ZERO; i = LINE(vcline + 1) - c; if (i < cnt && c <= WBOT && (!AL || !DL)) vinslin(c, cnt - i, vcline); } *genindent(ind) = 0; vdoappend(genbuf); vcline++; oldhold = hold; hold |= HOLDROL; vopen(dot, c); hold = oldhold; if (value(SLOWOPEN)) /* * Oh, so lazy! */ vscrap(); else vsync1(LINE(vcline)); cursor = linebuf; linebuf[0] = 0; vappend('o', 1, ind); #ifdef SIGWINCH sigprocmask(SIG_SETMASK, &oset, NULL); #endif }
/* * Change operator. * * In a single line we mark the end of the changed area with '$'. * On multiple whole lines, we clear the lines first. * Across lines with both wcursor and wdot given, we delete * and sync then append (but one operation for undo). */ void vchange(int c) { register char *cp; register int i, ind, cnt; line *addr; if (wdot) { /* * Change/delete of lines or across line boundaries. */ if ((cnt = xdw()) < 0) return; getDOT(); if (wcursor && cnt == 1) { /* * Not really. */ wdot = 0; if (c == EOF) { vdelete(c); return; } goto smallchange; } if (cursor && wcursor) { /* * Across line boundaries, but not * necessarily whole lines. * Construct what will be left. */ *cursor = 0; strcpy(genbuf, linebuf); getline(*wdot); if (strlen(genbuf) + strlen(wcursor) > LBSIZE - 2) { getDOT(); beep(); return; } strcat(genbuf, wcursor); if (c == EOF && *vpastwh(genbuf) == 0) { /* * Although this is a delete * spanning line boundaries, what * would be left is all white space, * so take it all away. */ wcursor = 0; getDOT(); op = 0; notpart(lastreg); notpart('1'); vdelete(c); return; } ind = -1; } else if (c == EOF && wcursor == 0) { vdelete(c); return; } else #ifdef LISPCODE /* * We are just substituting text for whole lines, * so determine the first autoindent. */ if (value(LISP) && value(AUTOINDENT)) ind = lindent(dot); else #endif ind = whitecnt(linebuf); i = vcline >= 0 ? LINE(vcline) : WTOP; /* * Delete the lines from the buffer, * and remember how the partial stuff came about in * case we are told to put. */ addr = dot; vremote(cnt, delete, 0); setpk(); notenam = "delete"; if (c != EOF) notenam = "change"; /* * If DEL[0] were nonzero, put would put it back * rather than the deleted lines. */ DEL[0] = 0; if (cnt > 1) killU(); /* * Now hack the screen image coordination. */ vreplace(vcline, cnt, 0); wdot = NOLINE; noteit(0); vcline--; if (addr <= dol) dot--; /* * If this is a across line delete/change, * cursor stays where it is; just splice together the pieces * of the new line. Otherwise generate a autoindent * after a S command. */ if (ind >= 0) { *genindent(ind) = 0; vdoappend(genbuf); } else { vmcurs = cursor; strcLIN(genbuf); vdoappend(linebuf); } /* * Indicate a change on hardcopies by * erasing the current line. */ if (c != EOF && state != VISUAL && state != HARDOPEN) { int oldhold = hold; hold |= HOLDAT, vclrlin(i, dot), hold = oldhold; } /* * Open the line (logically) on the screen, and * update the screen tail. Unless we are really a delete * go off and gather up inserted characters. */ vcline++; if (vcline < 0) vcline = 0; vopen(dot, i); vsyncCL(); noteit(1); if (c != EOF) { if (ind >= 0) { cursor = linebuf; linebuf[0] = 0; vfixcurs(); } else { ind = 0; vcursat(cursor); } vappend('x', 1, ind); return; } if (*cursor == 0 && cursor > linebuf) cursor += skipleft(linebuf, cursor); vrepaint(cursor); return; } smallchange: /* * The rest of this is just low level hacking on changes * of small numbers of characters. */ if (wcursor < linebuf) wcursor = linebuf; if (cursor == wcursor) { beep(); return; } i = vdcMID(); cp = cursor; if (state != HARDOPEN) vfixcurs(); /* * Put out the \\'s indicating changed text in hardcopy, * or mark the end of the change with $ if not hardcopy. */ if (state == HARDOPEN) bleep(i, cp); else { int c, d, n; vcursbef(wcursor); d = skipleft(linebuf, wcursor); nextc(c, &wcursor[d], n); if (colsc(c) > 1) putchar(' '); putchar('$'); i = cindent(); } /* * Remember the deleted text for possible put, * and then prepare and execute the input portion of the change. */ cursor = cp; setDEL(); CP(cursor, wcursor); if (state != HARDOPEN) { vcursaft(cursor - 1); doomed = i - cindent(); } else { /* sethard(); wcursor = cursor; cursor = linebuf; vgoto(outline, value(NUMBER) << 3); vmove(); */ doomed = 0; } prepapp(); vappend('c', 1, 0); }
void vundo ( int show /* if true update the screen */ ) { register int cnt; register line *addr; register char *cp; char *temp = smalloc(LBSIZE); bool savenote; int (*OO)(int); short oldhold = hold; switch (vundkind) { case VMANYINS: wcursor = 0; addr1 = undap1; addr2 = undap2 - 1; vsave(); YANKreg('1'); notecnt = 0; /* fall into ... */ case VMANY: case VMCHNG: vsave(); addr = dot - vcline; notecnt = 1; if (undkind == UNDPUT && undap1 == undap2) { beep(); break; } /* * Undo() call below basically replaces undap1 to undap2-1 * with dol through unddol-1. Hack screen image to * reflect this replacement. */ if (show) if (undkind == UNDMOVE) vdirty(0, TLINES); else vreplace(undap1 - addr, undap2 - undap1, undkind == UNDPUT ? 0 : unddol - dol); savenote = notecnt; undo(1); if (show && (vundkind != VMCHNG || addr != dot)) killU(); vundkind = VMANY; cnt = dot - addr; if (cnt < 0 || cnt > vcnt || state != VISUAL) { if (show) vjumpto(dot, NOSTR, '.'); break; } if (!savenote) notecnt = 0; if (show) { vcline = cnt; vrepaint(vmcurs); } vmcurs = 0; break; case VCHNG: case VCAPU: vundkind = VCHNG; CP(temp, vutmp); CP(vutmp, linebuf); doomed = column(vUA2 - 1) - column(vUA1 - 1); strcLIN(temp); cp = vUA1; vUA1 = vUD1; vUD1 = cp; cp = vUA2; vUA2 = vUD2; vUD2 = cp; if (!show) break; cursor = vUD1; if (state == HARDOPEN) { doomed = 0; vsave(); vopen(dot, WBOT); vnline(cursor); break; } /* * Pseudo insert command. */ vcursat(cursor); OO = Outchar; Outchar = vinschar; hold |= HOLDQIK; vprepins(); temp[vUA2 - linebuf] = 0; for (cp = &temp[vUA1 - linebuf]; *cp;) { int c, n; nextc(c, cp, n); cp += n; putchar(c); } Outchar = OO; hold = oldhold; endim(); physdc(cindent(), cindent() + doomed); doomed = 0; vdirty(vcline, 1); vsyncCL(); if (cursor > linebuf && cursor >= strend(linebuf)) cursor += skipleft(linebuf, cursor); vfixcurs(); break; case VNONE: beep(); break; } free(temp); }
// Overkill (2006-07-20): Saver functions! void MAP::save(FILE *f) { int i; char tempfn[16] = "$$v3map.tmp"; FILE *out = fopen(tempfn, "wb"); if (!out) err("Unable to open %s for writing!", tempfn); // Map signature. char signature[8]; strcpy(signature, maptag); fwrite(&signature, 1, 6, f); // Version int version = MAP_VERSION; fwrite(&version, 1, 4, f); // USE OUTPUT BUFFER FROM THIS POINT ON. fwrite(mapname, 1, 256, out); //log("mapname: %s", mapname); // savevspname, not vspname because it's what the vsp file WILL be, // not necessarily what it IS at that moment. // So, you can set it then FileSaveVSP() down the line. fwrite(savevspname, 1, 256, out); //log("savevspname: %s", savevspname); fwrite(musicname, 1, 256, out); //log("musicname: %s", musicname); fwrite(renderstring, 1, 256, out); //log("renderstring: %s", renderstring); fwrite(startupscript, 1, 256, out); //log("startupscript: %s", startupscript); fwrite(&startx, 1, 2, out); fwrite(&starty, 1, 2, out); fwrite(&numlayers, 1, 4, out); for (i = 0; i < numlayers; i++) { layers[i]->save(out); } // Obs. cfwrite(obslayer, 1, mapwidth*mapheight, out); // Zones cfwrite(zonelayer, 1, mapwidth*mapheight*2, out); fwrite(&numzones, 1, 4, out); for (i=0; i<numzones; i++) { fwrite(zones[i]->name, 1, 256, out); fwrite(zones[i]->script, 1, 256, out); fwrite(&zones[i]->percent, 1, 1, out); fwrite(&zones[i]->delay, 1, 1, out); fwrite(&zones[i]->method, 1, 1, out); } // ENTITIES! <3. fwrite(&entities, 1, 4, out); for (i=0; i<entities; i++) { //log("ENT %d of %d", i, entities); // Tile coords. int x = entity[i]->x / 16; int y = entity[i]->y / 16; fwrite(&x, 1, 2, out); fwrite(&y, 1, 2, out); fwrite(&entity[i]->face, 1, 1, out); fwrite(&entity[i]->obstructable, 1, 1, out); fwrite(&entity[i]->obstruction, 1, 1, out); fwrite(&entity[i]->autoface, 1, 1, out); fwrite(&entity[i]->speed, 1, 2, out); //log("HERE?"); // FIXME: ACTIVATION MODE int activationMode = 0; fwrite(&activationMode, 1, 1, out); // Movecode and wandering. fwrite(&entity[i]->movecode, 1, 1, out); fwrite(&entity[i]->wx1, 1, 2, out); fwrite(&entity[i]->wy1, 1, 2, out); fwrite(&entity[i]->wx2, 1, 2, out); fwrite(&entity[i]->wy2, 1, 2, out); fwrite(&entity[i]->wdelay, 1, 2, out); //log("YAR?"); // Expand! whatever, man. int expand = 0; fwrite(&expand, 1, 4, out); // h8 u STD::string. char tempchar[256]; //log("movestr: %s", entity[i]->movestr); fwrite(entity[i]->movestr, 1, 256, out); strcpy(tempchar, entity[i]->chr->name.c_str()); fwrite(tempchar, 1, 256, out); strcpy(tempchar, entity[i]->description.c_str()); fwrite(tempchar, 1, 256, out); // description strcpy(tempchar, entity[i]->script.c_str()); fwrite(tempchar, 1, 256, out); // The actual script position. } // NO LONGER NEED TO USE THE OUTPUT BUFFER fclose(out); // Why vopen instead? I... don't know! // Now that we've finished the buffer though, we can // use this to fill in the unknown map information. VFILE *tmp = vopen(tempfn); if (!tmp) err("Could not open %s for reading!", tempfn); int bufferlength = filesize(tmp); byte* buf = new byte[bufferlength]; vread(buf, bufferlength, tmp); vclose(tmp); // Delete the temporary buffer, we've gotten what we wanted. remove(tempfn); // Alright... finally, all this to get the offset for the VC stuffs. int vcofs = 14 + bufferlength; fwrite(&vcofs, 1, 4, f); // Write the buffer into the map now. fwrite(buf, 1, bufferlength, f); // VC funcs are waaay down here. int vcfuncs = 0; // number compiled should be none. //log("VCOFS: %d CURRENT POS: %d", vcofs, ftell(f)); fwrite(&vcfuncs, 1, 4, f); }
MAP::MAP(char *fname) { VFILE *f = vopen(fname); if (!f) err("MAP::MAP() - could not load map %s", fname); strcpy(mapfname, fname); strlwr(mapfname); char signature[8]; vread(signature, 6, f); if (strcmp(signature, maptag)) err("MAP::MAP() - %s is not a valid mapfile!", fname); int version; vread(&version, 4, f); if (version != MAP_VERSION) err("MAP::MAP() - %s is not the correct MAP format version!", fname); vread(&version, 4, f); // skip vc offset vread(mapname, 256, f); vread(vspname, 256, f); strcpy(savevspname, vspname); // Overkill 2006-05-21 vread(musicname, 256, f); vread(renderstring, 256, f); vread(startupscript, 256, f); PlayMusic(musicname); startx = starty = 0; vread(&startx, 2, f); vread(&starty, 2, f); std::string s = std::string(fname); int offs = s.rfind('\\'); if (offs >= 0) { s.replace(offs+1,strlen(fname),vspname); tileset = new VSP((char *)s.c_str()); } else { offs = s.rfind('/'); if (offs >= 0) { s.replace(offs+1,strlen(fname),vspname); tileset = new VSP((char *)s.c_str()); } else tileset = new VSP(vspname); } vread(&numlayers, 4, f); //layers = new Layer*[numlayers]; layers.resize(numlayers); int i; for (i=0; i<numlayers; i++) layers[i] = new Layer(f); mapwidth = layers[0]->width; mapheight = layers[0]->height; obslayer = new byte[mapwidth*mapheight]; zonelayer = new word[mapwidth*mapheight]; cvread(obslayer, mapwidth*mapheight, f); cvread(zonelayer, mapwidth*mapheight*2, f); vread(&numzones, 4, f); zones.resize(numzones); for (i=0; i<numzones; i++) { zones[i] = new Zone; zones[i]->percent = zones[i]->method = zones[i]->delay = 0; vread(zones[i]->name, 256, f); vread(zones[i]->script, 256, f); vread(&zones[i]->percent, 1, f); vread(&zones[i]->delay, 1, f); vread(&zones[i]->method, 1, f); } vread(&mapentities, 4, f); for (i=0; i<mapentities; i++) { int t=0, x1=0, y1=0, x2=0, y2=0; char movescript[256], chrname[256], script[256], description[256]; vread(&x1, 2, f); vread(&y1, 2, f); int o1 = vtell(f); vseek(f, 22, 1); vread(movescript, 256, f); vread(chrname, 256, f); vread(description, 256, f); // this is actually the description which we dont care about vread(script, 256, f); // this is the actual script vseek(f, o1, 0); int i = AllocateEntity(x1*16, y1*16, chrname); entity[i]->description = description; entity[i]->script = script; vread(&t, 1, f); if (!t) t = SOUTH; entity[i]->setface(t); t=0; vread(&t, 1, f); entity[i]->obstructable = t ? true : false; t=0; vread(&t, 1, f); entity[i]->obstruction = t ? true : false; t=0; vread(&t, 1, f); entity[i]->autoface = (t!=0); t=0; vread(&t, 2, f); entity[i]->setspeed(t); t=0; vread(&t, 1, f); // activation mode FIXME vread(&t, 1, f); vread(&x1, 2, f); vread(&y1, 2, f); vread(&x2, 2, f); vread(&y2, 2, f); switch(t) { case 0: entity[i]->SetMotionless(); break; case 1: entity[i]->SetWanderZone(); break; case 2: entity[i]->SetWanderBox(x1, y1, x2, y2); break; //FIXME case 3: entity[i]->SetMoveScript(movescript); break; } t=0; vread(&t, 2, f); entity[i]->SetWanderDelay(t); vread(&t, 4, f); vseek(f, 1024, 1); /* vread(&tlen, 4, f); vread(ename, tlen+1, f); // chr filename vread(&tlen, 4, f); vread(chrfn, tlen+1, f); // script vread(&tlen, 4, f); vread(escript, tlen+1, f); // movescript vread(&tlen, 4, f); vread(emovescript, tlen+1, f); vread(&tlen, 4, f); vread(&tlen, 4, f); int eface, speed, tx, ty; vread(&eface, 4, f); vread(&speed, 4, f); vread(&tx, 4, f); vread(&ty, 4, f); vread(&x1, 4, f); vread(&y1, 4, f); vread(&x2, 4, f); vread(&y2, 4, f); int idx = AllocateEntity(tx*16, ty*16, chrfn); entity[idx]->setface(eface); entity[idx]->setspeed(speed); entity[idx]->script = escript; entity[idx]->autoface = (eflags & ENT_AUTOFACE) ? true : false; entity[idx]->obstructable = (eflags & ENT_OBSTRUCTED) ? true : false; entity[idx]->obstruction = (eflags & ENT_OBSTRUCTS) ? true : false; if (method == ENT_MOVESCRIPT) entity[idx]->SetMoveScript(emovescript); if (method == ENT_WANDERZONE) entity[idx]->SetWanderZone(); if (method == ENT_WANDERBOX) entity[idx]->SetWanderBox(x1, y1, x2, y2);*/ } current_map = this; se->LoadMapScript(f, mapfname); vclose(f); se->ExecuteFunctionString(startupscript); }
// Build and pop up a buffer containing a list of all screens and their associated buffers. Render buffer and return status. int showScreens(Value *rp,int n) { Buffer *slistp; EScreen *scrp; // Pointer to current screen to list. EWindow *winp; // Pointer into current screens window list. uint wnum; StrList rpt; int windcol = 7; int filecol = 37; char *strp,wkbuf[filecol + 16]; // Get a buffer and open a string list. if(sysbuf(text160,&slistp) != SUCCESS) // "Screens" return rc.status; if(vopen(&rpt,NULL,false) != 0) return vrcset(); // Construct the header lines. if(vputs(text89,&rpt) != 0 || vputc('\n',&rpt) != 0 || // "Screen Window Buffer File" vputs("------ ------ -------------------- -------------------------------",&rpt) != 0) return vrcset(); // For all screens... scrp = sheadp; do { // Store the screen number. sprintf(wkbuf,"\n%4hu ",scrp->s_num); strp = strchr(wkbuf,'\0'); // List screen's window numbers and buffer names. wnum = 0; winp = scrp->s_wheadp; do { Buffer *bufp = winp->w_bufp; // Indent if not first time through. if(wnum != 0) { wkbuf[0] = '\n'; strp = wkbuf + 1; do { *strp++ = ' '; } while(strp <= wkbuf + windcol); } // Store window number, buffer name, and filename. sprintf(strp,"%4u %c%s",++wnum,(bufp->b_flags & BFCHGD) ? '*' : ' ',bufp->b_bname); strp = strchr(strp,'\0'); if(bufp->b_fname != NULL) // Pad if filename exists. do { *strp++ = ' '; } while(strp <= wkbuf + filecol); *strp = '\0'; // Save buffer and add filename. if(vputs(wkbuf,&rpt) != 0 || (bufp->b_fname != NULL && vputs(bufp->b_fname,&rpt) != 0)) return vrcset(); // On to the next window. } while((winp = winp->w_nextp) != NULL); // On to the next screen. } while((scrp = scrp->s_nextp) != NULL); // Add the results to the buffer. if(vclose(&rpt) != 0) return vrcset(); if(bappend(slistp,rpt.sl_vp->v_strp) != SUCCESS) return rc.status; // Display results. return render(rp,n < 0 ? -2 : n,slistp,RENDRESET | (n != INT_MIN && n < -1 ? RENDALTML : 0)); }
void vappend(int ch, int cnt, int indent) { int i; unsigned char *gcursor; bool escape; int repcnt, savedoomed; short oldhold = hold; int savecnt = cnt; line *startsrcline; int startsrccol, endsrccol; int gotNL = 0; int imultlinecnt = 0; int omultlinecnt = 0; if ((savecnt > 1) && (ch == 'o' || ch == 'O')) { omultlinecnt = 1; } #ifdef XPG6 if ((savecnt > 1) && (ch == 'a' || ch == 'A' || ch == 'i' || ch == 'I')) imultlinecnt = 1; #endif /* XPG6 */ /* * Before a move in hardopen when the line is dirty * or we are in the middle of the printed representation, * we retype the line to the left of the cursor so the * insert looks clean. */ if (ch != 'o' && state == HARDOPEN && (rubble || !ateopr())) { rubble = 1; gcursor = cursor; i = *gcursor; *gcursor = ' '; wcursor = gcursor; (void) vmove(); *gcursor = i; } /* * If vrep() passed indent = 0, this is the 'r' command, * so don't autoindent until the last char. */ vaifirst = indent == 0; /* * Handle replace character by (eventually) * limiting the number of input characters allowed * in the vgetline routine. */ if (ch == 'r') repcnt = 2; else repcnt = 0; /* * If an autoindent is specified, then * generate a mixture of blanks to tabs to implement * it and place the cursor after the indent. * Text read by the vgetline routine will be placed in genbuf, * so the indent is generated there. */ if (value(vi_AUTOINDENT) && indent != 0) { unsigned char x; gcursor = genindent(indent); *gcursor = 0; vgotoCL(nqcolumn(lastchr(linebuf, cursor), genbuf)); } else { gcursor = genbuf; *gcursor = 0; if (ch == 'o') vfixcurs(); } /* * Prepare for undo. Pointers delimit inserted portion of line. */ vUA1 = vUA2 = cursor; /* * If we are not in a repeated command and a ^@ comes in * then this means the previous inserted text. * If there is none or it was too long to be saved, * then beep() and also arrange to undo any damage done * so far (e.g. if we are a change.) */ switch (ch) { case 'r': break; case 'a': /* * TRANSLATION_NOTE * "A" is a terse mode message corresponding to * "APPEND MODE". * Translated message of "A" must be 1 character (not byte). * Or, just leave it. */ if (value(vi_TERSE)) { vshowmode(gettext("A")); } else { vshowmode(gettext("APPEND MODE")); } break; case 's': /* * TRANSLATION_NOTE * "S" is a terse mode message corresponding to * "SUBSTITUTE MODE". * Translated message of "S" must be 1 character (not byte). * Or, just leave it. */ if (value(vi_TERSE)) { vshowmode(gettext("S")); } else { vshowmode(gettext("SUBSTITUTE MODE")); } break; case 'c': /* * TRANSLATION_NOTE * "C" is a terse mode message corresponding to * "CHANGE MODE". * Translated message of "C" must be 1 character (not byte). * Or, just leave it. */ if (value(vi_TERSE)) { vshowmode(gettext("C")); } else { vshowmode(gettext("CHANGE MODE")); } break; case 'R': /* * TRANSLATION_NOTE * "R" is a terse mode message corresponding to * "REPLACE MODE". * Translated message of "R" must be 1 character (not byte). * Or, just leave it. */ if (value(vi_TERSE)) { vshowmode(gettext("R")); } else { vshowmode(gettext("REPLACE MODE")); } break; case 'o': /* * TRANSLATION_NOTE * "O" is a terse mode message corresponding to * "OPEN MODE". * Translated message of "O" must be 1 character (not byte). * Or, just leave it. */ if (value(vi_TERSE)) { vshowmode(gettext("O")); } else { vshowmode(gettext("OPEN MODE")); } break; case 'i': /* * TRANSLATION_NOTE * "I" is a terse mode message corresponding to * "INSERT MODE" and the following "INPUT MODE". * Translated message of "I" must be 1 character (not byte). * Or, just leave it. */ if (value(vi_TERSE)) { vshowmode(gettext("I")); } else { vshowmode(gettext("INSERT MODE")); } break; default: /* * TRANSLATION_NOTE * "I" is a terse mode message corresponding to * "INPUT MODE" and the previous "INSERT MODE". * Translated message of "I" must be 1 character (not byte). * Or, just leave it. */ if (value(vi_TERSE)) { vshowmode(gettext("I")); } else { vshowmode(gettext("INPUT MODE")); } } ixlatctl(1); if ((vglobp && *vglobp == 0) || peekbr()) { if (INS[128] == 0200) { (void) beep(); if (!splitw) ungetkey('u'); doomed = 0; hold = oldhold; return; } /* * Unread input from INS. * An escape will be generated at end of string. * Hold off n^^2 type update on dumb terminals. */ vglobp = INS; inscdcnt = INSCDCNT; hold |= HOLDQIK; } else if (vglobp == 0) { /* * Not a repeated command, get * a new inserted text for repeat. */ INS[0] = 0; INS[128] = 0; INSCDCNT = 0; } /* * For wrapmargin to hack away second space after a '.' * when the first space caused a line break we keep * track that this happened in gobblebl, which says * to gobble up a blank silently. */ gobblebl = 0; startsrcline = dot; startsrccol = cursor - linebuf; /* * Text gathering loop. * New text goes into genbuf starting at gcursor. * cursor preserves place in linebuf where text will eventually go. */ if (*cursor == 0 || state == CRTOPEN) hold |= HOLDROL; for (;;) { if (ch == 'r' && repcnt == 0) escape = 0; else { ixlatctl(1); /* * When vgetline() returns, gcursor is * pointing to '\0' and vgetline() has * read an ESCAPE or NL. */ gcursor = vgetline(repcnt, gcursor, &escape, ch); if (escape == '\n') { gotNL = 1; #ifdef XPG6 if (ch == 'r') { /* * XPG6 assertion 313 [count]r\n : * Arrange to set cursor correctly. */ endsrccol = gcursor - genbuf - 1; } #endif /* XPG6 */ } else { /* * Upon escape, gcursor is pointing to '\0' * terminating the string in genbuf. */ endsrccol = gcursor - genbuf - 1; } ixlatctl(0); /* * After an append, stick information * about the ^D's and ^^D's and 0^D's in * the repeated text buffer so repeated * inserts of stuff indented with ^D as backtab's * can work. */ if (HADUP) addtext("^"); else if (HADZERO) addtext("0"); if(!vglobp) INSCDCNT = CDCNT; while (CDCNT > 0) { addtext("\004"); CDCNT--; } if (gobbled) addtext(" "); addtext(ogcursor); } repcnt = 0; /* * Smash the generated and preexisting indents together * and generate one cleanly made out of tabs and spaces * if we are using autoindent and this isn't 'r' command. */ if (!vaifirst && value(vi_AUTOINDENT)) { i = fixindent(indent); if (!HADUP) indent = i; gcursor = strend(genbuf); } /* * Set cnt to 1 to avoid repeating the text on the same line. * Do this for commands 'i', 'I', 'a', and 'A', if we're * inserting anything with a newline for XPG6. Always do this * for commands 'o' and 'O'. */ if ((imultlinecnt && gotNL) || omultlinecnt) { cnt = 1; } /* * Limit the repetition count based on maximum * possible line length; do output implied * by further count (> 1) and cons up the new line * in linebuf. */ cnt = vmaxrep(ch, cnt); /* * cursor points to linebuf * Copy remaining old text (cursor) in original * line to after new text (gcursor + 1) in genbuf. */ CP(gcursor + 1, cursor); /* * For [count] r \n command, when replacing [count] chars * with '\n', this loop replaces [count] chars with "". */ do { /* cp new text (genbuf) into linebuf (cursor) */ CP(cursor, genbuf); if (cnt > 1) { int oldhold = hold; Outchar = vinschar; hold |= HOLDQIK; viprintf("%s", genbuf); hold = oldhold; Outchar = vputchar; } /* point cursor after new text in linebuf */ cursor += gcursor - genbuf; } while (--cnt > 0); endim(); vUA2 = cursor; /* add the remaining old text after the cursor */ if (escape != '\n') CP(cursor, gcursor + 1); /* * If doomed characters remain, clobber them, * and reopen the line to get the display exact. * eg. c$ to change to end of line */ if (state != HARDOPEN) { DEPTH(vcline) = 0; savedoomed = doomed; if (doomed > 0) { int cind = cindent(); physdc(cind, cind + doomed); doomed = 0; } if(MB_CUR_MAX > 1) rewrite = _ON; i = vreopen(LINE(vcline), lineDOT(), vcline); if(MB_CUR_MAX > 1) rewrite = _OFF; #ifdef TRACE if (trace) fprintf(trace, "restoring doomed from %d to %d\n", doomed, savedoomed); #endif if (ch == 'R') doomed = savedoomed; } /* * Unless we are continuing on to another line * (got a NL), break out of the for loop (got * an ESCAPE). */ if (escape != '\n') { vshowmode(""); break; } /* * Set up for the new line. * First save the current line, then construct a new * first image for the continuation line consisting * of any new autoindent plus the pushed ahead text. */ killU(); addtext(gobblebl ? " " : "\n"); /* save vutmp (for undo state) into temp file */ vsave(); cnt = 1; if (value(vi_AUTOINDENT)) { if (value(vi_LISP)) indent = lindent(dot + 1); else if (!HADUP && vaifirst) indent = whitecnt(linebuf); vaifirst = 0; strcLIN(vpastwh(gcursor + 1)); gcursor = genindent(indent); *gcursor = 0; if (gcursor + strlen(linebuf) > &genbuf[LBSIZE - 2]) gcursor = genbuf; CP(gcursor, linebuf); } else { /* * Put gcursor at start of genbuf to wipe * out previous line in preparation for * the next vgetline() loop. */ CP(genbuf, gcursor + 1); gcursor = genbuf; } /* * If we started out as a single line operation and are now * turning into a multi-line change, then we had better yank * out dot before it changes so that undo will work * correctly later. */ if (FIXUNDO && vundkind == VCHNG) { vremote(1, yank, 0); undap1--; } /* * Now do the append of the new line in the buffer, * and update the display, ie: append genbuf to * the file after dot. If slowopen * we don't do very much. */ vdoappend(genbuf); vundkind = VMANYINS; vcline++; if (state != VISUAL) vshow(dot, NOLINE); else { i += LINE(vcline - 1); vopen(dot, i); if (value(vi_SLOWOPEN)) vscrap(); else vsync1(LINE(vcline)); } switch (ch) { case 'r': break; case 'a': if (value(vi_TERSE)) { vshowmode(gettext("A")); } else { vshowmode(gettext("APPEND MODE")); } break; case 's': if (value(vi_TERSE)) { vshowmode(gettext("S")); } else { vshowmode(gettext("SUBSTITUTE MODE")); } break; case 'c': if (value(vi_TERSE)) { vshowmode(gettext("C")); } else { vshowmode(gettext("CHANGE MODE")); } break; case 'R': if (value(vi_TERSE)) { vshowmode(gettext("R")); } else { vshowmode(gettext("REPLACE MODE")); } break; case 'i': if (value(vi_TERSE)) { vshowmode(gettext("I")); } else { vshowmode(gettext("INSERT MODE")); } break; case 'o': if (value(vi_TERSE)) { vshowmode(gettext("O")); } else { vshowmode(gettext("OPEN MODE")); } break; default: if (value(vi_TERSE)) { vshowmode(gettext("I")); } else { vshowmode(gettext("INPUT MODE")); } } strcLIN(gcursor); /* zero genbuf */ *gcursor = 0; cursor = linebuf; vgotoCL(nqcolumn(cursor - 1, genbuf)); } /* end for (;;) loop in vappend() */ if (imultlinecnt && gotNL) { imultlinerep(savecnt, startsrcline, startsrccol, endsrccol); } else if (omultlinecnt) { omultlinerep(savecnt, startsrcline, endsrccol); #ifdef XPG6 } else if (savecnt > 1 && ch == 'r' && gotNL) { /* * XPG6 assertion 313 & 254 : Position cursor for [count]r\n * then insert [count -1] newlines. */ endsrccol = gcursor - genbuf - 1; rmultlinerep(savecnt, endsrccol); #endif /* XPG6 */ } /* * All done with insertion, position the cursor * and sync the screen. */ hold = oldhold; if ((imultlinecnt && gotNL) || omultlinecnt) { fixdisplay(); #ifdef XPG6 } else if (savecnt > 1 && ch == 'r' && gotNL) { fixdisplay(); /* * XPG6 assertion 313 & 254 [count]r\n : Set flag to call * fixdisplay() after operate() has finished. To be sure that * the text (after the last \n followed by an indent) is always * displayed, fixdisplay() is called right before getting * the next command. */ redisplay = 1; #endif /* XPG6 */ } else if (cursor > linebuf) { cursor = lastchr(linebuf, cursor); #ifdef XPG6 /* * XPG6 assertion 313 & 254 [count]r\n : * For 'r' command, when the replacement char causes new * lines to be created, point cursor to first non-blank. * The old code, ie: cursor = lastchr(linebuf, cursor); * set cursor to the blank before the first non-blank * for r\n */ if (ch == 'r' && gotNL && isblank((int)*cursor)) ++cursor; #endif /* XPG6 */ } if (state != HARDOPEN) vsyncCL(); else if (cursor > linebuf) back1(); doomed = 0; wcursor = cursor; (void) vmove(); }
// Display a pop-up window and page it for the user. If altmodeline is true, display buffer name and filename (only) on bottom // mode line. If endprompt is true, wait for user to press a key before returning (regardless of page size). Current bindings // (if any) for backPage, forwPage, backLine, and forwLine commands are recognized as well as 'b' (backward page), 'f' or space // (forward page), 'u' (backward half page), 'd' (forward half page), 'g' (goto first page), 'G' (goto last page), ESC or 'q' // (exit), and '?' (help). Any non-navigation key gets pushed back into the input stream to be interpeted later as a command. // Return status. int bpop(Buffer *bufp,bool altmodeline,bool endprompt) { Line *lnp1,*lnp,*lpmax; int crow; // Current screen row number. int disprows; // Total number of display rows. int halfpage; // Rows in a half page. int n; // Rows to move. ushort ek; // Input extended key. char *strp,*strpz; // Line text pointers. char *hprompt = NULL; // Help prompt; bool firstpass = true; // Display special mode line if requested. if(altmodeline) { // Find last window on screen and rewrite its mode line. wupd_modeline(wnextis(NULL),bufp); } // Set up and display a pop-up "window". disprows = term.t_nrow - 2; // Check if buffer will fit on one page and if not, set lpmax to first line of last page. lpmax = NULL; n = 0; for(lnp = lforw(bufp->b_hdrlnp); lnp != bufp->b_hdrlnp; lnp = lforw(lnp)) { if(++n > disprows) { // Find beginning of last page. lpmax = bufp->b_hdrlnp; n = disprows; do { lpmax = lback(lpmax); } while(--n > 0); break; } } // Begin at the beginning. lnp1 = lforw(bufp->b_hdrlnp); halfpage = disprows / 2; n = 0; // Display a page (beginning at line lnp1 + n) and prompt for a naviagtion command. Loop until exit key entered or // endprompt is false and buffer fits on one page (lpmax is NULL). for(;;) { lnp = lnp1; // Moving backward? if(n < 0) { do { // At beginning of buffer? if(lpmax == NULL || lnp1 == lforw(bufp->b_hdrlnp)) break; // No, back up one line. lnp1 = lback(lnp1); } while(++n < 0); } // Moving forward? else if(n > 0) { do { // At end of buffer or max line? if(lpmax == NULL || lnp1 == bufp->b_hdrlnp || lnp1 == lpmax) break; // No, move forward one line. lnp1 = lforw(lnp1); } while(--n > 0); } // Illegal command? if(n != 0 && lnp1 == lnp) // Yes, ignore it. n = 0; else { // Found first row ... display page. lnp = lnp1; crow = 0; do { // At end of buffer? if(lnp == bufp->b_hdrlnp) { // Yes, erase remaining lines on physical screen. while(crow < disprows) { vtmove(crow,0); vteeol(); #if COLOR vscreen[crow]->v_rfcolor = gfcolor; vscreen[crow]->v_rbcolor = gbcolor; #endif vscreen[crow]->v_left = FARRIGHT; vscreen[crow]->v_right = 0; #if COLOR vscreen[crow++]->v_flags |= VFCHGD | VFCOLOR; #else vscreen[crow++]->v_flags |= VFCHGD; #endif } break; } // Update the virtual screen image for this line. Characters past right edge of screen won't be // displayed, so ignore those. vtmove(crow,0); strpz = (strp = ltext(lnp)) + (lused(lnp) <= (int) term.t_ncol ? lused(lnp) : term.t_ncol); while(strp < strpz) vtputc(*strp++); vteeol(); #if COLOR vscreen[crow]->v_rfcolor = gfcolor; vscreen[crow]->v_rbcolor = gbcolor; #endif vscreen[crow]->v_left = FARRIGHT; vscreen[crow]->v_right = 0; #if COLOR vscreen[crow++]->v_flags |= VFCHGD | VFCOLOR; #else vscreen[crow++]->v_flags |= VFCHGD; #endif // On to the next line. lnp = lforw(lnp); } while(crow < disprows); // Screen is full. Copy the virtual screen to the physical screen. if(pupd_all(false) != SUCCESS) return rc.status; // Bail out if called from terminp() and one-page buffer. if(firstpass && !endprompt && lpmax == NULL) goto uexit; firstpass = false; } // Display prompt. mlputs(MLHOME | MLFORCE,hprompt != NULL ? hprompt : lpmax == NULL || lnp1 == lpmax ? text201 : ": "); // "End: " if(TTflush() != SUCCESS) return rc.status; // Get response. for(;;) { // Get a keystroke and decode it. if(getkey(&ek) != SUCCESS) return rc.status; // Exit? if(ek == (CTRL | '[') || ek == 'q') goto uexit; // Forward whole page? if(ek == ' ' || ek == 'f' || iscmd(ek,forwPage)) { n = disprows - overlap; break; } // Forward half page? if(ek == 'd') { n = halfpage; break; } // Backward whole page? if(ek == 'b' || iscmd(ek,backPage)) { n = overlap - disprows; break; } // Backward half page? if(ek == 'u') { n = -halfpage; break; } // Forward a line? if(iscmd(ek,forwLine)) { n = 1; break; } // Backward a line? if(iscmd(ek,backLine)) { n = -1; break; } // First page? if(ek == 'g') { if(lpmax == NULL || lnp1 == lforw(bufp->b_hdrlnp)) n = -1; // Force beep. else { lnp1 = lforw(bufp->b_hdrlnp); n = 0; } break; } // Last page? if(ek == 'G') { if(lpmax == NULL || lnp1 == lpmax) n = 1; // Force beep. else { lnp1 = lpmax; n = 0; } break; } // Help? if(ek == '?') { StrList msg; // Get string list... if(vopen(&msg,NULL,false) != 0) return vrcset(); // build prompt... if(vputs(text202,&msg) != 0) // "(<SPC>,f" return vrcset(); if(hkey(&msg,forwPage,0) != SUCCESS) return rc.status; if(vputs(text203,&msg) != 0) // ") +page (b" return vrcset(); if(hkey(&msg,backPage,0) != SUCCESS) return rc.status; if(vputs(text204,&msg) != 0) // ") -page (d) +half (u) -half" return vrcset(); if(hkey(&msg,forwLine,'+') != SUCCESS || hkey(&msg,backLine,'-') != SUCCESS) return rc.status; if(vputs(text206,&msg) != 0) // " (g) first (G) last (ESC,q) quit (?) help: " return vrcset(); // and display it. if(vclose(&msg) != 0) return vrcset(); mlputs(MLHOME | MLFORCE,msg.sl_vp->v_strp); } else { // Other key. "Unget" the key for reprocessing and return. tungetc(ek); goto uexit; } } } uexit: uphard(); if(endprompt) mlerase(MLFORCE); return rc.status; }