1 /* SCCS Id: @(#)winfuncs.c 3.1 2000/01/12 */
2 /* Copyright (c) Gregg Wonderly, Naperville, Illinois, 1991,1992,1993,1996. */
3 /* NetHack may be freely redistributed. See license for details. */
5 #include "NH:sys/amiga/windefs.h"
6 #include "NH:sys/amiga/winext.h"
7 #include "NH:sys/amiga/winproto.h"
8 #include "patchlevel.h"
10 extern struct TagItem scrntags[];
12 static BitMapHeader amii_bmhd;
13 static void cursor_common(struct RastPort *, int, int);
18 /* Changing clipping region, skip clear of screen in overview window. */
21 /* Must be set to at least two or you will get stuck! */
22 int xclipbord = 4, yclipbord = 2;
26 struct Rectangle amii_oldover;
27 struct Rectangle amii_oldmsg;
29 extern struct TextFont *RogueFont;
41 long amii_libvers = LIBRARY_FONT_VERSION;
44 ami_wininit_data( void )
46 extern unsigned short amii_init_map[ AMII_MAXCOLORS ];
47 extern unsigned short amiv_init_map[ AMII_MAXCOLORS ];
55 amii_defpens[ 0 ] = C_BLACK; /* DETAILPEN */
56 amii_defpens[ 1 ] = C_BLUE; /* BLOCKPEN */
57 amii_defpens[ 2 ] = C_BROWN; /* TEXTPEN */
58 amii_defpens[ 3 ] = C_WHITE; /* SHINEPEN */
59 amii_defpens[ 4 ] = C_BLUE; /* SHADOWPEN */
60 amii_defpens[ 5 ] = C_CYAN; /* FILLPEN */
61 amii_defpens[ 6 ] = C_WHITE; /* FILLTEXTPEN */
62 amii_defpens[ 7 ] = C_CYAN; /* BACKGROUNDPEN */
63 amii_defpens[ 8 ] = C_RED; /* HIGHLIGHTTEXTPEN */
64 amii_defpens[ 9 ] = C_WHITE; /* BARDETAILPEN */
65 amii_defpens[ 10 ] = C_CYAN; /* BARBLOCKPEN */
66 amii_defpens[ 11 ] = C_BLUE; /* BARTRIMPEN */
67 amii_defpens[ 12 ] = (unsigned short) ~0;
69 amii_msgAPen = C_WHITE;
70 amii_msgBPen = C_BLACK;
71 amii_statAPen = C_WHITE;
72 amii_statBPen = C_BLACK;
73 amii_menuAPen = C_WHITE;
74 amii_menuBPen = C_BLACK;
75 amii_textAPen = C_WHITE;
76 amii_textBPen = C_BLACK;
77 amii_otherAPen = C_RED;
78 amii_otherBPen = C_BLACK;
83 amii_libvers = LIBRARY_FONT_VERSION;
84 memcpy( amii_initmap, amii_init_map, sizeof( amii_initmap ) );
93 amii_defpens[ 0 ] = C_BLACK; /* DETAILPEN */
94 amii_defpens[ 1 ] = C_WHITE; /* BLOCKPEN */
95 amii_defpens[ 2 ] = C_BLACK; /* TEXTPEN */
96 amii_defpens[ 3 ] = C_CYAN; /* SHINEPEN */
97 amii_defpens[ 4 ] = C_BLUE; /* SHADOWPEN */
98 amii_defpens[ 5 ] = C_GREYBLUE; /* FILLPEN */
99 amii_defpens[ 6 ] = C_LTGREY; /* FILLTEXTPEN */
100 amii_defpens[ 7 ] = C_GREYBLUE; /* BACKGROUNDPEN */
101 amii_defpens[ 8 ] = C_RED; /* HIGHLIGHTTEXTPEN */
102 amii_defpens[ 9 ] = C_WHITE; /* BARDETAILPEN */
103 amii_defpens[ 10] = C_GREYBLUE; /* BARBLOCKPEN */
104 amii_defpens[ 11] = C_BLUE; /* BARTRIMPEN */
105 amii_defpens[ 12] = (unsigned short) ~0;
107 amii_msgAPen = C_WHITE;
108 amii_msgBPen = C_GREYBLUE;
109 amii_statAPen = C_WHITE;
110 amii_statBPen = C_GREYBLUE;
111 amii_menuAPen = C_BLACK;
112 amii_menuBPen = C_LTGREY;
113 amii_textAPen = C_BLACK;
114 amii_textBPen = C_LTGREY;
115 amii_otherAPen = C_RED;
116 amii_otherBPen = C_BLACK;
117 amii_libvers = LIBRARY_TILE_VERSION;
119 memcpy( amii_initmap, amiv_init_map, sizeof( amii_initmap ) );
124 memcpy(flags.amii_dripens,amii_defpens,sizeof(flags.amii_dripens));
127 # ifdef INTUI_NEW_LOOK
128 struct Hook SM_FilterHook;
129 struct Hook fillhook;
130 struct TagItem wintags[] =
132 { WA_BackFill, (ULONG)&fillhook },
133 { WA_PubScreenName, (ULONG)"NetHack" },
139 amii_destroy_nhwindow(win) /* just hide */
144 register struct amii_WinDesc *cw;
146 if( win == WIN_ERR || ( cw = amii_wins[win] ) == NULL )
148 panic(winpanicstr,win,"destroy_nhwindow");
153 if( cw->type == NHW_MAP )
155 /* If inventory is up, close it now, it will be freed later */
156 if( alwaysinvent && WIN_INVEN != WIN_ERR &&
157 amii_wins[ WIN_INVEN ] &&
158 amii_wins[ WIN_INVEN ]->win )
160 dismiss_nhwindow( WIN_INVEN );
163 /* Tear down overview window if it is up */
164 if( WIN_OVER != WIN_ERR )
166 amii_destroy_nhwindow( WIN_OVER );
170 else if( cw->type == NHW_OVER )
172 struct Window *w = amii_wins[ WIN_OVER ]->win;
173 amii_oldover.MinX = w->LeftEdge;
174 amii_oldover.MinY = w->TopEdge;
175 amii_oldover.MaxX = w->Width;
176 amii_oldover.MaxY = w->Height;
178 if( WIN_MESSAGE != WIN_ERR && amii_wins[ WIN_MESSAGE ] )
180 w = amii_wins[ WIN_MESSAGE ]->win;
181 amii_oldmsg.MinX = w->LeftEdge;
182 amii_oldmsg.MinY = w->TopEdge;
183 amii_oldmsg.MaxX = w->Width;
184 amii_oldmsg.MaxY = w->Height;
185 SizeWindow( amii_wins[ WIN_MESSAGE ]->win,
187 amii_wins[ WIN_MESSAGE ]->win->LeftEdge) -
188 amii_wins[ WIN_MESSAGE ]->win->Width,
194 /* Tear down the Intuition stuff */
195 dismiss_nhwindow(win);
215 if( cw->data && ( cw->type == NHW_MESSAGE ||
216 cw->type == NHW_MENU || cw->type == NHW_TEXT ) )
218 for( i = 0; i < cw->maxrow; ++i )
221 free( cw->data[ i ] );
227 amii_wins[win] = NULL;
229 /* Set globals to WIN_ERR for known one-of-a-kind windows. */
230 if( win == WIN_MAP) WIN_MAP = WIN_ERR;
231 else if( win == WIN_STATUS) WIN_STATUS = WIN_ERR;
232 else if( win == WIN_MESSAGE) WIN_MESSAGE = WIN_ERR;
233 else if( win == WIN_INVEN) WIN_INVEN = WIN_ERR;
237 #ifdef INTUI_NEW_LOOK
241 struct Rectangle bounds;
248 void PPC_LayerFillHook(void);
249 struct EmulLibEntry LayerFillHook = {TRAP_LIB, 0, (void (*)(void)) PPC_LayerFillHook};
250 void PPC_LayerFillHook(void) {
251 struct Hook *hk = (struct Hook*)REG_A0;
252 struct RastPort *rp = (struct RastPort *)REG_A2;
253 struct FillParams *fp = (struct FillParams*)REG_A1;
255 void LayerFillHook(void) {
256 register struct Hook *hk asm("a0");
257 register struct RastPort *rp asm("a2");
258 register struct FillParams *fp asm("a1");
265 __saveds __asm LayerFillHook(
266 register __a0 struct Hook *hk,
267 register __a2 struct RastPort *rp,
268 register __a1 struct FillParams *fp )
272 register long x, y, xmax, ymax;
274 struct RastPort rptmp;
276 memcpy(&rptmp, rp, sizeof(struct RastPort));
279 switch( (int)hk->h_Data )
282 apen = amii_statBPen;
288 apen = amii_textBPen;
291 apen = amii_menuBPen;
294 apen = amii_otherBPen;
306 xmax = fp->bounds.MaxX;
307 ymax = fp->bounds.MaxY;
309 SetAPen(&rptmp, apen);
310 SetBPen(&rptmp, apen);
311 SetDrMd(&rptmp, JAM2);
312 RectFill(&rptmp, x, y, xmax, ymax);
317 amii_create_nhwindow(type)
320 register struct Window *w = NULL;
321 register struct NewWindow *nw = NULL;
322 register struct amii_WinDesc *wd = NULL;
323 struct Window *mapwin = NULL, *stwin = NULL, *msgwin = NULL;
325 int maph, stath, scrfontysize;
327 scrfontysize = HackScreen->Font->ta_YSize;
330 * Initial mapwindow height, this might change later in tilemode
333 maph = ( 21 * mxsize ) + 2 + (bigscreen ?
334 HackScreen->WBorTop + HackScreen->WBorBottom + scrfontysize + 1 : 0);
336 /* Status window height, avoids having to calculate many times */
337 stath = txheight * 2 + 2 + (WINVERS_AMIV || bigscreen ?
338 HackScreen->WBorTop + HackScreen->WBorBottom +
339 ( bigscreen ? scrfontysize + 1 : 0 ) : 0);
341 if( WIN_STATUS != WIN_ERR && amii_wins[ WIN_STATUS ] )
342 stwin = amii_wins[ WIN_STATUS ]->win;
344 if( WIN_MESSAGE != WIN_ERR && amii_wins[ WIN_MESSAGE ] )
345 msgwin = amii_wins[ WIN_MESSAGE ]->win;
347 if( WIN_MAP != WIN_ERR && amii_wins[ WIN_MAP ] )
348 mapwin = amii_wins[ WIN_MAP ]->win;
350 /* Create Port anytime that we need it */
352 if( HackPort == NULL )
354 HackPort = CreateMsgPort();
356 panic( "no memory for msg port" );
359 nw = &new_wins[ type ].newwin;
360 nw->Width = amiIDisplay->xpix;
361 nw->Screen = HackScreen;
365 nw->DetailPen = C_WHITE;
366 nw->BlockPen = C_GREYBLUE;
370 nw->DetailPen = C_WHITE;
371 nw->BlockPen = C_BLACK;
374 if ( type == NHW_BASE ) {
376 nw->TopEdge = HackScreen->BarHeight+1;
377 nw->Width = HackScreen->Width;
378 nw->Height = HackScreen->Height - nw->TopEdge;
379 } else if( !WINVERS_AMIV && type == NHW_MAP ) {
383 if( msgwin && stwin ) {
384 nw->TopEdge = stwin->TopEdge - maph;
386 panic( "msgwin and stwin must open before map" );
389 panic( "Too small screen to fit map" );
391 else if( type == NHW_MAP && WINVERS_AMIV )
395 w = amii_wins[ WIN_MESSAGE ]->win;
397 nw->TopEdge = w->TopEdge + w->Height;
398 nw->Width = amiIDisplay->xpix - nw->LeftEdge;
400 w = amii_wins[ WIN_STATUS ]->win;
401 nw->Height = w->TopEdge - nw->TopEdge;
402 nw->MaxHeight = 0xffff;
403 nw->MaxWidth = 0xffff;
405 if( nw->TopEdge + nw->Height > amiIDisplay->ypix - 1 )
406 nw->Height = amiIDisplay->ypix - nw->TopEdge - 1;
408 else if( type == NHW_STATUS )
410 if( !WINVERS_AMIV && ( WIN_MAP != WIN_ERR && amii_wins[ WIN_MAP ] ) )
411 w = amii_wins[ WIN_MAP ]->win;
412 else if( WIN_BASE != WIN_ERR && amii_wins[ WIN_BASE ] )
413 w = amii_wins[ WIN_BASE ]->win;
415 panic( "No window to base STATUS location from" );
418 nw->TopEdge = amiIDisplay->ypix - nw->Height;
419 nw->LeftEdge = w->LeftEdge;
421 if( nw->LeftEdge + nw->Width >= amiIDisplay->xpix )
424 if( nw->Width >= amiIDisplay->xpix - nw->LeftEdge )
425 nw->Width = amiIDisplay->xpix - nw->LeftEdge;
427 else if( WINVERS_AMIV && type == NHW_OVER )
429 nw->Flags |= WINDOWSIZING|WINDOWDRAG|WINDOWCLOSE;
430 nw->IDCMPFlags |= CLOSEWINDOW;
431 /* Bring up window as half the width of the message window, and make
432 * the message window change to one half the width...
434 if( amii_oldover.MaxX != 0 )
436 nw->LeftEdge = amii_oldover.MinX;
437 nw->TopEdge = amii_oldover.MinY;
438 nw->Width = amii_oldover.MaxX;
439 nw->Height = amii_oldover.MaxY;
440 ChangeWindowBox( amii_wins[ WIN_MESSAGE ]->win,
441 amii_oldmsg.MinX, amii_oldmsg.MinY,
442 amii_oldmsg.MaxX, amii_oldmsg.MaxY );
446 nw->LeftEdge = (amii_wins[ WIN_MESSAGE ]->win->Width*4)/9;
447 nw->TopEdge = amii_wins[ WIN_MESSAGE ]->win->TopEdge;
448 nw->Width = amiIDisplay->xpix - nw->LeftEdge;
449 nw->Height = amii_wins[ WIN_MESSAGE ]->win->Height;
450 SizeWindow( amii_wins[ WIN_MESSAGE ]->win,
451 nw->LeftEdge - amii_wins[ WIN_MESSAGE ]->win->Width, 0 );
454 else if( type == NHW_MESSAGE )
456 if( !WINVERS_AMIV && ( WIN_MAP != WIN_ERR && amii_wins[ WIN_MAP ] ) )
457 w = amii_wins[ WIN_MAP ]->win;
458 else if( WIN_BASE != WIN_ERR && amii_wins[ WIN_BASE ] )
459 w = amii_wins[ WIN_BASE ]->win;
461 panic( "No window to base STATUS location from" );
463 nw->TopEdge = bigscreen ? HackScreen->BarHeight+1 : 0;
465 /* Assume highest possible message window */
466 nw->Height = HackScreen->Height - nw->TopEdge - maph - stath;
468 /* In tilemode we can cope with this */
469 if (WINVERS_AMIV && nw->Height < 0)
472 /* If in fontmode messagewindow is too small, open it with 3 lines
473 and overlap it with map */
474 if (nw->Height < txheight+2) {
475 nw->Height = txheight*4 + 3 + HackScreen->WBorTop + HackScreen->WBorBottom;
478 if ((nw->Height-2)/txheight < 3) {
482 nw->FirstGadget = &MsgScroll;
483 nw->Flags |= WINDOWSIZING|WINDOWDRAG;
484 nw->Flags &= ~BORDERLESS;
486 if( WINVERS_AMIV || nw->Height == 0) {
488 nw->Height = TextsFont->tf_YSize + HackScreen->WBorTop + 3 +
489 HackScreen->WBorBottom;
491 nw->Height += ( txheight * 6 );
493 nw->Height += ( txheight * 3 );
497 nw->Height = HackScreen->Height - nw->TopEdge - stath - maph;
502 /* Do we have room for larger message window ?
503 * This is possible if we can show full height map in tile
504 * mode with default scaling.
506 if (nw->Height + stath + maph < HackScreen->Height - nw->TopEdge )
507 nw->Height = HackScreen->Height - nw->TopEdge - 1 - maph - stath;
509 #ifdef INTUI_NEW_LOOK
510 if( IntuitionBase->LibNode.lib_Version >= 37 )
512 MsgPropScroll.Flags |= PROPNEWLOOK;
513 PropScroll.Flags |= PROPNEWLOOK;
518 nw->IDCMPFlags |= MENUPICK;
520 /* Check if there is "Room" for all this stuff... */
521 if( ( WINVERS_AMIV || bigscreen ) &&
524 nw->Flags &= ~( BORDERLESS | BACKDROP );
528 if( type == NHW_STATUS )
530 nw->Flags &= ~( WINDOWDRAG | WINDOWDEPTH | SIZEBRIGHT | WINDOWSIZING );
531 nw->IDCMPFlags &= ~NEWSIZE;
535 nw->Flags |= ( WINDOWDRAG | WINDOWDEPTH | SIZEBRIGHT | WINDOWSIZING );
536 nw->IDCMPFlags |= NEWSIZE;
541 if( HackScreen->Width < 657 )
543 nw->Flags |= ( WINDOWDRAG | WINDOWDEPTH );
547 nw->Flags |= ( WINDOWDRAG | WINDOWDEPTH | SIZEBRIGHT );
552 if ( WINVERS_AMII && type == NHW_MAP )
553 nw->Flags &= ~WINDOWSIZING;
555 if ( type == NHW_MESSAGE && scrollmsg ) {
556 nw->Flags |= WINDOWDRAG|WINDOWDEPTH|SIZEBRIGHT|WINDOWSIZING;
557 nw->Flags &= ~BORDERLESS;
560 /* No titles on a hires only screen except for messagewindow */
561 if( !(WINVERS_AMIV && type == NHW_MAP) && !bigscreen && type != NHW_MESSAGE )
564 wd = (struct amii_WinDesc *)alloc(sizeof(struct amii_WinDesc));
565 memset( wd, 0, sizeof( struct amii_WinDesc ) );
567 /* Both, since user may have changed the pen settings so respect those */
568 if( WINVERS_AMII || WINVERS_AMIV )
570 /* Special backfill for these types of layers */
583 fillhook.h_Entry = (void *)&LayerFillHook;
585 fillhook.h_Entry = (ULONG(*)())LayerFillHook;
587 fillhook.h_Data = (void *)type;
588 fillhook.h_SubEntry = 0;
589 wd->hook = alloc( sizeof( fillhook ) );
590 memcpy( wd->hook, &fillhook, sizeof( fillhook ) );
591 memcpy( wd->wintags, wintags, sizeof( wd->wintags) );
592 wd->wintags[0].ti_Data = (long)wd->hook;
593 nw->Extension = (void *)wd->wintags;
599 /* Don't open MENU or TEXT windows yet */
601 if( type == NHW_MENU || type == NHW_TEXT )
604 w=OpenShWindow( (void *)nw );
606 if( w == NULL && type != NHW_MENU && type != NHW_TEXT )
610 sprintf( buf, "nw type (%d) dims l: %d, t: %d, w: %d, h: %d",
612 nw->LeftEdge, nw->TopEdge,
613 nw->Width, nw->Height );
615 panic("bad openwin %d",type);
618 /* Check for an empty slot */
620 for(newid = 0; newid<MAXWIN + 1; newid++)
622 if(amii_wins[newid] == 0)
627 panic("time to write re-alloc code\n");
629 /* Set wincnt accordingly */
634 /* Do common initialization */
636 amii_wins[newid] = wd;
643 wd->curx=wd->cury = 0;
644 wd->resp = wd->canresp = wd->morestr = 0; /* CHECK THESE */
645 wd->maxrow = new_wins[type].maxrow;
646 wd->maxcol = new_wins[type].maxcol;
648 if( type != NHW_TEXT && type != NHW_MENU )
650 if( TextsFont && ( type == NHW_MESSAGE || type == NHW_STATUS ) )
652 SetFont(w->RPort, TextsFont);
653 txheight = w->RPort->TxHeight;
654 txwidth = w->RPort->TxWidth;
655 txbaseline = w->RPort->TxBaseline;
656 if( type == NHW_MESSAGE )
662 WindowLimits( w, 100, w->BorderTop +
664 ((txheight+1)*2) + 1, 0, 0 );
668 WindowLimits( w, w->Width, w->BorderTop +
670 ((txheight+1)*2) + 1, 0, 0 );
675 WindowLimits( w, w->Width, w->BorderTop +
677 txheight + 2, 0, 0 );
681 if ( type != NHW_MAP) {
682 SetFont(w->RPort, TextsFont);
686 SetFont(w->RPort, HackFont);
690 /* Text and menu windows are not opened yet */
693 wd->rows = ( w->Height - w->BorderTop -
694 w->BorderBottom - 2 ) / w->RPort->TxHeight;
695 wd->cols = ( w->Width - w->BorderLeft -
696 w->BorderRight - 2 ) / w->RPort->TxWidth;
699 /* Okay, now do the individual type initialization */
703 /* History lines for MESSAGE windows are stored in cw->data[?].
704 * maxcol and maxrow are used as cursors. maxrow is the count
705 * of the number of history lines stored. maxcol is the cursor
706 * to the last line that was displayed by ^P.
709 SetMenuStrip(w, MenuStrip);
710 MsgScroll.TopEdge = HackScreen->WBorTop + scrfontysize + 1;
711 iflags.msg_history = wd->rows*10;
712 if (iflags.msg_history < 40)
713 iflags.msg_history = 40;
714 if (iflags.msg_history > 400)
715 iflags.msg_history = 400;
716 iflags.window_inited=TRUE;
717 wd->data = (char **)alloc( iflags.msg_history*sizeof( char * ) );
718 memset( wd->data, 0, iflags.msg_history * sizeof( char * ) );
719 wd->maxrow = wd->maxcol = 0;
720 /* Indicate that we have not positioned the cursor yet */
724 /* A MENU contains a list of lines in wd->data[?]. These
725 * lines are created in amii_putstr() by reallocating the size
726 * of wd->data to hold enough (char *)'s. wd->rows is the
727 * number of (char *)'s allocated. wd->maxrow is the number
728 * used. wd->maxcol is used to track how wide the menu needs
729 * to be. wd->resp[x] contains the characters that correspond
730 * to selecting wd->data[x]. wd->resp[x] corresponds to
731 * wd->data[x] for any x. Elements of wd->data[?] that are not
732 * valid selections have the corresponding element of
733 * wd->resp[] set to a value of '\01'; i.e. a ^A which is
734 * not currently a valid keystroke for responding to any
735 * MENU or TEXT window.
738 MenuScroll.TopEdge = HackScreen->WBorTop + scrfontysize + 1;
739 wd->resp=(char*)alloc(256);
741 wd->rows = wd->maxrow = 0;
742 wd->cols = wd->maxcol = 0;
746 /* See the explanation of MENU above. Except, wd->resp[] is not
747 * used for TEXT windows since there is no selection of a
748 * a line performed/allowed. The window is always full
752 MenuScroll.TopEdge = HackScreen->WBorTop + scrfontysize + 1;
753 wd->rows = wd->maxrow = 0;
754 wd->cols = wd->maxcol = amiIDisplay->cols;
759 /* The status window has only two lines. These are stored in
760 * wd->data[], and here we allocate the space for them.
763 SetMenuStrip(w, MenuStrip);
764 /* wd->cols is the number of characters which fit across the
767 wd->data=(char **)alloc(3*sizeof(char *));
768 wd->data[0] = (char *)alloc(wd->cols + 10);
769 wd->data[1] = (char *)alloc(wd->cols + 10);
773 /* NHW_OVER does not use wd->data[] or the other text
774 * manipulating members of the amii_WinDesc structure.
777 SetMenuStrip(w, MenuStrip);
780 /* NHW_MAP does not use wd->data[] or the other text
781 * manipulating members of the amii_WinDesc structure.
784 SetMenuStrip(w, MenuStrip);
787 CO = (w->Width-w->BorderLeft-w->BorderRight)/mxsize;
788 LI = (w->Height-w->BorderTop-w->BorderBottom)/mysize;
790 SetFont( w->RPort, RogueFont);
791 SetAPen( w->RPort, C_WHITE); /* XXX not sufficient */
792 SetBPen( w->RPort, C_BLACK);
793 SetDrMd( w->RPort, JAM2);
798 SetFont( w->RPort, HackFont );
802 /* The base window must exist until CleanUp() deletes it. */
804 SetMenuStrip(w, MenuStrip);
805 /* Make our requesters come to our screen */
807 register struct Process *myProcess =
808 (struct Process *) FindTask(NULL);
809 pr_WindowPtr = (struct Window *)(myProcess->pr_WindowPtr);
810 myProcess->pr_WindowPtr = (APTR) w;
813 /* Need this for RawKeyConvert() */
815 ConsoleIO.io_Data = (APTR) w;
816 ConsoleIO.io_Length = sizeof( struct Window );
817 ConsoleIO.io_Message.mn_ReplyPort = CreateMsgPort();
818 if( OpenDevice("console.device", -1L,
819 (struct IORequest *) &ConsoleIO, 0L) != 0)
821 Abort(AG_OpenDev | AO_ConsoleDev);
824 ConsoleDevice = (struct Library *) ConsoleIO.io_Device;
830 SetFont( w->RPort, TextsFont );
832 SetFont( w->RPort, HackFont );
834 txwidth = w->RPort->TxWidth;
835 txheight = w->RPort->TxHeight;
836 txbaseline = w->RPort->TxBaseline;
840 panic("bad create_nhwindow( %d )\n",type);
849 int PPC_SM_Filter(void);
850 struct EmulLibEntry SM_Filter = {TRAP_LIB, 0, (int (*)(void)) PPC_SM_Filter};
851 int PPC_SM_Filter(void) {
852 struct Hook *hk = (struct Hook*)REG_A0;
853 ULONG modeID = (ULONG)REG_A1;
854 struct ScreenModeRequester *smr = (struct ScreenModeRequester *)REG_A2;
856 int SM_Filter(void) {
857 register struct Hook *hk asm("a0");
858 register ULONG modeID asm("a1");
859 register struct ScreenModeRequester *smr asm("a2");
866 __saveds __asm SM_Filter(
867 register __a0 struct Hook *hk,
868 register __a1 ULONG modeID,
869 register __a2 struct ScreenModeRequester *smr)
872 struct DimensionInfo dims;
873 struct DisplayInfo disp;
874 DisplayInfoHandle handle;
875 handle = FindDisplayInfo(modeID);
877 GetDisplayInfoData(handle, (char *)&dims, sizeof(dims), DTAG_DIMS, modeID);
878 GetDisplayInfoData(handle, (char *)&disp, sizeof(disp), DTAG_DISP, modeID);
879 if (!disp.NotAvailable &&
880 dims.MaxDepth <= 8 &&
881 dims.StdOScan.MaxX >= WIDTH-1 &&
882 dims.StdOScan.MaxY >= SCREENHEIGHT-1) {
889 /* Initialize the windowing environment */
892 amii_init_nhwindows(argcp,argv)
897 struct Screen *wbscr;
901 panic( "init_nhwindows() called twice", 0 );
903 /* run args & set bigscreen from -L(1)/-l(-1) */
905 int lclargc = *argcp;
907 char **argv_in = argv;
908 char **argv_out = argv;
910 for(t=1;t<=lclargc;t++){
911 if(!strcmp("-L",*argv_in) || !strcmp("-l",*argv_in)){
912 bigscreen = (*argv_in[1]=='l') ? -1 : 1;
913 /* and eat the flag */
916 *argv_out = *argv_in; /* keep the flag */
924 WIN_MESSAGE = WIN_ERR;
926 WIN_STATUS = WIN_ERR;
931 if ( (IntuitionBase = (struct IntuitionBase *)
932 OpenLibrary("intuition.library", amii_libvers )) == NULL)
934 Abort(AG_OpenLib | AO_Intuition);
937 if ( (GfxBase = (struct GfxBase *)
938 OpenLibrary("graphics.library", amii_libvers )) == NULL)
940 Abort(AG_OpenLib | AO_GraphicsLib);
943 if( (LayersBase = (struct Library *)
944 OpenLibrary("layers.library", amii_libvers )) == NULL)
946 Abort(AG_OpenLib | AO_LayersLib);
949 if ((GadToolsBase = OpenLibrary("gadtools.library", amii_libvers)) == NULL) {
950 Abort(AG_OpenLib | AO_GadTools);
953 if ((AslBase = OpenLibrary("asl.library", amii_libvers)) == NULL) {
957 amiIDisplay=(struct amii_DisplayDesc *)alloc(sizeof(struct amii_DisplayDesc));
958 memset( amiIDisplay, 0, sizeof( struct amii_DisplayDesc ) );
960 /* Use Intuition sizes for overscan screens... */
962 amiIDisplay->xpix = 0;
963 #ifdef INTUI_NEW_LOOK
964 if( IntuitionBase->LibNode.lib_Version >= 37 )
966 if( wbscr = LockPubScreen( "Workbench" ) )
968 amiIDisplay->xpix = wbscr->Width;
969 amiIDisplay->ypix = wbscr->Height;
970 UnlockPubScreen( NULL, wbscr );
974 if( amiIDisplay->xpix == 0 )
976 amiIDisplay->ypix = GfxBase->NormalDisplayRows;
977 amiIDisplay->xpix = GfxBase->NormalDisplayColumns;
980 amiIDisplay->cols = amiIDisplay->xpix / FONTWIDTH;
982 amiIDisplay->toplin=0;
983 amiIDisplay->rawprint=0;
984 amiIDisplay->lastwin=0;
988 if( ( GfxBase->ActiView->ViewPort->Modes & LACE ) == LACE )
990 amiIDisplay->ypix *= 2;
991 NewHackScreen.ViewModes |= LACE;
994 else if( GfxBase->NormalDisplayRows >= 300 ||
995 amiIDisplay->ypix >= 300 )
1000 else if( bigscreen == -1 )
1005 else if( bigscreen )
1007 /* If bigscreen requested and we don't have enough rows in
1008 * noninterlaced mode, switch to interlaced...
1010 if( GfxBase->NormalDisplayRows < 300 )
1012 amiIDisplay->ypix *= 2;
1013 NewHackScreen.ViewModes |= LACE;
1021 amiIDisplay->rows = amiIDisplay->ypix / FONTHEIGHT;
1025 * Load the fonts that we need.
1029 OpenLibrary( "diskfont.library", amii_libvers ) )
1031 Hack80.ta_Name -= SIZEOF_DISKNAME;
1032 HackFont = OpenDiskFont( &Hack80 );
1033 Hack80.ta_Name += SIZEOF_DISKNAME;
1035 /* Textsfont13 is filled in with "FONT=" settings. The default is
1040 TextsFont = OpenDiskFont( &TextsFont13 );
1042 /* Try hack/8 for texts if no user specified font */
1043 if( TextsFont == NULL )
1045 Hack80.ta_Name -= SIZEOF_DISKNAME;
1046 TextsFont = OpenDiskFont( &Hack80 );
1047 Hack80.ta_Name += SIZEOF_DISKNAME;
1050 /* If no fonts, make everything topaz 8 for non-view windows.
1052 Hack80.ta_Name = "topaz.font";
1053 RogueFont = OpenFont( &Hack80 );
1054 if(!RogueFont) panic("Can't get topaz:8");
1055 if( !HackFont || !TextsFont )
1059 HackFont = OpenFont( &Hack80 );
1061 panic( "Can't get a map font, topaz:8" );
1066 TextsFont = OpenFont( &Hack80 );
1068 panic( "Can't open text font" );
1071 CloseLibrary(DiskfontBase);
1072 DiskfontBase = NULL;
1076 /* Adjust getlin window size to font */
1079 extern SHORT BorderVectors1[];
1080 extern SHORT BorderVectors2[];
1081 extern struct Gadget Gadget2;
1082 extern struct Gadget String;
1083 extern struct NewWindow StrWindow;
1084 BorderVectors1[2] += (TextsFont->tf_XSize-8)*6; /* strlen("Cancel") == 6 */
1085 BorderVectors1[4] += (TextsFont->tf_XSize-8)*6;
1086 BorderVectors1[5] += TextsFont->tf_YSize-8;
1087 BorderVectors1[7] += TextsFont->tf_YSize-8;
1088 BorderVectors2[2] += (TextsFont->tf_XSize-8)*6;
1089 BorderVectors2[4] += (TextsFont->tf_XSize-8)*6;
1090 BorderVectors2[5] += TextsFont->tf_YSize-8;
1091 BorderVectors2[7] += TextsFont->tf_YSize-8;
1092 Gadget2.TopEdge += TextsFont->tf_YSize-8;
1093 Gadget2.Width += (TextsFont->tf_XSize-8)*6;
1094 Gadget2.Height += TextsFont->tf_YSize-8;
1095 String.LeftEdge += (TextsFont->tf_XSize-8)*6;
1096 String.TopEdge += TextsFont->tf_YSize-8;
1097 String.Width += TextsFont->tf_XSize-8;
1098 String.Height += TextsFont->tf_YSize-8;
1099 StrWindow.Width += (TextsFont->tf_XSize-8)*7;
1100 StrWindow.Height += (TextsFont->tf_YSize-8)*2; /* Titlebar + 1 row of gadgets */
1103 /* This is the size screen we want to open, within reason... */
1105 NewHackScreen.Width = max( WIDTH, amiIDisplay->xpix );
1106 NewHackScreen.Height = max( SCREENHEIGHT, amiIDisplay->ypix );
1108 static char fname[18];
1109 sprintf(fname,"NetHack %d.%d.%d", VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL);
1110 NewHackScreen.DefaultTitle=fname;
1113 NewHackScreen.BlockPen = C_BLACK;
1114 NewHackScreen.DetailPen = C_WHITE;
1116 #ifdef INTUI_NEW_LOOK
1117 if( IntuitionBase->LibNode.lib_Version >= 37 )
1120 struct DimensionInfo dims;
1121 DisplayInfoHandle handle;
1122 struct DisplayInfo disp;
1123 ULONG modeid = DEFAULT_MONITOR_ID|HIRES_KEY;
1125 NewHackScreen.Width = STDSCREENWIDTH;
1126 NewHackScreen.Height = STDSCREENHEIGHT;
1130 NewHackScreen.Font = &TextsFont13;
1134 if ( amii_scrnmode == 0xffffffff ) {
1135 struct ScreenModeRequester *SMR;
1137 SM_FilterHook.h_Entry = (void *)&SM_Filter;
1139 SM_FilterHook.h_Entry = (ULONG(*)())SM_Filter;
1141 SM_FilterHook.h_Data = 0;
1142 SM_FilterHook.h_SubEntry = 0;
1143 SMR = AllocAslRequest(ASL_ScreenModeRequest,NULL);
1144 if (AslRequestTags(SMR,
1145 ASLSM_FilterFunc, (ULONG)&SM_FilterHook,
1147 amii_scrnmode = SMR->sm_DisplayID;
1150 FreeAslRequest(SMR);
1153 if( forcenobig == 0 )
1155 if( ( wbscr = LockPubScreen( "Workbench" ) ) != NULL ||
1156 ( wbscr = LockPubScreen( NULL ) ) != NULL )
1158 /* Get the default pub screen's size */
1159 modeid = GetVPModeID( &wbscr->ViewPort );
1160 if( modeid == INVALID_ID ||
1161 ModeNotAvailable( modeid ) ||
1162 ( handle = FindDisplayInfo( modeid ) ) == NULL ||
1163 GetDisplayInfoData( handle, (char *)&dims, sizeof( dims ),
1164 DTAG_DIMS, modeid ) <= 0 ||
1165 GetDisplayInfoData( handle, (char *)&disp, sizeof( disp ),
1166 DTAG_DISP, modeid ) <= 0 )
1168 modeid = DEFAULT_MONITOR_ID|HIRES_KEY;
1169 /* If the display database seems to not work, use the screen
1172 NewHackScreen.Height = wbscr->Height;
1173 NewHackScreen.Width = wbscr->Width;
1176 * Request LACE if it looks laced. For 2.1/3.0, we will get
1177 * promoted to the users choice of modes (if promotion is allowed)
1178 * If the user is using a dragable screen, things will get hosed
1179 * but that is life...
1181 if( wbscr->ViewPort.Modes & LACE )
1182 NewHackScreen.ViewModes |= LACE;
1187 /* Use the display database to get the correct information */
1188 if( disp.PropertyFlags & DIPF_IS_LACE )
1189 NewHackScreen.ViewModes |= LACE;
1190 NewHackScreen.Height = dims.StdOScan.MaxY+1;
1191 NewHackScreen.Width = dims.StdOScan.MaxX+1;
1193 NewHackScreen.TopEdge = 0;
1194 NewHackScreen.LeftEdge = 0;
1196 UnlockPubScreen( NULL, wbscr );
1200 for( i = 0; scrntags[i].ti_Tag != TAG_DONE; ++i )
1202 switch( scrntags[i].ti_Tag )
1205 if( !amii_scrnmode || ModeNotAvailable( amii_scrnmode ) )
1207 if( ModeNotAvailable( modeid ) )
1209 scrntags[i].ti_Tag = TAG_IGNORE;
1213 scrntags[i].ti_Data = (long)modeid;
1216 modeid = scrntags[i].ti_Data = (long)amii_scrnmode;
1217 if( ( handle = FindDisplayInfo( modeid ) ) != NULL &&
1218 GetDisplayInfoData( handle, (char *)&dims, sizeof( dims ),
1219 DTAG_DIMS, modeid ) > 0 &&
1220 GetDisplayInfoData( handle, (char *)&disp, sizeof( disp ),
1221 DTAG_DISP, modeid ) > 0 )
1223 if( disp.PropertyFlags & DIPF_IS_LACE )
1224 NewHackScreen.ViewModes |= LACE;
1225 NewHackScreen.Height = dims.StdOScan.MaxY+1;
1226 NewHackScreen.Width = dims.StdOScan.MaxX+1;
1231 scrntags[i].ti_Data = (long)flags.amii_dripens;
1239 amii_bmhd = ReadTileImageFiles( );
1241 memcpy( amii_initmap, amii_init_map, sizeof( amii_initmap ) );
1242 memcpy(flags.amii_curmap,amii_initmap,sizeof(flags.amii_curmap));
1244 /* Find out how deep the screen needs to be, 32 planes is enough! */
1245 for( i = 0; i < 32; ++i )
1247 if( ( 1L << i ) >= amii_numcolors )
1251 NewHackScreen.Depth = i;
1253 /* If for some reason Height/Width became smaller than the required,
1254 have the required one */
1255 if (NewHackScreen.Height < SCREENHEIGHT)
1256 NewHackScreen.Height = SCREENHEIGHT;
1257 if (NewHackScreen.Width < WIDTH)
1258 NewHackScreen.Width = WIDTH;
1260 i = max(TextsFont->tf_XSize, HackFont->tf_XSize);
1261 if (NewHackScreen.Width < 80*i+4)
1262 NewHackScreen.Width = 80*i+4;
1265 /* While openscreen fails try fewer colors to see if that is the problem. */
1266 while( ( HackScreen = OpenScreen( (void *)&NewHackScreen ) ) == NULL )
1269 if( --NewHackScreen.Depth < 3 )
1271 if( --NewHackScreen.Depth < 2 )
1273 Abort( AN_OpenScreen & ~AT_DeadEnd );
1275 amii_numcolors = 1L << NewHackScreen.Depth;
1276 if( HackScreen->Height > 300 && forcenobig == 0 )
1281 #ifdef INTUI_NEW_LOOK
1282 if( IntuitionBase->LibNode.lib_Version >= 37 )
1283 PubScreenStatus( HackScreen, 0 );
1286 amiIDisplay->ypix = HackScreen->Height;
1287 amiIDisplay->xpix = HackScreen->Width;
1289 LoadRGB4(&HackScreen->ViewPort, flags.amii_curmap, amii_numcolors );
1291 VisualInfo = GetVisualInfo(HackScreen, TAG_END);
1292 MenuStrip = CreateMenus(GTHackMenu, TAG_END);
1293 LayoutMenus(MenuStrip, VisualInfo, GTMN_NewLookMenus, TRUE, TAG_END);
1295 /* Display the copyright etc... */
1297 if( WIN_BASE == WIN_ERR )
1298 WIN_BASE = amii_create_nhwindow( NHW_BASE );
1299 amii_clear_nhwindow( WIN_BASE );
1300 amii_putstr( WIN_BASE, 0, "" );
1301 amii_putstr( WIN_BASE, 0, "" );
1302 amii_putstr( WIN_BASE, 0, "" );
1303 amii_putstr( WIN_BASE, 0, COPYRIGHT_BANNER_A);
1304 amii_putstr( WIN_BASE, 0, COPYRIGHT_BANNER_B);
1305 amii_putstr( WIN_BASE, 0, COPYRIGHT_BANNER_C);
1306 amii_putstr( WIN_BASE, 0, "");
1312 amii_sethipens( struct Window *w, int type, int attr )
1317 SetAPen( w->RPort, attr ? C_RED : amii_otherAPen );
1318 SetBPen( w->RPort, C_BLACK );
1321 SetAPen( w->RPort, attr ? C_WHITE : amii_statAPen );
1322 SetBPen( w->RPort, amii_statBPen );
1325 SetAPen( w->RPort, attr ? C_WHITE : amii_msgAPen );
1326 SetBPen( w->RPort, amii_msgBPen );
1329 SetAPen( w->RPort, attr ? C_BLACK : amii_menuAPen );
1330 SetBPen( w->RPort, amii_menuBPen );
1333 SetAPen( w->RPort, attr ? C_BLACK : amii_textAPen );
1334 SetBPen( w->RPort, amii_textBPen );
1336 SetBPen( w->RPort, amii_otherBPen );
1337 SetAPen( w->RPort, attr ? C_RED : amii_otherAPen );
1343 amii_setfillpens( struct Window *w, int type )
1348 SetAPen( w->RPort, amii_msgBPen );
1349 SetBPen( w->RPort, amii_msgBPen );
1352 SetAPen( w->RPort, amii_statBPen );
1353 SetBPen( w->RPort, amii_statBPen );
1356 SetAPen( w->RPort, amii_menuBPen );
1357 SetBPen( w->RPort, amii_menuBPen );
1360 SetAPen( w->RPort, amii_textBPen );
1361 SetBPen( w->RPort, amii_textBPen );
1367 SetAPen( w->RPort, C_BLACK );
1368 SetBPen( w->RPort, C_BLACK );
1371 SetAPen( w->RPort, amii_otherBPen );
1372 SetBPen( w->RPort, amii_otherBPen );
1378 amii_setdrawpens( struct Window *w, int type )
1383 SetAPen( w->RPort, amii_msgAPen );
1384 SetBPen( w->RPort, amii_msgBPen );
1387 SetAPen( w->RPort, amii_statAPen );
1388 SetBPen( w->RPort, amii_statBPen );
1391 SetAPen( w->RPort, amii_menuAPen );
1392 SetBPen( w->RPort, amii_menuBPen );
1395 SetAPen( w->RPort, amii_textAPen );
1396 SetBPen( w->RPort, amii_textBPen );
1401 SetAPen( w->RPort, C_WHITE );
1402 SetBPen( w->RPort, C_BLACK );
1405 SetAPen( w->RPort, amii_otherAPen );
1406 SetBPen( w->RPort, amii_otherBPen );
1411 /* Clear the indicated window */
1414 amii_clear_nhwindow(win)
1417 register struct amii_WinDesc *cw;
1418 register struct Window *w;
1420 if( reclip == 2 ) return;
1422 if( win == WIN_ERR || ( cw = amii_wins[win] ) == NULL )
1423 panic( winpanicstr, win, "clear_nhwindow" );
1425 /* Clear the overview window too if it is displayed */
1426 if( WINVERS_AMIV && ( cw->type == WIN_MAP && WIN_OVER != WIN_ERR && reclip == 0 ) )
1428 amii_clear_nhwindow( WIN_OVER );
1432 SetDrMd( w->RPort, JAM2);
1436 if( (cw->wflags & FLMAP_CURSUP ) )
1438 if( cw->type != NHW_MAP )
1441 cw->wflags &= ~FLMAP_CURSUP;
1444 amii_setfillpens( w, cw->type );
1445 SetDrMd( w->RPort, JAM2 );
1447 if( cw->type == NHW_MENU || cw->type == NHW_TEXT )
1449 RectFill( w->RPort, w->BorderLeft, w->BorderTop,
1450 w->Width - w->BorderRight-1,
1451 w->Height - w->BorderBottom-1 );
1455 if( cw->type == NHW_MESSAGE )
1457 amii_curs( win, 1, 0 );
1459 TextSpaces( w->RPort, cw->cols );
1463 RectFill( w->RPort, w->BorderLeft, w->BorderTop,
1464 w->Width - w->BorderRight-1,
1465 w->Height - w->BorderBottom-1 );
1471 amii_curs( win, 1, 0 );
1474 /* Dismiss the window from the screen */
1477 dismiss_nhwindow(win)
1480 register struct Window *w;
1481 register struct amii_WinDesc *cw;
1483 if( win == WIN_ERR || ( cw = amii_wins[win] ) == NULL )
1485 panic(winpanicstr,win, "dismiss_nhwindow");
1492 /* All windows have this stuff attached to them. */
1493 if( cw->type == NHW_MAP ||
1494 cw->type == NHW_OVER ||
1495 cw->type == NHW_BASE ||
1496 cw->type == NHW_MESSAGE ||
1497 cw->type == NHW_STATUS )
1499 ClearMenuStrip( w );
1502 /* Save where user like inventory to appear */
1503 if( win == WIN_INVEN )
1505 lastinvent.MinX = w->LeftEdge;
1506 lastinvent.MinY = w->TopEdge;
1507 lastinvent.MaxX = w->Width;
1508 lastinvent.MaxY = w->Height;
1511 /* Close the window */
1515 /* Free copy of NewWindow structure for TEXT/MENU windows. */
1517 FreeNewWindow( (void *)cw->newwin );
1523 amii_exit_nhwindows(str)
1526 /* Seems strange to have to do this... but we need the BASE window
1529 kill_nhwindows( 0 );
1531 FreeTileImageFiles( );
1535 raw_print( "" ); /* be sure we're not under the top margin */
1541 amii_display_nhwindow(win,blocking)
1547 static int lastwin = -1;
1548 struct amii_WinDesc *cw;
1554 if( win == WIN_ERR || ( cw = amii_wins[win] ) == NULL )
1555 panic(winpanicstr,win,"display_nhwindow");
1557 if( cw->type == NHW_MESSAGE )
1558 cw->wflags &= ~FLMAP_SKIP;
1560 if( cw->type == NHW_MESSAGE || cw->type == NHW_STATUS )
1563 if( WIN_MAP != WIN_ERR && amii_wins[ WIN_MAP ] )
1565 flush_glyph_buffer( amii_wins[ WIN_MAP ]->win );
1568 if( cw->type == NHW_MENU || cw->type == NHW_TEXT )
1570 cnt = DoMenuScroll( win, blocking, PICK_ONE, &mip );
1572 else if( cw->type==NHW_MAP )
1574 amii_end_glyphout( win );
1575 /* Do more if it is time... */
1576 if( blocking == TRUE && amii_wins[ WIN_MESSAGE ]->curx )
1578 outmore( amii_wins[ WIN_MESSAGE ] );
1584 amii_curs(window, x, y)
1586 register int x, y; /* not xchar: perhaps xchar is unsigned and
1587 curx-x would be unsigned as well */
1589 register struct amii_WinDesc *cw;
1590 register struct Window *w;
1591 register struct RastPort *rp;
1593 if( window == WIN_ERR || ( cw = amii_wins[window] ) == NULL )
1594 panic(winpanicstr, window, "curs");
1595 if( (w = cw->win) == NULL )
1597 if( cw->type == NHW_MENU || cw->type == NHW_TEXT )
1600 panic( "No window open yet in curs() for winid %d\n", window );
1602 amiIDisplay->lastwin = window;
1604 /* Make sure x is within bounds */
1606 --x; /* column 0 is never used */
1614 if( x<0 || y<0 || y >= cw->rows || x >= cw->cols )
1616 char *s = "[unknown type]";
1619 case NHW_MESSAGE: s = "[topl window]"; break;
1620 case NHW_STATUS: s = "[status window]"; break;
1621 case NHW_MAP: s = "[map window]"; break;
1622 case NHW_MENU: s = "[menu window]"; break;
1623 case NHW_TEXT: s = "[text window]"; break;
1624 case NHW_BASE: s = "[base window]"; break;
1625 case NHW_OVER: s = "[overview window]"; break;
1627 impossible("bad curs positioning win %d %s (%d,%d)", window, s, x, y);
1633 if(clipping && cw->type == NHW_MAP)
1640 /* Output all saved output before doing cursor movements for MAP */
1642 if( cw->type == NHW_MAP )
1644 flush_glyph_buffer( w );
1647 /* Actually do it */
1650 if( cw->type == NHW_MENU )
1654 if( window == WIN_INVEN )
1656 Move( rp, (x * rp->TxWidth) + w->BorderLeft + 1 + pictdata.xsize + 4,
1657 (y * max(rp->TxHeight,pictdata.ysize + 3) ) +
1658 rp->TxBaseline + pictdata.ysize - rp->TxHeight + w->BorderTop + 4 );
1662 Move( rp, (x * rp->TxWidth) + w->BorderLeft + 1,
1663 (y * rp->TxHeight) + rp->TxBaseline + w->BorderTop + 1 );
1668 Move( rp, (x * rp->TxWidth) + w->BorderLeft + 1,
1669 (y*rp->TxHeight ) + rp->TxBaseline + w->BorderTop + 1 );
1672 else if( cw->type == NHW_TEXT )
1674 Move( rp, (x * rp->TxWidth) + w->BorderLeft + 1,
1675 (y*rp->TxHeight ) + rp->TxBaseline + w->BorderTop + 1 );
1677 else if( cw->type == NHW_MAP || cw->type == NHW_BASE )
1679 /* These coordinate calculations must be synced with those
1680 * in flush_glyph_buffer() in winchar.c. curs_on_u() will
1681 * use this code, all other drawing occurs through the glyph
1682 * code. In order for the cursor to appear on top of the hero,
1683 * the code must compute X,Y in the same manner relative to
1684 * the RastPort coordinates.
1686 * y = w->BorderTop + (g_nodes[i].y-2) * rp->TxHeight +
1687 * rp->TxBaseline + 1;
1688 * x = g_nodes[i].x * rp->TxWidth + w->BorderLeft;
1693 if( cw->type == NHW_MAP )
1695 if(Is_rogue_level(&u.uz)){
1697 int qqx= (x * w->RPort->TxWidth) + w->BorderLeft;
1698 int qqy= w->BorderTop + ( (y+1) * w->RPort->TxHeight ) + 1;
1699 printf("pos: (%d,%d)->(%d,%d)\n",x,y,qqx,qqy);
1701 SetAPen(w->RPort,C_WHITE); /* XXX should be elsewhere (was 4)*/
1702 Move( rp, (x * w->RPort->TxWidth) + w->BorderLeft,
1703 w->BorderTop + ( (y+1) * w->RPort->TxHeight ) + 1 );
1705 Move( rp, (x * mxsize) + w->BorderLeft,
1706 w->BorderTop + ( (y+1) * mysize ) + 1 );
1711 Move( rp, (x * w->RPort->TxWidth) + w->BorderLeft,
1712 w->BorderTop + ( (y + 1) * w->RPort->TxHeight ) +
1713 w->RPort->TxBaseline + 1 );
1718 Move( rp, (x * w->RPort->TxWidth) + w->BorderLeft,
1719 w->BorderTop + ( y * w->RPort->TxHeight ) +
1720 w->RPort->TxBaseline + 1 );
1723 else if( WINVERS_AMIV && cw->type == NHW_OVER )
1725 Move( rp, (x * w->RPort->TxWidth) + w->BorderLeft + 2,
1726 w->BorderTop + w->RPort->TxBaseline + 3 );
1728 else if( cw->type == NHW_MESSAGE && !scrollmsg )
1730 Move( rp, (x * w->RPort->TxWidth) + w->BorderLeft + 2,
1731 w->BorderTop + w->RPort->TxBaseline + 3 );
1733 else if( cw->type == NHW_STATUS )
1735 Move( rp, (x * w->RPort->TxWidth) + w->BorderLeft + 2,
1736 (y*(w->RPort->TxHeight+1)) + w->BorderTop +
1737 w->RPort->TxBaseline + 1 );
1741 Move( rp, (x * w->RPort->TxWidth) + w->BorderLeft + 2,
1742 (y*w->RPort->TxHeight) + w->BorderTop +
1743 w->RPort->TxBaseline + 1 );
1748 amii_set_text_font( name, size )
1753 register struct amii_WinDesc *cw;
1754 int osize = TextsFont13.ta_YSize;
1755 static char nname[ 100 ];
1757 strncpy( nname, name, sizeof( nname ) - 1 );
1758 nname[ sizeof( nname ) - 1 ] = 0;
1760 TextsFont13.ta_Name = nname;
1761 TextsFont13.ta_YSize = size;
1763 /* No alternate text font allowed for 640x269 or smaller */
1764 if( !HackScreen || !bigscreen )
1767 /* Look for windows to set, and change them */
1770 OpenLibrary( "diskfont.library", amii_libvers ) )
1772 TextsFont = OpenDiskFont( &TextsFont13 );
1773 for( i = 0; TextsFont && i < MAXWIN; ++i )
1775 if( (cw = amii_wins[ i ]) && cw->win != NULL )
1780 MoveWindow( cw->win, 0, -( size - osize ) * 2 );
1781 SizeWindow( cw->win, 0, ( size - osize ) * 2 );
1782 SetFont( cw->win->RPort, TextsFont );
1788 SetFont( cw->win->RPort, TextsFont );
1794 CloseLibrary(DiskfontBase);
1795 DiskfontBase = NULL;
1799 kill_nhwindows( all )
1803 register struct amii_WinDesc *cw;
1805 /* Foreach open window in all of amii_wins[], CloseShWindow, free memory */
1807 for( i = 0; i < MAXWIN; ++i )
1809 if( (cw = amii_wins[ i ]) && (cw->type != NHW_BASE || all) )
1811 amii_destroy_nhwindow( i );
1817 amii_cl_end( cw, curs_pos )
1818 register struct amii_WinDesc *cw;
1819 register int curs_pos;
1821 register struct Window *w = cw->win;
1822 register int oy, ox;
1825 panic("NULL window pointer in amii_cl_end()");
1827 oy = w->RPort->cp_y;
1828 ox = w->RPort->cp_x;
1830 TextSpaces( w->RPort, cw->cols - curs_pos );
1832 Move( w->RPort, ox, oy );
1836 cursor_off( window )
1839 register struct amii_WinDesc *cw;
1840 register struct Window *w;
1841 register struct RastPort *rp;
1848 if( window == WIN_ERR || ( cw = amii_wins[window] ) == NULL )
1850 iflags.window_inited=0;
1851 panic(winpanicstr,window, "cursor_off");
1854 if( !(cw->wflags & FLMAP_CURSUP ) )
1862 cw->wflags &= ~FLMAP_CURSUP;
1865 /* Save the current information */
1870 dmode = rp->DrawMode;
1873 SetAPen( rp, cw->curs_apen );
1874 SetBPen( rp, cw->curs_bpen );
1875 SetDrMd( rp, COMPLEMENT );
1876 /*printf("CURSOR OFF: %d %d\n",x,y);*/
1878 if( WINVERS_AMIV && cw->type == NHW_MAP)
1880 cursor_common(rp, x, y);
1881 if(Is_rogue_level(&u.uz))
1890 /* Put back the other stuff */
1892 Move( rp, curx, cury );
1894 SetDrMd( rp, dmode );
1895 SetAPen( rp, apen );
1896 SetBPen( rp, bpen );
1904 register struct amii_WinDesc *cw;
1905 register struct Window *w;
1906 register struct RastPort *rp;
1911 if( window == WIN_ERR || ( cw = amii_wins[window] ) == NULL )
1913 /* tty does this differently - is this OK? */
1914 iflags.window_inited=0;
1915 panic(winpanicstr,window, "cursor_on");
1918 /*printf("CURSOR ON: %d %d\n",cw->win->RPort->cp_x, cw->win->RPort->cp_y);*/
1919 if( (cw->wflags & FLMAP_CURSUP ) )
1920 cursor_off( window );
1927 cw->wflags |= FLMAP_CURSUP;
1930 /* Save the current information */
1933 if( WINVERS_AMIV && cw->type == NHW_MAP && !Is_rogue_level(&u.uz))
1934 x = cw->cursx = (rp->cp_x & -8) + 8;
1937 x = cw->cursx = rp->cp_x;
1938 y = cw->cursy = rp->cp_y;
1941 dmode = rp->DrawMode;
1943 /* Draw in complement mode. The cursor body will be C_WHITE */
1945 cw->curs_apen = 0xff; /* Last color/all planes, regardless of depth */
1946 cw->curs_bpen = 0xff;
1947 SetAPen( rp, cw->curs_apen );
1948 SetBPen( rp, cw->curs_bpen );
1949 SetDrMd( rp, COMPLEMENT );
1950 if( WINVERS_AMIV && cw->type == NHW_MAP)
1952 cursor_common(rp, x, y);
1962 SetDrMd( rp, dmode );
1963 SetAPen( rp, apen );
1964 SetBPen( rp, bpen );
1968 cursor_common(rp, x, y)
1969 struct RastPort *rp;
1974 if(Is_rogue_level(&u.uz)){
1975 x1 = x-2; y1 = y-rp->TxHeight;
1976 x2 = x+rp->TxWidth+1; y2 = y+3;
1977 /*printf("COMM: (%d %d) (%d %d) (%d %d) (%d %d)\n",x1,y1,x2,y2,x1+2,y1+2,x2-2,y2-2);*/
1979 x1 = x; y1 = y-mysize-1;
1980 x2 = x+mxsize-1; y2 = y-2;
1981 RectFill(rp, x1, y1, x2, y2);
1984 RectFill(rp, x1+2, y1+2, x2-2, y2-2);
1987 void amii_suspend_nhwindows( str )
1991 ScreenToBack( HackScreen );
1994 void amii_resume_nhwindows()
1997 ScreenToFront( HackScreen );
2002 DisplayBeep( NULL );
2009 struct amii_WinDesc *cw=amii_wins[WIN_MESSAGE];
2010 /* NB - this is sufficient for
2011 * yn_function, but that's it
2013 if(cw->curx < cnt)cw->curx=0;
2014 else cw->curx -= cnt;
2016 amii_curs(WIN_MESSAGE, cw->curx+1, cw->cury);
2017 amii_cl_end(cw, cw->curx);
2019 /*#endif /* AMIGA_INTUITION */
2025 display_file( PORT_HELP, 1 );
2032 * Print the glyph to the output device. Don't flush the output device.
2034 * Since this is only called from show_glyph(), it is assumed that the
2035 * position and glyph are always correct (checked there)!
2039 amii_print_glyph(win,x,y,glyph)
2044 struct amii_WinDesc *cw;
2047 extern const int zapcolors[];
2050 /* In order for the overview window to work, we can not clip here */
2054 /* If point not in visible part of window just skip it */
2057 if( x <= clipx || y < clipy || x >= clipxmax || y >= clipymax )
2063 if( win == WIN_ERR || (cw=amii_wins[win]) == NULL || cw->type != NHW_MAP)
2065 panic(winpanicstr,win,"amii_print_glyph");
2071 if(u.uz.dlevel != x){
2072 fprintf(stderr,"lvlchg: %d (%d)\n",u.uz.dlevel,Is_rogue_level(&u.uz));
2079 #ifdef REINCARNATION
2080 && !Is_rogue_level(&u.uz)
2085 amiga_print_glyph(win,0,glyph);
2087 else /* AMII, or Rogue level in either version */
2089 /* map glyph to character and color */
2090 mapglyph(glyph, &och, &color, &special, x, y);
2091 /* XXX next if should be ifdef REINCARNATION */
2093 if( WINVERS_AMIV ){ /* implies Rogue level here */
2095 amiga_print_glyph(win,NO_COLOR,ch + 10000);
2097 /* Move the cursor. */
2098 amii_curs(win,x,y+2);
2101 /* Turn off color if rogue level. */
2102 # ifdef REINCARNATION
2103 if (Is_rogue_level(&u.uz))
2107 amiga_print_glyph(win,color,ch);
2109 g_putch(ch); /* print the character */
2111 cw->curx++; /* one character over */
2116 /* Make sure the user sees a text string when no windowing is available */
2120 register const char *s;
2127 amiIDisplay->rawprint++;
2129 if (!Initialized) { /* Not yet screen open ... */
2135 if( Initialized == 0 && WIN_BASE == WIN_ERR )
2136 init_nhwindows(&argc, (char **)0);
2138 if( amii_rawprwin != WIN_ERR )
2139 amii_putstr( amii_rawprwin, 0, s );
2140 else if( WIN_MAP != WIN_ERR && amii_wins[ WIN_MAP ] )
2141 amii_putstr( WIN_MAP, 0, s );
2142 else if( WIN_BASE != WIN_ERR && amii_wins[ WIN_BASE ] )
2143 amii_putstr( WIN_BASE, 0, s );
2151 /* Make sure the user sees a bold text string when no windowing
2156 amii_raw_print_bold(s)
2157 register const char *s;
2165 amiIDisplay->rawprint++;
2167 if (!Initialized) { /* Not yet screen open ... */
2173 if( Initialized == 0 && WIN_BASE == WIN_ERR )
2174 init_nhwindows(&argc, (char **)0);
2176 if( amii_rawprwin != WIN_ERR )
2177 amii_putstr( amii_rawprwin, 1, s );
2178 else if( WIN_MAP != WIN_ERR && amii_wins[ WIN_MAP ] )
2179 amii_putstr( WIN_MAP, 1, s );
2180 else if( WIN_BASE != WIN_ERR && amii_wins[ WIN_BASE ] )
2181 amii_putstr( WIN_BASE, 1, s );
2184 printf("\33[1m%s\33[0m\n",s);
2189 /* Rebuild/update the inventory if the window is up.
2192 amii_update_inventory()
2194 register struct amii_WinDesc *cw;
2196 if( WIN_INVEN != WIN_ERR && ( cw = amii_wins[ WIN_INVEN ] ) &&
2197 cw->type == NHW_MENU && cw->win )
2199 display_inventory( NULL, FALSE );
2203 /* Humm, doesn't really do anything useful */
2210 /* anything else? do we need this much? */
2213 /* Wait for everything to sync. Nothing is asynchronous, so we just
2214 * ask for a key to be pressed.
2219 if(!amiIDisplay || amiIDisplay->rawprint)
2221 if(amiIDisplay) amiIDisplay->rawprint=0;
2225 if( WIN_MAP != WIN_ERR )
2227 display_nhwindow(WIN_MAP,TRUE);
2228 flush_glyph_buffer( amii_wins[ WIN_MAP ]->win );
2241 /* some of this is now redundant with top of amii_cliparound XXX */
2245 /* XXX still to do: suppress scrolling if we violate the boundary but the
2246 * edge of the map is already displayed
2249 amii_cliparound(x,y)
2252 extern boolean restoring;
2254 int oldx = clipx, oldy = clipy;
2255 int oldxmax = clipxmax, oldymax = clipymax;
2257 #define SCROLLCNT 1 /* Get there in 3 moves... */
2258 int scrollcnt = SCROLLCNT; /* ...or 1 if we changed level */
2259 if (!clipping) /* And 1 in anycase, cleaner, simpler, quicker */
2262 if(Is_rogue_level(&u.uz)){
2263 struct Window *w = amii_wins[WIN_MAP]->win;
2264 struct RastPort *rp = w->RPort;
2266 COx = (w->Width-w->BorderLeft-w->BorderRight)/rp->TxWidth;
2267 LIx = (w->Height-w->BorderTop-w->BorderBottom)/rp->TxHeight;
2273 * On a level change, move the clipping region so that for a
2274 * reasonablely large window extra motion is avoided; for
2275 * the rogue level hopefully this means no motion at all.
2278 static d_level saved_level = {127,127}; /* XXX */
2280 if(!on_level(&u.uz, &saved_level)){
2281 scrollcnt = 1; /* jump with blanking */
2283 clipxmax = COx; clipymax = LIx;
2284 saved_level = u.uz; /* save as new current level */
2288 if (x <= clipx + xclipbord ) {
2289 clipx = max(0, x - (clipxmax - clipx)/2 );
2290 clipxmax = clipx + COx;
2292 else if (x > clipxmax - xclipbord ) {
2293 clipxmax = min(COLNO, x + (clipxmax - clipx)/2 );
2294 clipx = clipxmax - COx;
2297 if (y <= clipy + yclipbord ) {
2298 clipy = max(0, y - (clipymax - clipy) / 2);
2299 clipymax = clipy + LIx;
2301 else if (y > clipymax - yclipbord ) {
2302 clipymax = min(ROWNO, y + (clipymax - clipy) / 2);
2303 clipy = clipymax - LIx;
2307 if (clipx != oldx || clipy != oldy || clipxmax != oldxmax || clipymax != oldymax )
2309 #ifndef NOSCROLLRASTER
2310 struct Window *w = amii_wins[ WIN_MAP ]->win;
2311 struct RastPort *rp = w->RPort;
2312 int xdelta, ydelta, xmod, ymod, i;
2313 int incx, incy, mincx, mincy;
2314 int savex, savey, savexmax, saveymax;
2317 if(Is_rogue_level(&u.uz)){
2319 scry = rp->TxHeight;
2325 /* Ask that the glyph routines not draw the overview window */
2327 cursor_off( WIN_MAP );
2329 /* Compute how far we are moving in terms of tiles */
2330 mincx = clipx - oldx ;
2331 mincy = clipy - oldy ;
2333 /* How many tiles to get there in SCROLLCNT moves */
2334 incx = ( clipx - oldx )/scrollcnt;
2335 incy = ( clipy - oldy )/scrollcnt;
2337 /* If less than SCROLLCNT tiles, then move by 1 tile if moving at all */
2338 if( incx == 0 ) incx = (mincx != 0);
2339 if( incy == 0 ) incy = (mincy != 0);
2341 /* Get count of pixels to move each iteration and final pixel count */
2342 xdelta = ((clipx-oldx )*scrx) / scrollcnt;
2343 xmod = ((clipx-oldx )*scrx) % scrollcnt;
2344 ydelta = ((clipy-oldy )*scry) / scrollcnt;
2345 ymod = ((clipy-oldy )*scry) % scrollcnt;
2347 /* Preserve the final move location */
2350 saveymax = clipymax;
2351 savexmax = clipxmax;
2354 * Set clipping rectangle to be just the region that will be exposed so
2355 * that drawing will be faster
2357 #if 0 /* Doesn't seem to work quite the way it should */
2358 /* In some cases hero is 'centered' offscreen */
2362 clipxmax = clipx + incx;
2364 else if( xdelta > 0 )
2367 clipx = clipxmax - incx;
2378 clipymax = clipy + incy;
2380 else if( ydelta > 0 )
2383 clipy = clipymax - incy;
2391 /* Now, in scrollcnt moves, move the picture toward the final view */
2392 for( i = 0; i < scrollcnt; ++i )
2395 if( i == scrollcnt - 1 && (xmod != 0 || ymod != 0) &&
2396 (xdelta != 0 || ydelta != 0) )
2398 incx += (clipx - oldx)%scrollcnt;
2399 incy += (clipy - oldy)%scrollcnt;
2404 /* Scroll the raster if we are scrolling */
2405 if( xdelta != 0 || ydelta != 0 )
2407 ScrollRaster( rp, xdelta, ydelta,
2408 w->BorderLeft, w->BorderTop,
2409 w->Width - w->BorderRight - 1,
2410 w->Height - w->BorderBottom - 1 );
2412 if( mincx == 0 ) incx = 0;
2418 if( mincy == 0 ) incy = 0;
2424 /* Draw the exposed portion */
2425 if (on_level(&u.uz0, &u.uz) && !restoring)
2427 flush_glyph_buffer( amii_wins[ WIN_MAP ]->win );
2433 clipymax = saveymax;
2434 clipxmax = savexmax;
2436 if (on_level(&u.uz0, &u.uz) && !restoring && moves > 1)
2438 flush_glyph_buffer( amii_wins[ WIN_MAP ]->win );
2446 struct MsgPort *port;
2448 struct Message *msg;
2449 while( msg = GetMsg( port ) )