1 /* SCCS Id: @(#)winami.c 3.2 2000/01/12 */
2 /* Copyright (c) Gregg Wonderly, Naperville, Illinois, 1991,1992,1993,1996. */
3 /* NetHack may be freely redistributed. See license for details. */
4
5 #include "NH:sys/amiga/windefs.h"
6 #include "NH:sys/amiga/winext.h"
7 #include "NH:sys/amiga/winproto.h"
8 #include "dlb.h"
9
10 #ifdef AMIGA_INTUITION
11
12 static int FDECL( put_ext_cmd, ( char *, int, struct amii_WinDesc *, int ) );
13
14 struct amii_DisplayDesc *amiIDisplay; /* the Amiga Intuition descriptor */
15 struct Rectangle lastinvent, lastmsg;
16 int clipping = 0;
17 int clipx=0;
18 int clipy=0;
19 int clipxmax=0;
20 int clipymax=0;
21 int scrollmsg = 1;
22 int alwaysinvent = 0;
23 int amii_numcolors;
24 long amii_scrnmode;
25
26 /* Interface definition, for use by windows.c and winprocs.h to provide
27 * the intuition interface for the amiga...
28 */
29 struct window_procs amii_procs =
30 {
31 "amii",
32 WC_COLOR|WC_HILITE_PET|WC_INVERSE,
33 0L,
34 amii_init_nhwindows,
35 amii_player_selection,
36 amii_askname,
37 amii_get_nh_event,
38 amii_exit_nhwindows,
39 amii_suspend_nhwindows,
40 amii_resume_nhwindows,
41 amii_create_nhwindow,
42 amii_clear_nhwindow,
43 amii_display_nhwindow,
44 amii_destroy_nhwindow,
45 amii_curs,
46 amii_putstr,
47 amii_display_file,
48 amii_start_menu,
49 amii_add_menu,
50 amii_end_menu,
51 amii_select_menu,
52 genl_message_menu,
53 amii_update_inventory,
54 amii_mark_synch,
55 amii_wait_synch,
56 #ifdef CLIPPING
57 amii_cliparound,
58 #endif
59 #ifdef POSITIONBAR
60 donull,
61 #endif
62 amii_print_glyph,
63 amii_raw_print,
64 amii_raw_print_bold,
65 amii_nhgetch,
66 amii_nh_poskey,
67 amii_bell,
68 amii_doprev_message,
69 amii_yn_function,
70 amii_getlin,
71 amii_get_ext_cmd,
72 amii_number_pad,
73 amii_delay_output,
74 #ifdef CHANGE_COLOR /* only a Mac option currently */
75 amii_change_color,
76 amii_get_color_string,
77 #endif
78 /* other defs that really should go away (they're tty specific) */
79 amii_delay_output,
80 amii_delay_output,
81 amii_outrip,
82 genl_preference_update
83 };
84
85 /* The view window layout uses the same function names so we can use
86 * a shared library to allow the executable to be smaller.
87 */
88 struct window_procs amiv_procs =
89 {
90 "amitile",
91 WC_COLOR|WC_HILITE_PET|WC_INVERSE,
92 0L,
93 amii_init_nhwindows,
94 amii_player_selection,
95 amii_askname,
96 amii_get_nh_event,
97 amii_exit_nhwindows,
98 amii_suspend_nhwindows,
99 amii_resume_nhwindows,
100 amii_create_nhwindow,
101 amii_clear_nhwindow,
102 amii_display_nhwindow,
103 amii_destroy_nhwindow,
104 amii_curs,
105 amii_putstr,
106 amii_display_file,
107 amii_start_menu,
108 amii_add_menu,
109 amii_end_menu,
110 amii_select_menu,
111 genl_message_menu,
112 amii_update_inventory,
113 amii_mark_synch,
114 amii_wait_synch,
115 #ifdef CLIPPING
116 amii_cliparound,
117 #endif
118 #ifdef POSITIONBAR
119 donull,
120 #endif
121 amii_print_glyph,
122 amii_raw_print,
123 amii_raw_print_bold,
124 amii_nhgetch,
125 amii_nh_poskey,
126 amii_bell,
127 amii_doprev_message,
128 amii_yn_function,
129 amii_getlin,
130 amii_get_ext_cmd,
131 amii_number_pad,
132 amii_delay_output,
133 #ifdef CHANGE_COLOR /* only a Mac option currently */
134 amii_change_color,
135 amii_get_color_string,
136 #endif
137 /* other defs that really should go away (they're tty specific) */
138 amii_delay_output,
139 amii_delay_output,
140 amii_outrip,
141 genl_preference_update
142 };
143
144 unsigned short amii_initmap[ AMII_MAXCOLORS ];
145 /* Default pens used unless user overides in nethack.cnf. */
146 unsigned short amii_init_map[ AMII_MAXCOLORS ] =
147 {
148 0x0000, /* color #0 C_BLACK */
149 0x0FFF, /* color #1 C_WHITE */
150 0x0830, /* color #2 C_BROWN */
151 0x07ac, /* color #3 C_CYAN */
152 0x0181, /* color #4 C_GREEN */
153 0x0C06, /* color #5 C_MAGENTA */
154 0x023E, /* color #6 C_BLUE */
155 0x0c00, /* color #7 C_RED */
156 };
157
158 unsigned short amiv_init_map[ AMII_MAXCOLORS ] =
159 {
160 0x0000, /* color #0 C_BLACK */
161 0x0fff, /* color #1 C_WHITE */
162 0x00bf, /* color #2 C_CYAN */
163 0x0f60, /* color #3 C_ORANGE */
164 0x000f, /* color #4 C_BLUE */
165 0x0090, /* color #5 C_GREEN */
166 0x069b, /* color #6 C_GREY */
167 0x0f00, /* color #7 C_RED */
168 0x06f0, /* color #8 C_LTGREEN */
169 0x0ff0, /* color #9 C_YELLOW */
170 0x0f0f, /* color #10 C_MAGENTA */
171 0x0940, /* color #11 C_BROWN */
172 0x0466, /* color #12 C_GREYBLUE */
173 0x0c40, /* color #13 C_LTBROWN */
174 0x0ddb, /* color #14 C_LTGREY */
175 0x0fb9, /* color #15 C_PEACH */
176
177 /* Pens for dripens etc under AA or better */
178 0x0222, /* color #16 */
179 0x0fdc, /* color #17 */
180 0x0000, /* color #18 */
181 0x0ccc, /* color #19 */
182 0x0bbb, /* color #20 */
183 0x0BA9, /* color #21 */
184 0x0999, /* color #22 */
185 0x0987, /* color #23 */
186 0x0765, /* color #24 */
187 0x0666, /* color #25 */
188 0x0555, /* color #26 */
189 0x0533, /* color #27 */
190 0x0333, /* color #28 */
191 0x018f, /* color #29 */
192 0x0f81, /* color #30 */
193 0x0fff, /* color #31 */
194 };
195
196 #if !defined( TTY_GRAPHICS ) || defined( SHAREDLIB ) /* this should be shared better */
197 char morc; /* the character typed in response to a --more-- prompt */
198 #endif
199 char spaces[ 76 ] =
200 " ";
201
202 winid WIN_BASE = WIN_ERR;
203 winid WIN_OVER = WIN_ERR;
204 winid amii_rawprwin = WIN_ERR;
205
206 /* Changed later during window/screen opens... */
207 int txwidth = FONTWIDTH, txheight = FONTHEIGHT, txbaseline = FONTBASELINE;
208
209 /* If a 240 or more row screen is in front when we start, this will be
210 * set to 1, and the windows will be given borders to allow them to be
211 * arranged differently. The Message window may eventually get a scroller...
212 */
213 int bigscreen = 0;
214
215 /* This gadget data is replicated for menu/text windows... */
216 struct PropInfo PropScroll = { AUTOKNOB|FREEVERT,
217 0xffff,0xffff, 0xffff,0xffff, };
218 struct Image Image1 = { 0,0, 7,102, 0, NULL, 0x0000,0x0000, NULL };
219 struct Gadget MenuScroll = {
220 NULL, -15,10, 15,-19, GRELRIGHT|GRELHEIGHT,
221 RELVERIFY|FOLLOWMOUSE|RIGHTBORDER|GADGIMMEDIATE|RELVERIFY,
222 PROPGADGET, (APTR)&Image1, NULL, NULL, NULL, (APTR)&PropScroll,
223 1, NULL
224 };
225
226 /* This gadget is for the message window... */
227 struct PropInfo MsgPropScroll = { AUTOKNOB|FREEVERT,
228 0xffff,0xffff, 0xffff,0xffff, };
229 struct Image MsgImage1 = { 0,0, 7,102, 0, NULL, 0x0000,0x0000, NULL };
230 struct Gadget MsgScroll = {
231 NULL, -15,10, 14,-19, GRELRIGHT|GRELHEIGHT,
232 RELVERIFY|FOLLOWMOUSE|RIGHTBORDER|GADGIMMEDIATE|RELVERIFY,
233 PROPGADGET, (APTR)&MsgImage1, NULL, NULL, NULL, (APTR)&MsgPropScroll,
234 1, NULL
235 };
236
237 int wincnt=0; /* # of nh windows opened */
238
239 /* We advertise a public screen to allow some people to do other things
240 * while they are playing... like compiling...
241 */
242
243 #ifdef INTUI_NEW_LOOK
244 extern struct Hook fillhook;
245 struct TagItem tags[] =
246 {
247 { WA_BackFill, (ULONG)&fillhook },
248 { WA_PubScreenName, (ULONG)"NetHack" },
249 { TAG_DONE, 0 },
250 };
251 #endif
252
253 /*
254 * The default dimensions and status values for each window type. The
255 * data here is generally changed in create_nhwindow(), so beware that
256 * what you see here may not be exactly what you get.
257 */
258 struct win_setup new_wins[] =
259 {
260
261 /* First entry not used, types are based at 1 */
262 {{0}},
263
264 /* NHW_MESSAGE */
265 {{0,1,640,11,
266 0xff,0xff,
267 NEWSIZE|GADGETUP|GADGETDOWN|MOUSEMOVE|MOUSEBUTTONS|RAWKEY,
268 BORDERLESS|ACTIVATE|SMART_REFRESH
269 #ifdef INTUI_NEW_LOOK
270 |WFLG_NW_EXTENDED
271 #endif
272 ,
273 NULL,NULL,(UBYTE*)"Messages",NULL,NULL,320,40,0xffff,0xffff,
274 #ifdef INTUI_NEW_LOOK
275 PUBLICSCREEN,tags
276 #else
277 CUSTOMSCREEN
278 #endif
279 },
280 0,0,1,1,80,80},
281
282 /* NHW_STATUS */
283 {{0,181,640,24,
284 0xff,0xff,
285 RAWKEY|MENUPICK|DISKINSERTED,
286 BORDERLESS|ACTIVATE|SMART_REFRESH|BACKDROP
287 #ifdef INTUI_NEW_LOOK
288 |WFLG_NW_EXTENDED
289 #endif
290 ,
291 NULL,NULL,(UBYTE*)"Game Status",NULL,NULL,0,0,0xffff,0xffff,
292 #ifdef INTUI_NEW_LOOK
293 PUBLICSCREEN,tags
294 #else
295 CUSTOMSCREEN
296 #endif
297 },
298 0,0,2,2,78,78},
299
300 /* NHW_MAP */
301 {{0,0,WIDTH,WINDOWHEIGHT,
302 0xff,0xff,
303 RAWKEY|MENUPICK|MOUSEBUTTONS|ACTIVEWINDOW|MOUSEMOVE,
304 BORDERLESS|ACTIVATE|SMART_REFRESH|BACKDROP
305 #ifdef INTUI_NEW_LOOK
306 |WFLG_NW_EXTENDED
307 #endif
308 ,
309 NULL,NULL,(UBYTE*)"Dungeon Map",NULL,NULL,64,64,0xffff,0xffff,
310 #ifdef INTUI_NEW_LOOK
311 PUBLICSCREEN,tags
312 #else
313 CUSTOMSCREEN
314 #endif
315 },
316 0,0,22,22,80,80},
317
318 /* NHW_MENU */
319 {{400,10,10,10,
320 0xff,0xff,
321 RAWKEY|MENUPICK|DISKINSERTED|MOUSEMOVE|MOUSEBUTTONS|
322 GADGETUP|GADGETDOWN|CLOSEWINDOW|VANILLAKEY|NEWSIZE|INACTIVEWINDOW,
323 WINDOWSIZING|WINDOWCLOSE|WINDOWDRAG|ACTIVATE|SMART_REFRESH
324 #ifdef INTUI_NEW_LOOK
325 |WFLG_NW_EXTENDED
326 #endif
327 ,
328 &MenuScroll,NULL,NULL,NULL,NULL,64,32,0xffff,0xffff,
329 #ifdef INTUI_NEW_LOOK
330 PUBLICSCREEN,tags
331 #else
332 CUSTOMSCREEN
333 #endif
334 },
335 0,0,1,1,22,78},
336
337 /* NHW_TEXT */
338 {{0,0,640,200,
339 0xff,0xff,
340 RAWKEY|MENUPICK|DISKINSERTED|MOUSEMOVE|
341 GADGETUP|CLOSEWINDOW|VANILLAKEY|NEWSIZE,
342 WINDOWSIZING|WINDOWCLOSE|WINDOWDRAG|ACTIVATE|SMART_REFRESH
343 #ifdef INTUI_NEW_LOOK
344 |WFLG_NW_EXTENDED
345 #endif
346 ,
347 &MenuScroll,NULL,(UBYTE*)NULL,NULL,NULL,100,32,0xffff,0xffff,
348 #ifdef INTUI_NEW_LOOK
349 PUBLICSCREEN,tags
350 #else
351 CUSTOMSCREEN
352 #endif
353 },
354 0,0,1,1,22,78},
355
356 /* NHW_BASE */
357 {{0,0,WIDTH,WINDOWHEIGHT,
358 0xff,0xff,
359 RAWKEY|MENUPICK|MOUSEBUTTONS,
360 BORDERLESS|ACTIVATE|SMART_REFRESH|BACKDROP
361 #ifdef INTUI_NEW_LOOK
362 |WFLG_NW_EXTENDED
363 #endif
364 ,
365 NULL,NULL,(UBYTE*)NULL,NULL,NULL,-1,-1,0xffff,0xffff,
366 #ifdef INTUI_NEW_LOOK
367 PUBLICSCREEN,tags
368 #else
369 CUSTOMSCREEN
370 #endif
371 },
372 0,0,22,22,80,80},
373
374 /* NHW_OVER */
375 {{320,20,319,179,
376 0xff,0xff,
377 RAWKEY|MENUPICK|MOUSEBUTTONS,
378 BORDERLESS|ACTIVATE|SMART_REFRESH|BACKDROP
379 #ifdef INTUI_NEW_LOOK
380 |WFLG_NW_EXTENDED
381 #endif
382 ,
383 NULL,NULL,(UBYTE*)NULL,NULL,NULL,64,32,0xffff,0xffff,
384 #ifdef INTUI_NEW_LOOK
385 PUBLICSCREEN,tags
386 #else
387 CUSTOMSCREEN
388 #endif
389 },
390 0,0,22,22,80,80},
391 };
392
393 const char winpanicstr[] = "Bad winid %d in %s()";
394
395 /* The opened windows information */
396 struct amii_WinDesc *amii_wins[ MAXWIN + 1 ];
397
398 #ifdef INTUI_NEW_LOOK
399 /*
400 * NUMDRIPENS varies based on headers, so don't use it
401 * here, its value is used elsewhere.
402 */
403 UWORD amii_defpens[ 20 ];
404
405 struct TagItem scrntags[] =
406 {
407 { SA_PubName, (ULONG)"NetHack" },
408 { SA_Overscan, OSCAN_TEXT },
409 { SA_AutoScroll, TRUE },
410 #if LIBRARY_VERSION >= 39
411 { SA_Interleaved, TRUE },
412 #endif
413 { SA_Pens, (ULONG)0 },
414 { SA_DisplayID, 0 },
415 { TAG_DONE, 0 },
416 };
417
418 #endif
419
420 struct NewScreen NewHackScreen =
421 {
422 0, 0, WIDTH, SCREENHEIGHT, 3,
423 0, 1, /* DetailPen, BlockPen */
424 HIRES,
425 CUSTOMSCREEN
426 #ifdef INTUI_NEW_LOOK
427 |NS_EXTENDED
428 #endif
429 ,
430 &Hack80, /* Font */
431 NULL, /*(UBYTE *)" NetHack X.Y.Z" */
432 NULL, /* Gadgets */
433 NULL, /* CustomBitmap */
434 #ifdef INTUI_NEW_LOOK
435 scrntags
436 #endif
437 };
438
439 /*
440 * plname is filled either by an option (-u Player or -uPlayer) or
441 * explicitly (by being the wizard) or by askname.
442 * It may still contain a suffix denoting pl_character.
443 * Always called after init_nhwindows() and before display_gamewindows().
444 */
445 void
amii_askname()446 amii_askname()
447 {
448 char plnametmp[300]; /* From winreq.c: sizeof(StrStringSIBuff) */
449 *plnametmp = 0;
450 do {
451 amii_getlin( "Who are you?", plnametmp );
452 } while( strlen( plnametmp ) == 0 );
453
454 strncpy(plname, plnametmp, PL_NSIZ-1); /* Avoid overflowing plname[] */
455 plname[PL_NSIZ-1] = 0;
456
457 if( *plname == '\33' )
458 {
459 clearlocks();
460 exit_nhwindows(NULL);
461 terminate(0);
462 }
463 }
464
465 /* Discarded ... -jhsa
466 #include "NH:sys/amiga/char.c"
467 */
468
469 /* Get the player selection character */
470
471 #if 0 /* New function at the bottom */
472 void
amii_player_selection()473 amii_player_selection()
474 {
475 register struct Window *cwin;
476 register struct IntuiMessage *imsg;
477 register int aredone = 0;
478 register struct Gadget *gd;
479 static int once = 0;
480 long class, code;
481
482 amii_clear_nhwindow( WIN_BASE );
483 if (validrole(flags.initrole))
484 return;
485 else {
486 flags.initrole=randrole();
487 return;
488 }
489 #if 0 /* Don't query the user ... instead give random character -jhsa */
490
491 #if 0 /* OBSOLETE */
492 if( *pl_character ){
493 pl_character[ 0 ] = toupper( pl_character[ 0 ] );
494 if( index( pl_classes, pl_character[ 0 ] ) )
495 return;
496 }
497 #endif
498
499 if( !once ){
500 if( bigscreen ){
501 Type_NewWindowStructure1.TopEdge =
502 (HackScreen->Height/2) - (Type_NewWindowStructure1.Height/2);
503 }
504 for( gd = Type_NewWindowStructure1.FirstGadget; gd;
505 gd = gd->NextGadget )
506 {
507 if( gd->GadgetID != 0 )
508 SetBorder( gd );
509 }
510 once = 1;
511 }
512
513 if( WINVERS_AMIV )
514 {
515 # ifdef INTUI_NEW_LOOK
516 Type_NewWindowStructure1.Extension = wintags;
517 Type_NewWindowStructure1.Flags |= WFLG_NW_EXTENDED;
518 fillhook.h_Entry = (ULONG(*)())LayerFillHook;
519 fillhook.h_Data = (void *)-2;
520 fillhook.h_SubEntry = 0;
521 #endif
522 }
523
524 Type_NewWindowStructure1.Screen = HackScreen;
525 if( ( cwin = OpenShWindow( (void *)&Type_NewWindowStructure1 ) ) == NULL )
526 {
527 return;
528 }
529 #if 0
530 WindowToFront( cwin );
531 #endif
532
533 while( !aredone )
534 {
535 WaitPort( cwin->UserPort );
536 while( ( imsg = (void *) GetMsg( cwin->UserPort ) ) != NULL )
537 {
538 class = imsg->Class;
539 code = imsg->Code;
540 gd = (struct Gadget *)imsg->IAddress;
541 ReplyMsg( (struct Message *)imsg );
542
543 switch( class )
544 {
545 case VANILLAKEY:
546 if( index( pl_classes, toupper( code ) ) )
547 {
548 pl_character[0] = toupper( code );
549 aredone = 1;
550 }
551 else if( code == ' ' || code == '\n' || code == '\r' )
552 {
553 flags.initrole = randrole();
554 #if 0 /* OBSOLETE */
555 #ifdef TOURIST
556 strcpy( pl_character, roles[ rnd( 11 ) ] );
557 #else
558 strcpy( pl_character, roles[ rnd( 10 ) ] );
559 #endif
560 #endif
561 aredone = 1;
562 amii_clear_nhwindow( WIN_BASE );
563 CloseShWindow( cwin );
564 RandomWindow( pl_character );
565 return;
566 }
567 else if( code == 'q' || code == 'Q' )
568 {
569 CloseShWindow( cwin );
570 clearlocks();
571 exit_nhwindows(NULL);
572 terminate(0);
573 }
574 else
575 DisplayBeep( NULL );
576 break;
577
578 case GADGETUP:
579 switch( gd->GadgetID )
580 {
581 case 1: /* Random Character */
582 flags.initrole = randrole();
583 #if 0 /* OBSOLETE */
584 #ifdef TOURIST
585 strcpy( pl_character, roles[ rnd( 11 ) ] );
586 #else
587 strcpy( pl_character, roles[ rnd( 10 ) ] );
588 #endif
589 #endif
590 amii_clear_nhwindow( WIN_BASE );
591 CloseShWindow( cwin );
592 RandomWindow( pl_character );
593 return;
594
595 default:
596 pl_character[0] = gd->GadgetID;
597 break;
598 }
599 aredone = 1;
600 break;
601
602 case CLOSEWINDOW:
603 CloseShWindow( cwin );
604 clearlocks();
605 exit_nhwindows(NULL);
606 terminate(0);
607 break;
608 }
609 }
610 }
611 amii_clear_nhwindow( WIN_BASE );
612 CloseShWindow( cwin );
613 #endif /* Do not query user ... -jhsa */
614 }
615 #endif /* Function elsewhere */
616
617 #if 0 /* Unused ... -jhsa */
618
619 #include "NH:sys/amiga/randwin.c"
620
621 void
RandomWindow(name)622 RandomWindow( name )
623 char *name;
624 {
625 struct MsgPort *tport;
626 struct timerequest *trq;
627 static int once = 0;
628 struct Gadget *gd;
629 struct Window *w;
630 struct IntuiMessage *imsg;
631 int ticks = 0, aredone = 0, timerdone = 0;
632 long mask, got;
633
634 tport = CreateMsgPort();
635 trq = (struct timerequest *)CreateIORequest( tport, sizeof( *trq ) );
636 if( tport == NULL || trq == NULL )
637 {
638 allocerr:
639 if( tport ) DeleteMsgPort( tport );
640 if( trq ) DeleteIORequest( (struct IORequest *)trq );
641 Delay( 8 * 50 );
642 return;
643 }
644
645 if( OpenDevice( TIMERNAME, UNIT_VBLANK, (struct IORequest *)trq, 0L ) != 0 )
646 goto allocerr;
647
648 trq->tr_node.io_Command = TR_ADDREQUEST;
649 trq->tr_time.tv_secs = 8;
650 trq->tr_time.tv_micro = 0;
651
652 SendIO( (struct IORequest *)trq );
653
654 /* Place the name in the center of the screen */
655 Rnd_IText5.IText = name;
656 Rnd_IText6.LeftEdge = Rnd_IText4.LeftEdge +
657 (strlen(Rnd_IText4.IText)+1)*8;
658 Rnd_NewWindowStructure1.Width = (
659 (strlen( Rnd_IText2.IText )+1) * 8 ) +
660 HackScreen->WBorLeft + HackScreen->WBorRight;
661 Rnd_IText5.LeftEdge = (Rnd_NewWindowStructure1.Width -
662 (strlen(name)*8))/2;
663
664 gd = Rnd_NewWindowStructure1.FirstGadget;
665 gd->LeftEdge = (Rnd_NewWindowStructure1.Width - gd->Width)/2;
666 /* Chose correct modifier */
667 Rnd_IText6.IText = "a";
668 switch( *name )
669 {
670 case 'a': case 'e': case 'i': case 'o':
671 case 'u': case 'A': case 'E': case 'I':
672 case 'O': case 'U':
673 Rnd_IText6.IText = "an";
674 break;
675 }
676
677 if( !once )
678 {
679 if( bigscreen )
680 {
681 Rnd_NewWindowStructure1.TopEdge =
682 (HackScreen->Height/2) - (Rnd_NewWindowStructure1.Height/2);
683 }
684 for( gd = Rnd_NewWindowStructure1.FirstGadget; gd; gd = gd->NextGadget )
685 {
686 if( gd->GadgetID != 0 )
687 SetBorder( gd );
688 }
689 Rnd_NewWindowStructure1.IDCMPFlags |= VANILLAKEY;
690
691 once = 1;
692 }
693
694 if( WINVERS_AMIV )
695 {
696 #ifdef INTUI_NEW_LOOK
697 Rnd_NewWindowStructure1.Extension = wintags;
698 Rnd_NewWindowStructure1.Flags |= WFLG_NW_EXTENDED;
699 fillhook.h_Entry = (ULONG(*)())LayerFillHook;
700 fillhook.h_Data = (void *)-2;
701 fillhook.h_SubEntry = 0;
702 #endif
703 }
704
705 Rnd_NewWindowStructure1.Screen = HackScreen;
706 if( ( w = OpenShWindow( (void *)&Rnd_NewWindowStructure1 ) ) == NULL )
707 {
708 AbortIO( (struct IORequest *)trq );
709 WaitIO( (struct IORequest *)trq );
710 CloseDevice( (struct IORequest *)trq );
711 DeleteIORequest( (struct IORequest *) trq );
712 DeleteMsgPort( tport );
713 Delay( 50 * 8 );
714 return;
715 }
716
717 PrintIText( w->RPort, &Rnd_IntuiTextList1, 0, 0 );
718
719 mask = (1L << tport->mp_SigBit)|(1L << w->UserPort->mp_SigBit);
720 while( !aredone )
721 {
722 got = Wait( mask );
723 if( got & (1L << tport->mp_SigBit ) )
724 {
725 aredone = 1;
726 timerdone = 1;
727 GetMsg( tport );
728 }
729 while( w && ( imsg = (struct IntuiMessage *) GetMsg( w->UserPort ) ) )
730 {
731 switch( (long)imsg->Class )
732 {
733 /* Must be up for a little while... */
734 case INACTIVEWINDOW:
735 if( ticks >= 40 )
736 aredone = 1;
737 break;
738
739 case INTUITICKS:
740 ++ticks;
741 break;
742
743 case GADGETUP:
744 aredone = 1;
745 break;
746
747 case VANILLAKEY:
748 if(imsg->Code=='\n' || imsg->Code==' ' || imsg->Code=='\r')
749 aredone = 1;
750 break;
751 }
752 ReplyMsg( (struct Message *)imsg );
753 }
754 }
755
756 if( !timerdone )
757 {
758 AbortIO( (struct IORequest *)trq );
759 WaitIO( (struct IORequest *)trq );
760 }
761
762 CloseDevice( (struct IORequest *)trq );
763 DeleteIORequest( (struct IORequest *) trq );
764 DeleteMsgPort( tport );
765 if(w) CloseShWindow( w );
766 }
767 #endif /* Discarded randwin ... -jhsa */
768
769 /* this should probably not be needed (or be renamed)
770 void
771 flush_output(){} */
772
773 /* Read in an extended command - doing command line completion for
774 * when enough characters have been entered to make a unique command.
775 */
776 int
amii_get_ext_cmd(void)777 amii_get_ext_cmd( void )
778 {
779 menu_item *mip;
780 anything id;
781 struct amii_WinDesc *cw;
782 #ifdef EXTMENU
783 winid win;
784 int i;
785 char buf[256];
786 #endif
787 int colx;
788 int bottom = 0;
789 struct Window *w;
790 char obufp[ 100 ];
791 register char *bufp = obufp;
792 register int c;
793 int com_index, oindex;
794 int did_comp=0; /* did successful completion? */
795 int sel = -1;
796
797 if( WIN_MESSAGE == WIN_ERR || ( cw = amii_wins[ WIN_MESSAGE ] ) == NULL )
798 panic(winpanicstr, WIN_MESSAGE, "get_ext_cmd");
799 w = cw->win;
800 bottom = amii_msgborder( w );
801 colx = 3;
802
803 #ifdef EXTMENU
804 if (iflags.extmenu) {
805 win = amii_create_nhwindow( NHW_MENU );
806 amii_start_menu( win );
807 pline("#");
808 amii_putstr( WIN_MESSAGE, -1, " " );
809
810 for( i = 0; extcmdlist[ i ].ef_txt != NULL; ++i )
811 {
812 id.a_char = *extcmdlist[ i ].ef_txt;
813 sprintf( buf, "%-10s - %s ",
814 extcmdlist[ i ].ef_txt,
815 extcmdlist[ i ].ef_desc );
816 amii_add_menu( win, NO_GLYPH, &id, extcmdlist[i].ef_txt[0], 0, 0, buf, MENU_UNSELECTED);
817 }
818
819 amii_end_menu( win, (char*)0 );
820 sel = amii_select_menu( win, PICK_ONE, &mip );
821 amii_destroy_nhwindow( win );
822
823 if( sel == 1 )
824 {
825 sel = mip->item.a_char;
826 for( i = 0; extcmdlist[ i ].ef_txt != NULL; ++i )
827 {
828 if( sel == extcmdlist[i].ef_txt[0] )
829 break;
830 }
831
832 /* copy in the text */
833 if( extcmdlist[ i ].ef_txt != NULL )
834 {
835 amii_clear_nhwindow( WIN_MESSAGE );
836 (void) put_ext_cmd( (char *)extcmdlist[i].ef_txt, 0, cw, bottom );
837 return( i );
838 }
839 else
840 DisplayBeep( NULL );
841 }
842
843 return( -1 );
844 } else {
845 #else
846
847 amii_clear_nhwindow( WIN_MESSAGE ); /* Was NHW_MESSAGE */
848 if( scrollmsg )
849 {
850 pline("#");
851 amii_addtopl(" ");
852 }
853 else
854 {
855 pline("# ");
856 }
857
858 sel = -1;
859 while((c = WindowGetchar()) != EOF)
860 {
861 amii_curs( WIN_MESSAGE, colx, bottom );
862 if(c == '?' )
863 {
864 int win, i;
865 char buf[ 100 ];
866
867 if(did_comp){
868 while(bufp!=obufp)
869 {
870 bufp--;
871 amii_curs(WIN_MESSAGE, --colx, bottom);
872 Text(w->RPort,spaces,1);
873 amii_curs(WIN_MESSAGE,colx,bottom);
874 did_comp=0;
875 }
876 }
877
878 win = amii_create_nhwindow( NHW_MENU );
879 amii_start_menu( win );
880
881 for( i = 0; extcmdlist[ i ].ef_txt != NULL; ++i )
882 {
883 id.a_char = extcmdlist[i].ef_txt[0];
884 sprintf( buf, "%-10s - %s ",
885 extcmdlist[ i ].ef_txt,
886 extcmdlist[ i ].ef_desc );
887 amii_add_menu( win, NO_GLYPH, &id, extcmdlist[i].ef_txt[0], 0,
888 0, buf, MENU_UNSELECTED);
889 }
890
891 amii_end_menu( win, (char*)0 );
892 sel = amii_select_menu( win, PICK_ONE, &mip );
893 amii_destroy_nhwindow( win );
894
895 if( sel == 0 )
896 {
897 return( -1 );
898 }
899 else
900 {
901 sel = mip->item.a_char;
902 for( i = 0; extcmdlist[ i ].ef_txt != NULL; ++i )
903 {
904 if( sel == extcmdlist[i].ef_txt[0] )
905 break;
906 }
907
908 /* copy in the text */
909 if( extcmdlist[ i ].ef_txt != NULL )
910 {
911 amii_clear_nhwindow( WIN_MESSAGE );
912 strcpy( bufp = obufp, extcmdlist[ i ].ef_txt );
913 (void) put_ext_cmd( obufp, colx, cw, bottom );
914 return( i );
915 }
916 else
917 DisplayBeep( NULL );
918 }
919 }
920 else if(c == '\033')
921 {
922 return( -1 );
923 }
924 else if(c == '\b')
925 {
926 if(did_comp){
927 while(bufp!=obufp){
928 bufp--;
929 amii_curs(WIN_MESSAGE, --colx, bottom);
930 Text(w->RPort,spaces,1);
931 amii_curs(WIN_MESSAGE,colx,bottom);
932 did_comp=0;
933 sel = -1;
934 }
935 }
936 else if(bufp != obufp)
937 {
938 sel = -1;
939 bufp--;
940 amii_curs( WIN_MESSAGE, --colx, bottom);
941 Text( w->RPort, spaces, 1 );
942 amii_curs( WIN_MESSAGE, colx, bottom);
943 }
944 else
945 DisplayBeep( NULL );
946 }
947 else if( c == '\n' || c == '\r' )
948 {
949 return(sel);
950 }
951 else if( c >= ' ' && c < '\177')
952 {
953 /* avoid isprint() - some people don't have it
954 ' ' is not always a printing char */
955 *bufp = c;
956 bufp[1] = 0;
957 oindex = 0;
958 com_index = -1;
959
960 while(extcmdlist[oindex].ef_txt != NULL)
961 {
962 if(!strnicmp(obufp, (char *)extcmdlist[oindex].ef_txt, strlen(obufp)))
963 {
964 if(com_index == -1) /* No matches yet*/
965 com_index = oindex;
966 else /* More than 1 match */
967 com_index = -2;
968 }
969 oindex++;
970 }
971
972 if(com_index >= 0 && *obufp )
973 {
974 Strcpy(obufp, extcmdlist[com_index].ef_txt);
975 /* finish printing our string */
976 colx = put_ext_cmd( obufp, colx, cw, bottom );
977 bufp = obufp; /* reset it */
978 if(strlen(obufp) < BUFSZ-1 && strlen(obufp) < COLNO)
979 bufp += strlen(obufp);
980 did_comp=1;
981 sel = com_index;
982 }
983 else
984 {
985 colx = put_ext_cmd( obufp, colx, cw, bottom );
986 if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
987 bufp++;
988 }
989 }
990 else if(c == ('X'-64) || c == '\177')
991 {
992 colx = 0;
993 amii_clear_nhwindow( WIN_MESSAGE );
994 pline( "# " );
995 bufp = obufp;
996 } else
997 DisplayBeep( NULL );
998 }
999 return(-1);
1000 #endif
1001 }
1002
1003 static int
1004 put_ext_cmd( obufp, colx, cw, bottom )
1005 char *obufp;
1006 int colx, bottom;
1007 struct amii_WinDesc *cw;
1008 {
1009 struct Window *w = cw->win;
1010 char *t;
1011
1012 t = (char *)alloc( strlen( obufp ) + 7 );
1013 if( t != NULL )
1014 {
1015 if( scrollmsg )
1016 {
1017 sprintf( t, "xxx%s", obufp );
1018 t[0] = 1;
1019 t[1] = 1;
1020 t[2] = '#';
1021 amii_curs( WIN_MESSAGE, 0, bottom);
1022 SetAPen( w->RPort, C_WHITE );
1023 Text(w->RPort, "># ", 3 );
1024 /* SetAPen( w->RPort, C_BLACK ); */ /* Black text on black screen doesn't look too well ... -jhsa */
1025 Text(w->RPort, t+3, strlen( t ) - 3 );
1026 }
1027 else
1028 {
1029 sprintf( t, "# %s", obufp );
1030 amii_curs( WIN_MESSAGE, 0, bottom);
1031 SetAPen( w->RPort, C_WHITE );
1032 Text(w->RPort, t, strlen( t ) );
1033 }
1034 if( scrollmsg )
1035 SetAPen( w->RPort, C_WHITE );
1036 if( cw->data[ cw->maxrow - 1 ] )
1037 free( cw->data[ cw->maxrow - 1 ] );
1038 cw->data[ cw->maxrow - 1 ] = t;
1039 }
1040 else
1041 {
1042 amii_curs( WIN_MESSAGE, 0, bottom);
1043 SetAPen( w->RPort, C_WHITE );
1044 Text(w->RPort, "# ", 2 );
1045 /* SetAPen( w->RPort, C_BLACK ); */ /* Black on black ... -jhsa */
1046 Text(w->RPort, obufp, strlen( obufp ) );
1047 SetAPen( w->RPort, C_WHITE );
1048 }
1049 amii_curs( WIN_MESSAGE, colx = strlen( obufp ) + 3 + ( scrollmsg != 0 ), bottom);
1050 return( colx );
1051 }
1052
1053 /* Ask a question and get a response */
1054
1055 char amii_yn_function(query, resp, def)
1056 const char *query,*resp;
1057 char def;
1058 /*
1059 * Generic yes/no function. 'def' is the default (returned by space or
1060 * return; 'esc' returns 'q', or 'n', or the default, depending on
1061 * what's in the string. The 'query' string is printed before the user
1062 * is asked about the string.
1063 * If resp is NULL, any single character is accepted and returned.
1064 * If not-NULL, only characters in it are allowed (exceptions: the
1065 * quitchars are always allowed, and if it contains '#' then digits
1066 * are allowed); if it includes an <esc>, anything beyond that won't
1067 * be shown in the prompt to the user but will be acceptable as input.
1068 */
1069 {
1070 register char q;
1071 char rtmp[40];
1072 boolean digit_ok, allow_num;
1073 char prompt[QBUFSZ];
1074 register struct amii_WinDesc *cw;
1075
1076 if( cw = amii_wins[ WIN_MESSAGE ] )
1077 cw->disprows = 0;
1078 if (resp) {
1079 char *rb, respbuf[QBUFSZ];
1080
1081 allow_num = (index(resp, '#') != 0);
1082 Strcpy(respbuf, resp);
1083 /* any acceptable responses that follow <esc> aren't displayed */
1084 if ((rb = index(respbuf, '\033')) != 0) *rb = '\0';
1085 Sprintf(prompt, "%s [%s] ", query, respbuf);
1086 if (def) Sprintf(eos(prompt), "(%c) ", def);
1087 pline("%s", prompt);
1088 } else {
1089 amii_putstr(WIN_MESSAGE, 0, query);
1090 cursor_on(WIN_MESSAGE);
1091 q = WindowGetchar();
1092 cursor_off(WIN_MESSAGE);
1093 *rtmp = q;
1094 rtmp[ 1 ] = 0;
1095 amii_addtopl(rtmp);
1096 goto clean_up;
1097 }
1098
1099 do { /* loop until we get valid input */
1100 cursor_on(WIN_MESSAGE);
1101 q = lowc(WindowGetchar());
1102 cursor_off(WIN_MESSAGE);
1103 #if 0
1104 /* fix for PL2 */
1105 if (q == '\020') { /* ctrl-P */
1106 if(!doprev) (void) tty_doprev_message(); /* need two initially */
1107 (void) tty_doprev_message();
1108 q = (char)0;
1109 doprev = 1;
1110 continue;
1111 } else if(doprev) {
1112 tty_clear_nhwindow(WIN_MESSAGE);
1113 cw->maxcol = cw->maxrow;
1114 doprev = 0;
1115 amii_addtopl(prompt);
1116 continue;
1117 }
1118 #endif
1119 digit_ok = allow_num && isdigit(q);
1120 if (q == '\033') {
1121 if (index(resp, 'q'))
1122 q = 'q';
1123 else if (index(resp, 'n'))
1124 q = 'n';
1125 else
1126 q = def;
1127 break;
1128 } else if (index(quitchars, q)) {
1129 q = def;
1130 break;
1131 }
1132 if (!index(resp, q) && !digit_ok) {
1133 amii_bell();
1134 q = (char)0;
1135 } else if (q == '#' || digit_ok) {
1136 char z, digit_string[2];
1137 int n_len = 0;
1138 long value = 0;
1139 amii_addtopl("#"), n_len++;
1140 digit_string[1] = '\0';
1141 if (q != '#') {
1142 digit_string[0] = q;
1143 amii_addtopl(digit_string), n_len++;
1144 value = q - '0';
1145 q = '#';
1146 }
1147 do { /* loop until we get a non-digit */
1148 cursor_on(WIN_MESSAGE);
1149 z = lowc(WindowGetchar());
1150 cursor_off(WIN_MESSAGE);
1151 if (isdigit(z)) {
1152 value = (10 * value) + (z - '0');
1153 if (value < 0) break; /* overflow: try again */
1154 digit_string[0] = z;
1155 amii_addtopl(digit_string), n_len++;
1156 } else if (z == 'y' || index(quitchars, z)) {
1157 if (z == '\033') value = -1; /* abort */
1158 z = '\n'; /* break */
1159 } else if ( z == '\b') {
1160 if (n_len <= 1) { value = -1; break; }
1161 else { value /= 10; removetopl(1), n_len--; }
1162 } else {
1163 value = -1; /* abort */
1164 amii_bell();
1165 break;
1166 }
1167 } while (z != '\n');
1168 if (value > 0) yn_number = value;
1169 else if (value == 0) q = 'n'; /* 0 => "no" */
1170 else { /* remove number from top line, then try again */
1171 removetopl(n_len), n_len = 0;
1172 q = '\0';
1173 }
1174 }
1175 } while(!q);
1176
1177 if (q != '#' && q != '\033') {
1178 Sprintf(rtmp, "%c", q);
1179 amii_addtopl(rtmp);
1180 }
1181 clean_up:
1182 cursor_off(WIN_MESSAGE);
1183 clear_nhwindow(WIN_MESSAGE);
1184 return q;
1185 }
1186
1187 void
1188 amii_display_file(fn, complain)
1189 const char *fn;
1190 boolean complain;
1191 {
1192 register struct amii_WinDesc *cw;
1193 register int win;
1194 register dlb *fp;
1195 register char *t;
1196 register char buf[ 200 ];
1197
1198 if( fn == NULL )
1199 panic("NULL file name in display_file()");
1200
1201 if( ( fp = dlb_fopen( fn, RDTMODE ) ) == (dlb *)NULL )
1202 {
1203 if (complain) {
1204 sprintf( buf, "Can't display %s: %s", fn,
1205 #if defined(_DCC) || defined(__GNUC__)
1206 strerror(errno)
1207 #else
1208 # ifdef __SASC_60
1209 __sys_errlist[ errno ]
1210 # else
1211 sys_errlist[ errno ]
1212 # endif
1213 #endif
1214 );
1215 amii_addtopl( buf );
1216 }
1217 return;
1218 }
1219 win = amii_create_nhwindow( NHW_TEXT );
1220
1221 /* Set window title to file name */
1222 if( cw = amii_wins[ win ] )
1223 cw->morestr = (char *)fn;
1224
1225 while( dlb_fgets( buf, sizeof( buf ), fp ) != NULL )
1226 {
1227 if( t = index( buf, '\n' ) )
1228 *t = 0;
1229 amii_putstr( win, 0, buf );
1230 }
1231 dlb_fclose( fp );
1232
1233 /* If there were lines in the file, display those lines */
1234
1235 if( amii_wins[ win ]->cury > 0 )
1236 amii_display_nhwindow( win, TRUE );
1237
1238 amii_wins[win]->morestr = NULL; /* don't free title string */
1239 amii_destroy_nhwindow( win );
1240 }
1241
1242 /* Put a 3-D motif border around the gadget. String gadgets or those
1243 * which do not have highlighting are rendered down. Boolean gadgets
1244 * are rendered in the up position by default.
1245 */
1246
1247 void
1248 SetBorder( gd )
1249 register struct Gadget *gd;
1250 {
1251 register struct Border *bp;
1252 register short *sp;
1253 register int i, inc = -1, dec = -1;
1254 int borders = 6;
1255 int hipen = flags.amii_dripens[ SHINEPEN ], shadowpen = flags.amii_dripens[ SHADOWPEN ];
1256 #ifdef INTUI_NEW_LOOK
1257 struct DrawInfo *dip;
1258 #endif
1259
1260 #ifdef INTUI_NEW_LOOK
1261 if( IntuitionBase->LibNode.lib_Version >= 37 )
1262 {
1263 if( dip = GetScreenDrawInfo( HackScreen ) )
1264 {
1265 hipen = dip->dri_Pens[ SHINEPEN ];
1266 shadowpen = dip->dri_Pens[ SHADOWPEN ];
1267 FreeScreenDrawInfo( HackScreen, dip );
1268 }
1269 }
1270 #endif
1271 /* Allocate two border structures one for up image and one for down
1272 * image, plus vector arrays for the border lines.
1273 */
1274
1275 if( gd->GadgetType == STRGADGET )
1276 borders = 12;
1277
1278 if( ( bp = (struct Border *)alloc( ( ( sizeof( struct Border ) * 2 ) +
1279 ( sizeof( short ) * borders ) ) * 2 ) ) == NULL )
1280 {
1281 return;
1282 }
1283
1284 /* For a string gadget, we expand the border beyond the area where
1285 * the text will be entered.
1286 */
1287
1288 /* Remove any special rendering flags to avoid confusing intuition
1289 */
1290
1291 gd->Flags &= ~(GADGHIGHBITS|GADGIMAGE);
1292
1293 sp = (short *)(bp + 4);
1294 if( gd->GadgetType == STRGADGET || ( gd->GadgetType == BOOLGADGET &&
1295 ( gd->Flags & GADGHIGHBITS ) == GADGHNONE ) )
1296 {
1297 sp[0] = -1;
1298 sp[1] = gd->Height - 1;
1299 sp[2] = -1;
1300 sp[3] = -1;
1301 sp[4] = gd->Width - 1;
1302 sp[5] = -1;
1303
1304 sp[6] = gd->Width + 1;
1305 sp[7] = -2;
1306 sp[8] = gd->Width + 1;
1307 sp[9] = gd->Height + 1;
1308 sp[10] = -2;
1309 sp[11] = gd->Height + 1;
1310
1311 sp[12] = -2;
1312 sp[13] = gd->Height;
1313 sp[14] = -2;
1314 sp[15] = -2;
1315 sp[16] = gd->Width;
1316 sp[17] = -2;
1317 sp[18] = gd->Width;
1318 sp[19] = gd->Height;
1319 sp[20] = -2;
1320 sp[21] = gd->Height;
1321
1322 for( i = 0; i < 3; ++i )
1323 {
1324 bp[ i ].LeftEdge = bp[ i ].TopEdge = -1;
1325 bp[ i ].FrontPen = ( i == 0 || i == 1 ) ? shadowpen : hipen;
1326
1327 /* Have to use JAM2 so that the old colors disappear. */
1328 bp[ i ].BackPen = C_BLACK;
1329 bp[ i ].DrawMode = JAM2;
1330 bp[ i ].Count = ( i == 0 || i == 1 ) ? 3 : 5;
1331 bp[ i ].XY = &sp[ i*6 ];
1332 bp[ i ].NextBorder = ( i == 2 ) ? NULL : &bp[ i + 1 ];
1333 }
1334
1335 /* bp[0] and bp[1] two pieces for the up image */
1336 gd->GadgetRender = (APTR) bp;
1337
1338 /* No image change for select */
1339 gd->SelectRender = (APTR) bp;
1340
1341 gd->LeftEdge++;
1342 gd->TopEdge++;
1343 gd->Flags |= GADGHCOMP;
1344 }
1345 else
1346 {
1347 /* Create the border vector values for up and left side, and
1348 * also the lower and right side.
1349 */
1350
1351 sp[0] = dec;
1352 sp[1] = gd->Height + inc;
1353 sp[2] = dec;
1354 sp[3] = dec;
1355 sp[4] = gd->Width + inc;
1356 sp[5] = dec;
1357
1358 sp[6] = gd->Width + inc;
1359 sp[7] = dec;
1360 sp[8] = gd->Width + inc;
1361 sp[9] = gd->Height + inc;
1362 sp[10] = dec;
1363 sp[11] = gd->Height + inc;
1364
1365 /* We are creating 4 sets of borders, the two sides of the
1366 * rectangle share the border vectors with the opposite image,
1367 * but specify different colors.
1368 */
1369
1370 for( i = 0; i < 4; ++i )
1371 {
1372 bp[ i ].TopEdge = bp[ i ].LeftEdge = 0;
1373
1374 /* A GADGHNONE is always down */
1375
1376 if( gd->GadgetType == BOOLGADGET &&
1377 ( gd->Flags & GADGHIGHBITS ) != GADGHNONE )
1378 {
1379 bp[ i ].FrontPen =
1380 ( i == 1 || i == 2 ) ? shadowpen : hipen;
1381 }
1382 else
1383 {
1384 bp[ i ].FrontPen =
1385 ( i == 1 || i == 3 ) ? hipen : shadowpen;
1386 }
1387
1388 /* Have to use JAM2 so that the old colors disappear. */
1389 bp[ i ].BackPen = C_BLACK;
1390 bp[ i ].DrawMode = JAM2;
1391 bp[ i ].Count = 3;
1392 bp[ i ].XY = &sp[ 6 * ((i &1) != 0) ];
1393 bp[ i ].NextBorder =
1394 ( i == 1 || i == 3 ) ? NULL : &bp[ i + 1 ];
1395 }
1396
1397 /* bp[0] and bp[1] two pieces for the up image */
1398 gd->GadgetRender = (APTR) bp;
1399
1400 /* bp[2] and bp[3] two pieces for the down image */
1401 gd->SelectRender = (APTR) (bp + 2);
1402 gd->Flags |= GADGHIMAGE;
1403 }
1404 }
1405
1406 /* Following function copied from wintty.c */
1407 /* Modified slightly to fit amiga needs */
1408
1409 void
1410 amii_player_selection()
1411 {
1412 int i, k, n;
1413 char pick4u = 'n', thisch, lastch = 0;
1414 char pbuf[QBUFSZ], plbuf[QBUFSZ], rolenamebuf[QBUFSZ];
1415 winid win;
1416 anything any;
1417 menu_item *selected = 0;
1418
1419 rigid_role_checks();
1420
1421 /* Should we randomly pick for the player? */
1422 if (flags.initrole == ROLE_NONE || flags.initrace == ROLE_NONE ||
1423 flags.initgend == ROLE_NONE || flags.initalign == ROLE_NONE) {
1424 char *prompt = build_plselection_prompt(pbuf, QBUFSZ, flags.initrole,
1425 flags.initrace, flags.initgend, flags.initalign);
1426 pline("%s", prompt);
1427 do { /* loop until we get valid input */
1428 cursor_on(WIN_MESSAGE);
1429 pick4u = lowc(WindowGetchar());
1430 cursor_off(WIN_MESSAGE);
1431 if (index(quitchars, pick4u)) pick4u = 'y';
1432 } while(!index(ynqchars, pick4u));
1433 pbuf[0] = pick4u;
1434 pbuf[1] = 0;
1435 amii_addtopl(pbuf);
1436
1437 if (pick4u != 'y' && pick4u != 'n') {
1438 give_up: /* Quit */
1439 if (selected) free((genericptr_t) selected);
1440 clearlocks();
1441 exit_nhwindows(NULL);
1442 terminate(0);
1443 /*NOTREACHED*/
1444 return;
1445 }
1446 }
1447
1448 (void) root_plselection_prompt(plbuf, QBUFSZ - 1,
1449 flags.initrole, flags.initrace, flags.initgend, flags.initalign);
1450
1451 /* Select a role, if necessary */
1452 /* we'll try to be compatible with pre-selected race/gender/alignment,
1453 * but may not succeed */
1454 if (flags.initrole < 0) {
1455 /* Process the choice */
1456 if (pick4u == 'y' || flags.initrole == ROLE_RANDOM || flags.randomall) {
1457 /* Pick a random role */
1458 flags.initrole = pick_role(flags.initrace, flags.initgend,
1459 flags.initalign, PICK_RANDOM);
1460 if (flags.initrole < 0) {
1461 amii_putstr(WIN_MESSAGE, 0, "Incompatible role!");
1462 flags.initrole = randrole();
1463 }
1464 } else {
1465 /* Prompt for a role */
1466 win = create_nhwindow(NHW_MENU);
1467 start_menu(win);
1468 any.a_void = 0; /* zero out all bits */
1469 for (i = 0; roles[i].name.m; i++) {
1470 if (ok_role(i, flags.initrace, flags.initgend,
1471 flags.initalign)) {
1472 any.a_int = i+1; /* must be non-zero */
1473 thisch = lowc(roles[i].name.m[0]);
1474 if (thisch == lastch) thisch = highc(thisch);
1475 if (flags.initgend != ROLE_NONE && flags.initgend != ROLE_RANDOM) {
1476 if (flags.initgend == 1 && roles[i].name.f)
1477 Strcpy(rolenamebuf, roles[i].name.f);
1478 else
1479 Strcpy(rolenamebuf, roles[i].name.m);
1480 } else {
1481 if (roles[i].name.f) {
1482 Strcpy(rolenamebuf, roles[i].name.m);
1483 Strcat(rolenamebuf, "/");
1484 Strcat(rolenamebuf, roles[i].name.f);
1485 } else
1486 Strcpy(rolenamebuf, roles[i].name.m);
1487 }
1488 add_menu(win, NO_GLYPH, &any, thisch,
1489 0, ATR_NONE, an(rolenamebuf), MENU_UNSELECTED);
1490 lastch = thisch;
1491 }
1492 }
1493 any.a_int = pick_role(flags.initrace, flags.initgend,
1494 flags.initalign, PICK_RANDOM)+1;
1495 if (any.a_int == 0) /* must be non-zero */
1496 any.a_int = randrole()+1;
1497 add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE,
1498 "Random", MENU_UNSELECTED);
1499 any.a_int = i+1; /* must be non-zero */
1500 add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE,
1501 "Quit", MENU_UNSELECTED);
1502 Sprintf(pbuf, "Pick a role for your %s", plbuf);
1503 end_menu(win, pbuf);
1504 n = select_menu(win, PICK_ONE, &selected);
1505 destroy_nhwindow(win);
1506
1507 /* Process the choice */
1508 if (n != 1 || selected[0].item.a_int == any.a_int)
1509 goto give_up; /* Selected quit */
1510
1511 flags.initrole = selected[0].item.a_int - 1;
1512 free((genericptr_t) selected), selected = 0;
1513 }
1514 (void) root_plselection_prompt(plbuf, QBUFSZ - 1,
1515 flags.initrole, flags.initrace, flags.initgend, flags.initalign);
1516 }
1517
1518 /* Select a race, if necessary */
1519 /* force compatibility with role, try for compatibility with
1520 * pre-selected gender/alignment */
1521 if (flags.initrace < 0 || !validrace(flags.initrole, flags.initrace)) {
1522 /* pre-selected race not valid */
1523 if (pick4u == 'y' || flags.initrace == ROLE_RANDOM || flags.randomall) {
1524 flags.initrace = pick_race(flags.initrole, flags.initgend,
1525 flags.initalign, PICK_RANDOM);
1526 if (flags.initrace < 0) {
1527 amii_putstr(WIN_MESSAGE, 0, "Incompatible race!");
1528 flags.initrace = randrace(flags.initrole);
1529 }
1530 } else { /* pick4u == 'n' */
1531 /* Count the number of valid races */
1532 n = 0; /* number valid */
1533 k = 0; /* valid race */
1534 for (i = 0; races[i].noun; i++) {
1535 if (ok_race(flags.initrole, i, flags.initgend,
1536 flags.initalign)) {
1537 n++;
1538 k = i;
1539 }
1540 }
1541 if (n == 0) {
1542 for (i = 0; races[i].noun; i++) {
1543 if (validrace(flags.initrole, i)) {
1544 n++;
1545 k = i;
1546 }
1547 }
1548 }
1549
1550 /* Permit the user to pick, if there is more than one */
1551 if (n > 1) {
1552 win = create_nhwindow(NHW_MENU);
1553 start_menu(win);
1554 any.a_void = 0; /* zero out all bits */
1555 for (i = 0; races[i].noun; i++)
1556 if (ok_race(flags.initrole, i, flags.initgend,
1557 flags.initalign)) {
1558 any.a_int = i+1; /* must be non-zero */
1559 add_menu(win, NO_GLYPH, &any, races[i].noun[0],
1560 0, ATR_NONE, races[i].noun, MENU_UNSELECTED);
1561 }
1562 any.a_int = pick_race(flags.initrole, flags.initgend,
1563 flags.initalign, PICK_RANDOM)+1;
1564 if (any.a_int == 0) /* must be non-zero */
1565 any.a_int = randrace(flags.initrole)+1;
1566 add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE,
1567 "Random", MENU_UNSELECTED);
1568 any.a_int = i+1; /* must be non-zero */
1569 add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE,
1570 "Quit", MENU_UNSELECTED);
1571 Sprintf(pbuf, "Pick the race of your %s", plbuf);
1572 end_menu(win, pbuf);
1573 n = select_menu(win, PICK_ONE, &selected);
1574 destroy_nhwindow(win);
1575 if (n != 1 || selected[0].item.a_int == any.a_int)
1576 goto give_up; /* Selected quit */
1577
1578 k = selected[0].item.a_int - 1;
1579 free((genericptr_t) selected), selected = 0;
1580 }
1581 flags.initrace = k;
1582 }
1583 (void) root_plselection_prompt(plbuf, QBUFSZ - 1,
1584 flags.initrole, flags.initrace, flags.initgend, flags.initalign);
1585 }
1586
1587 /* Select a gender, if necessary */
1588 /* force compatibility with role/race, try for compatibility with
1589 * pre-selected alignment */
1590 if (flags.initgend < 0 || !validgend(flags.initrole, flags.initrace,
1591 flags.initgend)) {
1592 /* pre-selected gender not valid */
1593 if (pick4u == 'y' || flags.initgend == ROLE_RANDOM || flags.randomall) {
1594 flags.initgend = pick_gend(flags.initrole, flags.initrace,
1595 flags.initalign, PICK_RANDOM);
1596 if (flags.initgend < 0) {
1597 amii_putstr(WIN_MESSAGE, 0, "Incompatible gender!");
1598 flags.initgend = randgend(flags.initrole, flags.initrace);
1599 }
1600 } else { /* pick4u == 'n' */
1601 /* Count the number of valid genders */
1602 n = 0; /* number valid */
1603 k = 0; /* valid gender */
1604 for (i = 0; i < ROLE_GENDERS; i++) {
1605 if (ok_gend(flags.initrole, flags.initrace, i,
1606 flags.initalign)) {
1607 n++;
1608 k = i;
1609 }
1610 }
1611 if (n == 0) {
1612 for (i = 0; i < ROLE_GENDERS; i++) {
1613 if (validgend(flags.initrole, flags.initrace, i)) {
1614 n++;
1615 k = i;
1616 }
1617 }
1618 }
1619
1620 /* Permit the user to pick, if there is more than one */
1621 if (n > 1) {
1622 win = create_nhwindow(NHW_MENU);
1623 start_menu(win);
1624 any.a_void = 0; /* zero out all bits */
1625 for (i = 0; i < ROLE_GENDERS; i++)
1626 if (ok_gend(flags.initrole, flags.initrace, i,
1627 flags.initalign)) {
1628 any.a_int = i+1;
1629 add_menu(win, NO_GLYPH, &any, genders[i].adj[0],
1630 0, ATR_NONE, genders[i].adj, MENU_UNSELECTED);
1631 }
1632 any.a_int = pick_gend(flags.initrole, flags.initrace,
1633 flags.initalign, PICK_RANDOM)+1;
1634 if (any.a_int == 0) /* must be non-zero */
1635 any.a_int = randgend(flags.initrole, flags.initrace)+1;
1636 add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE,
1637 "Random", MENU_UNSELECTED);
1638 any.a_int = i+1; /* must be non-zero */
1639 add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE,
1640 "Quit", MENU_UNSELECTED);
1641 Sprintf(pbuf, "Pick the gender of your %s", plbuf);
1642 end_menu(win, pbuf);
1643 n = select_menu(win, PICK_ONE, &selected);
1644 destroy_nhwindow(win);
1645 if (n != 1 || selected[0].item.a_int == any.a_int)
1646 goto give_up; /* Selected quit */
1647
1648 k = selected[0].item.a_int - 1;
1649 free((genericptr_t) selected), selected = 0;
1650 }
1651 flags.initgend = k;
1652 }
1653 (void) root_plselection_prompt(plbuf, QBUFSZ - 1,
1654 flags.initrole, flags.initrace, flags.initgend, flags.initalign);
1655 }
1656
1657 /* Select an alignment, if necessary */
1658 /* force compatibility with role/race/gender */
1659 if (flags.initalign < 0 || !validalign(flags.initrole, flags.initrace,
1660 flags.initalign)) {
1661 /* pre-selected alignment not valid */
1662 if (pick4u == 'y' || flags.initalign == ROLE_RANDOM || flags.randomall) {
1663 flags.initalign = pick_align(flags.initrole, flags.initrace,
1664 flags.initgend, PICK_RANDOM);
1665 if (flags.initalign < 0) {
1666 amii_putstr(WIN_MESSAGE, 0, "Incompatible alignment!");
1667 flags.initalign = randalign(flags.initrole, flags.initrace);
1668 }
1669 } else { /* pick4u == 'n' */
1670 /* Count the number of valid alignments */
1671 n = 0; /* number valid */
1672 k = 0; /* valid alignment */
1673 for (i = 0; i < ROLE_ALIGNS; i++) {
1674 if (ok_align(flags.initrole, flags.initrace, flags.initgend,
1675 i)) {
1676 n++;
1677 k = i;
1678 }
1679 }
1680 if (n == 0) {
1681 for (i = 0; i < ROLE_ALIGNS; i++) {
1682 if (validalign(flags.initrole, flags.initrace, i)) {
1683 n++;
1684 k = i;
1685 }
1686 }
1687 }
1688
1689 /* Permit the user to pick, if there is more than one */
1690 if (n > 1) {
1691 win = create_nhwindow(NHW_MENU);
1692 start_menu(win);
1693 any.a_void = 0; /* zero out all bits */
1694 for (i = 0; i < ROLE_ALIGNS; i++)
1695 if (ok_align(flags.initrole, flags.initrace,
1696 flags.initgend, i)) {
1697 any.a_int = i+1;
1698 add_menu(win, NO_GLYPH, &any, aligns[i].adj[0],
1699 0, ATR_NONE, aligns[i].adj, MENU_UNSELECTED);
1700 }
1701 any.a_int = pick_align(flags.initrole, flags.initrace,
1702 flags.initgend, PICK_RANDOM)+1;
1703 if (any.a_int == 0) /* must be non-zero */
1704 any.a_int = randalign(flags.initrole, flags.initrace)+1;
1705 add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE,
1706 "Random", MENU_UNSELECTED);
1707 any.a_int = i+1; /* must be non-zero */
1708 add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE,
1709 "Quit", MENU_UNSELECTED);
1710 Sprintf(pbuf, "Pick the alignment of your %s", plbuf);
1711 end_menu(win, pbuf);
1712 n = select_menu(win, PICK_ONE, &selected);
1713 destroy_nhwindow(win);
1714 if (n != 1 || selected[0].item.a_int == any.a_int)
1715 goto give_up; /* Selected quit */
1716
1717 k = selected[0].item.a_int - 1;
1718 free((genericptr_t) selected), selected = 0;
1719 }
1720 flags.initalign = k;
1721 }
1722 }
1723 /* Success! */
1724 }
1725 #endif /* AMIGA_INTUITION */
1726