Monday, November 08, 2010 at 12:04 AM.
system.verbs.builtins.mainResponder.discuss.renderOneMessage
on renderOneMessage (adrMsgTable, adrTemplate, flShowAuthor=true, flShowPostTime=true, flShowReadCount=true, flShowResponseCount=true, flShowEnclosures=true, flShowResponseForm=true, flShowCowSkullLink=false, editPageUrl="", adrData=nil, bgColor="ivory", otherColor="beige", headerColor="black", headerTextColor="ivory", adrGetBodyCallback=nil, adrGetTimeCallback=nil, cssPrefix="", y=nil, m=nil, d=nil, defaultMode="day", responseItemTemplate=nil, responseListHeader=nil, responseListFooter=nil, responseIndentTemplate=nil, responseSubThreadStartTemplate=nil, responseSubThreadEndTemplate=nil, pta=nil, userIcon=nil, adrInDgCallback=nil, depthToExpandResponses=0, flResponsesInChronologicalOrder=false, responseFullItemTemplate=nil, flUseMappedMemberKeys=false) { <<Render a single message in a thread, flowing through a template if specified. <<10/11/00; 10:30:27 PM by JES <<Changes: <<4/8/03; 11:43:18 PM by JES <<Added support for the {ipAddress} pseudo-macro in the template. <<4/4/02; 1:07:05 AM by JES <<New optional parameter, adrInDgCallback, is the address of a callback which determines whether a message should be included in the rendering. If the callback returns true, add the message. If it returns false, don't add the message. <<More new optional params: depthToExpandResponses, flResponsesInChronologicalOrder and responseFullItemTemplate, used for displaying the full text of responses in the response list. These support the Slashdot-style discussion group renderings. <<10/18/01; 11:11:11 AM by PBS <<Don't use IP address when constructing URLs to built-in icons. Fixes a bug with machines with multiple IP addresses. <<11/21/00; 6:04:09 PM by PBS <<Use new bottleneck for displaying edit message in Pike button. <<10/18/00; 10:48:50 PM by JES <<Commented out code that adds the Edit in Frontier button. <<10/14/00; 2:29:42 PM by JES <<Added 'in response to xxx' to the msg number when rendered in a template. <<10/13/00; 12:05:00 AM by JES <<Added support for template-based rendering. bundle { // get pta, adrData, y, m and d if pta == nil { pta = html.getPageTableAddress ()}; if adrData == nil { adrData = mainResponder.discuss.openRoot (pta)}; if y == nil { y = date.year ()}; if m == nil { m = date.month ()}; if d == nil { d = date.day ()}}; bundle { //increment read stats on the top message adrMsgTable^.ctReads++; config.mainResponder.stats.ctDiscussionGroupReads++}; local (flMember = defined (pta^.adrMemberInfo)); local (membershipGroup = pta^.responderAttributes.defaultMembershipGroup); local (flCss = (cssPrefix != "")); local (msgReaderUrl = pta^.urls^.discussMsgReader); if not (msgReaderUrl endsWith "$") { msgReaderUrl = msgReaderUrl + "$"}; on buildSearchArgs (adrArgTable) { local (ct = sizeOf (adrArgTable^), i, s = "?"); for i = 1 to ct { s = s + nameOf (adrArgTable^[i]) + "=" + adrArgTable^[i] + "&"}; s = string.mid (s, 1, sizeOf (s) - 1); return (s)}; local (mode, thisModeSearchArgs, otherModeSearchArgs, replyToThisSearchArgs, flShowResponses=true); bundle { // get the mode, and the search args for preserving and switching the mode local (searchArgs = "", argTable); new (tableType, @argTable); bundle { //parse search args if defined (pta^.searchArgs) { searchArgs = pta^.searchArgs}; webserver.parseArgs (searchArgs, @argTable)}; if not defined (argTable.mode) { argTable.mode = defaultMode}; bundle { //user-specifiable search args if defined (argTable.showResponses) { flShowResponses = boolean (argTable.showResponses)}; if defined (argTable.expandToDepth) { depthToExpandResponses = number (argTable.expandToDepth)}; if defined (argTable.newestFirst) { flResponsesInChronologicalOrder = not boolean (argTable.newestFirst)}}; bundle { //this mode search args argTable.mode = string.lower (argTable.mode); mode = argTable.mode; thisModeSearchArgs = buildSearchArgs (@argTable)}; bundle { //reply to this search args local (replyArgsTable = argTable); replyArgsTable.showResponses = false; replyToThisSearchArgs = buildSearchArgs (@replyArgsTable)}; bundle { //other mode search args local (otherModeArgsTable = argTable); if otherModeArgsTable.mode == "day" { otherModeArgsTable.mode = "topic"} else { otherModeArgsTable.mode = "day"}; otherModeSearchArgs = buildSearchArgs (@otherModeArgsTable)}}; local (htmltext); local (msgnum = adrMsgTable^.msgnum); local (template); if adrTemplate != nil { template = string (adrTemplate^)}; local (userIconUrl, userIconHeight = 16, userIconWidth = 16); local (internalLinkImgUrl, internalLinkImgWidth = 11, internalLinkImgHeight = 9, internalLinkUrl); bundle { // build image data for internal link arrows and message status icons <<local (myDottedId = tcp.myDottedId ()) <<local (myPort = user.inetd.config.http.port) <<local (portString = "") <<if myPort != 80 <<portString = ":" + myPort <<local (resourcesUrl = "http://" + myDottedId + portString + "/mainResponderResources/") local (resourcesUrl = "/mainResponderResources/"); internalLinkImgUrl = resourcesUrl + "icons/leftArrow"; internalLinkUrl = pta^.responderAttributes.urls^.discussMsgReader; if not (internalLinkUrl endsWith '$') { internalLinkUrl = internalLinkUrl + "$"}; <<internalLinkUrl = internalLinkUrl + msgNum + "#" userIconUrl = resourcesUrl + "icons/user"; <<msgIconUrl = resourcesUrl + "icons/message" if userIcon == nil { userIcon = "<img src=\"" + userIconUrl + "\" height=\"" + userIconHeight + "\" width=\"" + userIconWidth + "\" border=\"0\" alt=\"user\">"}}; local (cowskullImg = mainResponder.discuss.cowSkullImage (pta), cowskullLink); bundle { // get the cowskull link html cowskullLink = "<a href=\"" + pta^.responderAttributes.urls^.discussMsgReader + msgNum + otherModeSearchArgs + "\">" + cowskullImg + "</a>"}; on add (s) { htmlText = htmlText + s}; on countResponses (adrMsgTable) { // count all the responses in a thread local (responseCount); local (i, ct = sizeOf (adrMsgTable^.responses)); responseCount = ct; for i = 1 to ct { local (adrResponse = @adrData^.messages.[string.padWithZeros (adrMsgTable^.responses[i], 7)]); if sizeOf (adrResponse^.responses) { responseCount = responseCount + countResponses (adrResponse)}}; return (responseCount)}; on getBody (adrMsgTable) { // get the body of the message, calling callbacks if necessary local (body, flCallbackReturnedBody = false); if adrGetBodyCallback != nil { body = adrGetBodyCallback^ (adrMsgTable); if body != "" { <<add (body) flCallbackReturnedBody = true}}; if not flCallbackReturnedBody { bundle { //PBS 10/20/99: if an image is attached to this message, display it above the body if defined (adrMsgTable^.image) { if defined (pta^.responderAttributes.urls^.imageViewer) { //must be defined: it's the link to the imageViewer script <<The imageViewer script takes a msgNum as pathArgs and displays the picture attached to that dg message. body = body + mainResponder.discuss.buildImageTag (adrMsgTable^.msgNum); body = body + "<p>"}}}; if typeOf (adrMsgTable^.body) == outlineType { //outlines get passed through an outline renderer local (oldRenderOutlineWith = nil); if defined (pta^.renderOutlineWith) { oldRenderOutlineWith = pta^.renderOutlineWith}; if defined (pta^.renderDiscussOutlinesWith) { pta^.renderOutlineWith = pta^.renderDiscussOutlinesWith}; if defined (pta^.flReadMessageProcessMacros) and pta^.flReadMessageProcessMacros { try {body = body + html.processMacros (html.tenderRender (@adrMsgTable^.body), false, pta)}} else { if defined (pta^.flReadMessageExpandUrls) and not pta^.flReadMessageExpandUrls { try {body = body + html.tenderRender (@adrMsgTable^.body)}} else { //default, original behavior try {body = body + html.expandURLs (html.tenderRender (@adrMsgTable^.body))}}}; if oldRenderOutlineWith != nil { pta^.renderOutlineWith = oldRenderOutlineWith}} else { //it's not an outline local (s = string (adrMsgTable^.body)); s = string.replaceAll (s, "\n", ""); //2/15/99 DW, inside <pre>s these cause extra line-skips if not (defined (pta^.flReadMessageAutoParagraphs)) or pta^.flReadMessageAutoParagraphs { s = string.replaceAll (s, "\r\r", "\r\r<p>")}; if not (defined (pta^.flReadMessageProcessMacros)) or pta^.flReadMessageProcessMacros { s = html.processMacros (s, false, pta)}; body = body + s}}; return (body)}; on getEditButtons () { //add Edit button (or buttons) to the page local (s, editableInFrontier = false); <<s = s + "<table cellpadding=\"5\" cellspacing=\"0\" border=\"0\" bgcolor=\"white\"><tr>" <<if defined (pta^.adrMemberInfo^.isFrontierSixAlpha) //edit in Frontier button <<local (url = pta^.responderAttributes.urls^.discussEditInFrontier + msgNum) << <<Build the Edit in Frontier button. <<s = s + "<td valign=\"baseline\">" <<s = s + "<form method=\"POST\" action=\"" + url + "\">" <<s = s + "<input name=\"msgnum\" type=\"hidden\" value=\"" + msgNum + "\">" <<s = s + " <input type=\"submit\" value=\"" + mainResponder.getString ("discuss.editInFrontier") + "\">" <<s = s + "</form>" <<s = s + "</td>" << <<editableInFrontier = true bundle { //edit in web browser button if editPageURL == "" { editPageURL = pta^.responderAttributes.urls^.discussEditInBrowser}; <<s = s + "<td valign=\"baseline\">" s = s + "<form method=\"POST\" action=\"" + editPageURL + msgNum + "\">"; s = s + "<input name=\"msgnum\" type=\"hidden\" value=\"" + msgNum + "\">"; local (buttonValue = " " + mainResponder.getString ("discuss.editThisPage") + " "); if editableInFrontier { buttonValue = mainResponder.getString ("discuss.editInBrowser"); //change button name from Edit this Page to Edit in Browser s = s + " "}; s = s + " <input type=\"submit\" value=\"" + buttonValue + "\">"; s = s + "</form>"; }; <<s = s + "</td>" bundle { //PBS 01/13/00: Add the Edit in Pike button <<if defined (pta^.responderAttributes.urls^.editInPike) <<Pike support is a feature not of mainResponder but of Manila. However, this script, which displays the discussion group messages and the Edit this Page button, needs to be Pike-aware enough to display the Pike button. <<if manilaSuite.pike.memberHasPike (pta) <<local (editInPikeUrl = pta^.responderAttributes.urls^.editInPike) <<if not (editInPikeUrl endsWith "$") <<editInPikeUrl = editInPikeUrl + "$" <<editInPikeUrl = editInPikeUrl + msgNum <<local (adrSite = pta^.adrSiteRootTable) <<local (adrMember = pta^.adrMemberInfo) << <<s = s + "<td valign=\"baseline\">" <<s = s + " " + manilaSuite.pike.pikeButton (editInPikeUrl, adrMsgTable, adrMember, adrSite, true, mainResponder.getString ("discuss.editThisStoryInPikeOutline"), pta) //true because this is a message <<s = s + "</td>" s = s + " " + manilaSuite.pike.editMessageButton (adrMsgTable, pta:pta)}; //PBS 11/21/00: use new bottleneck for displaying edit message in Pike button <<s = s + "</tr></table>" return (s)}; on getTopicMsgTable () { local (nomad = adrMsgTable); while nomad^.inResponseTo > 0 { <<nomad = @adrData^.messages.[string.padWithZeros (nomad^.inResponseTo, 7)] nomad = mainResponder.discuss.getMessageTable (nomad^.inResponseTo, pta, adrData)}; return (nomad)}; on getNextMsgNum () { local (lastMsgNum = adrData^.prefs.nextMsgNum - 1); local (nomad, nextMsgNum = msgNum + 1); while nextMsgNum <= lastMsgNum { nomad = mainResponder.discuss.getMessageTable (nextMsgNum, pta, adrData); if not (mainResponder.discuss.isMessageDeleted (nextMsgNum, nomad, pta:pta)) { if adrInDgCallback == nil { return (nextMsgNum)} else { local (adrmsg = mainResponder.discuss.getMessageTable (nextMsgNum, pta)); if adrInDgCallback^ (adrmsg) { return (nextMsgNum)}}}; nextMsgNum++}; return (0)}; on getPrevMsgNum () { local (nomad, prevMsgNum = msgNum - 1); while prevMsgNum > 0 { nomad = mainResponder.discuss.getMessageTable (prevMsgNum, pta, adrData); if not (mainResponder.discuss.isMessageDeleted (prevMsgNum, nomad, pta:pta)) { if adrInDgCallback == nil { return (prevMsgNum)} else { local (adrmsg = mainResponder.discuss.getMessageTable (prevMsgNum, pta)); if adrInDgCallback^ (adrmsg) { return (prevMsgNum)}}}; prevMsgNum--}; return (prevMsgNum)}; on obscureEmail (s, link=false) { if s contains '@' { local (part1 = string.nthField (s, '@', 1)); local (part2 = string.nthField (s, '@', 2)); if link { return ("<a href=\"mailto:" + s + "\">" + part1 + "@" + part2[1] + "...</a>")} else { return (part1 + "@" + part2[1] + "...")}}; return (s)}; if mainResponder.discuss.isMessageDeleted (msgNum, adrMsgTable, pta) { return ("")}; bundle { //calculate enclosure and edit buttons display flags flShowEnclosures = flShowEnclosures and (defined (adrMsgTable^.enclosureAddress) and (adrMsgTable^.enclosureAddress != "")); flShowEditButtons = (flMember and (mainResponder.discuss.memberCanEdit (adrMsgTable, pta^.adrMemberInfo, pta)))}; if adrTemplate == nil { //render the message in default fashion bundle { //add member, internal link, read count and date if flCss { // the header row and cell add ("<tr class=\"" + cssPrefix + "HeaderRow\">"); add ("<td class=\"" + cssPrefix + "AuthorCell\">")} else { add ("<tr><td>")}; bundle { // the header table add ("<table bgcolor=\"" + othercolor + "\" cellpadding=\"5\" cellspacing=\"0\" border=\"0\" width=\"100%\"><tr><td>"); if flShowAuthor { add (mainResponder.members.linkToMember (membershipGroup, adrMsgTable^.member, hideEmail: true, useMap:flUseMappedMemberKeys))} else { add (" ")}; bundle { // add internal link add ("<a name=\"" + msgNum + "\"> </a>"); add ("<a href=\"" + internalLinkUrl + msgNum + "?y=" + y + "&m=" + m + "&d=" + d + "\" title=\"Permanent link to this message in archives.\">"); add ("<img src=\"" + internalLinkImgUrl + "\" height=\"" + internalLinkImgHeight + "\" width=\"" + internalLinkImgWidth + "\" border=\"0\" alt=\"blueArrow\"></a>")}; if flShowReadCount or flShowResponseCount { local (s = " ("); if flShowReadCount { s = s + adrMsgTable^.ctReads + " read"; if adrMsgTable^.ctReads != 1 { s = s + "s"}; if flShowResponseCount { s = s + ", "}}; if flShowResponseCount { local (responses = countResponses (adrMsgTable)); s = s + responses + " response"; if responses != 1 { s = s + "s"}}; s = s + ")"; add ("<font size=\"-1\">" + s + "</font>")}; add ("</td>"); if flCss { // the post time cell and font add ("<td class=\"" + cssPrefix + "DateCell\" align=\"right\"><font size=\"-1\">")} else { add ("<td align=\"right\" width=\"100%\"><font size=\"-1\">")}; if flShowPostTime { local (postTime = adrMsgTable^.postTime); if adrGetTimeCallback != nil { postTime = adrGetTimeCallback^ (postTime)}; add (mainResponder.localization.abbrevDateString (postTime, pta) + " " + mainResponder.localization.timeString (postTime, pta))} else { add (" ")}; add ("</font></td>"); add ("</table>")}; add ("</td></tr>"); }; <<add ("</font></td></tr>") bundle { //add the body of the message if flCss { // the row and cell containing the body of the message add ("<tr bgcolor=\"white\" class=\"" + cssPrefix + "BodyRow\">"); add ("<td class=\"" + cssPrefix + "BodyCell\">")} else { add ("<tr bgcolor=\"white\"><td>")}; bundle { // the body table add ("<table cellpadding=\"5\" cellspacing=\"0\" border=\"0\" width=\"100%\"><tr><td>"); add (getBody (adrMsgTable)); if flShowEditButtons { add (getEditButtons ())}; if flShowCowSkullLink { //add cowskull link to standard msgReader page <<The cowskull link is a link to the discussion group interface version of this page. add ("<p>" + cowskullLink + "</p>")}; add ("</td></tr></table>")}; add ("</td></tr>")}} else { //flow the message through the template, and add it local (s = template, lowerTemplate = string.lower (template)); bundle { // replace bgcolor, headerColor and headerTextColor s = string.replaceAll (s, "{bgcolor}", otherColor, false); s = string.replaceAll (s, "{headerColor}", headerColor, false); s = string.replaceAll (s, "{headerTextColor}", headerTextColor, false)}; bundle { // replace author local (memberLink = mainResponder.members.linkToMember (membershipGroup, adrMsgTable^.member, hideEmail: true, useMap:flUseMappedMemberKeys)); s = string.replaceAll (s, "{author}", memberLink, false)}; bundle { // replace authorIcon s = string.replaceAll (s, "{authorIcon}", userIcon, false)}; bundle { // replace subject s = string.replaceAll (s, "{subject}", adrMsgTable^.subject, false)}; bundle { // replace topic link -- this does a mode flip local (topicLink, topicMsgTable = getTopicMsgTable ()); topicLink = "<a href=\"" + msgReaderUrl + topicMsgTable^.msgNum + otherModeSearchArgs + "\""; if flCss { topicLink = topicLink + " class=\"" + cssPrefix + "TopicLink\""}; topicLink = topicLink + ">" + topicMsgTable^.subject + "</a>"; s = string.replaceAll (s, "{topicLink}", topicLink, false)}; bundle { // replace messageNumberLink -- this doea a mode flip local (msgNumLink = "<a href=\"" + msgReaderUrl + msgNum + otherModeSearchArgs + "\""); if flCss { msgNumLink = msgNumLink + " class=\"" + cssPrefix + "MessageNumberLink\""}; msgNumLink = msgNumLink + ">" + msgNum + "</a>"; s = string.replaceAll (s, "{messageNumberLink}", msgNumLink, false)}; bundle { // replace inResponseToLink local (inResponseToLink); if adrMsgTable^.inResponseTo > 0 { local (replacementTable); new (tableType, @replacementTable); replacementTable.msglink = "<a href=\"" + msgReaderUrl + adrMsgTable^.inResponseTo + thisModeSearchArgs + "\">" + adrMsgTable^.inResponseTo + "</a>"; inResponseToLink = mainResponder.getString ("discuss.inResponseTo", @replacementTable, pta: pta)} else { inResponseToLink = mainResponder.getString ("discuss.topMsgInThread", pta: pta)}; s = string.replaceAll (s, "{inResponseToLink}", inResponseToLink, false)}; bundle { // replace previousMessageLink local (prevMsgNum = getPrevMsgNum (), msgNumLink = ""); if prevMsgNum { msgNumLink = "<a href=\"" + msgReaderUrl + prevMsgNum + thisModeSearchArgs + "\""; if flCss { msgNumLink = msgNumLink + " class=\"" + cssPrefix + "PreviousMessageLink\""}; msgNumLink = msgNumLink + ">" + prevMsgNum + "</a>"}; s = string.replaceAll (s, "{previousMessageLink}", msgNumLink, false)}; bundle { // replace nextMessageLink local (nextMsgNum = getNextMsgNum (), msgNumLink = ""); if nextMsgNum { msgNumLink = "<a href=\"" + msgReaderUrl + nextMsgNum + thisModeSearchArgs + "\""; if flCss { msgNumLink = msgNumLink + " class=\"" + cssPrefix + "NextMessageLink\""}; msgNumLink = msgNumLink + ">" + nextMsgNum + "</a>"}; s = string.replaceAll (s, "{nextMessageLink}", msgNumLink, false)}; bundle { // replace postTime local (d = adrMsgTable^.postTime); if adrGetTimeCallback != nil { d = adrGetTimeCallback^ (d)}; s = string.replaceAll (s, "{postTime}", d, false)}; bundle { // replace readCount s = string.replaceAll (s, "{readCount}", adrMsgTable^.ctReads, false)}; bundle { // replace response count if lowerTemplate contains "{responsecount}" { // this may be time-consuming if there are lots of responses s = string.replaceAll (s, "{responseCount}", countResponses (adrMsgTable), false)}}; bundle { // replace editLink if flShowEditButtons { s = string.replaceAll (s, "{editLink}", getEditButtons (), false)} else { // replace with the empty string s = string.replaceAll (s, "{editLink}", "", false)}}; bundle { // replace discussLink -- this is the cowskull, and it's a mode flip if flShowCowSkullLink { s = string.replaceAll (s, "{discussLink}", cowskullLink, false)} else { // replace with the empty string s = string.replaceAll (s, "{discussLink}", "", false)}}; bundle { // replace internal link local (internalLink); internalLink = internalLink + "<a name=\"" + msgNum + "\"> </a>"; internalLink = internalLink + "<a href=\"" + internalLinkUrl + msgNum + "?y=" + y + "&m=" + m + "&d=" + d + "\" title=\"Permanent link to this message in archives.\">"; internalLink = internalLink + "<img src=\"" + internalLinkImgUrl + "\" height=\"" + internalLinkImgHeight + "\" width=\"" + internalLinkImgWidth + "\" border=\"0\" alt=\"blueArrow\"></a>"; s = string.replaceAll (s, "{internalLink}", internalLink, false)}; bundle { // replace responseList if lowerTemplate contains "{responselist}" { // short circuit if the template doesn't include a responseList macro because it may be time-consuming local (responseList = ""); if flShowResponses { bundle { // set default templates, headers, etc. <<It's not ideal, but we check to see if the value of mini-templates equals nil, and also that the type == typeOf (nil). That way we can tell the difference between the empty string and not having passed in a value. This is because the empty string equals nil, but its type is stringType, not typeOf (nil) if responseListHeader == nil and typeOf (responseListHeader) == typeOf (nil) { responseListHeader = "<p><hr><b>" + mainResponder.getString ("discuss.thereAreResponsesToThisMsg") + "</b></p>"}; if responseSubThreadStartTemplate == nil and typeOf (responseSubThreadStartTemplate) == typeOf (nil) { responseSubThreadStartTemplate = "<ul>"}; if responseSubThreadEndTemplate == nil and typeOf (responseSubThreadEndTemplate) == typeOf (nil) { responseSubThreadEndTemplate = "</ul>"}; if responseItemTemplate == nil and typeOf (responseItemTemplate) == typeOf (nil) { responseItemTemplate = "<li><p><a href=\"{responseUrl}\">{responseSubject}</a>, {responseAuthor}, {responsePostTime}</p></li>"}; if responseFullItemTemplate == nil and typeOf (responseFullItemTemplate) == typeOf (nil) { responseFullItemTemplate = responseItemTemplate}}; local (stack = {}); // keep track of which messages have been added to aviod infinite recursion on addResponses (adrItem, level = 0) { local (adrTable, msgNum, responseMember, i, ct = sizeOf (adrItem^.responses), itemHtml); local (flFullMessage = level <= (depthToExpandResponses - 1) ); //level is zero-based but the pref is 1-based if not flFullMessage { //add threadSubStartTemplate responseList = responseList + responseSubThreadStartTemplate}; on addResponse () { msgNum = adrItem^.responses [i]; if stack contains msgNum { //avoid infinite recursion continue; }; adrTable = mainResponder.discuss.getMessageTable (msgNum, pta, adrData); if not defined (adrTable^) { continue}; local (flAddMessage = not mainResponder.discuss.isMessageDeleted (msgNum, adrTable, pta) ); <<if flAddMessage <<if adrInDgCallback != nil <<flAddMessage = adrInDgCallback^ (adrTable) if flAddMessage { responseMember = mainResponder.members.getMemberName (membershipGroup, adrTable^.member); if flFullMessage { itemHtml = responseFullItemTemplate; if string.lower (responseFullItemTemplate) contains "{responsetext}" { //bump read count adrTable^.ctReads++; config.mainResponder.stats.ctDiscussionGroupReads++}; itemHtml = string.replaceAll (itemHtml, "{responseText}", adrTable^.body, false)} else { itemHtml = responseItemTemplate; itemHtml = string.replaceAll (itemHtml, "{responseText}", "", false)}; itemHtml = string.replaceAll (itemHtml, "{replyUrl}", msgReaderUrl + msgNum + replyToThisSearchArgs, false); itemHtml = string.replaceAll (itemHtml, "{responseUrl}", msgReaderUrl + msgNum + thisModeSearchArgs, false); itemHtml = string.replaceAll (itemHtml, "{responseSubject}", adrTable^.subject, false); itemHtml = string.replaceAll (itemHtml, "{responseAuthor}", obscureEmail (responseMember), false); itemHtml = string.replaceAll (itemHtml, "{responsePostTime}", mainResponder.localization.dateTimeString (adrTable^.postTime, pta: pta), false); itemHtml = string.replaceAll (itemHtml, "{responseMessageNumber}", adrTable^.msgNum, false); if responseIndentTemplate != "" { // work around kernel bug on windows: string.filledString ("", n) == crash. responseList = responseList + string.filledString (responseIndentTemplate, level)}; responseList = responseList + itemHtml; if sizeof (adrTable^.responses) > 0 { stack = stack + {adrTable^.msgNum}; addResponses (adrTable, level + 1); delete (@stack [sizeof (stack)])}}}; if flResponsesInChronologicalOrder { for i = 1 to ct { addResponse ()}} else { for i = ct downTo 1 { addResponse ()}}; if not flFullMessage { //add subThreadEntTemplate responseList = responseList + responseSubThreadEndTemplate}; }; if sizeOf (adrMsgTable^.responses) { responseList = responseListHeader; addResponses (adrMsgTable); //it's recursive responseList = responseList + responseListFooter}}; s = string.replaceAll (s, "{responseList}", responseList, false)}}; bundle { // replace messageText s = string.replaceAll (s, "{messageText}", getBody (adrMsgTable), false)}; bundle { // replace responseForm local (responseForm = "", responseFormHeader = "<p><hr>", responseFormFooter = ""); if flMember and flShowResponseForm { local (subject = adrMsgTable^.subject); if not (string.lower (subject) beginswith string.lower (string.trimWhiteSpace (mainResponder.getString ("discuss.rePrefix")))) { subject = mainResponder.getString ("discuss.rePrefix") + subject}; local (subjectprompt, buttontext, bodyprompt); subjectprompt = mainResponder.getString ("discuss.responseSubjectPrompt"); buttontext = mainResponder.getString ("discuss.postResponseButtonText"); bodyprompt = mainResponder.getString ("discuss.responseBodyPrompt"); responseForm = responseFormHeader + mainResponder.discuss.newMessageForm (msgNum, subject, subjectprompt, buttontext, bodyprompt: bodyprompt, pta:pta) + responseFormFooter}; s = string.replaceAll (s, "{responseForm}", responseForm, false)}; bundle { // 11/03/00 JES: replace enclosureLink if flShowEnclosures { local (viewingUrl = pta^.responderAttributes.urls^.discussEnclosureViewer + msgNum); local (listingLink = "<a href=\"" + viewingUrl + "\">" + mainResponder.getString ("discuss.viewEnclosure") + "</a>"); local (fatPageLink = "<a href=\"" + pta^.responderAttributes.urls^.discussEnclosureDownloader + msgNum + "\">" + mainResponder.getString ("discuss.fatPageEnclosure") + "</a>"); local (rpcLink = "<a href=\"" + pta^.responderAttributes.urls^.discussEnclosureRPCer + msgNum + "\">" + mainResponder.getString ("discuss.RPCenclosure") + "</a>"); s = string.replaceAll (s, "{enclosureLink}", listingLink + ", " + fatPageLink + ", " + rpcLink, false)} else { s = string.replaceAll (s, "{enclosureLink}", "", false)}}; bundle { //replace ipAddress local (ipAddress = ""); if defined (adrMsgTable^.ipAddress) { ipAddress = adrMsgTable^.ipAddress}; s = string.replaceAll (s, "{ipAddress}", ipAddress, false)}; add (s)}; bundle { //set member info <<For every member, store the highest message read for the current discussion group. <<First make sure the discussionGroupInfo table exists for this member, then make sure there's a table for this dg, then set highestMessageRead for this dg for this member. if flMember { //is this a member? local (adrMember = pta^.adrMemberInfo); if not defined (adrMember^.discussionGroupInfo) { new (tabletype, @adrmember^.discussionGroupInfo)}; local (rootName = nameOf (adrData^)); local (adrTable = @adrMember^.discussionGroupInfo.[rootName]); if not defined (adrTable^) { new (tableType, adrTable)}; if not defined (adrTable^.highestMessageRead) { adrTable^.highestMessageRead = 0}; if msgNum > adrTable^.highestMessageRead { adrTable^.highestMessageRead = msgNum}}}; return (htmltext)}
This listing is for code that runs in the OPML Editor environment. I created these listings because I wanted the search engines to index it, so that when I want to look up something in my codebase I don't have to use the much slower search functionality in my object database. Dave Winer.