]> 4ch.mooo.com Git - 16.git/blob - 16/keen456/KEEN4-6/CK_TEXT.C
extrcted keen code remake
[16.git] / 16 / keen456 / KEEN4-6 / CK_TEXT.C
1 /* Reconstructed Commander Keen 4-6 Source Code\r
2  * Copyright (C) 2021 K1n9_Duk3\r
3  *\r
4  * This file is primarily based on:\r
5  * Wolfenstein 3-D Source Code\r
6  * Copyright (C) 1992 id Software\r
7  *\r
8  * This program is free software; you can redistribute it and/or modify\r
9  * it under the terms of the GNU General Public License as published by\r
10  * the Free Software Foundation; either version 2 of the License, or\r
11  * (at your option) any later version.\r
12  *\r
13  * This program is distributed in the hope that it will be useful,\r
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
16  * GNU General Public License for more details.\r
17  *\r
18  * You should have received a copy of the GNU General Public License along\r
19  * with this program; if not, write to the Free Software Foundation, Inc.,\r
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
21  */\r
22 \r
23 #include "CK_DEF.H"\r
24 \r
25 /*\r
26 =============================================================================\r
27 \r
28 TEXT FORMATTING COMMANDS\r
29 ------------------------\r
30 ^C<hex digit>                   Change text color\r
31 ^E[enter]                               End of layout (all pages)\r
32 ^G<y>,<x>,<pic>[enter]  Draw a graphic and push margins\r
33 ^P[enter]                               start new page, must be the first chars in a layout\r
34 ^L<x>,<y>[ENTER]                Locate to a specific spot, x in pixels, y in lines\r
35 \r
36 =============================================================================\r
37 */\r
38 \r
39 /*\r
40 =============================================================================\r
41 \r
42                                                  LOCAL CONSTANTS\r
43 \r
44 =============================================================================\r
45 */\r
46 \r
47 #if GRMODE == CGAGR\r
48 #ifdef KEEN5\r
49 #define BACKCOLOR 2     // CGA magenta\r
50 #else\r
51 #define BACKCOLOR WHITE\r
52 #endif\r
53 #else\r
54 #define BACKCOLOR RED\r
55 #endif\r
56 \r
57 #define WORDLIMIT 80\r
58 #define FONTHEIGHT 10\r
59 #define TOPMARGIN 10\r
60 #define BOTTOMMARGIN 10\r
61 #define LEFTMARGIN 10\r
62 #define RIGHTMARGIN 10\r
63 #define PICMARGIN 8\r
64 #define SPACEWIDTH 7\r
65 #define TEXTROWS ((200-TOPMARGIN-BOTTOMMARGIN)/FONTHEIGHT)\r
66 #define SCREENPIXWIDTH 320\r
67 #define SCREENMID (SCREENPIXWIDTH/2)\r
68 \r
69 /*\r
70 =============================================================================\r
71 \r
72                                                  LOCAL VARIABLES\r
73 \r
74 =============================================================================\r
75 */\r
76 \r
77 Sint16 pagenum,numpages;\r
78 Uint16 leftmargin[TEXTROWS],rightmargin[TEXTROWS];\r
79 char far *text;\r
80 Uint16 rowon;\r
81 Sint16 picx,picy,picnum,picdelay;\r
82 boolean layoutdone;\r
83 \r
84 Sint16 helpmenupos;\r
85 \r
86 //===========================================================================\r
87 \r
88 /*\r
89 =====================\r
90 =\r
91 = RipToEOL\r
92 =\r
93 =====================\r
94 */\r
95 \r
96 void RipToEOL(void)\r
97 {\r
98         while (*text++ != '\n');\r
99 }\r
100 \r
101 \r
102 /*\r
103 =====================\r
104 =\r
105 = ParseNumber\r
106 =\r
107 =====================\r
108 */\r
109 \r
110 Sint16 ParseNumber(void)\r
111 {\r
112         char c, buffer[80];\r
113         char *bufptr;\r
114 \r
115 //\r
116 // scan until a number is found\r
117 //\r
118         c = *text;\r
119         while (c < '0' || c > '9')\r
120                 c = *++text;\r
121 \r
122 //\r
123 // copy the number out\r
124 //\r
125         bufptr = buffer;\r
126         do\r
127         {\r
128                 *bufptr = c;\r
129                 bufptr++;\r
130                 text++;\r
131                 c = *text;\r
132         } while (c >= '0' && c <= '9');\r
133         *bufptr = 0;\r
134 \r
135         return atoi(buffer);\r
136 }\r
137 \r
138 \r
139 /*\r
140 =====================\r
141 =\r
142 = ParsePicCommand\r
143 =\r
144 = Call with text pointing just after a ^P\r
145 = Upon exit text points to the start of next line\r
146 =\r
147 =====================\r
148 */\r
149 \r
150 void ParsePicCommand(void)\r
151 {\r
152         picy = ParseNumber();\r
153         picx = ParseNumber();\r
154         picnum = ParseNumber();\r
155         RipToEOL();\r
156 }\r
157 \r
158 void ParseTimedCommand(void)\r
159 {\r
160         picy = ParseNumber();\r
161         picx = ParseNumber();\r
162         picnum = ParseNumber();\r
163         picdelay = ParseNumber();\r
164         RipToEOL();\r
165 }\r
166 \r
167 /*\r
168 =====================\r
169 =\r
170 = TimedPicCommand\r
171 =\r
172 = Call with text pointing just after a ^P\r
173 = Upon exit text points to the start of next line\r
174 =\r
175 =====================\r
176 */\r
177 \r
178 void TimedPicCommand(void)\r
179 {\r
180         ParseTimedCommand();\r
181 \r
182 //\r
183 // update the screen, and wait for time delay\r
184 //\r
185 #if GRMODE == CGAGR\r
186         VW_UpdateScreen();\r
187 #else\r
188         VW_WaitVBL(1);\r
189         VW_ScreenToScreen(bufferofs, displayofs, 40, 200);\r
190 #endif\r
191 \r
192 //\r
193 // wait for time\r
194 //\r
195         TimeCount = 0;\r
196         while (picdelay > TimeCount)\r
197         ;\r
198 \r
199 //\r
200 // draw pic\r
201 //\r
202         VWB_DrawPic(picx & ~7, picy, picnum);\r
203 }\r
204 \r
205 \r
206 /*\r
207 =====================\r
208 =\r
209 = HandleCommand\r
210 =\r
211 =====================\r
212 */\r
213 \r
214 void HandleCommand(void)\r
215 {\r
216         Sint16 i,margin,top,bottom;\r
217         Sint16 picwidth,picheight,picmid;\r
218 \r
219         switch (toupper(*(++text)))\r
220         {\r
221         case 'B':\r
222                 picy = ParseNumber();\r
223                 picx = ParseNumber();\r
224                 picwidth = ParseNumber();\r
225                 picheight = ParseNumber();\r
226                 VWB_Bar(picx, picy, picwidth, picheight, BACKCOLOR);\r
227                 RipToEOL();\r
228                 break;\r
229 \r
230         case 'P':               // ^P is start of next page, ^E is end of file\r
231         case 'E':\r
232                 layoutdone = true;\r
233                 text--;\r
234                 break;\r
235 \r
236         case 'C':               // ^c<hex digit> changes text color\r
237                 i = toupper(*(++text));\r
238                 if (i >= '0' && i <= '9')\r
239                 {\r
240                         fontcolor = i + 0 - '0';\r
241                 }\r
242                 else if (i >= 'A' && i <= 'F')\r
243                 {\r
244                         fontcolor = i + 10 - 'A';\r
245                 }\r
246 #if GRMODE == CGAGR\r
247                 {\r
248                         static Sint16 colormap[16] = {2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0};\r
249                         // Note: This mapping is a bit problematic for Keen 5 CGA,\r
250                         // since some colors get mapped to CGA magenta, which is\r
251                         // used as the background color in that version. Luckily\r
252                         // those colors aren't used in the Keen 5 texts anyway.\r
253 \r
254                         fontcolor = colormap[fontcolor];\r
255                 }\r
256 #endif\r
257                 fontcolor ^= BACKCOLOR;\r
258                 text++;\r
259                 break;\r
260 \r
261         case 'L':\r
262                 py = ParseNumber();\r
263                 rowon = (py - 10)/10;\r
264                 py = rowon * 10 + 10;\r
265                 px = ParseNumber();\r
266                 while (*(text++) != '\n')       // scan to end of line\r
267                 ;\r
268                 break;\r
269 \r
270         case 'T':               // ^Tyyy,xxx,ppp,ttt waits ttt tics, then draws pic\r
271                 TimedPicCommand();\r
272                 break;\r
273 \r
274         case 'G':               // ^Gyyy,xxx,ppp draws graphic\r
275                 ParsePicCommand();\r
276                 VWB_DrawPic(picx & ~7, picy, picnum);\r
277                 picwidth = pictable[picnum-STARTPICS].width * BYTEPIXELS;\r
278                 picheight = pictable[picnum-STARTPICS].height;\r
279                 picmid = picx + picwidth/2;\r
280                 //\r
281                 // adjust margins\r
282                 //\r
283                 if (picmid > SCREENMID)\r
284                 {\r
285                         margin = picx-PICMARGIN;                        // new right margin\r
286                 }\r
287                 else\r
288                 {\r
289                         margin = picx+picwidth+PICMARGIN;       // new left margin\r
290                 }\r
291                 top = (picy-TOPMARGIN)/FONTHEIGHT;\r
292                 if (top < 0)\r
293                 {\r
294                         top = 0;\r
295                 }\r
296                 bottom = (picy+picheight-TOPMARGIN)/FONTHEIGHT;\r
297                 if (bottom >= TEXTROWS)\r
298                 {\r
299                         bottom = TEXTROWS-1;\r
300                 }\r
301 \r
302                 for (i=top; i<=bottom; i++)\r
303                 {\r
304                         if (picmid > SCREENMID)\r
305                         {\r
306                                 rightmargin[i] = margin;\r
307                         }\r
308                         else\r
309                         {\r
310                                 leftmargin[i] = margin;\r
311                         }\r
312                 }\r
313 \r
314                 //\r
315                 // adjust this line if needed\r
316                 //\r
317                 if (leftmargin[rowon] > px)\r
318                 {\r
319                         px = leftmargin[rowon];\r
320                 }\r
321                 break;\r
322         }\r
323 }\r
324 \r
325 \r
326 /*\r
327 =====================\r
328 =\r
329 = NewLine\r
330 =\r
331 =====================\r
332 */\r
333 \r
334 void NewLine(void)\r
335 {\r
336         char c;\r
337 \r
338         if (++rowon == TEXTROWS)\r
339         {\r
340         //\r
341         // overflowed the page, so skip until next page break\r
342         //\r
343                 layoutdone = true;\r
344                 do\r
345                 {\r
346                         if (*text == '^')\r
347                         {\r
348                                 c = toupper(text[1]);\r
349                                 if (c == 'E' || c == 'P')\r
350                                 {\r
351                                         layoutdone = true;\r
352                                         return;\r
353                                 }\r
354                         }\r
355                         text++;\r
356                 } while (1);\r
357         }\r
358         px = leftmargin[rowon];\r
359         py += FONTHEIGHT;\r
360 }\r
361 \r
362 \r
363 /*\r
364 =====================\r
365 =\r
366 = HandleCtrls\r
367 =\r
368 =====================\r
369 */\r
370 \r
371 void HandleCtrls(void)\r
372 {\r
373         char c;\r
374 \r
375         c = *(text++);                  // get the character and advance\r
376 \r
377         if (c == '\n')\r
378         {\r
379                 NewLine();\r
380                 return;\r
381         }\r
382 }\r
383 \r
384 /*\r
385 =====================\r
386 =\r
387 = HandleWord\r
388 =\r
389 =====================\r
390 */\r
391 \r
392 void HandleWord(void)\r
393 {\r
394         Uint16 wwidth, wheight, newpos, wordindex;\r
395         char word[WORDLIMIT];\r
396 \r
397         //\r
398         // copy the next word into [word]\r
399         //\r
400         word[0] = *(text++);\r
401         wordindex = 1;\r
402         while (*text > ' ')\r
403         {\r
404                 word[wordindex] = *(text++);\r
405                 if (++wordindex == WORDLIMIT)\r
406                 {\r
407                         Quit("PageLayout: Word limit exceeded");\r
408                 }\r
409         }\r
410         word[wordindex] = 0;            // stick a null at end for C\r
411 \r
412         //\r
413         // see if it fits on this line\r
414         //\r
415         VW_MeasurePropString(word, &wwidth, &wheight);\r
416         \r
417         while (rightmargin[rowon] < px+wwidth)\r
418         {\r
419                 NewLine();\r
420                 if (layoutdone)\r
421                 {\r
422                         return;         // overflowed page\r
423                 }\r
424         }\r
425 \r
426         //\r
427         // print it\r
428         //\r
429         newpos = px+wwidth;\r
430         VWB_DrawPropString(word);\r
431         px = newpos;\r
432 \r
433         //\r
434         // suck up any extra spaces\r
435         //\r
436         while (*text == ' ')\r
437         {\r
438                 px += SPACEWIDTH;\r
439                 text++;\r
440         }\r
441 }\r
442 \r
443 /*\r
444 =====================\r
445 =\r
446 = PageLayout\r
447 =\r
448 = Clears the screen, draws the pics on the page, and word wraps the text.\r
449 = Returns a pointer to the terminating command\r
450 =\r
451 =====================\r
452 */\r
453 \r
454 void PageLayout(boolean shownumber)\r
455 {\r
456         Sint16 oldcolor, i;\r
457         char c;\r
458 \r
459         oldcolor = fontcolor;\r
460 \r
461 #if GRMODE == CGAGR\r
462         fontcolor = BLACK^BACKCOLOR;\r
463 #else\r
464         fontcolor = YELLOW^BACKCOLOR;\r
465 #endif\r
466 \r
467 //\r
468 // clear the screen\r
469 //\r
470         VWB_Bar(0, 0, 320, 200, BACKCOLOR);\r
471 #ifndef KEEN6\r
472         VWB_DrawPic(  0, 0, H_TOPWINDOWPIC);\r
473         VWB_DrawPic(  0, 8, H_LEFTWINDOWPIC);\r
474         VWB_DrawPic(312, 8, H_RIGHTWINDOWPIC);\r
475         if (shownumber)\r
476         {\r
477                 VWB_DrawPic(8, 176, H_BOTTOMINFOPIC);\r
478         }\r
479         else\r
480         {\r
481                 VWB_DrawPic(8, 192, H_BOTTOMWINDOWPIC);\r
482         }\r
483 #endif\r
484 \r
485         for (i=0; i<TEXTROWS; i++)\r
486         {\r
487                 leftmargin[i] = LEFTMARGIN;\r
488                 rightmargin[i] = SCREENPIXWIDTH-RIGHTMARGIN;\r
489         }\r
490 \r
491         px = LEFTMARGIN;\r
492         py = TOPMARGIN;\r
493         rowon = 0;\r
494         layoutdone = false;\r
495 \r
496 //\r
497 // make sure we are starting layout text (^P first command)\r
498 //\r
499         while (*text <= ' ')\r
500         {\r
501                 text++;\r
502         }\r
503         if (*text != '^' || toupper(*(++text)) != 'P')\r
504         {\r
505                 Quit("PageLayout: Text not headed with ^P");\r
506         }\r
507         while (*(text++) != '\n')\r
508         ;\r
509 \r
510 //\r
511 // process text stream\r
512 //\r
513         do\r
514         {\r
515                 c = *text;\r
516                 if (c == '^')\r
517                 {\r
518                         HandleCommand();\r
519                 }\r
520                 else if (c <= ' ')\r
521                 {\r
522                         HandleCtrls();\r
523                 }\r
524                 else\r
525                 {\r
526                         HandleWord();\r
527                 }\r
528         } while (!layoutdone);\r
529 \r
530         pagenum++;\r
531 \r
532         if (shownumber)\r
533         {\r
534                 strcpy(str, "pg ");\r
535                 itoa(pagenum, str2, 10);\r
536                 strcat(str, str2);\r
537                 strcat(str, " of ");\r
538                 itoa(numpages, str2, 10);\r
539                 strcat(str, str2);\r
540 #if GRMODE == CGAGR\r
541                 fontcolor = BLACK^BACKCOLOR;\r
542 #else\r
543                 fontcolor = LIGHTRED^BACKCOLOR;\r
544 #endif\r
545                 py = 186;\r
546                 px = 218;\r
547                 VWB_DrawPropString(str);\r
548         }\r
549 \r
550         fontcolor = oldcolor;\r
551 }\r
552 \r
553 //===========================================================================\r
554 \r
555 /*\r
556 =====================\r
557 =\r
558 = BackPage\r
559 =\r
560 = Scans for a previous ^P\r
561 =\r
562 =====================\r
563 */\r
564 \r
565 void BackPage(void)\r
566 {\r
567         pagenum--;\r
568         do\r
569         {\r
570                 text--;\r
571                 if (text[0] == '^' && toupper(text[1]) == 'P')\r
572                 {\r
573                         return;\r
574                 }\r
575         } while (1);\r
576 }\r
577 \r
578 //===========================================================================\r
579 \r
580 \r
581 /*\r
582 =====================\r
583 =\r
584 = CacheLayoutGraphics\r
585 =\r
586 = Scans an entire layout file (until a ^E) marking all graphics used, and\r
587 = counting pages, then caches the graphics in\r
588 =\r
589 =====================\r
590 */\r
591 void CacheLayoutGraphics(void)\r
592 {\r
593         char    far *bombpoint, far *textstart;\r
594         char    ch;\r
595 \r
596         textstart = text;\r
597         bombpoint = text+30000;\r
598         numpages = pagenum = 0;\r
599 \r
600 #ifndef KEEN6\r
601         CA_MarkGrChunk(H_TOPWINDOWPIC);\r
602         CA_MarkGrChunk(H_LEFTWINDOWPIC);\r
603         CA_MarkGrChunk(H_RIGHTWINDOWPIC);\r
604         CA_MarkGrChunk(H_BOTTOMINFOPIC);\r
605         CA_MarkGrChunk(H_BOTTOMWINDOWPIC);\r
606 #endif\r
607 \r
608         do\r
609         {\r
610                 if (*text == '^')\r
611                 {\r
612                         ch = toupper(*(++text));\r
613                         if (ch == 'P')          // start of a page\r
614                         {\r
615                                 numpages++;\r
616                         }\r
617                         if (ch == 'E')          // end of file, so load graphics and return\r
618                         {\r
619                                 CA_CacheMarks(NULL);\r
620                                 text = textstart;\r
621                                 return;\r
622                         }\r
623                         if (ch == 'G')          // draw graphic command, so mark graphics\r
624                         {\r
625                                 ParsePicCommand();\r
626                                 CA_MarkGrChunk(picnum);\r
627                         }\r
628                         if (ch == 'T')          // timed draw graphic command, so mark graphics\r
629                         {\r
630                                 ParseTimedCommand();\r
631                                 CA_MarkGrChunk(picnum);\r
632                         }\r
633                 }\r
634                 else\r
635                 {\r
636                         text++;\r
637                 }\r
638 \r
639         } while (text < bombpoint);\r
640 \r
641         Quit("CacheLayoutGraphics: No ^E to terminate file!");\r
642 }\r
643 \r
644 //===========================================================================\r
645 \r
646 #ifndef KEEN6\r
647 /*\r
648 =================\r
649 =\r
650 = HelpMenu\r
651 =\r
652 =================\r
653 */\r
654 Sint16 HelpMenu(void)\r
655 {\r
656         CursorInfo cursor;\r
657         ControlInfo control;\r
658         Sint16 ydelta;\r
659         Uint16 key;\r
660 \r
661         VWB_Bar(0, 0, 320, 200, BACKCOLOR);\r
662 \r
663         CA_CacheGrChunk(H_HELPPIC);\r
664         CA_CacheGrChunk(H_HANDPIC);\r
665         CA_CacheGrChunk(H_TOPWINDOWPIC);\r
666         CA_CacheGrChunk(H_LEFTWINDOWPIC);\r
667         CA_CacheGrChunk(H_RIGHTWINDOWPIC);\r
668         CA_CacheGrChunk(H_BOTTOMWINDOWPIC);\r
669 \r
670         VWB_DrawPic(  0,   0, H_TOPWINDOWPIC);\r
671         VWB_DrawPic(  0,   8, H_LEFTWINDOWPIC);\r
672         VWB_DrawPic(312,   8, H_RIGHTWINDOWPIC);\r
673         VWB_DrawPic(  8, 192, H_BOTTOMWINDOWPIC);\r
674         VWB_DrawPic( 96,   8, H_HELPPIC);\r
675 \r
676         ydelta = 0;\r
677         IN_ClearKeysDown();\r
678         do\r
679         {\r
680                 if (helpmenupos < 0)\r
681                 {\r
682                         helpmenupos = 0;\r
683                 }\r
684 #ifdef GOODTIMES\r
685                 else if (helpmenupos > 3)\r
686                 {\r
687                         helpmenupos = 3;\r
688                 }\r
689 #else\r
690                 else if (helpmenupos > 4)\r
691                 {\r
692                         helpmenupos = 4;\r
693                 }\r
694 #endif\r
695                 VWB_DrawPic(48, 24*helpmenupos+48, H_HANDPIC);\r
696                 VW_UpdateScreen();\r
697                 VWB_Bar(48, 24*helpmenupos+48, 39, 24, BACKCOLOR);\r
698                 IN_ReadControl(0, &control);\r
699                 IN_ReadCursor(&cursor);\r
700                 if (LastScan)\r
701                 {\r
702                         key = LastScan;\r
703                         IN_ClearKeysDown();\r
704                         switch (key)\r
705                         {\r
706                         case sc_UpArrow:\r
707                                 helpmenupos--;\r
708                                 break;\r
709                         case sc_DownArrow:\r
710                                 helpmenupos++;\r
711                                 break;\r
712                         case sc_Enter:\r
713                                 VW_ClearVideo(BACKCOLOR);\r
714                                 return helpmenupos;\r
715                         case sc_Escape:\r
716                                 VW_ClearVideo(BACKCOLOR);\r
717                                 return -1;\r
718                         }\r
719                 }\r
720                 ydelta += cursor.y;\r
721                 if (cursor.button0 || cursor.button1 || control.button0 || control.button1)\r
722                 {\r
723                         VW_ClearVideo(BACKCOLOR);\r
724                         return helpmenupos;\r
725                 }\r
726                 if (ydelta < -40)\r
727                 {\r
728                         ydelta += 40;\r
729                         helpmenupos--;\r
730                 }\r
731                 else if (ydelta > 40)\r
732                 {\r
733                         ydelta -= 40;\r
734                         helpmenupos++;\r
735                 }\r
736         } while (1);\r
737 }\r
738 \r
739 /*\r
740 =================\r
741 =\r
742 = HelpScreens\r
743 =\r
744 =================\r
745 */\r
746 void HelpScreens(void)\r
747 {\r
748         static Uint16 layouttable[5] =\r
749         {\r
750                 T_HELPART,\r
751                 T_CONTRART,\r
752                 T_STORYART,\r
753 #ifndef GOODTIMES\r
754                 T_ORDERART,\r
755 #endif\r
756                 T_IDART\r
757         };\r
758 \r
759         Uint16 olddisplayofs, oldbufferofs, oldfontnumber, temp;\r
760         Sint16 pos;\r
761         boolean newpage;\r
762 \r
763         oldfontnumber = fontnumber;\r
764         olddisplayofs = displayofs;\r
765         oldbufferofs = bufferofs;\r
766         fontnumber = 0;\r
767 \r
768 #if GRMODE == EGAGR\r
769         EGAMAPMASK(15);\r
770 #endif\r
771 \r
772         CA_UpLevel();\r
773         CA_SetGrPurge();\r
774         VW_ClearVideo(BACKCOLOR);\r
775 \r
776 #if GRMODE == EGAGR\r
777         RF_FixOfs();\r
778         bufferofs = 0;\r
779         displayofs = 0x8000;\r
780         VW_SetScreen(displayofs, 0);\r
781 #endif\r
782 \r
783 #ifdef KEEN5\r
784         StartMusic(19);\r
785 #endif\r
786 \r
787         do\r
788         {\r
789                 pos = HelpMenu();\r
790 \r
791                 VW_ClearVideo(BACKCOLOR);\r
792 \r
793                 if (pos == -1)\r
794                 {\r
795                         CA_DownLevel();\r
796                         IN_ClearKeysDown();\r
797                         bufferofs = oldbufferofs;\r
798                         displayofs = olddisplayofs;\r
799                         fontnumber = oldfontnumber;\r
800                         VW_ClearVideo(BACKCOLOR);\r
801                         RF_FixOfs();\r
802 #ifdef KEEN5\r
803                         StopMusic();    // Note: it's safer to call StopMusic BEFORE CA_DownLevel\r
804 #endif\r
805                         return;\r
806                 }\r
807 \r
808                 pos = layouttable[pos];\r
809                 CA_CacheGrChunk(pos);\r
810                 text = grsegs[pos];\r
811                 CacheLayoutGraphics();\r
812 \r
813                 newpage = true;\r
814                 do\r
815                 {\r
816                         if (newpage)\r
817                         {\r
818                                 newpage = false;\r
819                                 PageLayout(true);\r
820 #if GRMODE == CGAGR\r
821                                 VW_UpdateScreen();\r
822 #else\r
823                                 VW_SetScreen(bufferofs, 0);\r
824                                 temp = displayofs;\r
825                                 displayofs = bufferofs;\r
826                                 bufferofs = temp;\r
827 #endif\r
828                         }\r
829 \r
830                         LastScan = 0;\r
831                         while (!LastScan);\r
832 \r
833                         switch (LastScan)\r
834                         {\r
835                         case sc_UpArrow:\r
836                         case sc_LeftArrow:\r
837                         case sc_PgUp:\r
838                                 if (pagenum > 1)\r
839                                 {\r
840                                         BackPage();\r
841                                         BackPage();\r
842                                         newpage = true;\r
843                                 }\r
844                                 break;\r
845                         case sc_DownArrow:\r
846                         case sc_RightArrow:\r
847                         case sc_PgDn:\r
848                                 if (pagenum < numpages)\r
849                                 {\r
850                                         newpage = true;\r
851                                 }\r
852                                 break;\r
853                         }\r
854                 } while (LastScan != sc_Escape);\r
855 \r
856                 MM_FreePtr(&grsegs[pos]);\r
857                 IN_ClearKeysDown();\r
858         } while (true);\r
859 }\r
860 \r
861 #endif\r
862 \r
863 //===========================================================================\r
864 \r
865 /*\r
866 =================\r
867 =\r
868 = FinaleLayout\r
869 =\r
870 =================\r
871 */\r
872 void FinaleLayout(void)\r
873 {\r
874         char _seg *textseg;\r
875         Sint16 i;\r
876 \r
877         VW_ClearVideo(BACKCOLOR);\r
878         RF_FixOfs();\r
879         CA_UpLevel();\r
880         CA_SetGrPurge();\r
881         CA_CacheGrChunk(H_FLASHARROW2PIC);\r
882         CA_CacheGrChunk(H_FLASHARROW1PIC);\r
883 \r
884 #ifdef KEEN5\r
885         if (gamestate.leveldone[13] == ex_fusebroke)\r
886         {\r
887                 CA_CacheGrChunk(T_ENDART2);\r
888                 textseg = grsegs[T_ENDART2];\r
889         }\r
890         else\r
891         {\r
892                 CA_CacheGrChunk(T_ENDART);\r
893                 textseg = grsegs[T_ENDART];\r
894         }\r
895 #else\r
896         CA_CacheGrChunk(T_ENDART);\r
897         textseg = grsegs[T_ENDART];\r
898 #endif\r
899 \r
900         text = textseg;\r
901         CacheLayoutGraphics();\r
902 \r
903         StartMusic(ENDINGMUSIC);\r
904 \r
905         while (pagenum < numpages)\r
906         {\r
907                 PageLayout(false);\r
908                 IN_ClearKeysDown();\r
909 #if GRMODE == CGAGR\r
910                 VW_UpdateScreen();\r
911 #else\r
912                 VW_SetScreen(bufferofs, 0);\r
913 #endif\r
914 \r
915                 do\r
916                 {\r
917                         VWB_DrawPic(298, 184, H_FLASHARROW1PIC);\r
918 #if GRMODE == CGAGR\r
919                         VW_UpdateScreen();\r
920 #endif\r
921                         for (i=0; i<TickBase; i++)\r
922                         {\r
923                                 if (IN_IsUserInput())\r
924                                 {\r
925                                         goto nextpage;\r
926                                 }\r
927                                 VW_WaitVBL(1);\r
928                         }\r
929 \r
930                         VWB_DrawPic(298, 184, H_FLASHARROW2PIC);\r
931 #if GRMODE == CGAGR\r
932                         VW_UpdateScreen();\r
933 #endif\r
934                         for (i=0; i<TickBase; i++)\r
935                         {\r
936                                 if (IN_IsUserInput())\r
937                                 {\r
938                                         goto nextpage;\r
939                                 }\r
940                                 VW_WaitVBL(1);\r
941                         }\r
942                 } while (1);\r
943 \r
944 nextpage:\r
945                 ;       // Borland C++ 2.0 needs a semicolon here...\r
946         }\r
947 \r
948         StopMusic();\r
949 \r
950 #ifdef KEEN5\r
951         if (gamestate.leveldone[13] == ex_fusebroke)\r
952         {\r
953                 MM_FreePtr(&grsegs[T_ENDART2]);\r
954         }\r
955         else\r
956         {\r
957                 MM_FreePtr(&grsegs[H_FLASHARROW1PIC]);  // BUG! this should free T_ENDART, the arrow should be freed after the else branch!\r
958         }\r
959 #else\r
960         MM_FreePtr(&grsegs[T_ENDART]);\r
961         MM_FreePtr(&grsegs[H_FLASHARROW1PIC]);\r
962 #endif\r
963         MM_FreePtr(&grsegs[H_FLASHARROW2PIC]);\r
964         CA_DownLevel();\r
965         IN_ClearKeysDown();\r
966 #if GRMODE != CGAGR\r
967         VW_ClearVideo(BACKCOLOR);\r
968         RF_FixOfs();\r
969 #endif\r
970         CA_FreeGraphics();\r
971 }