dominus icon

Untitled

dominus | PRO | 02/12/25 08:53:27 AM UTC | 0 ⭐ | 13618 👁️ | Never ⏰ | []
Diff |

10.17 KB

|

None

|

0 👍

/

0 👎

diff --git a/gumps/Book_gump.cc b/gumps/Book_gump.cc
index 3e7da65bb..1433fdaa9 100644
--- a/gumps/Book_gump.cc
+++ b/gumps/Book_gump.cc
@@ -1,5 +1,5 @@
 /*
-Copyright (C) 2000-2022 The Exult Team
+Copyright (C) 2000-2025 The Exult Team
 
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
@@ -40,7 +40,7 @@ void Book_gump::paint() {
    // Paint the gump itself.
    paint_shape(x, y);
    // Paint left page.
-   curend = paint_page(TileRect(36, 10, 122, 130), curtop);
+   curend = paint_page(TileRect(35, 8, 125, 130), curtop);
    // Paint right page.
-   curend = paint_page(TileRect(174, 10, 122, 130), curend);
+   curend = paint_page(TileRect(173, 8, 125, 130), curend);
 }
diff --git a/gumps/Scroll_gump.cc b/gumps/Scroll_gump.cc
index 533f4f49b..9d57b2302 100644
--- a/gumps/Scroll_gump.cc
+++ b/gumps/Scroll_gump.cc
@@ -1,5 +1,5 @@
 /*
-Copyright (C) 2000-2022 The Exult Team
+Copyright (C) 2000-2025 The Exult Team
 
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
@@ -39,5 +39,5 @@ Scroll_gump::Scroll_gump(int fnt, int gump)
 void Scroll_gump::paint() {
    // Paint the gump itself.
    paint_shape(x, y);
-   curend = paint_page(TileRect(52, 30, 142, 118), curtop);
+   curend = paint_page(TileRect(51, 31, 142, 118), curtop);
 }
diff --git a/gumps/Text_gump.cc b/gumps/Text_gump.cc
index 5feb93b07..5594115fc 100644
--- a/gumps/Text_gump.cc
+++ b/gumps/Text_gump.cc
@@ -1,5 +1,5 @@
 /*
-Copyright (C) 2000-2022 The Exult Team
+Copyright (C) 2000-2025 The Exult Team
 
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
@@ -21,10 +21,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #endif
 
 #include "Text_gump.h"
-
+#include "game.h"
 #include "gamewin.h"
 
 #include <cstring>
+#include <string>
 
 using std::strchr;
 
@@ -33,21 +34,23 @@ using std::strchr;
  */
 
 void Text_gump::add_text(const char* str) {
-   const int slen = strlen(str);    // Length of new text.
-   // Allocate new space.
-   char* newtext = new char[textlen + (textlen != 0) + slen + 1];
-   if (textlen) {    // Copy over old.
-       strcpy(newtext, text);
-       // Add new line if not starting a new page and if first char of new
-       // string is not a new line
+   std::string newtext;
+   if (textlen) {
+       newtext = text;
        if (newtext[textlen - 1] != '*') {
-           newtext[textlen++] = '~';
+           // Scrolls in SI break page with embedded 0x00
+           if (GAME_SI && get_shapenum() == game->get_shape("gumps/scroll")) {
+               newtext += "*";
+           } else {
+               newtext += "~";
+           }
        }
    }
-   strcpy(newtext + textlen, str);    // Append new.
+   newtext += str;
    delete[] text;
-   text = newtext;
-   textlen += slen;
+   text = new char[newtext.length() + 1];
+   strcpy(text, newtext.c_str());
+   textlen = newtext.length();
 }
 
 /*
@@ -56,50 +59,172 @@ void Text_gump::add_text(const char* str) {
  *  Output: Index past end of displayed page.
  */
 
-int Text_gump::paint_page(
-       const TileRect& box,     // Display box rel. to gump.
-       int             start    // Starting offset into text.
-) {
-   const int vlead      = 1;    // Extra inter-line spacing.
+int Text_gump::paint_page(const TileRect& box, int start) {
    int       ypos       = 0;
+   const int vlead      = 1;
    const int textheight = sman->get_text_height(font) + vlead;
    char*     str        = text + start;
-   while (*str && *str != '*' && ypos + textheight <= box.h) {
-       if (*str == '~') {    // Empty paragraph?
-           ypos += textheight;
-           str++;
-           continue;
+   curend = start;    // Initialize curend to the starting position
+
+   char* lineBreak     = nullptr;
+   char* pageBreakStar = nullptr;
+   char* extraBreak    = nullptr;
+   char* epage         = nullptr;    // page break marker
+   char* eol           = nullptr;    // end-of-line marker
+
+   while (*str && ypos + textheight <= box.h) {
+       lineBreak     = strchr(str, '~');
+       pageBreakStar = strchr(str, '*');
+
+       if (GAME_BG && get_shapenum() == game->get_shape("gumps/scroll")) {
+           extraBreak = strstr(str, " ~~");
+           if (extraBreak) {
+               // If " ~~" is preceded by "~~", ignore it.
+               if (extraBreak - text >= 2 && *(extraBreak - 2) == '~'
+                   && *(extraBreak - 1) == '~') {
+                   extraBreak = nullptr;
+               }
+           }
        }
-       // Look for page break.
-       char* epage = strchr(str, '*');
-       // Look for line break.
-       char* eol = strchr(str, '~');
-       if (epage && (!eol || eol > epage)) {
-           eol = epage;
+
+       // if extraBreak is found and it occurs at the same position
+       // as the first tilde, use it as page break.
+       if (extraBreak && lineBreak && extraBreak + 1 == lineBreak) {
+           epage = extraBreak;
+           eol   = extraBreak;
+       } else if (pageBreakStar && (!lineBreak || pageBreakStar < lineBreak)) {
+           epage = pageBreakStar;
+           eol   = pageBreakStar;
+       } else {
+           eol   = lineBreak;
+           epage = nullptr;    // no page break marker
        }
-       if (!eol) {    // No end found?
+
+       if (!eol) {
+           // No marker found: paint until the end of text.
            eol = text + textlen;
        }
-       const char eolchr = *eol;    // Save char. at EOL.
-       *eol              = 0;
-       const int endoff  = sman->paint_text_box(
-                font, str, x + box.x, y + box.y + ypos, box.w, box.h - ypos,
-                vlead);
-       *eol = eolchr;       // Restore char.
-       if (endoff > 0) {    // All painted?
-           // Value returned is height.
-           str = eol + (eolchr == '~');
+
+       // Temporarily null-terminate at eol for painting.
+       const char eolchr = *eol;
+       *eol              = '\0';
+
+       int endoff = sman->paint_text_box(
+               font, str, x + box.x, y + box.y + ypos, box.w, box.h - ypos,
+               vlead);
+       // Restore the character at eol.
+       *eol = eolchr;
+
+       if (endoff > 0) {
+           // Check for a page‑break marker
+           if (epage && get_shapenum() == game->get_shape("gumps/scroll")) {
+               if (GAME_SI && start == 0 && ypos <= 5 * textheight) {
+                   // ignore page breaks on the first 5 lines of a scroll
+                   str    = pageBreakStar + 1;
+                   curend = str - text;
+                   ypos += endoff;
+                   continue;
+               }
+               // Calculate vertical space remaining after the current
+               // block has been painted.
+               int remaining = box.h - (ypos + endoff);
+
+               // Require room for at least two extra full line.
+               if (remaining >= 2 * textheight) {
+                   // Reserve two extra line for spacing; the rest is
+                   // available for the next text chunk.
+                   int available = remaining - (2 * textheight);
+                   if (available < 0) {
+                       available = 0;
+                   }
+
+                   // Use existing markers to find earliest upcoming marker
+                   const char* earliest
+                           = text + textlen;    // default: measure to
+                                                // end-of-text
+
+                   // Use same check for both page break markers
+                   const char* nextBreak = nullptr;
+                   if ((pageBreakStar > eol + (epage == extraBreak ? 3 : 1)
+                        && pageBreakStar < earliest)
+                       || (extraBreak > eol + (epage == extraBreak ? 3 : 1)
+                           && extraBreak < earliest)) {
+                       earliest = (pageBreakStar && pageBreakStar < earliest)
+                                          ? pageBreakStar
+                                          : extraBreak;
+                   }
+
+                   // Temporarily replace the character at 'earliest' with
+                   // '\0' to isolate the next chunk.
+                   char saved = *earliest;
+
+                   // PEEK MEASUREMENT:
+                   // To avoid drawing on top of already painted text, we
+                   // use an off-screen y coordinate (e.g. -1000).
+                   int peekHeight = sman->paint_text_box(
+                           font, eol + (epage == extraBreak ? 3 : 1),
+                           x + box.x,
+                           -1000,    // off-screen y coordinate for
+                                     // measurement only
+                           box.w, available, vlead);
+                   // Restore the character we replaced.
+                   *((char*)earliest) = saved;
+
+                   if (peekHeight > 0
+                       && peekHeight
+                                  <= available
+                                             + 5)    // Add 5 pixels tolerance
+                   {
+                       // The entire upcoming text fits in the available
+                       // space. Consume most of the extraBreak/pageBreakStar
+                       // marker and add an extra line spacing.
+                       eol += (epage == extraBreak ? 2 : 1);
+                       ypos += endoff;    // update vertical offset
+                       str    = eol;      // continue painting after the marker
+                       curend = str - text;    // Update curend
+                       continue;    // next iteration: the peeked block
+                                    // will be painted on this page only
+                   } else {
+                       // The upcoming block does not fully fit;
+                       // consume the marker and break so that it will be
+                       // painted on the next page.
+                       eol += (epage == extraBreak ? 3 : 1);
+                       str    = eol;
+                       curend = str - text;    // Update curend
+                       break;
+                   }
+               }
+           } else if (eolchr == '~' || (lineBreak && lineBreak == eol)) {
+               // Normal handling for a tilde line break.
+               eol++;
+           }
+
+           // After handling markers (or if none applied), update the text
+           // pointer and vertical offset.
            ypos += endoff;
-       } else {    // Out of room.
+           str    = eol;
+           curend = str - text;    // Update curend
+
+           // Skip any leading space at the beginning of a new line.
+           if (*str == ' ') {
+               str++;
+           }
+       } else {
+           // Out of room or partial paint -> back up
            str += -endoff;
+           curend = str - text;    // Update curend
            break;
        }
    }
-   if (*str == '*') {    // Saw end of page?
-       str++;
+
+   // After the loop, check for markers at current position
+   if (pageBreakStar && pageBreakStar == str) {
+       str++;    // skip "*"
    }
-   gwin->set_painted();    // Force blit.
-   return str - text;      // Return offset past end.
+
+   curend = str - text;    // Update curend one last time after the loop
+   gwin->set_painted();
+   return str - text;
 }
 
 /*
@@ -113,6 +238,12 @@ int Text_gump::show_next_page() {
        return 0;    // That's all, folks.
    }
    curtop = curend;    // Start next page or pair of pages.
-   paint();            // Paint.  This updates curend.
+
+   // Skip any leading tildes at the beginning of the new page.
+   while (curtop < textlen && text[curtop] == '~') {
+       curtop++;
+   }
+
+   paint();    // Paint.  This updates curend.
    return 1;
 }
 

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎