dominus icon

Untitled

dominus | PRO | 02/10/25 09:24:37 AM UTC | 0 ⭐ | 13536 👁️ | Never ⏰ | []
Diff |

9.53 KB

|

None

|

0 👍

/

0 👎

diff --git a/gumps/Book_gump.cc b/gumps/Book_gump.cc
index 3e7da65bb..daed28bad 100644
--- a/gumps/Book_gump.cc
+++ b/gumps/Book_gump.cc
@@ -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, 132), curtop);
    // Paint right page.
-   curend = paint_page(TileRect(174, 10, 122, 130), curend);
+   curend = paint_page(TileRect(173, 8, 125, 132), curend);
 }
diff --git a/gumps/Scroll_gump.cc b/gumps/Scroll_gump.cc
index 533f4f49b..f66837026 100644
--- a/gumps/Scroll_gump.cc
+++ b/gumps/Scroll_gump.cc
@@ -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..5f3032c26 100644
--- a/gumps/Text_gump.cc
+++ b/gumps/Text_gump.cc
@@ -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,18 @@ 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++] = '~';
+           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 +54,185 @@ 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) {
+       // Find the first tilde (line break marker)
+       lineBreak = strchr(str, '~');
+       // Update markers based on current position
+       pageBreakStar = strchr(str, '*');
+
+       if (GAME_SI) {
+           extraBreak = strstr(str, "~~~");
+       }
+       if (GAME_BG) {
+           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
+           && ((GAME_SI && extraBreak == lineBreak)
+               || (GAME_BG && 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) {
+               // Handle extraBreak marker (e.g. "~~~" or " ~~")
+               if (extraBreak && epage == extraBreak) {
+                   if (GAME_SI && start == 0 && ypos == 0) {
+                       // If it's the first line of the entire text, ignore the
+                       // extraBreak
+                       eol    = extraBreak + 1;
+                       str    = eol;
+                       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
+
+                       if (pageBreakStar > eol + 3
+                           && pageBreakStar < earliest) {
+                           earliest = pageBreakStar;
+                       }
+                       if (extraBreak > eol + 3 && extraBreak < earliest) {
+                           earliest = 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 + 3,    // start after extraBreak marker
+                               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 a tolerance
+                                                           // of 5 pixels
+                       {
+                           // The entire upcoming text fits in the available
+                           // space. Consume the extraBreak marker and add an
+                           // extra line spacing.
+                           eol += 1;    // skip extraBreak marker ("~~~" or "
+                                        // ~~")
+                           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 += 3;
+                           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 (GAME_SI && extraBreak && extraBreak == str) {
+       str += 3;    // skip "~~~"
+   } else 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 +246,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

    |

    👍

    /

    👎