Libretta's text system isn't too complex, but some of the scripts (like dynamic movement that depends on your position going into a scene) got complicated - though the main cause of that was I was too lazy to make convenient functions for things. Loverinth is using more a streamlined version (partly by necessity, since I can't just use execute_string anymore).
In Libretta, checkable objects (objReadable) have a "text" variable (but I'll call it myScript to be less confusing) defined in their creation code, which is the script that's run when they get checked. Specifically, Libra tries to run User Event 0 for whatever's in front of her; User Event 0 in objReadable creates an objTextbox and sends over myScript and some other things. (The same applies for stepping onto a new tile and User Event 1, utilized by objTriggers.)
Each line of a script is either a message, or it's an action. Messages are plain, actions start with a \ or /. ("\" executes code in the context of objTextbox, "/" executes it in the context of the objReadable. objTextbox also has a "parent" variable to refer to that object when necessary.) Messages cause the textbox itself to appear and type that message, and when you advance the message, the next line of myScript gets read (it just keeps removing the first line until it's empty). Actions just execute_string() whatever you put, then continue to the next line unless they ran something that told them to wait. There's wait() which sets an alarm for when to advance the script, and external objects (like a few which display choices) that tell objTextbox to advance when they're done.
There were two big weird things I could do with this system: insert variables into text just by going "myScript = string_replace(myScript, "REPLACE", variable)", and handle branching by doing stuff like "\if global.choice == 1 { myScript = parent.anotherScript }". Most objects not only define myScript in their creation code, but also a myScript2, myScript3, etcetera, which can be switched between by updating "myScript", since that's effectively just the active script. (Since the myScript variable gets copied over to objTextbox at the start, the objReadable's original definitions don't get altered.) Oh yeah, and for the midway closing thing, it basically just backs up the current variables in the objReadable to resume from later.
Anyway, that was a bit messy, so Loverinth instead reads external text files which are broken up into "pages" (labeled by <Header>s) that can be jumped between, storing the script contents in a proper data structure (a Script which contains ScriptPages which contain lines as strings). It also has to be able to actually parse actions, including conditionals. And the textbox drawing function supports simple tags in text (pretty much BBcode style) for things like partial color and wavy text, rather than only having "textbox options" that affect the whole message like Libretta. (There are still some options, like for centered text.)
EDIT: And for posterity: Nakko-Bazookie only supports passing a series of messages to a textbox ("Nakko: Rockets!" ": I'm the narrator."), and all actions in-between are done using cutscene objects with counters that wait for the current textbox to finish. So yeah.