/* * A simple curses emulation for the Amiga, specifically for WANDERER * * Alan Bland */ #ifdef AMIGA #include #include #include #include #include #include #include #include #include #include #include /* generated by Power Windows 2.0 */ #include "pw.palette.h" #include "pw.menus.h" struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; struct Screen *S; struct Window *W; struct RastPort *R; struct TextFont *map_font, *text_font; struct Library *DiskfontBase; #define TOPEDGE 12 /* how much of screen bar to show */ int WindowWidth = 640; int WindowHeight = 200 - TOPEDGE; int MouseX, MouseY; /* getmouse - get current row and column of mouse */ getmouse(amr,amc) int *amr; int *amc; { *amr = MouseY / 8; *amc = MouseX / 8; } /* Return when either a console key or mouse button is pressed. */ mouseorkey() { return nextevent(MOUSEBUTTONS | RAWKEY | MENUPICK, 1); } flushinput() { while (nextevent(RAWKEY, 0) >= 0) ; } /* returns next character, with special WANDERER translations */ getch() { return nextevent(RAWKEY | MENUPICK, 1); } /* returns next character with no special translations */ /* used mainly for getstr() */ getvanillach() { return nextevent(VANILLAKEY, 1); } cursor(state) int state; { int x, y; x = R->cp_x; y = R->cp_y - R->Font->tf_Baseline; SetDrMd(R, COMPLEMENT); RectFill(R, x, y, x+8, y+R->Font->tf_YSize-1); SetDrMd(R, JAM2); } /* special keymap for wanderer raw mode - translates function keys and * cursor keys to wanderer single-key commands */ char mykeys[] = { '`','1','2','3','4','5','6','7','8','9','0','-','=','\\',0,0, 'q','w','e','r','t','y','u','i','o','p','[',']',0,0,'j',0, 'a','s','d','f','g','h','j','k','l',';','\'',0,0,'h','@','l', 0,'z','x','c','v','b','n','m',',','.','/',0,0,0,'k',0, ' ','\b',0,'\n','\n','q',0,0,0,0,0,0,'k','j','l','h', '~','#','@',0,0,'S','R',0,0,'!',0,0,0,0,0,'?', 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; char myshiftkeys[] = { '~','!','@','#','$','%','^','&','*','(',')','_','+','|',0,0, 'Q','W','E','R','T','Y','U','I','O','P','{','}',0,0,0,0, 'A','S','D','F','G','H','J','K','L',':','"',0,0,0,0,0, 0,'Z','X','C','V','B','N','M','<','>','?',0,0,0,0,0, ' ','\b',0,'\n','\n',0,0,0,0,0,0,0,'k','j','l','h', '~','#','@',0,0,'S','R',0,0,'!',0,0,0,0,0,'?', 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; nextevent(flags, wait) long flags; int wait; { register int class, code; register struct IntuiMessage *message; int result, qual; /* show cursor if inputting a stream of text */ if (flags & VANILLAKEY) cursor(1); ModifyIDCMP(W, CLOSEWINDOW | flags); while (1) { if (wait) { /* get next event, waiting if none are available */ while ((message = (struct IntuiMessage *)GetMsg(W->UserPort)) == NULL) { Wait(1<UserPort->mp_SigBit); } } else { /* get next event, but return if none are available */ message = (struct IntuiMessage *)GetMsg(W->UserPort); if (message == NULL) { result = -1; break; } } class = message->Class; code = message->Code; qual = message->Qualifier; MouseX = message->MouseX; MouseY = message->MouseY; ReplyMsg((struct Message *)message); switch (class) { case CLOSEWINDOW: /* ignore for now */ continue; case VANILLAKEY: result = code; if (result == '\r') result = '\n'; break; case RAWKEY: if (code&0x80) continue; /* ignore key releases */ /* only recognize wanderer keys */ /* can use cursor keys, hjkl, ibm keypad for moving */ if (qual & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) result = myshiftkeys[code]; else result = mykeys[code]; if (result == 0) continue; /* ignore undef keys */ break; case MENUPICK: if (code == MENUNULL) continue; switch (MENUNUM(code)) { case 0: switch (ITEMNUM(code)) { case 0: result = 'W'; break; case 1: result = 'S'; break; case 2: result = 'R'; break; case 4: result = 'c'; break; case 5: result = 'q'; break; default: continue; } break; case 1: switch (ITEMNUM(code)) { case 0: result = '~'; break; case 1: result = '#'; break; case 2: result = '@'; break; case 3: result = '!'; break; case 4: result = '?'; break; default: continue; } break; default: continue; } break; case MOUSEBUTTONS: switch (code) { case SELECTDOWN: break; /* left button pressed */ default: continue; /* ignore button releases */ } result = MOUSE; break; default: continue; } break; } /* turn off cursor if it was on */ if (flags & VANILLAKEY) cursor(0); return result; } struct TextAttr font = { "topaz.font",TOPAZ_EIGHTY,FS_NORMAL,FPF_ROMFONT }; struct NewScreen ns = { 0,0,640,200,4,BLACK,WHITE,HIRES,CUSTOMSCREEN,&font,"Wanderer V2.2",NULL,NULL }; initscr() { struct NewWindow nw; struct TextAttr font_attr; if (S != NULL) return; IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 0); GfxBase = (struct GfxBase *) OpenLibrary("graphics.library",0); if (IntuitionBase == NULL || GfxBase == NULL) exit(1); /* load the digitized sound effects (yeah, what's it doing here?) */ initSounds(); /* load the map font */ DiskfontBase = (struct Library *) OpenLibrary("diskfont.library",0); font_attr.ta_Name = "wanderer.font"; font_attr.ta_YSize = 8; font_attr.ta_Style = 0; font_attr.ta_Flags = 0; map_font = (struct TextFont *) OpenDiskFont(&font_attr); if ((S = (struct Screen *) OpenScreen(&ns)) == NULL) exit(1); nw.LeftEdge = 0; nw.TopEdge = TOPEDGE; nw.Width = WindowWidth; nw.Height = WindowHeight; nw.DetailPen = BLACK; nw.BlockPen = WHITE; nw.Title = NULL; nw.Flags = SMART_REFRESH | ACTIVATE | BACKDROP | BORDERLESS | NOCAREREFRESH; nw.IDCMPFlags = RAWKEY; nw.Type = CUSTOMSCREEN; nw.FirstGadget = NULL; nw.CheckMark = NULL; nw.Screen = S; nw.BitMap = NULL; if ((W = (struct Window *) OpenWindow(&nw)) == NULL) exit(1); R = W->RPort; /* setup colors */ LoadRGB4(&S->ViewPort, Palette, PaletteColorCount); /* keep track of original font */ text_font = R->Font; SetAPen(R, TEXT_COLOR); SetBPen(R, BACK_COLOR); ShowTitle(S, FALSE); SetMenuStrip(W, &MenuList1); clear(); } move(r,c) int r,c; { Move(R, c*8, r*8 + R->Font->tf_Baseline); } eraseeol() { int x, y; x = R->cp_x; y = R->cp_y - R->Font->tf_Baseline; SetAPen(R, BACK_COLOR); RectFill(R, x, y, WindowWidth, y+R->Font->tf_YSize-1); SetAPen(R, TEXT_COLOR); } eraserow(r) { move(r,0); eraseeol(); } endwin() { freeSounds(NULL); if (map_font) CloseFont(map_font); if (W) { ClearMenuStrip(W); CloseWindow(W); } if (S) CloseScreen(S); } set_map_font(flag) int flag; { if (flag) SetFont(R, map_font); else SetFont(R, text_font); } clear() { SetAPen(R, BACK_COLOR); RectFill(R, 0, 0, WindowWidth, WindowHeight); SetAPen(R, TEXT_COLOR); move(0,0); } /* get a line of input from the console, handling backspaces */ /* menus are disable while inputting */ getstr(s) char *s; { char *origs = s; int c; ClearMenuStrip(W); SetAPen(R, INPUT_COLOR); while ( (c=getvanillach()) != '\n' && c!='\r' && c!= EOF ) { if ( c == '\b' ) { if ( s > origs ) { addstr("\b \b"); s--; } } else if (c == 24) { while (s > origs) { addstr("\b \b"); s--; } } else if (isprint(c)) { addch(c); *s++ = c; } refresh(); } *s = '\0'; SetAPen(R, TEXT_COLOR); SetMenuStrip(W, &MenuList1); } addstr(s) char *s; { /* output is fastest if is many chars as possible can be */ /* displayed in a single Text() call, so we scan for special */ /* characters that need to be interpreted, and do the rest */ /* in as few Text() calls as possible */ register int i,a; for (i=0,a=0; ; ++i) { if (s[i] < ' ') { /* special character found */ /* output everything up to this character */ if (i-a>0) Text(R, s+a, i-a); /* interpret the special character */ if (s[i] == 0) break; addch(s[i]); /* continue after the special character */ a = i+1; } } } addch(c) int c; { char s; switch (c) { case '\n': Move(R, 0, R->cp_y + 8); break; case '\r': Move(R, 0, R->cp_y); break; case '\t': Move(R, R->cp_x + 64 - (R->cp_x % 64), R->cp_y); break; case '\b': Move(R, R->cp_x - 8, R->cp_y); break; case '\007': DisplayBeep(S); break; default: s = c; Text(R, &s, 1); break; } } struct IntuiText fataltext = { 1,0,COMPLEMENT,16,32,NULL,NULL,NULL }; struct IntuiText canceltext = { 1,0,COMPLEMENT,2,2,NULL,"goodbye",NULL }; fatal(text) char *text; { fataltext.IText = text; AutoRequest(W, &fataltext, NULL, &canceltext, 0, 0, 320, 90); endwin(); exit(1); } #endif