From dacd1919e8324d0af7ee0ee3d0caaecaa6d224fc Mon Sep 17 00:00:00 2001 From: jwalz Date: Sat, 5 Jan 2002 21:05:55 +0000 Subject: [PATCH] *** empty log message *** --- sys/amiga/winstr.c | 522 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 522 insertions(+) create mode 100644 sys/amiga/winstr.c diff --git a/sys/amiga/winstr.c b/sys/amiga/winstr.c new file mode 100644 index 000000000..0ff2f7d81 --- /dev/null +++ b/sys/amiga/winstr.c @@ -0,0 +1,522 @@ +/* SCCS Id: @(#)winstr.c 3.1 93/04/02 */ +/* Copyright (c) Gregg Wonderly, Naperville, Illinois, 1991,1992,1993. */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "NH:sys/amiga/windefs.h" +#include "NH:sys/amiga/winext.h" +#include "NH:sys/amiga/winproto.h" + +/* Put a string into the indicated window using the indicated attribute */ + +void +amii_putstr(window,attr,str) + winid window; + int attr; + const char *str; +{ + int fudge; + int len; + struct Window *w; + register struct amii_WinDesc *cw; + char *ob; + int i, j, n0, bottom, totalvis, wheight; + static int wrapping = 0; + + /* Always try to avoid a panic when there is no window */ + if( window == WIN_ERR ) + { + window = WIN_BASE; + if( window == WIN_ERR ) + window = WIN_BASE = amii_create_nhwindow( NHW_BASE ); + } + + if( window == WIN_ERR || ( cw = amii_wins[window] ) == NULL ) + { + iflags.window_inited=0; + panic(winpanicstr,window, "putstr"); + } + + w = cw->win; + + if(!str) return; + amiIDisplay->lastwin = window; /* do we care??? */ + + /* NHW_MENU windows are not opened immediately, so check if we + * have the window pointer yet + */ + + if( w ) + { + /* Set the drawing mode and pen colors */ + SetDrMd( w->RPort, JAM2 ); + amii_sethipens( w, cw->type, attr ); + } + else if( cw->type != NHW_MENU && cw->type != NHW_TEXT ) + { + panic( "NULL window pointer in putstr 2: %d", window ); + } + + /* Okay now do the work for each type */ + + switch(cw->type) + { + case NHW_MESSAGE: + if( WINVERS_AMIV ) + fudge = 2; + else + { + /* 8 for --more--, 1 for preceeding sp, 1 for putstr pad */ + fudge = 10; + } + + /* There is a one pixel border at the borders, so subtract two */ + bottom = amii_msgborder( w ); + + wheight = ( w->Height - w->BorderTop - + w->BorderBottom - 3 ) / w->RPort->TxHeight; + + if (scrollmsg || wheight > 1) + fudge = 0; + + amii_scrollmsg( w, cw ); + + while (isspace(*str)) str++; + strncpy( toplines, str, TBUFSZ ); + toplines[ TBUFSZ - 1 ] = 0; + + /* For initial message to be visible, we need to explicitly position the + * cursor. This flag, cw->curx == -1 is set elsewhere to force the + * cursor to be repositioned to the "bottom". + */ + if( cw->curx == -1 ) + { + amii_curs( WIN_MESSAGE, 1, bottom ); + cw->curx = 0; + } + + /* If used all of history lines, move them down */ + if( cw->maxrow >= iflags.msg_history ) + { + if( cw->data[ 0 ] ) + free( cw->data[ 0 ] ); + memcpy( cw->data, &cw->data[ 1 ], + ( iflags.msg_history - 1 ) * sizeof( char * ) ); + cw->data[ iflags.msg_history - 1 ] = + (char *) alloc( strlen( toplines ) + 5 ); + strcpy( cw->data[ i = iflags.msg_history - 1 ] + + SOFF + (scrollmsg!=0), toplines ); + } + else + { + /* Otherwise, allocate a new one and copy the line in */ + cw->data[ cw->maxrow ] = (char *) + alloc( strlen( toplines ) + 5 ); + strcpy( cw->data[ i = cw->maxrow++ ] + + SOFF + (scrollmsg!=0), toplines ); + } + cw->data[ i ][ SEL_ITEM ] = 1; + cw->data[ i ][ VATTR ] = attr+1; + + if( scrollmsg ) + { + cw->curx = 0; + cw->data[ i ][2] = (cw->wflags & FLMSG_FIRST ) ? '>' : ' '; + } + + str = cw->data[i] + SOFF; + if( cw->curx + strlen(str) >= (cw->cols-fudge) ) + { + int i; + char *ostr = (char *)str; + char *p; + + while( cw->curx + strlen( str ) >= (cw->cols-fudge) ) + { + for(p=((char *)&str[ cw->cols-1 - cw->curx ])-fudge; !isspace(*p) && p > str;) + --p; + if (p < str) p = (char *)str; + + if( p == str ) { + /* p = (char *)&str[ cw->cols ]; */ + outmore(cw); + continue; + } + + i = (long)p-(long)str; + outsubstr( cw, (char *)str, i, fudge ); + cw->curx += i; + + while(isspace(*p)) p++; + str = p; + +#if 0 + if( str != ostr ) { + outsubstr( cw, "+", 1, fudge ); + cw->curx+=2; + } +#endif + if(*str) + amii_scrollmsg( w, cw ); + amii_cl_end( cw, cw->curx ); + } + + if( *str ) + { + if( str != ostr ) + { + outsubstr( cw, "+", 1, fudge ); + cw->curx+=2; + } + while ( isspace( *str ) ) + ++str; + outsubstr( cw, (char *)str, i = strlen( (char *)str ), fudge ); + cw->curx += i; + amii_cl_end( cw, cw->curx ); + } + } + else + { + outsubstr( cw, (char *)str, i = strlen( (char *)str ), fudge ); + cw->curx += i; + amii_cl_end( cw, cw->curx ); + } + cw->wflags &= ~FLMSG_FIRST; + len = 0; + if( scrollmsg ) + { + totalvis = CountLines( window ); + SetPropInfo( w, &MsgScroll, + ( w->Height-w->BorderTop-w->BorderBottom ) / w->RPort->TxHeight, + totalvis, totalvis ); + } + i = strlen( toplines + SOFF ); + cw->maxcol = max( cw->maxcol, i ); + cw->vwy = cw->maxrow; + break; + + case NHW_STATUS: + if( cw->data[ cw->cury ] == NULL ) + panic( "NULL pointer for status window" ); + ob = &cw->data[cw->cury][j = cw->curx]; + if(flags.botlx) *ob = 0; + + /* Display when beam at top to avoid flicker... */ + WaitTOF(); + Text(w->RPort,(char *)str,strlen((char *)str)); + if( cw->cols > strlen( str ) ) + TextSpaces( w->RPort, cw->cols - strlen( str ) ); + + (void) strncpy(cw->data[cw->cury], str, cw->cols ); + cw->data[cw->cury][cw->cols-1] = '\0'; /* null terminate */ + cw->cury = (cw->cury+1) % 2; + cw->curx = 0; + break; + + case NHW_MAP: + case NHW_BASE: + if (cw->type == NHW_BASE && wrapping) { + amii_curs(window, cw->curx+1, cw->cury); + TextSpaces(w->RPort, cw->cols); + if (cw->cury < cw->rows) { + amii_curs(window, cw->curx+1, cw->cury+1); + TextSpaces(w->RPort, cw->cols); + cw->cury--; + } + } + amii_curs(window, cw->curx+1, cw->cury); + Text(w->RPort,(char *)str,strlen((char *)str)); + cw->curx = 0; + /* CR-LF is automatic in these windows */ + cw->cury++; + if (cw->type == NHW_BASE && cw->cury >= cw->rows) { + cw->cury = 0; + wrapping = 1; + } + break; + + case NHW_MENU: + case NHW_TEXT: + + /* always grows one at a time, but alloc 12 at a time */ + + if( cw->cury >= cw->rows || !cw->data ) + { + char **tmp; + + /* Allocate 12 more rows */ + cw->rows += 12; + tmp = (char**) alloc(sizeof(char*) * cw->rows); + + /* Copy the old lines */ + for(i=0; icury; i++) + tmp[i] = cw->data[i]; + + if( cw->data ) { + free( cw->data ); + cw->data = NULL; + } + + cw->data = tmp; + + /* Null out the unused entries. */ + for(i=cw->cury; irows; i++) + cw->data[i] = 0; + } + + if( !cw->data ) + panic("no data storage"); + + /* Shouldn't need to do this, but... */ + + if( cw->data && cw->data[cw->cury] ) { + free( cw->data[cw->cury] ); + cw->data[cw->cury] = NULL; + } + + n0 = strlen(str)+1; + cw->data[cw->cury] = (char*) alloc(n0+SOFF); + + /* avoid nuls, for convenience */ + cw->data[cw->cury][VATTR] = attr+1; + cw->data[cw->cury][SEL_ITEM] = 0; + Strcpy( cw->data[cw->cury] + SOFF, str); + + if(n0 > cw->maxcol) cw->maxcol = n0; + if(++cw->cury > cw->maxrow) cw->maxrow = cw->cury; + break; + + default: + panic("Invalid or unset window type in putstr()"); + } +} + +void +amii_scrollmsg( w, cw ) + register struct Window *w; + register struct amii_WinDesc *cw; +{ + int bottom, wheight; + + bottom = amii_msgborder( w ); + + wheight = ( w->Height - w->BorderTop - + w->BorderBottom - 3 ) / w->RPort->TxHeight; + + if( scrollmsg ) + { + if( ++cw->disprows > wheight ) + { + outmore( cw ); + cw->disprows = 1; /* count this line... */ + } + else + { + ScrollRaster( w->RPort, 0, w->RPort->TxHeight, + w->BorderLeft, w->BorderTop + 1, + w->Width - w->BorderRight-1, + w->Height - w->BorderBottom - 1 ); + } + amii_curs( WIN_MESSAGE, 1, bottom ); + } +} + +int +amii_msgborder( w ) + struct Window *w; +{ + register int bottom; + + /* There is a one pixel border at the borders, so subtract two */ + bottom = w->Height - w->BorderTop - w->BorderBottom - 2; + bottom /= w->RPort->TxHeight; + if( bottom > 0 ) + --bottom; + return( bottom ); +} + +void +outmore( cw ) + register struct amii_WinDesc *cw; +{ + struct Window *w = cw->win; + + if((cw->wflags & FLMAP_SKIP) == 0) + { + if( scrollmsg ) + { + int bottom; + + bottom = amii_msgborder( w ); + + ScrollRaster( w->RPort, 0, w->RPort->TxHeight, + w->BorderLeft, w->BorderTop+1, + w->Width - w->BorderRight-1, + w->Height - w->BorderBottom - 1 ); + amii_curs( WIN_MESSAGE, 1, bottom ); /* -1 for inner border */ + Text( w->RPort, "--more--", 8 ); + } + else + Text( w->RPort, " --more--", 9 ); + + /* Make sure there are no events in the queue */ + flushIDCMP( HackPort ); + + /* Allow mouse clicks to clear --more-- */ + WindowGetchar(); + if( lastevent.type == WEKEY && lastevent.un.key == '\33' ) + cw->wflags |= FLMAP_SKIP; + } + if( !scrollmsg ) + { + amii_curs( WIN_MESSAGE, 1, 0 ); + amii_cl_end( cw, cw->curx ); + } +} + +void +outsubstr( cw, str, len, fudge ) + register struct amii_WinDesc *cw; + char *str; + int len; + int fudge; +{ + struct Window *w = cw->win; + + if( cw->curx ) + { + /* Check if this string and --more-- fit, if not, + * then put out --more-- and wait for a key. + */ + if( (len + fudge ) + cw->curx >= cw->cols ) + { + if( !scrollmsg ) + outmore( cw ); + } + else + { + /* Otherwise, move and put out a blank separator */ + Text( w->RPort, spaces, 1 ); + cw->curx += 1; + } + } + + Text(w->RPort,str,len); +} + +/* Put a graphics character onto the screen */ + +void +amii_putsym( st, i, y, c ) + winid st; + int i, y; + CHAR_P c; +{ + amii_curs( st, i, y ); + Text(amii_wins[st]->win->RPort, &c, 1); +} + +/* Add to the last line in the message window */ + +void +amii_addtopl(s) + const char *s; +{ + register struct amii_WinDesc *cw = amii_wins[WIN_MESSAGE]; + + while(*s) { + if(cw->curx == cw->cols - 1) + amii_putstr(WIN_MESSAGE, 0, ""); + amii_putsym(WIN_MESSAGE, cw->curx + 1, amii_msgborder(cw->win), *s++); + cw->curx++; + } +} + +void +TextSpaces( rp, nr ) + struct RastPort *rp; + int nr; +{ + if( nr < 1 ) + return; + + while (nr > sizeof(spaces) - 1) + { + Text(rp, spaces, (long)sizeof(spaces) - 1); + nr -= sizeof(spaces) - 1; + } + if (nr > 0) + Text(rp, spaces, (long)nr); +} + +void +amii_remember_topl() +{ + /* ignore for now. I think this will be done automatically by + * the code writing to the message window, but I could be wrong. + */ +} + +int +amii_doprev_message() +{ + struct amii_WinDesc *cw; + struct Window *w; + char *str; + + if( WIN_MESSAGE == WIN_ERR || + ( cw = amii_wins[ WIN_MESSAGE ] ) == NULL || ( w = cw->win ) == NULL ) + { + panic(winpanicstr,WIN_MESSAGE, "doprev_message"); + } + + /* When an interlaced/tall screen is in use, the scroll bar will be there */ + /* Or in some other cases as well */ + if( scrollmsg ) + { + struct Gadget *gd; + struct PropInfo *pip; + int hidden, topidx, i, total, wheight; + + for( gd = w->FirstGadget; gd && gd->GadgetID != 1; ) + gd = gd->NextGadget; + + if( gd ) + { + pip = (struct PropInfo *)gd->SpecialInfo; + wheight = ( w->Height - w->BorderTop - + w->BorderBottom - 2 ) / w->RPort->TxHeight; + hidden = max( cw->maxrow - wheight, 0 ); + topidx = (((ULONG)hidden * pip->VertPot) + (MAXPOT/2)) >> 16; + for( total = i = 0; i < cw->maxrow; ++i ) + { + if( cw->data[i][1] != 0 ) + ++total; + } + + i = 0; + topidx -= wheight/4 + 1; + if (topidx < 0) + topidx = 0; + SetPropInfo( w, &MsgScroll, wheight, total, topidx ); + DisplayData( WIN_MESSAGE, topidx ); + } + return(0); + } + + if( --cw->vwy < 0 ) + { + cw->maxcol = 0; + DisplayBeep( NULL ); + str = "\0\0No more history saved..."; + } + else + str = cw->data[ cw->vwy ]; + + amii_cl_end(cw, 0); + amii_curs( WIN_MESSAGE, 1, 0 ); + amii_setdrawpens( amii_wins[WIN_MESSAGE]->win, NHW_MESSAGE ); + Text(w->RPort,str+SOFF,strlen(str+SOFF)); + cw->curx = cw->cols + 1; + + return( 0 ); +}