I don't even know whether that's a good idea - therefore the name of this thread

The first part is the «function» itself. Put this in a script and put it in a prim (single prim or linked-object). I named the script «func.show_dialog» so I'll remember what it is

[EDIT]
I slightly altered the script, sending the Command (SHOW_DIALOG) back to the requesting script to make it easier to determine, what's in the linked message
CODE
// Dialog-Maker
// By Haruki Watanabe
// This script is public domain - use it, share it, to whatever you wanna do... :)
// If you've got any improvements, please post them in the forum
// *******************************************************
// Constants
// *******************************************************
integer REQUESTING_SCRIPT; // Number of the requesting script
integer REQUESTING_LINK; // Link-Number where the request comes from
integer DLG_CHANNEL; // Channel on which the result of the dialog will be passed back
integer LISTENER_DLG; // The Listener-ID
integer LIST_OFFSET; // Offset of the List
integer TOTAL_ENTRIES; // Total Entries in the whole list to be presented
integer SHOW_ENTRIES; // BOOLEAN Whether or not to show the number of entries in the dialog-title (e.g. 'showing 1-9/25')
integer BACKLINK; // BOOLEAN Whether or not give the user the option to go back (useful if you're in a Sub-Menu)
string DLG_TITLE; // Title of the dialog
string CMD; // The Command that's passed to this function-script
key AGENT_REQUEST; // Key of the requesting Agent
list DLG_CONTENT; // The contents that the user can choose from
float MAX_LISTEN_TIME = 240.0; // Maximum seconds the Listener keeps listening for an answer
// *******************************************************
// Functions
// *******************************************************
show_dlg(list PASS_MENU) // Presents the Dialog-Menu to the requesting user
{
llListenRemove(LISTENER_DLG); // Delete any old listener
if(llGetListLength(PASS_MENU) == 0 || TOTAL_ENTRIES == 0) // If there are no entries in the list, send an error-Message to the User
{
llInstantMessage(AGENT_REQUEST, "There are no entries in the list...");
}
else
{
string TITLE = DLG_TITLE;
integer start; // number where the list starts
integer end; // number where the list ends -> these two shouldn't be confused with the list offset!
start = LIST_OFFSET + 1;
end = start + 9;
if(end > TOTAL_ENTRIES)
end = TOTAL_ENTRIES;
if(SHOW_ENTRIES == TRUE)
{
TITLE = TITLE + "\n showing entries " + (string)start + " - " + (string)end + " of " + (string)TOTAL_ENTRIES;
}
list MENU = llList2List(PASS_MENU, LIST_OFFSET, LIST_OFFSET + 9); // Get the portion of the list that fits into a dialog
// Give the user a 'back'-option
if(BACKLINK == TRUE || LIST_OFFSET > 0)
MENU += ["Back..."];
// if the list is too big to fit into one Menu, give the user a 'next'-option
if(end < TOTAL_ENTRIES)
MENU += ["Next..."];
// Show the dialog and initialize a listener
LISTENER_DLG = llListen(DLG_CHANNEL, "", AGENT_REQUEST, "");
llDialog(AGENT_REQUEST, TITLE, MENU, DLG_CHANNEL);
llSetTimerEvent(MAX_LISTEN_TIME); // Initialize a timer, in case the user clicks on 'ignore'
}
}
// Create an arbitrary dialog channel
integer randInt(integer n)
{
return (integer)llFrand(n + 1);
}
integer randIntBetween(integer min, integer max)
{
return min + randInt(max - min);
}
integer make_dlg_channel()
{
return randIntBetween(-65356, 0);
}
// *******************************************************
// Main-Section
// *******************************************************
default
{
link_message(integer sender, integer num, string str, key id)
{
AGENT_REQUEST = id;
REQUESTING_LINK = sender;
// split up the passed string into a list
list temp = llParseString2List(str, ["|"], []);
CMD = llList2String(temp, 0);
if(CMD == "SHOW_DIALOG")
{
DLG_CONTENT = llCSV2List(llList2String(temp, 1));
DLG_TITLE = llList2String(temp, 2);
REQUESTING_SCRIPT = llList2Integer(temp, 3);
SHOW_ENTRIES = llList2Integer(temp, 4);
BACKLINK = llList2Integer(temp, 5);
LIST_OFFSET = 0; // Set the List offset to the beginning of the list
TOTAL_ENTRIES = llGetListLength(DLG_CONTENT); // Determine the total length of the list
DLG_CHANNEL = make_dlg_channel(); // Create an arbitrary channel to listen for the dialog
show_dlg(DLG_CONTENT);
}
}
listen(integer channel, string name, key id, string message)
{
if(channel == DLG_CHANNEL && id == AGENT_REQUEST) // The User clicked on an option
{
if(message == "Back...") // The selected option was 'back'
{
if(LIST_OFFSET > 0)
{
// if we're not at the beginning of the options-list,
// set the Offset back and call the dialog again
LIST_OFFSET -= 10;
show_dlg(DLG_CONTENT);
}
else
{
// We're at the beginning of the options list - send the back-msg back to the calling script
llMessageLinked(REQUESTING_LINK, REQUESTING_SCRIPT, "back", AGENT_REQUEST);
}
}
else if(message == "Next...")
{
// The User wants to see the next portion of the options-list
// increment the list-offset and show the dialog again
LIST_OFFSET += 10;
show_dlg(DLG_CONTENT);
}
else
{
// The user has made her/his choice - send the answer back to the calling script
llMessageLinked(REQUESTING_LINK, REQUESTING_SCRIPT, CMD + "|" + message, AGENT_REQUEST);
}
}
}
timer()
{
llListenRemove(LISTENER_DLG);
}
on_rez(integer bla)
{
llResetScript();
}
}
****************
Here comes the second part - a.k.a. how to call this function
Alter this script an put it in whatever object in your linkset (or a single-prim object) where you need to call a dialog.
CODE
// Dialog-Caller
// By Haruki Watanabe
// This script is public domain - use it, share it, to whatever you wanna do... :)
// The MENU is just for example purposes - you can add your own list of choice here...
// Event something like ["Yes", "No"] to simply present a yes/no dialog
list MENU = ["1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th", "10th", "11th", "12th", "13th"];
integer THIS_SCRIPT = 1000; // Number of this script - will be used to determine, whether a linked message is meant for this script
key AGENT_REQUEST; // ID of the Agent that clicked
default
{
state_entry()
{
llSetText("func.show_dialog", <255,255,255>, 1.0);
}
touch_start(integer total_number)
{
AGENT_REQUEST = llDetectedKey(0);
// Call the script with the Dialog maker
// The String that we send to the dialog-function is parsed by a pipe-sign «|»
// 6 Parts
// 0 = SHOW_DIALOG -> To tell the dialog-maker, that it's its turn
// 1 = The menu-options as CSV-List
// 2 = The title of the Dialog
// 3 = The number of this script (will be sent back with llMessageLinked, when the user clicked an option
// 4 = Whether or not to show the shown entries / total entries in the dialog-title
// 5 = Whether or not to show a «back»-Button in the dialog
// 4 and 5 -> 1 = Yes, 0 = No
string to_send = "SHOW_DIALOG|" + llList2CSV(MENU) + "|Please choose an item|" + (string)THIS_SCRIPT + "|1|1";
llMessageLinked(0, 0, to_send, AGENT_REQUEST);
}
link_message(integer sender, integer num, string str, key id)
{
if(num == THIS_SCRIPT && id == AGENT_REQUEST)
{
// parse the message to look for Commands
list tmp = llParseString2List(str, ["|"], []);
string CMD = llList2String(tmp, 0);
if(CMD == "SHOW_DIALOG")
{
llOwnerSay("The Agent's answer to the dialog was '" + str + "'");
}
}
}
}