<MIVA standardoutputlevel=""></MIVA>

<MvASSIGN NAME="OFF" VALUE = "{'<MIVA standardoutputlevel=\"\">'}">

<MvASSIGN NAME="ON"  VALUE = "{'<MIVA standardoutputlevel=\"text,html\">'}">

 

<MvCOMMENT>###################################################################

# Message Board                 Version 1.1                                  #

# Developed by Michael Sussna   Yahoo!                                       #

# Created 12/11/97              Last Modified 9/28/99                        #

# Based on WWWBoard                                                          #

# Copyright 1996 Matt Wright    mattw@worldwidemart.com                      #

# Scripts Archive at:           http://www.worldwidemart.com/scripts/        #

##############################################################################

# WWWBoard COPYRIGHT NOTICE                                                  #

# Copyright 1996 Matthew M. Wright  All Rights Reserved.                     #

#                                                                            #

# WWWBoard may be used and modified free of charge by anyone so long as      #

# this copyright notice and the comments above remain intact.  By using this #

# code you agree to indemnify Matthew M. Wright from any liability that      # 

# might arise from it's use.                                                 # 

#                                                                            #

# Selling the code for this program without prior written consent is         #

# expressly forbidden.  In other words, please ask first before you try and  #

# make money off of my program.                                              #

#                                                                            #

# Obtain permission before redistributing this software over the Internet or #

# in any other medium.  In all cases copyright and header must remain intact.#

##############################################################################

# Yahoo!, Inc. COPYRIGHT NOTICE                                              #

# Copyright 1998-1999 Simple Network Communications, Inc.                    #

# Copyright 1999-2000 Yahoo!, Inc.                                           #

# All rights reserved.                                                       #

##############################################################################

#                                                                            #

# CHANGE LOG                                                                 #

#                                                                            #

# Version 1.16, 8/01/01:                                                     #

#                                                                            #

# Added additional checks for executable code being submitted in form        #

# fields.                                                                    #

#                                                                            #

# Version 1.15, 8/16/00:                                                     #

#                                                                            #

# Added additional checks for executable code being submitted in form        #

# fields.                                                                    #

#                                                                            #

# Version 1.14, 6/7/00:                                                      #

#                                                                            #

# Added additional file locking logic to Remove and Compress Database        #

# functions.                                                                 #

#                                                                            #

# Version 1.13, 9/28/99:                                                     #

#                                                                            #

# Added MvLOCKFILE to Compress Database function.  This should prevent       #

# potential conflicting write accesses to the database during a compress.    #

#                                                                            #

# Version 1.12, 2/11/99:                                                     #

#                                                                            #

# Changed default year in search to be current year.                         #

#                                                                            #

# Version 1.11, 12/24/98:                                                    #

#                                                                            #

# Added URL information in post and followup preview.                        #

#                                                                            #

# Version 1.10, 12/18/98:                                                    #

#                                                                            #

# Added "In reply to" feature when viewing a message.                        #

# Changed access of messages to use MvFIND, significantly speeding access.   #

# Added wildcard to IP blocking in Admin.                                    #

#                                                                            #

##################################################################</MvCOMMENT>

 

<MvCOMMENT> Define Variables </MvCOMMENT>

 

<MvASSIGN NAME = "mesgdir"         VALUE = "{'messages'}">

<MvASSIGN NAME = "passwd_file"     VALUE = "{'passwd.txt'}">

<MvASSIGN NAME = "config_file"     VALUE = "{'config.txt'}">

<MvASSIGN NAME = "unwelcome_list"  VALUE = "{'unwelcome.txt'}">

<MvASSIGN NAME = "unwelcome_list2" VALUE = "{'unwelcome2.txt'}">

<MvASSIGN NAME = "ext"             VALUE = "{'txt'}">

<MvCOMMENT> This is a special self number in the database: </MvCOMMENT>

<MvASSIGN NAME = "super_root"      VALUE = "{'9999999'}">

<MvCOMMENT>

      The message board is displayed in a specific sequence.  The most recent

      main postings (or roots) are displayed first.  Within each main posting

      any followup postings are then displayed, most recent first.  Followups

      to followups are displayed most recent first, and so on.  This produces

      a hierarchy of postings.

 

      To build this display as fast as possible from the database, each posting

      is assigned a sequence number.  The sequence numbers are designed so that

      the hierarchy follows from simply listing the postings in sequence.  For

      example, suppose that there are 10 postings that should display in the

      following hierarchy:

 

            4

                  10

                  5

                        8

                              9

                        6

                              7

            3

            1

                  2

 

      The main postings are 1, 3, and 4.  4 is the most recent main posting.

      Posting 4 has 2 followups, 5 and 10.  10 is more recent than 5 and has

      no followups.  5 has two followups, 6 and 8, each of which has a followup.

      The numbering of the postings reflects the order in which they were

      created, 10 being the most recently created posting.

 

      To simply list the postings so that they would display in the proper

      order above, we would need the following relationships between any

      sequence numbers assigned: 4's sequence number should be first in the

      list, followed by 10's, 5's, 8's, 9's, 6's, 7's, 3's, 1's, and finally

      2's.

 

      We could assign ascending sequence numbers, but we actually assign

      descending numbers.  So, in our example, we could think of the sequence

      number assignments as 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 for postings

      4, 10, 5, 8, 9, 6, 7, 3, 1, and 2 respectively.

 

      There are several constraints which influence our scheme for sequence

      numbering:

 

      Each posting should have a unique sequence number --- we want to avoid

      duplicates so that there is no ambiguity when listing postings.

 

      Each sequence number should correctly reflect the relative position of its

      posting in the hierarchy --- thus it should fall between the sequence

      numbers of the postings between which the new posting is being inserted.

 

      Insertion can occur at any arbitrary point in the hierarchy.  We cannot

      know ahead of time how many postings will be placed at any given location.

 

      Finally, we need to allow for a reasonably large number of levels of

      followup.  In actual practice it is not unusual to see 20 levels of

      followup.  That is, one main posting could have a followup which could

      have a followup which could have a followup, and so on, to 20 levels of

      followup.

 

      To accommodate these constraints, we have devised the following scheme

      for sequence numbering.  Unique numbering is supported by careful planning

      for handling the other constraints.  Reflecting relative position in the

      hierarchy is provided by selecting a sequence number for a new posting

      that lies between the sequence numbers of the postings before and after

      the new posting.

 

      By assigning each root a comfortable range of numbers for its followups,

      we lay the foundation for satisfying the final two constraints.  Suppose

      that we allow 1000 followups per root.  So the roots are numbered 1000,

      2000, and so on as they are created.  Followups are numbered sequentially

      from 1 within that range.  So root 2000's followups fall in the range

      1001 - 1999, since posting 2000 must display before any of its followups.

      The first followup gets 1001.  If a second followup to posting 2000 is

      created, it gets sequence number 1002.  But what if a followup to posting

      1001 is created?  It needs a sequence number lower than 1001, since it

      must display after 1001, right?  What if we renumber so that what was 1001

      becomes 1002, and the new posting gets 1001?  This is the scheme that we use.

 

      As a followup is inserted, it causes a renumbering of all followups between

      it and the root.  So suppose we have 1001 - 1005, and need to insert a new

      followup to 1003?  1001 and 1002 can stay unchanged.  1003 - 1005 need to

      be incremented, and the new posting becomes 1003.  The root stays at 2000.

 

      This scheme satisfies both of the final constraints because arbitrary

      insertion is accommodated and because any number of levels of followup is

      allowed as well.  At least, any number of followups that fit within the

      range of 1000 numbers.  Nested followups share the range of numbers with

      any other followups.

 

      But how does this method affect performance?  Since the renumbering is

      localized to just the region of numbers assigned to a single root, this 

      minimizes the impact.  Since just the followups between the new posting and

      the root must be visited, this reduces the impact further.

 

      All ancestors of a new posting must be visited, to update their count of

      descendents.  We do this by moving back from the parent to the root.  All

      of the postings between the root and the new posting must have their

      sequence numbers incremented.  We do this by moving forward from the root

      to the parent.

 

      Unfortunately these two movements oppose each other.  But, each requires

      its specific direction of motion.  The chain of ancestors flows bottom up

      in the hierarchy, that is, from leaf to root.  We learn the parent of a

      posting from the posting's database record.  This means traveling from

      parent to grandparent etc. as we move back to the root via index1

      (sequence number).  Not all of the postings encountered are necessarily

      in the lineage of the new posting.

 

      For updating the sequence numbers, we move forward from the root because

      otherwise we would be assigning duplicate numbers temporarily, which is

      enough time to do damage.  For example, say we have root 2000 and followups

      1002 and 1001 under it.  We want to insert a followup to 1001.  Note

      that it doesn't matter whether 1001 and 1002 are both followups to 2000,

      or 1001 is a followup to 1002.  We want the end result of the insertion

      to be the sequence 2000, 1003, 1002, 1001 with the new posting being 1001.

 

      If we start the renumbering with the old 1001 and move back towards the

      root, when we make 1001 into 1002 we now temporarily have two 1002's.

      This throws off the index and plays havoc.  Skipping back from this finds

      2000, not the original 1002.  So, we must start from the root and move

      forward, making 1002 into 1003, then 1001 into 1002.  Then we can safely

      create a new sequence number of 1001 for the new posting.

 

      One final note on performance considerations is the following.  The current

      maximum sequence number is stored in the super root as its sequence number.

      This means that we have to retrieve that sequence number before inserting

      a main posting, and update that number with the new value.  But we have to

      access the super root's database record anyway when we create a posting,

      because we need to update its number of descendents, which generates the

      message number for the new posting.

 

      By using a 10-digit number for sequencing, and allowing 1000 followups per

      main posting, we are allowing for 10,000,000 main postings.  We can change

      these values, but doing so means that existing postings would be obsolete.

 

</MvCOMMENT>

<MvASSIGN NAME = "max_seqnum_increment" VALUE = "{'0000001000'}">

<MvASSIGN NAME = "seqnum_size"           VALUE = "{'10'}">

<MvCOMMENT> Increment for creating self and parent numbers: </MvCOMMENT>

<MvASSIGN NAME = "big_bump"        VALUE = "{'1000000'}">

 

<MvASSIGN NAME = "db_just_created" VALUE = "{'0'}">

<MvASSIGN NAME = "textwidth"       VALUE = "{'60'}">

<MvASSIGN NAME = "urlwidth"        VALUE = "{'80'}">

 

<MvASSIGN NAME = "admin_banner_ad"       VALUE = "{''

}">

 

<MvASSIGN NAME = "banner_ad"       VALUE = "{''

}">

 

<MvASSIGN NAME = "newline"      VALUE = "{asciichar(10)}">

<MvASSIGN NAME = "carriage"      VALUE = "{asciichar(13)}">

<MvASSIGN NAME = "crlf"            VALUE = "{carriage $ newline}">

<MvASSIGN NAME = "amp"            VALUE = "{asciichar(38)}">

<MvASSIGN NAME = "quote"      VALUE = "{asciichar(39)}">

<MvASSIGN NAME = "longquote"      VALUE = "{'&#039;'}">

<MvASSIGN NAME = "period"      VALUE = "{asciichar(46)}">

<MvASSIGN NAME = "slash"      VALUE = "{asciichar(47)}">

<MvASSIGN NAME = "less"            VALUE = "{asciichar(60)}">

<MvASSIGN NAME = "greater"      VALUE = "{asciichar(62)}">

<MvASSIGN NAME = "qmark"      VALUE = "{asciichar(63)}">

<MvASSIGN NAME = "atsign"      VALUE = "{asciichar(64)}">

<MvASSIGN NAME = "backslash"      VALUE = "{asciichar(92)}">

<MvASSIGN NAME = "newlines"      VALUE = "{crlf $ crlf}">

<MvASSIGN NAME = "longless"      VALUE = "{'&lt;'}">

<MvASSIGN NAME = "longgreater"     VALUE = "{'&gt;'}">

<MvASSIGN NAME = "dquote"      VALUE = "{'\"'}">

<MvASSIGN NAME = "longdquote"      VALUE = "{'&quot;'}">

<MvASSIGN NAME = "bullet"      VALUE = "{asciichar(149)}">

<MvASSIGN NAME = "nbsp"            VALUE = "{asciichar(174)}">

<MvASSIGN NAME = "longnbsp"      VALUE = "{'&nbsp;'}">

<MvASSIGN NAME = "indent"      VALUE = "{'&nbsp;&nbsp;&nbsp;&nbsp;'}">

<MvASSIGN NAME = "delim"      VALUE = "{'!!##!!'}">

<MvASSIGN NAME = "yuml"            VALUE = "{asciichar(255)}">

 

<MvCOMMENT>###########################################################</MvCOMMENT>

 

<MvCOMMENT>###########################################################</MvCOMMENT>

 

<MvCOMMENT> MAIN PROCESSING </MvCOMMENT>

 

      <MvEVAL EXPR = Initialization()>

 

      <MvIF EXPR = "{parm_func EQ 'showmain' OR parm_func EQ ''}">

            <MvEVAL EXPR = ShowMain()>

            <MvEXIT>

      <MvELSE>

      <MvIF EXPR = "{parm_func EQ 'showmsg'}">

            <MvEVAL EXPR = ShowMessage()>

            <MvEXIT>

      <MvELSE>

      <MvIF EXPR = "{parm_func EQ 'showpostform'}">

            <MvEVAL EXPR = ShowPostForm()>

            <MvEXIT>

      <MvELSE>

      <MvIF EXPR = "{parm_func EQ 'showsearch'}">

            <MvEVAL EXPR = ShowSearchForm()>

            <MvEXIT>

      <MvELSE>

      <MvIF EXPR = "{parm_func EQ 'post'}">

            <MvEVAL EXPR = PostControl()>

            <MvEXIT>

      <MvELSE>

      <MvIF EXPR = "{parm_func EQ 'postpreview'}">

            <MvEVAL EXPR = ShowPostPreview()>

            <MvEXIT>

      <MvELSE>

      <MvIF EXPR = "{parm_func EQ 'followuppreview'}">

            <MvEVAL EXPR = ShowFollowupPreview()>

            <MvEXIT>

      <MvELSE>

      <MvIF EXPR = "{parm_func EQ 'showfaq'}">

            <MvEVAL EXPR = ShowFAQ()>

            <MvEXIT>

      <MvELSE>

      <MvIF EXPR = "{parm_func EQ 'admin'}">

            <MvEVAL EXPR = Admin()>

            <MvEXIT>

      </MvIF>

      </MvIF>

      </MvIF>

      </MvIF>

      </MvIF>

      </MvIF>

      </MvIF>

      </MvIF>

      </MvIF>

 

      <MvEXIT>

 

<MvCOMMENT> END OF MAIN PROCESSING </MvCOMMENT>

 

 

<MvFUNCTION NAME = "Initialization">

 

      <MvIF EXPR = "{nargs GT 1 AND arg2 EQ 'admin'}">

            <MvASSIGN NAME = "parm_func" VALUE="{'admin'}">

      <MvELSE>

            <MvEVAL EXPR = GetFormInput()>

      </MvIF>

 

      <MvEVAL EXPR = FindMboardName()>

 

      <MvIF EXPR = "{NOT fexists(dirprefix)}">

            <MvASSIGN NAME = "x" VALUE = "{fmkdir(dirprefix)}">

      </MvIF>

 

      <MvASSIGN NAME = "msgfiledir" VALUE = "{dirprefix $ '/' $ mesgdir}">

      <MvIF EXPR = "{NOT fexists(msgfiledir)}">

            <MvASSIGN NAME = "x" VALUE = "{fmkdir(msgfiledir)}">

      </MvIF>

 

      <MvIF EXPR = "{NOT fexists(database)}">

            <MvEVAL EXPR = CreateDatabase()>

      </MvIF>

 

      <MvASSIGN NAME = "passwdfile" VALUE = "{dirprefix $ '/' $ passwd_file}">

      <MvIF EXPR = "{NOT fexists(passwdfile)}">

            <MvIF EXPR = "{action EQ 'provide_identity'}">      <MvCOMMENT> Done til input errors fixed </MvCOMMENT>

                  <MvEVAL EXPR = ProvideIdentity("ShowProvideIdentity")>

            <MvELSE>

                  <MvIF EXPR = "{parm_func EQ ''}">      <MvCOMMENT> 1st time in </MvCOMMENT>

                        <MvEVAL EXPR = ShowWelcome()>

                  <MvELSE>

                        <MvEVAL EXPR = ShowProvideIdentity()>

                  </MvIF>

            </MvIF>

      </MvIF>

 

      <MvASSIGN NAME = "configfile" VALUE = "{dirprefix $ '/' $ config_file}">

      <MvIF EXPR = "{NOT fexists(configfile)}">

            <MvEVAL EXPR = SetupLinks()>      <MvCOMMENT> No title yet, but don't care. </MvCOMMENT>

            <MvEVAL EXPR = AssignDefaultSettings()>

            <MvEVAL EXPR = ExportSettings()>

            <MvIF EXPR = "{p_user NE ''}">      <MvCOMMENT> If we just came from ShowProvideIdentity </MvCOMMENT>

                  <MvEVAL EXPR = ChooseAdminFunction(p_user,p_pass1)>

            <MvELSE>

                  <MvEVAL EXPR = ChooseAdminFunction(parm_user,parm_pass)>

            </MvIF>

            <MvEXIT>

      </MvIF>

      <MvASSIGN NAME = "unwelcomelist" VALUE = "{dirprefix $ '/' $ unwelcome_list}">

      <MvASSIGN NAME = "unwelcomelist2" VALUE = "{dirprefix $ '/' $ unwelcome_list2}">

 

      <MvEVAL EXPR = GetSettings()>   

      <MvEVAL EXPR = DateAndTime()>

      <MvEVAL EXPR = SetupLinks()>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "GetFormInput">

 

      <MvASSIGN NAME = "lenny" VALUE = "{len(QUERY_STRING)}">

      <MvASSIGN NAME = "curr_pos" VALUE = "{1}">

      <MvWHILE EXPR = "{curr_pos LE lenny}">

            <MvASSIGN NAME = "a1" VALUE = "{'=' CIN substring(QUERY_STRING,curr_pos,lenny-curr_pos+1)}">

            <MvIF EXPR = "{a1 GT 0}">

                  <MvASSIGN NAME = "a2" VALUE = "{'+' CIN substring(QUERY_STRING,curr_pos+a1,lenny-curr_pos-a1+1)}">

                  <MvIF EXPR = "{a2 EQ 0}">

                        <MvASSIGN NAME = "a2" VALUE = "{lenny-curr_pos-a1+2}">

                  </MvIF>

                  <MvASSIGN NAME = "x" VALUE = "{substring(QUERY_STRING,curr_pos,a1-1)}">

                  <MvASSIGN NAME = "&[x]"

                        VALUE = "{substring(QUERY_STRING,curr_pos+a1,a2-1)}">

            </MvIF>

            <MvASSIGN NAME = "curr_pos" VALUE = "{curr_pos + a1 + a2}">

      </MvWHILE>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "FindMboardName">

 

      <MvCOMMENT>

            The name of the msgboard is what immediately precedes ".mv" in the

            document URL, but parsing depends on whether the URL is an NSAPI or CGI URL.

 

            The user must give each message board Miva doc a unique name, e.g. msgboard1.mv,

            msgboard2.mv, etc.  Each message board will have a separate subdirectory

            under mivadata.  The subdirectory will be named with the unique message board

            name, e.g. msgboard1.  The path to the database files, etc. will be based on the

            message board name, e.g. mivadata/msgboard1/msgboard.dbf.

 

            If CGI, URL looks like either

                  .../cgi-bin/miva?xxx.mv+

            or

                  .../cgi-bin/miva?zzz/xxx.mv+

            where zzz is the path within the Documents directory (so could have >1 slash).

 

            If NSAPI, URL looks like either

                  ...xxx.mv?

            or

                  ...zzz/xxx.mv?

            where zzz is the path within the Documents directory (so could have >1 slash).

      </MvCOMMENT>

 

      <MvASSIGN NAME = "a1" VALUE = "{'.mv' CIN documenturl}">

      <MvASSIGN NAME = "curr_pos" VALUE = "{a1 - 1}">

 

      <MvIF EXPR = "{substring(documenturl,curr_pos+4,1) EQ qmark}">

            <MvWHILE EXPR = "{substring(documenturl,curr_pos,1) NE slash}">

                  <MvASSIGN NAME = "curr_pos" VALUE = "{curr_pos - 1}">

            </MvWHILE>

      <MvELSE>

            <MvWHILE EXPR = "{(substring(documenturl,curr_pos,1) NE slash)

                        AND (substring(documenturl,curr_pos,1) NE qmark)}">

                  <MvASSIGN NAME = "curr_pos" VALUE = "{curr_pos - 1}">

            </MvWHILE>

      </MvIF>

 

      <MvASSIGN NAME = "dirprefix" VALUE = "{substring(documenturl,curr_pos+1,a1-curr_pos-1)}">

 

      <MvASSIGN NAME = "database"    VALUE = "{'&[dirprefix];/msgboard.dbf'}"><MvCOMMENT> path name </MvCOMMENT>

      <MvASSIGN NAME = "index_file1" VALUE = "{'&[dirprefix];/msgboard1.mvx'}"><MvCOMMENT> path name </MvCOMMENT>

      <MvASSIGN NAME = "index_file2" VALUE = "{'&[dirprefix];/msgboard2.mvx'}"><MvCOMMENT> path name </MvCOMMENT>

      <MvASSIGN NAME = "index_file3" VALUE = "{'&[dirprefix];/msgboard3.mvx'}"><MvCOMMENT> path name </MvCOMMENT>

      <MvASSIGN NAME = "dbname"      VALUE = "{'&[dirprefix];'}"><MvCOMMENT> short name </MvCOMMENT>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "SetupLinks">

 

      <MvASSIGN NAME = "link_main_short"

             VALUE = "{'[ <a href="&[documenturl];parm_func=showmain+parm_starting_root=1">&[title];</a> ]'}">

      <MvASSIGN NAME = "link_main_short_dflt"

             VALUE = "{'[ <a href="&[documenturl];parm_func=showmain+parm_starting_root=1">Message Board</a> ]'}">

      <MvASSIGN NAME = "link_post_short"

             VALUE = "{'[ <a href="&[documenturl];parm_func=showpostform">Post Message</a> ]'}">

      <MvASSIGN NAME = "link_search_short"

             VALUE = "{'[ <a href="&[documenturl];parm_func=showsearch+parm_starting_root=1">Search</a> ]'}">

      <MvASSIGN NAME = "link_faq_short"

             VALUE = "{'[ <a href="&[documenturl];parm_func=showfaq">FAQ</a> ]'}">

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "GetSettings">

 

      <MvCOMMENT>

      Importing a single big field and parsing it into data fields takes

      one second.  Importing the fields individually takes several seconds.

      </MvCOMMENT>

 

      <MvIMPORT FILE = "&[configfile];" DELIMITER = "%%%%%%" FIELDS = "glob">

      </MvIMPORT>

      <MvASSIGN NAME = "curr_pos" VALUE = "{1}">

 

      <MvEVAL EXPR = ExtractSetting("roots_to_view")>

      <MvEVAL EXPR = ExtractSetting("entries_thread")>

      <MvEVAL EXPR = ExtractSetting("entries_msgnum")>

      <MvEVAL EXPR = ExtractSetting("entries_date")>

      <MvEVAL EXPR = ExtractSetting("entries_author")>

      <MvEVAL EXPR = ExtractSetting("time_zone")>

      <MvEVAL EXPR = ExtractSetting("show_faq")>

      <MvEVAL EXPR = ExtractSetting("quote_text")>

      <MvEVAL EXPR = ExtractSetting("use_time")>

      <MvEVAL EXPR = ExtractSetting("show_preview")>

      <MvEVAL EXPR = ExtractSetting("allow_gif")>

      <MvEVAL EXPR = ExtractSetting("allow_html_body")>

      <MvEVAL EXPR = ExtractSetting("allow_html_subj")>

      <MvEVAL EXPR = ExtractSetting("subject_line")>

      <MvEVAL EXPR = ExtractSetting("title")>

      <MvEVAL EXPR = ExtractSetting("header")>

      <MvEVAL EXPR = ExtractSetting("footer")>

      <MvASSIGN NAME = "linkline" VALUE = "{substring(glob,curr_pos,len(glob)-curr_pos+1)}">

     

      <MvIF EXPR = "{roots_to_view EQ '0'}">

            <MvASSIGN NAME = "roots_to_view" VALUE = "{'1'}">

      </MvIF>

 

      <MvASSIGN NAME = "admin_lit" VALUE = "{' Admin'}">

      <MvASSIGN NAME = "title2" VALUE = "{title $ admin_lit}">

                                                   

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "ExtractSetting" PARAMETERS = "glob_field">

 

      <MvASSIGN NAME = "a1" VALUE = "{delim CIN substring(glob,curr_pos,len(glob)-curr_pos+1)}">

      <MvASSIGN NAME = "&[glob_field];" VALUE = "{substring(glob,curr_pos,a1-1)}">

      <MvASSIGN NAME = "curr_pos" VALUE = "{curr_pos + a1 - 1 + len(delim)}">

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "DateAndTime">

 

      <MvCOMMENT> Figure out the date and time of the entry, accounting for the different time zones.

            The "time_zone" field is set in admin.</MvCOMMENT>

 

      <MvIF EXPR = "{tm_isdst}">           <MvCOMMENT> If daylight savings </MvCOMMENT>

            <MvASSIGN NAME = "time_t" VALUE = "{time_t + 3600}">      <MvCOMMENT> add one hour </MvCOMMENT>

      </MvIF>

 

      <MvASSIGN NAME = "month"  VALUE = "{time_t_month(time_t,time_zone)}">

      <MvASSIGN NAME = "day"    VALUE = "{time_t_dayofmonth(time_t,time_zone)}">

      <MvASSIGN NAME = "year"   VALUE = "{time_t_year(time_t,time_zone)}">

      <MvASSIGN NAME = "hour"   VALUE = "{time_t_hour(time_t,time_zone)}">

      <MvASSIGN NAME = "minute" VALUE = "{time_t_min(time_t,time_zone)}">

      <MvASSIGN NAME = "second" VALUE = "{time_t_sec(time_t,time_zone)}">

 

      <MvEVAL EXPR = DateAndTimeMonth()>

 

      <MvIF EXPR = "{minute LT '10'}">

            <MvASSIGN NAME = "minute" VALUE = "{'0' $ minute}">

      </MvIF>

 

      <MvIF EXPR = "{second LT '10'}">

            <MvASSIGN NAME = "second" VALUE = "{'0' $ second}">

      </MvIF>

 

      <MvASSIGN NAME = "time" VALUE = "{hour $ ':' $ minute $ ':' $ second}">

      <MvASSIGN NAME = "date" VALUE = "{month $ '/' $ day $ '/' $ year}">

 

      <MvCOMMENT> Get rid of any newlines </MvCOMMENT>

 

      <MvASSIGN NAME = "date" VALUE = "{glosub(date,newline,'')}">

 

      <MvASSIGN NAME = "long_date" VALUE = "{monthname $ ' ' $ day $ ', ' $ year $ ' at ' $ hour $ ':' $ minute $ ':' $ second}">

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "DateAndTimeMonth">

 

      <MvIF EXPR = "{month EQ '1'}">      <MvASSIGN NAME = "monthname" VALUE = "{'January'}">

      <MvELSE>

      <MvIF EXPR = "{month EQ '2'}">      <MvASSIGN NAME = "monthname" VALUE = "{'February'}">

      <MvELSE>

      <MvIF EXPR = "{month EQ '3'}">      <MvASSIGN NAME = "monthname" VALUE = "{'March'}">

      <MvELSE>

      <MvIF EXPR = "{month EQ '4'}">      <MvASSIGN NAME = "monthname" VALUE = "{'April'}">

      <MvELSE>

      <MvIF EXPR = "{month EQ '5'}">      <MvASSIGN NAME = "monthname" VALUE = "{'May'}">

      <MvELSE>

      <MvIF EXPR = "{month EQ '6'}">      <MvASSIGN NAME = "monthname" VALUE = "{'June'}">

      <MvELSE>

      <MvIF EXPR = "{month EQ '7'}">      <MvASSIGN NAME = "monthname" VALUE = "{'July'}">

      <MvELSE>

      <MvIF EXPR = "{month EQ '8'}">      <MvASSIGN NAME = "monthname" VALUE = "{'August'}">

      <MvELSE>

      <MvIF EXPR = "{month EQ '9'}">      <MvASSIGN NAME = "monthname" VALUE = "{'September'}">

      <MvELSE>

      <MvIF EXPR = "{month EQ '10'}">      <MvASSIGN NAME = "monthname" VALUE = "{'October'}">

      <MvELSE>

      <MvIF EXPR = "{month EQ '11'}">      <MvASSIGN NAME = "monthname" VALUE = "{'November'}">

      <MvELSE>          <MvASSIGN NAME = "monthname" VALUE = "{'December'}">

      </MvIF>

      </MvIF>

      </MvIF>

      </MvIF>

      </MvIF>

      </MvIF>

      </MvIF>

      </MvIF>

      </MvIF>

      </MvIF>

      </MvIF>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "RemoveYumlaut" PARAMETERS="infield">

 

      <MvCOMMENT> This subroutine should be physically before any calls to it.

            That's because of the following scenario.

 

            Yumlaut, which is ascii 255, means end of file to Miva.  If it is

            encountered at any point by a Miva script, the script terminates

            immediately, whether that is the desired action or not.

 

            Suppose there *is* a yumlaut in an input field.  Suppose also that

            we think we're prepared for this and we call this Remove function

            before we try to use the field for anything.  If the code for the

            function is physically after the call and the usage of the input

            field, the function is not found and the script crashes.

 

            Because the function is not found, the yumlaut in the input field

            is not removed.  The usage of the field thus still has the yumlaut.

            This causes immediate termination of the script at that point.

            This in turn causes the code following that point to not be seen,

            including this Remove function.  Thus the function is not found.

 

            The script crashes because it has a function that doesn't have a

            </MvFUNCTION>.  This is due to the false end of file, which causes

            the function within which the input field is used to end right away,

            before any more code is seen, including its </MvFUNCTION>.

      </MvCOMMENT>

 

      <MvASSIGN NAME = "curr_pos" VALUE = "{1}">

      <MvASSIGN NAME = "lenny" VALUE = "{len(infield)}">

      <MvASSIGN NAME = "outfield" VALUE = "{''}">

 

      <MvWHILE EXPR = "{curr_pos LE lenny}">

            <MvASSIGN NAME = "a1" VALUE = "{asciichar(255) CIN

                  substring(infield,curr_pos,lenny-curr_pos+1)}">

            <MvIF EXPR = "{a1 GT 0}">

                  <MvASSIGN NAME = "outfield" VALUE = "{outfield $

                        substring(infield,curr_pos,a1 - 1)}">

            <MvELSE>

                  <MvASSIGN NAME = "outfield" VALUE = "{outfield $

                        substring(infield,curr_pos,lenny-curr_pos+1)}">

                  <MvWHILESTOP>

            </MvIF>

            <MvASSIGN NAME = "curr_pos" VALUE = "{curr_pos + a1}">

      </MvWHILE>

 

      <MvFUNCRETURN VALUE = "{outfield}"></MvFUNCRETURN>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "ShowMain">

     

      <MvIF EXPR = "{dosearch NE ''}">

            <MvASSIGN NAME = "search_string" VALUE = "{RemoveYumlaut(search_string)}">

            <MvEVAL EXPR = CheckSearchCriteria()>

            <MvIF EXPR = "{search_input_error GE '1'}">

                  <MvEVAL EXPR = ShowSearchForm()>

                  <MvFUNCRETURN></MvFUNCRETURN>

            </MvIF>

      </MvIF>

 

      <MvEVAL EXPR = FindStart(roots_to_view,parm_starting_root)>

      <MvEVAL EXPR = MainPageHeader()>

      <MvEVAL EXPR = MainPageBody()>

      <MvEVAL EXPR = MainPageFooter()>      <MvCOMMENT> Doesn't include post form </MvCOMMENT>

     

      <MvEXIT>

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "CheckSearchCriteria">

 

      <MvIF EXPR = "{(use_searchstring EQ '' AND use_startdate EQ '' AND use_enddate EQ '')}">

            <MvASSIGN NAME = "search_input_error" VALUE = "{'1'}">

      <MvELSE>

      <MvIF EXPR = "{(use_searchstring NE '' AND search_string EQ '')

            OR (use_startdate NE '' AND start_month EQ '' AND start_day EQ '' AND start_year EQ '')

            OR (use_enddate NE '' AND end_month EQ '' AND end_day EQ '' AND end_year EQ '')}">

            <MvASSIGN NAME = "search_input_error" VALUE = "{'2'}">

      </MvIF>

      </MvIF>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "FindStart" PARAMETERS = "rootstoview,startingroot">

 

      <MvIF EXPR = "{db_just_created EQ '1'}">      <MvCOMMENT> 1st record, super-root not visible yet. </MvCOMMENT>

            <MvASSIGN NAME = "is_last_page"          VALUE = "{'1'}">

            <MvASSIGN NAME = "starting_recno"  VALUE = "{'0'}">

            <MvASSIGN NAME = "last_rootnum"          VALUE = "{'0'}">

            <MvFUNCRETURN></MvFUNCRETURN>

      </MvIF>

 

      <MvASSIGN NAME = "starting_root"   VALUE = "{startingroot}">

      <MvASSIGN NAME = "starting_root_save"       VALUE = "{startingroot}">

      <MvIF EXPR = "{starting_root EQ ''}">

            <MvASSIGN NAME = "starting_root" VALUE = "{'1'}">

      </MvIF>

 

      <MvCOMMENT> Find main posting to start page with. </MvCOMMENT>

 

      <MvEVAL EXPR = FindDirection()>

 

      <MvIF EXPR = "{dosearch EQ '' AND nextmatch EQ '' AND prevmatch EQ ''}">

            <MvEVAL EXPR = FindStartingRoot(rootstoview)>

            <MvEVAL EXPR = FindStartingRec(rootstoview)>

      <MvELSE>

            <MvEVAL EXPR = FindStartingRootSearch(rootstoview)>

            <MvEVAL EXPR = FindStartingRecSearch()>

      </MvIF>

 

      <MvEVAL EXPR = FindScrolling(rootstoview)>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "FindDirection">

 

      <MvIF EXPR = "{parm_starting_root NE ''}">

            <MvIF EXPR = "{backintime NE '' OR nextmatch NE ''}">

                  <MvASSIGN NAME = "direction" VALUE = "{'back'}">

            <MvELSE>

            <MvIF EXPR = "{forwardintime NE '' OR prevmatch NE ''}">

                  <MvASSIGN NAME = "direction" VALUE = "{'forward'}">

            </MvIF>

            </MvIF>

      </MvIF>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "FindStartingRoot" PARAMETERS = "rootstoview">

 

      <MvIF EXPR = "{direction EQ 'back'}">

            <MvIF EXPR = "{form_num_displayed EQ ''}">

                  <MvASSIGN NAME = "starting_root" VALUE = "{starting_root + rootstoview}">

            <MvELSE>   

                  <MvASSIGN NAME = "starting_root" VALUE = "{starting_root + form_num_displayed}">

            </MvIF>

      <MvELSE>

      <MvIF EXPR = "{parm_starting_root EQ ''}">      <MvCOMMENT> First time in, no direction specified. </MvCOMMENT>

            <MvASSIGN NAME = "starting_root" VALUE = "{'1'}">

      <MvELSE>   

      <MvIF EXPR = "{direction EQ 'forward'}">

            <MvIF EXPR = "{starting_root GT rootstoview}">

                  <MvASSIGN NAME = "starting_root" VALUE = "{starting_root - rootstoview}">

            <MvELSE>

                  <MvASSIGN NAME = "partial_page"          VALUE = "{'1'}">

                  <MvASSIGN NAME = "starting_root"   VALUE = "{'1'}">

            </MvIF>

      </MvIF>

      </MvIF>

      </MvIF>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "FindStartingRootSearch" PARAMETERS = "rootstoview">

 

      <MvCOMMENT> First time in, start at top of database, else at current pagetop. </MvCOMMENT>

 

      <MvIF EXPR = "{parm_starting_root EQ '' OR dosearch NE ''}">

            <MvASSIGN NAME = "starting_root" VALUE = "{'0'}">

      </MvIF>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "FindStartingRec" PARAMETERS = "rootstoview">

 

      <MvCOMMENT> Find record number of root that will start page. </MvCOMMENT>

 

      <MvEVAL EXPR = GetSuperRoot()>

 

      <MvSKIP ROWS = starting_root - 1>

      <MvASSIGN NAME = "starting_recno" VALUE = "{&[dbname];.d.recno}">

      <MvASSIGN NAME = "starting_seqnum" VALUE = "{dbseqnum}">

 

      <MvCLOSE NAME = "&[dbname];">

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "GetSuperRoot">

 

      <MvOPEN NAME = "&[dbname];" DATABASE = "&[database];"

            INDEXES = "&[index_file1];,&[index_file2];,&[index_file3];">

      <MvGO ROW = 1>

 

      <MvASSIGN NAME = "last_rootnum" VALUE = "{dbparentno}">

      <MvIF EXPR = "{last_rootnum GT 0}">

            <MvASSIGN NAME = "roots_exist" VALUE = "{'1'}">

      <MvELSE>

            <MvASSIGN NAME = "roots_exist" VALUE = "{'0'}">

      </MvIF>

 

      <MvFILTER NAME = "&[dbname];"

            FILTER = "{dbparentno EQ super_root AND NOT &[dbname];.d.deleted}">

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "FindScrolling" PARAMETERS = "rootstoview">

 

      <MvCOMMENT> Determine which scrolling options make sense, if any. </MvCOMMENT>

 

      <MvIF EXPR = "{direction EQ 'forward' AND partial_page NE ''}">

            <MvCOMMENT> Starting value of roots_displayed_count > 0 since displaying partial page. </MvCOMMENT>

            <MvASSIGN NAME = "roots_displayed_count" VALUE = "{rootstoview - starting_root_save + 1}">

            <MvASSIGN NAME = "num_displayed" VALUE = "{starting_root_save - 1}">

      <MvELSE>

            <MvASSIGN NAME = "roots_displayed_count" VALUE = "{'0'}">

            <MvIF EXPR = "{last_rootnum - starting_root GE rootstoview}">

                  <MvASSIGN NAME = "num_displayed" VALUE = "{rootstoview}">

            <MvELSE>

                  <MvASSIGN NAME = "num_displayed" VALUE = "{last_rootnum - starting_root + 1}">

            </MvIF>

      </MvIF>

 

      <MvASSIGN NAME = "ending_root" VALUE = "{starting_root + num_displayed - 1}">

 

      <MvIF EXPR = "{roots_exist EQ '1'}">

            <MvIF EXPR = "{ending_root EQ last_rootnum}">

                  <MvASSIGN NAME = "is_last_page" VALUE = "{'1'}">

            <MvELSE>

                  <MvASSIGN NAME = "is_last_page" VALUE = "{'0'}">

            </MvIF>

      <MvELSE>

            <MvCOMMENT> Almost empty database </MvCOMMENT>

            <MvASSIGN NAME = "starting_recno" VALUE = "{'1'}">

            <MvASSIGN NAME = "is_last_page" VALUE = "{'1'}">

      </MvIF>

 

</MvFUNCTION>

 

 

 

<MvFUNCTION NAME = "FindStartingRecSearch">

 

      <MvCOMMENT> Find record number of root that will start page, whether 1st search or

            search for next match.  For 1st search, starting_root s/b zero.

            Get root count from super_root's parent field.

      </MvCOMMENT>

 

      <MvEVAL EXPR = GetSuperRoot()>

 

      <MvASSIGN NAME = "root_count" VALUE = "{'0'}">

      <MvASSIGN NAME = "match_found" VALUE = "{'0'}">

      <MvIF EXPR = "{prevmatch EQ ''}">

            <MvWHILE EXPR = "{NOT &[dbname];.d.eof}">

                  <MvIF EXPR = "{match_found EQ '0'}">

                        <MvASSIGN NAME = "root_count" VALUE = "{root_count + 1}">

                        <MvIF EXPR = "{root_count GT starting_root}">

                              <MvIF EXPR = "{use_startdate NE '' OR use_enddate NE ''}">

                                    <MvEVAL EXPR = ExtractDateFields()>

                              </MvIF>

                              <MvEVAL EXPR = SeeIfMatch()>

                              <MvIF EXPR = "{match_found EQ '1'}">

                                    <MvASSIGN NAME = "starting_recno" VALUE = "{&[dbname];.d.recno}">

                                    <MvASSIGN NAME = "starting_root" VALUE = "{root_count}">

                                    <MvWHILESTOP></MvWHILESTOP>

                              </MvIF>

                        </MvIF>

                  </MvIF>

                  <MvSKIP>

            </MvWHILE>

      <MvELSE>

            <MvEVAL EXPR = DoPreviousMatch()>

      </MvIF>

 

      <MvIF EXPR = "{match_found EQ '0'}">

            <MvIF EXPR = "{starting_recno_save NE ''}">

                  <MvASSIGN NAME = "starting_recno" VALUE = "{starting_recno_save}">

            <MvELSE>

                  <MvASSIGN NAME = "starting_recno" VALUE = "{'1'}">

            </MvIF>

      </MvIF>

 

      <MvCLOSE NAME = "&[dbname];">

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "DoPreviousMatch">

 

      <MvCOMMENT> First go forward to find starting point.  Start backward from

             there and look for match. </MvCOMMENT>

 

      <MvWHILE EXPR = "{NOT &[dbname];.d.eof}">

            <MvASSIGN NAME = "root_count" VALUE = "{root_count + 1}">

            <MvIF EXPR = "{root_count EQ starting_root}">

                  <MvASSIGN NAME = "starting_recno" VALUE = "{&[dbname];.d.recno}">

                  <MvWHILESTOP></MvWHILESTOP>

            </MvIF>

            <MvSKIP>

      </MvWHILE>

      <MvSKIP ROWS = -1>      <MvCOMMENT> Back up 1 from curr rec so don't match on it again.</MvCOMMENT>

      <MvWHILE EXPR = "{NOT &[dbname];.d.eof}">

            <MvIF EXPR = "{match_found EQ '0'}">

                  <MvASSIGN NAME = "root_count" VALUE = "{root_count - 1}">

                  <MvIF EXPR = "{use_startdate NE '' OR use_enddate NE ''}">

                        <MvEVAL EXPR = ExtractDateFields()>

                  </MvIF>

                  <MvEVAL EXPR = SeeIfMatch()>

                  <MvIF EXPR = "{match_found EQ '1'}">

                        <MvASSIGN NAME = "starting_recno" VALUE = "{&[dbname];.d.recno}">

                        <MvASSIGN NAME = "starting_root" VALUE = "{root_count}">

                        <MvWHILESTOP></MvWHILESTOP>

                  </MvIF>

            </MvIF>

            <MvCOMMENT> If we're at beginning of index, i.e. recno 1, stop. </MvCOMMENT>

            <MvSKIP ROWS = -1>

      </MvWHILE>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "ExtractDateFields">

 

      <MvASSIGN NAME = "a1" VALUE = "{'/' CIN dbdate}">

      <MvIF EXPR = "{a1 EQ '2'}">

            <MvASSIGN NAME = "db_month" VALUE = "{'0' $ substring(dbdate,1,1)}">

      <MvELSE>

            <MvASSIGN NAME = "db_month" VALUE = "{substring(dbdate,1,2)}">

      </MvIF>

 

      <MvASSIGN NAME = "a2" VALUE = "{'/' CIN substring(dbdate,a1+1,10-a1)}">

      <MvIF EXPR = "{a2 EQ '2'}">

            <MvASSIGN NAME = "db_day" VALUE = "{'0' $ substring(dbdate,a1+1,1)}">

      <MvELSE>

            <MvASSIGN NAME = "db_day" VALUE = "{substring(dbdate,a1+1,2)}">

      </MvIF>

 

      <MvASSIGN NAME = "db_year" VALUE = "{substring(dbdate,a1+a2+1,4)}">

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "SeeIfMatch">

 

      <MvIF EXPR = "{      (use_searchstring EQ '' OR search_string CIN dbsubject)

            AND       (use_startdate EQ ''

                  OR start_year LT db_year

                  OR (start_year EQ db_year

                        AND (start_month LT db_month)

                              OR (start_month EQ db_month

                                    AND start_day LE db_day)))

            AND       (use_enddate EQ ''

                  OR db_year LT end_year

                  OR (db_year EQ end_year

                        AND (db_month LT end_month)

                              OR (db_month EQ end_month

                                    AND db_day LE end_day)))

            }">

            <MvASSIGN NAME = "match_found" VALUE = "{'1'}">

      </MvIF>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "MainPageHeader">

 

      &[ON];&[header];<h1 align="center">&[title];</h1>&[crlf];&[OFF];

      <MvEVAL EXPR = LinkLine(parm_admin_flag,parm_user,parm_pass)>

 

      <MvIF EXPR = "{dosearch NE '' OR nextmatch NE '' OR prevmatch NE ''}">

            <MvIF EXPR = "{match_found EQ '0'}">

                  &[ON];<center><font color="#ff0000" size = "+1">Match not found.</font></center><br>&[crlf];&[OFF];

            <MvELSE>

                  &[ON];<center><font color="#ff0000" size = "+1">Match found:</font></center><br>&[crlf];&[OFF];

            </MvIF>

      </MvIF>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "MainPageBody">

 

      <MvCOMMENT>

          Each posting which is not a followup is the root of a tree of postings.  To tie all

          of these roots together, we use an artificial posting called the super-root.  It

          forms the root of a tree or hierarchy.  Its children are the original roots.  Their

          children, if any, are their followups.  To display the overall hierarchy of postings

          in most-recent-first sequence, we traverse the overall tree recursively.  To do so, we

          start at the super-root and print its "followups" (postings which are *not* followups).

          While processing a posting, we print *its* followups, etc., recursively traversing

          the hierarchy of postings and followups in most-recent-first sequence.

 

          Additionally, we don't just print the whole database.  We only print a limited number

          of postings at a time.  Other postings can be viewed by "scrolling" forward or

          backward in time.  A practical way to limit the amount of material to display

          at a time is to pick a fixed number of roots to display postings for.  This

          prevents us from cutting off a set of related postings under one root.  Rather,

          we finish the set of postings related to a root.  So, the exact number of

          postings per page will fluctuate, though the number of *roots* is fixed.  The

          scrolling amount can be set in the administration function of the message board.

          The amount is called "roots_to_view".

      </MvCOMMENT>

 

      <MvASSIGN NAME = "traverse_function" VALUE = "{'AddLine'}">

      <MvASSIGN NAME = "starting_nestlvl" VALUE = "{'0'}">

      <MvASSIGN NAME = "roots_per_page" VALUE = "{roots_to_view}">

 

      <MvOPEN NAME = "&[dbname];" DATABASE = "&[database];"

            INDEXES = "&[index_file1];,&[index_file2];,&[index_file3];">

      <MvFILTER NAME = "&[dbname];" FILTER = "{NOT &[dbname];.d.deleted}">

 

      &[ON]<BLOCKQUOTE>&[OFF]

      <MvEVAL EXPR = TraverseTree(parm_admin_flag,parm_user,parm_pass)>          <MvCOMMENT> Start recursion </MvCOMMENT>

      <MvEVAL EXPR = Unindent()>

 

      <MvCLOSE NAME = "&[dbname];">

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "TraverseTree" PARAMETERS = "admin,uname,pass">

 

      <MvCOMMENT>

      The following example should help one visualize this processing.  Suppose the

      messsage board has 10 postings so far, numbered 1 to 10, the oldest being 1.

      There would 11 records in the database, the eleventh being the super-root.

      Suppose the posting structure should print out like this:

 

            4

                  10

                  5

                        8

                              9

                        6

                              7

            3

            1

                  2

 

      The records are in exactly this hierarchical and most-recent-first sequence

      within the database because the index used here is decreasing sequence number.

      Sequence number for a posting is midway between the preceding and following

      postings' sequence numbers.  This speeds up displaying the list as it looks above.

      </MvCOMMENT>

 

      <MvCOMMENT> Start at beginning of database, or at starting point if scrolling,

          according to index 1 (sequence number). </MvCOMMENT>

 

      <MvIF EXPR = "{dosearch NE '' AND match_found EQ '0'}">

            <MvGO ROW = "top">

            <MvSKIP>

      <MvELSE>

            <MvGO ROW = starting_recno>

            <MvIF EXPR = "{dbselfnum EQ super_root}">

                  <MvSKIP>

            </MvIF>

      </MvIF>

 

      <MvIF EXPR = "{traverse_reason EQ 'followups'}">

            <MvSKIP>

            <MvIF EXPR = "{dbnestlvl LE starting_nestlvl}">

                  <MvFUNCRETURN></MvFUNCRETURN>

            </MvIF>

      </MvIF>

 

      <MvASSIGN NAME = "save_nestlvl" VALUE = "{starting_nestlvl}">

 

      <MvIF EXPR = "{currself EQ (1 + big_bump)}">      <MvCOMMENT> 1st record, super-root not visible yet. </MvCOMMENT>

            <MvEVAL EXPR = TravTreeFirstrec(admin,uname,pass)>

      <MvELSE>

            <MvWHILE EXPR = "{NOT &[dbname];.d.eof

                        AND (roots_displayed_count LT roots_per_page

                        OR (roots_displayed_count EQ roots_per_page

                              AND dbparentno NE super_root))}">

                  <MvEVAL EXPR = &[traverse_function];(admin,uname,pass)>

                  <MvIF EXPR = "{dbparentno EQ super_root}">

                        <MvASSIGN NAME = "roots_displayed_count" VALUE = "{roots_displayed_count + 1}">

                  </MvIF>

                  <MvSKIP>

                  <MvIF EXPR = "{dbnestlvl LE starting_nestlvl}">

                        <MvWHILESTOP></MvWHILESTOP>

                  </MvIF>

            </MvWHILE>

      </MvIF>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "TravTreeFirstrec" PARAMETERS = "admin,uname,pass">

 

      <MvASSIGN NAME = "dbselfnum"      VALUE = "{currself}">

      <MvASSIGN NAME = "dbnumdesc"      VALUE = "{'0'}">

      <MvASSIGN NAME = "dbdate"      VALUE = "{date}">

      <MvASSIGN NAME = "dbtime"      VALUE = "{time}">

      <MvASSIGN NAME = "dbname1"      VALUE = "{name}">

      <MvASSIGN NAME = "dbsubject"      VALUE = "{subject}">

      <MvEVAL EXPR = &[traverse_function];(admin,uname,pass)>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "AddLine" PARAMETERS = "admin,uname,pass">

 

      <MvIF EXPR = "{use_time EQ 'on'}">

            <MvASSIGN NAME = "print_date" VALUE = "{dbtime $ ' ' $ dbdate}">

      <MvELSE>

            <MvASSIGN NAME = "print_date" VALUE = "{dbdate}">

      </MvIF>

 

      <MvASSIGN NAME = "indent_string" VALUE = "{''}">

 

      <MvASSIGN NAME = "indent_count" VALUE = "{dbnestlvl - save_nestlvl}">

      <MvIF EXPR = "{indent_count GT 0}">

            <MvASSIGN NAME = "indent_string" VALUE = "{'<UL>'}">

      <MvELSE>

      <MvIF EXPR = "{indent_count LT 0}">

            <MvWHILE EXPR = "{indent_count LT 0}">

                  <MvASSIGN NAME = "indent_string" VALUE = "{indent_string $ '</UL>'}">

                  <MvASSIGN NAME = "indent_count" VALUE = "{indent_count + 1}">

            </MvWHILE>

      <MvELSE>

            <MvASSIGN NAME = "indent_string" VALUE = "{''}">

      </MvIF>

      </MvIF>

      <MvASSIGN NAME = "save_nestlvl" VALUE = "{dbnestlvl}">

      &[ON]&[indent_string];<LI>&[OFF]

 

      <MvIF EXPR = "{admin EQ 'y'}">

            &[ON];<a href = "&[documenturl];parm_func=showmsg+parm_msgnum=&[dbselfnum];+parm_admin_flag=&[admin];+parm_user=&[uname];+parm_pass=&[pass];">&[OFF];

      <MvELSE>

            &[ON];<a href = "&[documenturl];parm_func=showmsg+parm_msgnum=&[dbselfnum];">&[OFF];

      </MvIF>

 

      &[ON];&[dbsubject];</a> - <b>&[dbname1];&nbsp;&nbsp;&[crlf];&[OFF];

      &[ON];</b><i>&[print_date];</i> (&[dbnumdesc];)&[crlf];&[OFF];     

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "Unindent">

 

      <MvASSIGN NAME = "unindent_string" VALUE = "{''}">

      <MvWHILE EXPR = "{save_nestlvl GT 0}">

            <MvASSIGN NAME = "unindent_string" VALUE = "{unindent_string $ '</UL>'}">

            <MvASSIGN NAME = "save_nestlvl" VALUE = "{save_nestlvl - 1}">

      </MvWHILE>

      &[ON]&[unindent_string];</BLOCKQUOTE>&[OFF]

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "MainPageFooter">

 

      <MvCOMMENT> If first page, no previous button.  If last page, no next button.

          Except when we're first coming in to message board, and it's page 1,

          starting root in url reflects page we're coming *from*, not page we're on.

      </MvCOMMENT>

 

      <MvIF EXPR = "{starting_root EQ '0'}">

            <MvASSIGN NAME = "starting_root" VALUE = "{'1'}">

      </MvIF>

 

      &[ON];<CENTER>&[crlf];&[OFF];

      <MvIF EXPR = "{parm_admin_flag EQ 'y'}">

            &[ON];<form method="post" action="&[documenturl];parm_func=showmain+parm_starting_root=&[starting_root];+parm_admin_flag=y+parm_user=&[parm_user];+parm_pass=&[parm_pass];">&[crlf];&[OFF];

      <MvELSE>

            &[ON];<form method="post" action="&[documenturl];parm_func=showmain+parm_starting_root=&[starting_root];">&[crlf];&[OFF];

      </MvIF>

 

      &[ON];<input type = "hidden" name = "form_num_displayed"      value = &[num_displayed];></INPUT>&[crlf];&[OFF];

      &[ON];<input type = "hidden" name = "starting_recno_save"      value = &[starting_recno];></INPUT>&[crlf];&[OFF];

 

      <MvIF EXPR = "{(is_last_page NE '1') AND (starting_root LT last_rootnum)}">

            &[ON];<input name="backintime" type="submit" value="Next Page"></INPUT>&[crlf];&[OFF];

      </MvIF>

 

      <MvIF EXPR = "{starting_root GT '1'}">

            &[ON];<input name="forwardintime" type="submit" value="Previous Page"></INPUT>&[crlf];&[OFF];

      </MvIF>

 

      <MvEVAL EXPR = SearchFields()>

      &[ON];</form></CENTER>&[OFF];

 

      <MvEVAL EXPR = LinkLine(parm_admin_flag,parm_user,parm_pass)>

      &[ON];&[banner_ad];&[footer];&[crlf];&[OFF];

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "SearchFields">

 

      <MvIF EXPR = "{(dosearch NE '' AND match_found EQ '1') OR search_started NE ''}">

            <MvIF EXPR = "{nextmatch NE '' AND (match_found EQ '0' OR starting_root GE last_rootnum)}">

            <MvELSE>

                  &[ON];<input name="nextmatch" type="submit" value="Next Match"></INPUT>&[crlf];&[OFF];

                  <MvASSIGN NAME = "button_out" VALUE = "{'1'}">

            </MvIF>

 

            <MvIF EXPR = "{(dosearch NE '') OR (prevmatch NE '' AND match_found EQ '0') OR (starting_root LE '1')}">

            <MvELSE>

                  &[ON];<input name="prevmatch" type="submit" value="Previous Match"></INPUT>&[crlf];&[OFF];

                  <MvASSIGN NAME = "button_out" VALUE = "{'1'}">

            </MvIF>

 

            <MvIF EXPR = "{button_out EQ '1'}">

                  &[ON];<input name="search_started"       type="hidden" value="'1'"></INPUT>&[crlf];&[OFF];

                  &[ON];<input name="use_searchstring"      type="hidden" value="&[use_searchstring];"></INPUT>&[crlf];&[OFF];

                  &[ON];<input name="use_startdate"      type="hidden" value="&[use_startdate];"></INPUT>&[crlf];&[OFF];

                  &[ON];<input name="use_enddate"            type="hidden" value="&[use_enddate];"></INPUT>&[crlf];&[OFF];

                  &[ON];<input name="search_string"      type="hidden" value="&[search_string];"></INPUT>&[crlf];&[OFF];

                  &[ON];<input name="start_month"            type="hidden" value="&[start_month];"></INPUT>&[crlf];&[OFF];

                  &[ON];<input name="start_day"        type="hidden" value="&[start_day];"></INPUT>&[crlf];&[OFF];

                  &[ON];<input name="start_year"       type="hidden" value="&[start_year];"></INPUT>&[crlf];&[OFF];

                  &[ON];<input name="end_month"        type="hidden" value="&[end_month];"></INPUT>&[crlf];&[OFF];

                  &[ON];<input name="end_day"          type="hidden" value="&[end_day];"></INPUT>&[crlf];&[OFF];

                  &[ON];<input name="end_year"         type="hidden" value="&[end_year];"></INPUT>&[crlf];&[OFF];

            </MvIF>

      </MvIF>

     

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "LinkLine" PARAMETERS = "admin,uname,pass">

 

      <MvEVAL EXPR = GeneralLinkLineParms(admin,uname,pass)>

      &[ON];&[general_data_area];&[crlf];&[OFF];

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "GeneralLinkLineParms" PARAMETERS = "admin,uname,pass">

 

      <MvEVAL EXPR = GenLinkLineIntro(admin,uname,pass)>

      <MvEVAL EXPR = GenLinkLineParmsFaqShort()>

      <MvEVAL EXPR = GenLinkLineParmsShowpostform(admin)>

      <MvEVAL EXPR = GenLinkLineParmsShowmain(admin)>

      <MvEVAL EXPR = GenLinkLineParmsShowsearch(admin)>

      <MvEVAL EXPR = GenLinkLineParmsShowFaq(admin)>

      <MvEVAL EXPR = GenLinkLineParmsFinishLinks()>

      <MvEVAL EXPR = GenLinkLineParmsWrapup(admin)>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "GenLinkLineIntro" PARAMETERS = "admin,uname,pass">

 

      <MvASSIGN NAME = "data_area" VALUE = "{linkline}">

 

      <MvASSIGN NAME = "link_admin"

             VALUE = "{'[ <a href="&[documenturl];parm_func=admin+parm_admin_func=null'

                  $ '+parm_user=&[uname];+parm_pass=&[pass];'

                  $ '">&[title2];</a> ]'}">

 

      <MvASSIGN NAME = "extra_parms" VALUE = "{'+parm_admin_flag=&[admin];+parm_user=&[uname];+parm_pass=&[pass];'}">

      <MvASSIGN NAME = "curr_pos" VALUE = "{'1'}">

      <MvASSIGN NAME = "general_data_area" VALUE = "{''}">

 

      <MvASSIGN NAME = "a1" VALUE = "{'[' CIN data_area}">

 

      <MvIF EXPR = "{(a1 GT '0')}">

            <MvASSIGN NAME = "general_data_area" VALUE = "{substring(data_area,1,a1-1)}">

            <MvASSIGN NAME = "curr_pos" VALUE = "{a1}">

      </MvIF>

 

      <MvIF EXPR = "{showing_message EQ 1}">

            <MvASSIGN NAME = "general_data_area"

                  VALUE = "{general_data_area $ '[ <a href="#followups">Followups</a> ] '

                        $ '[ <a href="#postfollowup">Post Followup</a> ] '}">

      </MvIF>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "GenLinkLineParmsFaqShort">

 

      <MvCOMMENT> Omit faq link if not to be shown </MvCOMMENT>

 

      <MvASSIGN NAME = "a1" VALUE = "{link_faq_short CIN data_area}">

 

      <MvIF EXPR = "{(a1 GT '0') AND (show_faq NE 'on')}">

            <MvASSIGN NAME = "data_area" VALUE = "{substring(data_area,1,a1-1)

            $ substring(data_area,a1+len(link_faq_short),len(data_area)-(a1+len(link_faq_short)-1))}">

      </MvIF>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "GenLinkLineParmsShowpostform" PARAMETERS = "admin">

 

      <MvASSIGN NAME = "a1" VALUE = "{'parm_func=showpostform' CIN substring(data_area,curr_pos,len(data_area)-curr_pos+1)}">

 

      <MvIF EXPR = "{a1 GT '0'}">

            <MvASSIGN NAME = "general_data_area" VALUE = "{general_data_area $ substring(data_area,curr_pos,a1+21)}">

            <MvASSIGN NAME = "curr_pos" VALUE = "{curr_pos + a1+21}">

 

            <MvIF EXPR = "{admin EQ 'y'}">

                  <MvASSIGN NAME = "general_data_area" VALUE = "{general_data_area $ extra_parms}">

            </MvIF>

      </MvIF>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "GenLinkLineParmsShowmain" PARAMETERS = "admin">

 

      <MvASSIGN NAME = "a1" VALUE = "{'parm_func=showmain+parm_starting_root=1' CIN substring(data_area,curr_pos,len(data_area)-curr_pos+1)}">

 

      <MvIF EXPR = "{a1 GT '0'}">

            <MvASSIGN NAME = "general_data_area" VALUE = "{general_data_area $ substring(data_area,curr_pos,a1+38)}">

            <MvASSIGN NAME = "curr_pos" VALUE = "{curr_pos + a1+38}">

 

            <MvIF EXPR = "{admin EQ 'y'}">

                  <MvASSIGN NAME = "general_data_area" VALUE = "{general_data_area $ extra_parms}">

            </MvIF>

      </MvIF>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "GenLinkLineParmsShowsearch" PARAMETERS = "admin">

 

      <MvASSIGN NAME = "a1" VALUE = "{'parm_func=showsearch+parm_starting_root=1' CIN substring(data_area,curr_pos,len(data_area)-curr_pos+1)}">

 

      <MvIF EXPR = "{a1 GT '0'}">

            <MvASSIGN NAME = "general_data_area" VALUE = "{general_data_area $ substring(data_area,curr_pos,a1+40)}">

            <MvASSIGN NAME = "curr_pos" VALUE = "{curr_pos + a1+40}">

 

            <MvIF EXPR = "{admin EQ 'y'}">

                  <MvASSIGN NAME = "general_data_area" VALUE = "{general_data_area $ extra_parms}">

            </MvIF>

      </MvIF>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "GenLinkLineParmsShowfaq" PARAMETERS = "admin">

 

      <MvASSIGN NAME = "a1" VALUE = "{'parm_func=showfaq' CIN substring(data_area,curr_pos,len(data_area)-curr_pos+1)}">

 

      <MvIF EXPR = "{a1 GT '0'}">

            <MvASSIGN NAME = "general_data_area" VALUE = "{general_data_area $ substring(data_area,curr_pos,a1+16)}">

            <MvASSIGN NAME = "curr_pos" VALUE = "{curr_pos + a1+16}">

 

            <MvIF EXPR = "{admin EQ 'y'}">

                  <MvASSIGN NAME = "general_data_area" VALUE = "{general_data_area $ extra_parms}">

            </MvIF>

      </MvIF>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "GenLinkLineParmsFinishLinks">

 

      <MvASSIGN NAME = "a1" VALUE = "{']' CIN substring(data_area,curr_pos,len(data_area)-curr_pos+1)}">

 

      <MvIF EXPR = "{a1 GT '0'}">

            <MvASSIGN NAME = "general_data_area" VALUE = "{general_data_area $ substring(data_area,curr_pos,a1)}">

            <MvASSIGN NAME = "curr_pos" VALUE = "{curr_pos + a1}">

      </MvIF>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "GenLinkLineParmsWrapup" PARAMETERS = "admin">

 

      <MvIF EXPR = "{admin EQ 'y' AND data_area NE ''}">

            <MvASSIGN NAME = "general_data_area" VALUE = "{general_data_area $ ' ' $ link_admin}">

      </MvIF>

 

      <MvIF EXPR = "{curr_pos LE len(data_area)}">

            <MvASSIGN NAME = "general_data_area"

            VALUE = "{general_data_area $ substring(data_area,curr_pos,len(data_area)-curr_pos+1)}">

      </MvIF>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "PostControl">

 

      <MvEVAL EXPR = SeeIfBlocked()>

      <MvIF EXPR = "{blocked_ip EQ '1'}">

            <MvEVAL EXPR = Error("blocked_ip")>

            <MvFUNCRETURN></MvFUNCRETURN>

      </MvIF>

      <MvEVAL EXPR = EditInput()>

      <MvEVAL EXPR = UpdateDatabase()>

      <MvEVAL EXPR = BuildMessageFile()>

      <MvEVAL EXPR = ReturnHtml()>

      <MvEXIT>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "SeeIfBlocked">

 

      <MvCOMMENT>

            If visitor's IP in unwelcome list, go no further.

            Use &[REMOTE_ADDR];.  Import unwelcome list file, check for match.

      </MvCOMMENT>

 

      <MvASSIGN NAME = "blocked_ip" VALUE = "{0}">

 

      <MvIF EXPR = "{fexists(unwelcomelist)}">

            <MvIMPORT FILE = "&[unwelcomelist];" FIELDS = "ip" DELIMITER = "">

                  <MvIF EXPR = "{'*' CIN ip}">

                        <MvIF EXPR = "{gettoken(ip,'*',1) CIN &[REMOTE_ADDR];}">

                              <MvASSIGN NAME = "blocked_ip" VALUE = "{1}">

                              <MvIMPORTSTOP></MvIMPORTSTOP>

                        </MvIF>

                  <MvELSE>

                        <MvIF EXPR = "{&[REMOTE_ADDR]; EQ ip}">

                              <MvASSIGN NAME = "blocked_ip" VALUE = "{1}">

                              <MvIMPORTSTOP></MvIMPORTSTOP>

                        </MvIF>

                  </MvIF>

            </MvIMPORT>

      </MvIF>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "EditInput">

     

      <MvASSIGN NAME = "form_name"       VALUE = "{RemoveYumlaut(form_name)}">

      <MvASSIGN NAME = "form_email"            VALUE = "{RemoveYumlaut(form_email)}">

      <MvASSIGN NAME = "form_subject"          VALUE = "{RemoveYumlaut(form_subject)}">

      <MvASSIGN NAME = "form_body"       VALUE = "{RemoveYumlaut(form_body)}">

      <MvASSIGN NAME = "form_url"        VALUE = "{RemoveYumlaut(form_url)}">

      <MvASSIGN NAME = "form_url_title"  VALUE = "{RemoveYumlaut(form_url_title)}">

      <MvASSIGN NAME = "form_img"        VALUE = "{RemoveYumlaut(form_img)}">

 

      <MvIF EXPR = "{parm_followup_to NE ''}">

            <MvASSIGN NAME = "is_followup" VALUE = "{'1'}">

      <MvELSE>

            <MvASSIGN NAME = "is_followup" VALUE = "{'0'}">

      </MvIF>

 

      <MvIF EXPR = "{form_name NE ''}">

            <MvEVAL EXPR = EditInputName()>

      <MvELSE>

            <MvEVAL EXPR = Error("no_name")>

      </MvIF>

 

      <MvASSIGN NAME = "a1" VALUE = "{atsign IN form_email}">

      <MvIF EXPR = "{a1 GT 0}">

            <MvIF EXPR = "{period IN substring(form_email,a1+1,len(form_email)-a1)}">

                  <MvASSIGN NAME = "email" VALUE = "{ConvertTags(form_email)}">

            </MvIF>

      </MvIF>

 

      <MvEVAL EXPR = EditInputSubject()>

 

      <MvEVAL EXPR = EditInputBody()>

 

      <MvASSIGN NAME = "a1" VALUE = "{':' IN form_url}">

      <MvASSIGN NAME = "a2" VALUE = "{period IN form_url}">

      <MvIF EXPR = "{a1 GT 0 AND a2 GT 0 AND a1 LT a2 AND form_url_title NE ''}">

            <MvASSIGN NAME = "message_url" VALUE = "{ConvertTags(form_url)}">

            <MvASSIGN NAME = "message_url_title" VALUE = "{ConvertTags(form_url_title)}">

      </MvIF>

 

      <MvASSIGN NAME = "a1" VALUE = "{'tp://' IN form_img}">

      <MvASSIGN NAME = "a2" VALUE = "{period IN form_img}">

      <MvIF EXPR = "{a1 GT 0 AND a2 GT 0 AND a1 LT a2}">

            <MvASSIGN NAME = "message_img" VALUE = "{ConvertTags(form_img)}">

      </MvIF>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "EditInputName">

 

      <MvASSIGN NAME = "curr_pos" VALUE = "{1}">

      <MvASSIGN NAME = "len_limit" VALUE = "{len(form_name)}">

      <MvWHILE EXPR = "{curr_pos LE len_limit}">

            <MvASSIGN NAME = "curr_char" VALUE = "{substring(form_name,curr_pos,1)}">

            <MvIF EXPR = "{NOT isalpha(curr_char)

                        AND curr_char NE '0'

                        AND curr_char NE '1'

                        AND curr_char NE '2'

                        AND curr_char NE '3'

                        AND curr_char NE '4'

                        AND curr_char NE '5'

                        AND curr_char NE '6'

                        AND curr_char NE '7'

                        AND curr_char NE '8'

                        AND curr_char NE '9'

                        AND curr_char NE ' '

                        AND curr_char NE '_'}">

                  <MvASSIGN NAME = "form_name" VALUE = "{ConvertTags(form_name)}">

                  <MvEVAL EXPR = Error("bad_char_in_name")>

            </MvIF>

            <MvASSIGN NAME = "curr_pos" VALUE = "{curr_pos + 1}">

      </MvWHILE>

 

      <MvASSIGN NAME = "name" VALUE = "{form_name}">

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "EditInputSubject">

 

      <MvIF EXPR = "{form_subject NE ''}">

            <MvASSIGN NAME = "subject" VALUE = "{glosub(form_subject,'\cM','')}">

            <MvCOMMENT>Remove any anchors from subject, since it goes in an anchor on main page.</MvCOMMENT>

            <MvASSIGN NAME = "work_subject"    VALUE = "{''}">

            <MvASSIGN NAME = "a1"       VALUE = "{'<a href' CIN subject}">

            <MvASSIGN NAME = "a1_abs"       VALUE = "{a1}">

            <MvASSIGN NAME = "a2_abs"       VALUE = "{'1'}">

            <MvASSIGN NAME = "curr_pos"       VALUE = "{'1'}">

            <MvASSIGN NAME = "lenny"       VALUE = "{len(subject)}">

            <MvWHILE EXPR = "{a1 GT 0}">

                  <MvASSIGN NAME = "a2"       VALUE = "{'</a>' CIN

                        substring(subject,a1_abs,lenny - a1_abs + 1)}">

                  <MvASSIGN NAME = "a2_abs"       VALUE = "{a2 + a1_abs - 1}">

                  <MvASSIGN NAME = "work_subject" VALUE = "{work_subject $

                        substring(subject,curr_pos,a1_abs - curr_pos)}">

                  <MvASSIGN NAME = "curr_pos"       VALUE = "{a2_abs + 4}">

                  <MvASSIGN NAME = "a1"       VALUE = "{'<a href' CIN

                        substring(subject,a2_abs,lenny - a2_abs + 1)}">

                  <MvASSIGN NAME = "a1_abs"       VALUE = "{a1 + a2_abs - 1}">

            </MvWHILE>

            <MvCOMMENT>Copy part of subject following last anchor, if any.

                  Replace subject with anchor-free version.</MvCOMMENT>

            <MvIF EXPR = "{curr_pos GT 1}">

                  <MvIF EXPR = "{curr_pos GT lenny}">

                        <MvEVAL EXPR = Error("link_subject")>

                  <MvELSE>

                        <MvASSIGN NAME = "work_subject" VALUE = "{work_subject $

                              substring(subject,curr_pos,lenny-curr_pos+1)}">

                        <MvASSIGN NAME = "subject" VALUE = "{work_subject}">

                  </MvIF>                

            </MvIF>

            <MvIF EXPR = "{'<font' CIN subject}">

                  <MvIF EXPR = "{'</font' CIN subject}">

                  <MvELSE>

                        <MvASSIGN NAME = "subject" VALUE = "{subject $ '</font>'}">

                  </MvIF>

            </MvIF>

            <MvIF EXPR = "{'SCRIPT LANGUAGE' CIN subject}">

                  <MvASSIGN NAME = "foo" VALUE = "{'SCRIPT LANGUAGE' CIN subject}">

                  <MvASSIGN NAME = "subject" VALUE = "{substring(subject,0,foo-1) $ substring(subject,foo+16,len(subject)-foo)}">

            </MvIF>

            <MvIF EXPR = "{allow_html_subj NE 'on' OR 'MvEVAL' CIN subject}">

                  <MvASSIGN NAME = "subject" VALUE = "{ConvertTags(subject)}">

            </MvIF>

      <MvELSE>

            <MvEVAL EXPR = Error("no_subject")>

      </MvIF>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "EditInputBody">

 

      <MvIF EXPR = "{form_body NE ''}">

            <MvASSIGN NAME = "body" VALUE = "{glosub(form_body,'\cM','')}">

            <MvIF EXPR = "{allow_html_body NE 'on' OR 'MvEVAL' CIN body}">

                  <MvASSIGN NAME = "body" VALUE = "{ConvertTags(body)}">

            </MvIF>

            <MvIF EXPR = "{allow_html_body EQ 'on'}">

                  <MvIF EXPR = "{'<font' CIN body}">

                        <MvIF EXPR = "{'</font' CIN body}">

                        <MvELSE>

                              <MvASSIGN NAME = "body" VALUE = "{body $ '</font>'}">

                        </MvIF>

                  </MvIF>

                  <MvIF EXPR = "{'SCRIPT LANGUAGE' CIN body}">

                        <MvASSIGN NAME = "foo" VALUE = "{'SCRIPT LANGUAGE' CIN body}">

                        <MvASSIGN NAME = "body" VALUE = "{substring(body,0,foo-1) $ substring(body,foo+16,len(body)-foo)}">

                  </MvIF>

            </MvIF>

            <MvASSIGN NAME = "body" VALUE = "{glosub(body,crlf,'<br>')}">

            <MvASSIGN NAME = "body" VALUE = "{glosub(body,'<p>','<br>')}">

      <MvELSE>

            <MvEVAL EXPR = Error("no_body")>

      </MvIF>

 

</MvFUNCTION>

 

 

 

<MvFUNCTION NAME = "UpdateDatabase">

 

      <MvWHILE EXPR = "{fexists('&[dirprefix];/lockfile')}"></MvWHILE>

      <MvEXPORT FILE = "&[dirprefix];/lockfile" FIELDS = "" DELIMITER = "">

 

      <MvLOCKFILE FILE = "&[database];">

      <MvLOCKFILE FILE = "&[index_file2];">

      <MvLOCKFILE FILE = "&[index_file1];">

      <MvLOCKFILE FILE = "&[index_file3];">

 

      <MvIF EXPR = "{is_followup EQ '1'}">

            <MvEVAL EXPR = ProcessFollowup()>

      <MvELSE>

            <MvASSIGN NAME = "parentnum" VALUE = "{super_root}">

            <MvASSIGN NAME = "nest_level" VALUE = "{'1'}">

            <MvOPEN NAME = "&[dbname];" DATABASE = "&[database];"

                  INDEXES = "&[index_file1];,&[index_file2];,&[index_file3];">

      </MvIF>

 

      <MvEVAL EXPR = UpdateSuperRoot()>

 

      <MvEVAL EXPR = CreateDatabaseRecord()>

 

      </MvLOCKFILE>

      </MvLOCKFILE>

      </MvLOCKFILE>

      </MvLOCKFILE>

 

      <MvASSIGN NAME = "foo" VALUE = "{fdelete('&[dirprefix];/lockfile')}">

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "ProcessFollowup">

 

      <MvASSIGN NAME = "parentnum" VALUE = "{parm_followup_to}">

 

      <MvCOMMENT> The following will change as we ascend to super_root. </MvCOMMENT>

      <MvASSIGN NAME = "temp_parentnum" VALUE = "{parentnum}">

 

      <MvCOMMENT> Find parent quickly via selfnum index. </MvCOMMENT>

 

      <MvOPEN NAME = "&[dbname];" DATABASE = "&[database];"

            INDEXES = "&[index_file2];">

      <MvFIND NAME = "&[dbname];" VALUE = "{temp_parentnum}" EXACT = "EXACT"></MvFIND>

      <MvASSIGN NAME = "nest_level" VALUE = "{dbnestlvl + 1}">

      <MvASSIGN NAME = "parent_recno" VALUE = "{&[dbname];.d.recno}">

      <MvCLOSE NAME = "&[dbname];">

 

      <MvEVAL EXPR = UpdatePredecessors()>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "UpdatePredecessors">

 

      <MvCOMMENT> Visit the posting immediately after the new posting, and set up

            the new posting's sequence number.  Then visit each posting from the

            new posting's parent back up to the root which is the ancestor of

            the new posting.  Increment each *ancestor*'s number of descendents,

            including the root's.  Then travel *forward* from the root to the

            parent again, incrementing each posting's sequence number except

            for the root's.  We have to do the sequence number incrementing in

            the forward direction to avoid generating temporarily duplicate

            sequence numbers, which would throw off the index.

      </MvCOMMENT>

 

      <MvOPEN NAME = "&[dbname];" DATABASE = "&[database];"

            INDEXES = "&[index_file1];,&[index_file2];,&[index_file3];">

      <MvFILTER NAME = "&[dbname];" FILTER = "{NOT &[dbname];.d.deleted}">

 

      <MvEVAL EXPR = AccessFollowingPosting()>

      <MvEVAL EXPR = UpdateNumDescendents()>

      <MvEVAL EXPR = UpdateSequenceNumbers()>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "AccessFollowingPosting">

 

      <MvGO ROW = parent_recno>

 

      <MvCOMMENT> Read record after insert point. </MvCOMMENT>

      <MvSKIP>   

 

      <MvCOMMENT> Set up sequence number for new posting. </MvCOMMENT>

      <MvIF EXPR = "{NOT &[dbname];.d.eof}">

            <MvASSIGN NAME = "seqnum" VALUE = "{dbseqnum + 1}">

      <MvELSE>

            <MvASSIGN NAME = "seqnum" VALUE = "{'1'}">

      </MvIF>

      <MvASSIGN NAME = "seqnum" VALUE = "{padl(seqnum,seqnum_size,'0')}">

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "UpdateNumDescendents">

 

      <MvGO ROW = parent_recno>

      <MvWHILE EXPR = "{dbparentno NE super_root}">

            <MvIF EXPR = "{dbselfnum EQ temp_parentnum}">

                  <MvASSIGN NAME = "dbnumdesc" VALUE = "{dbnumdesc + 1}">

                  <MvASSIGN NAME = "temp_parentnum" VALUE = "{dbparentno}">

                  <MvUPDATE NAME = "&[dbname];"></MvUPDATE>

            </MvIF>

            <MvSKIP ROWS = -1>

      </MvWHILE>

 

      <MvCOMMENT> Update root. </MvCOMMENT>

      <MvASSIGN NAME = "dbnumdesc" VALUE = "{dbnumdesc + 1}">

      <MvUPDATE NAME = "&[dbname];"></MvUPDATE>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "UpdateSequenceNumbers">

 

      <MvCOMMENT> We're at root. </MvCOMMENT>

      <MvIF EXPR = "{dbselfnum EQ parentnum}">

            <MvFUNCRETURN></MvFUNCRETURN>

      </MvIF>

 

      <MvWHILE EXPR = "{dbselfnum NE parentnum}">

            <MvSKIP>

            <MvASSIGN NAME = "dbseqnum" VALUE = "{dbseqnum + 1}">

            <MvASSIGN NAME = "dbseqnum" VALUE = "{padl(dbseqnum,seqnum_size,'0')}">

            <MvUPDATE NAME = "&[dbname];"></MvUPDATE>

      </MvWHILE>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "UpdateSuperRoot">

 

      <MvGO ROW = 1>

 

      <MvASSIGN NAME = "dbnumdesc" VALUE = "{dbnumdesc + 1}">

      <MvASSIGN NAME = "currself" VALUE = "{dbnumdesc + big_bump}">

 

      <MvCOMMENT> If adding a root, assign new root's sequence number, and

            update super root's root count and sequence number. </MvCOMMENT>

      <MvIF EXPR = "{is_followup NE '1'}">

            <MvASSIGN NAME = "seqnum" VALUE = "{dbseqnum}">

            <MvASSIGN NAME = "dbparentno" VALUE = "{dbparentno + 1}">

            <MvASSIGN NAME = "dbseqnum" VALUE = "{dbseqnum + max_seqnum_increment}">

            <MvASSIGN NAME = "dbseqnum" VALUE = "{padl(dbseqnum,seqnum_size,'0')}">

      </MvIF>

 

      <MvASSIGN NAME = "last_rootnum" VALUE = "{dbparentno}">

 

      <MvUPDATE NAME = "&[dbname];"></MvUPDATE>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "CreateDatabaseRecord">

 

      <MvCOMMENT> Create database record for the new posting. </MvCOMMENT>

 

      <MvASSIGN NAME = "dbselfnum"      VALUE = "{currself}">

      <MvASSIGN NAME = "dbparentno"      VALUE = "{parentnum}">

      <MvASSIGN NAME = "dbnumdesc"      VALUE = "{'0'}">

      <MvASSIGN NAME = "dbseqnum"      VALUE = "{seqnum}">

      <MvASSIGN NAME = "dbnestlvl"      VALUE = "{nest_level}">

      <MvASSIGN NAME = "dbdate"      VALUE = "{date}">

      <MvASSIGN NAME = "dbtime"      VALUE = "{time}">

      <MvASSIGN NAME = "dblongdate"      VALUE = "{long_date}">

      <MvASSIGN NAME = "dbipaddr"      VALUE = "{&[REMOTE_ADDR];}">

      <MvASSIGN NAME = "dbname1"      VALUE = "{name}">

      <MvASSIGN NAME = "dbemail"      VALUE = "{email}">

      <MvASSIGN NAME = "dbsubject"      VALUE = "{subject}">

      <MvASSIGN NAME = "dblinkurl"      VALUE = "{message_url}">

      <MvASSIGN NAME = "dblinktitl"      VALUE = "{message_url_title}">

      <MvASSIGN NAME = "dbimageurl"      VALUE = "{message_img}">

 

      <MvADD NAME = "&[dbname];"></MvADD>

      <MvCLOSE NAME = "&[dbname];">

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "BuildMessageFile">

 

      <MvCOMMENT> Create a file for the message text </MvCOMMENT>

 

      <MvASSIGN NAME = "filename" VALUE = "{dirprefix $ '/' $ mesgdir $ '/' $ currself $ '.' $ ext}">

      <MvEXPORT FILE = filename FIELDS = "body" DELIMITER = ""></MvEXPORT>

     

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "ShowMessage">

 

      <MvEVAL EXPR = ShowMessageInit()>

      <MvEVAL EXPR = ShowMessageHTML1()>

      <MvEVAL EXPR = ShowMessageHTML2()>

      <MvEVAL EXPR = ShowMessageHTML3()>

      <MvEVAL EXPR = ShowMessageFormIntro()>

      <MvEVAL EXPR = ShowMessageFormSubject()>

      <MvEVAL EXPR = ShowMessageFormComments()>

      <MvEVAL EXPR = ShowMessageWrapup()>

      <MvEXIT>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "ShowMessageInit">

 

      <MvASSIGN NAME = "filename" VALUE = "{dirprefix $ '/' $ mesgdir $ '/' $ parm_msgnum $ '.' $ ext}">

 

      <MvIMPORT FILE = filename FIELDS = "body" DELIMITER = "">

      </MvIMPORT>

 

      <MvCOMMENT> Get hidden field data from database. </MvCOMMENT>

 

      <MvOPEN NAME = "&[dbname];" DATABASE = "&[database];"

            INDEXES = "&[index_file2];,&[index_file1];,&[index_file3];">

      <MvFILTER NAME = "&[dbname];" FILTER = "{NOT &[dbname];.d.deleted}">

 

      <MvFIND NAME = "&[dbname];" VALUE = "{parm_msgnum}" EXACT = "EXACT"></MvFIND>

      <MvASSIGN NAME = "parent"                  VALUE = "{dbparentno}">  

      <MvASSIGN NAME = "name"                  VALUE = "{dbname1}">     

      <MvASSIGN NAME = "email"                 VALUE = "{dbemail}">

      <MvASSIGN NAME = "subject"               VALUE = "{dbsubject}">

      <MvASSIGN NAME = "date"                  VALUE = "{dbdate}">

      <MvASSIGN NAME = "time"                  VALUE = "{dbtime}">

      <MvASSIGN NAME = "longdate"              VALUE = "{dblongdate}">

      <MvASSIGN NAME = "ipaddr"          VALUE = "{dbipaddr}">

      <MvASSIGN NAME = "url"                   VALUE = "{dblinkurl}">

      <MvASSIGN NAME = "url_title"             VALUE = "{dblinktitl}">

      <MvASSIGN NAME = "img"                   VALUE = "{dbimageurl}">

      <MvASSIGN NAME = "starting_recno"         VALUE = "{&[dbname];.d.recno}">

      <MvASSIGN NAME = "starting_nestlvl"       VALUE = "{dbnestlvl}">

 

      <MvIF EXPR = "{parent NE super_root}">

            <MvFIND NAME = "&[dbname];" VALUE = "{parent}" EXACT = "EXACT"></MvFIND>

            <MvASSIGN NAME = "parent_name"           VALUE = "{dbname1}">     

            <MvASSIGN NAME = "parent_subject"         VALUE = "{dbsubject}">

            <MvASSIGN NAME = "parent_date"            VALUE = "{dbdate}">

            <MvASSIGN NAME = "parent_time"            VALUE = "{dbtime}">

            <MvASSIGN NAME = "parent_ipaddr"  VALUE = "{dbipaddr}">

      </MvIF>

 

      <MvCLOSE NAME = "&[dbname];">

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "ShowMessageHTML1">

     

      &[ON];&[header];<center><h1>&[subject];</h1></center>&[crlf];&[OFF];

 

      <MvASSIGN NAME = "showing_message" VALUE = "{1}">

      <MvEVAL EXPR = LinkLine(parm_admin_flag,parm_user,parm_pass)>

      <MvASSIGN NAME = "showing_message" VALUE = "{0}">

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "ShowMessageHTML2">

 

      &[ON];<BLOCKQUOTE>Posted by&[crlf];&[OFF];

 

      <MvIF EXPR = "{use_time EQ 'on'}">

            <MvASSIGN NAME = "print_date" VALUE = "{time $ ' ' $ date}">

            <MvASSIGN NAME = "parent_print_date" VALUE = "{parent_time $ ' ' $ parent_date}">

      <MvELSE>

            <MvASSIGN NAME = "print_date" VALUE = "{date}">

            <MvASSIGN NAME = "parent_print_date" VALUE = "{parent_date}">

      </MvIF>

 

      <MvIF EXPR = "{email NE ''}">

            &[ON];<a href="mailto:&[email];">&[name];</a> on &[print_date]; from &[ipaddr];:<p>&[crlf];&[OFF];

      <MvELSE>

            &[ON];&[name]; on &[print_date]; from &[ipaddr];:<p>&[crlf];&[OFF];

      </MvIF>

 

      <MvIF EXPR = "{parent NE super_root}">

            <MvIF EXPR = "{parm_admin_flag EQ 'y'}">

                  <MvASSIGN NAME = "parent_msg" VALUE = "{'&[documenturl];parm_func=showmsg+parm_msgnum=&[parent];+parm_admin_flag=y+parm_user=&[parm_user];+parm_pass=&[parm_pass];'}">

            <MvELSE>

                  <MvASSIGN NAME = "parent_msg" VALUE = "{'&[documenturl];parm_func=showmsg+parm_msgnum=&[parent];'}">

            </MvIF>

 

            &[ON];In reply to: <a href="&[parent_msg];">&[parent_subject];</a> posted by &[crlf];&[OFF];

 

            <MvIF EXPR = "{parent_email NE ''}">

                  &[ON];<a href="&[parent_email];">&[parent_name];</a> on &[parent_print_date];:<p>&[crlf];&[OFF];

            <MvELSE>

                  &[ON];&[parent_name]; on &[parent_print_date]; from &[parent_ipaddr];:<p>&[crlf];&[OFF];

            </MvIF>

      </MvIF>

 

      <MvIF EXPR = "{allow_gif EQ 'on' AND img NE ''}">

            &[ON];<center><img src="&[img];"></center><p>&[crlf];&[OFF];

      </MvIF>

 

      &[ON];&[body];&[crlf];&[OFF];

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "ShowMessageHTML3">

 

     

      <MvIF EXPR = "{url NE ''}">

            &[ON];<ul><li><a href="&[url];">&[url_title];</a></ul>&[crlf];&[OFF];

      </MvIF>

 

      &[ON];</BLOCKQUOTE><hr width=90%><p>&[crlf];&[OFF];

      &[ON];<a NAME = followups><UL><H3>Follow Ups:</H3></UL>&[crlf];&[OFF];

 

      <MvASSIGN NAME = "roots_per_page" VALUE = "{'1'}">

      <MvASSIGN NAME = "roots_displayed_count" VALUE = "{'0'}">

      <MvASSIGN NAME = "traverse_function"      VALUE = "{'AddLine'}">

      <MvASSIGN NAME = "traverse_reason" VALUE = "{'followups'}">

 

      <MvOPEN NAME = "&[dbname];" DATABASE = "&[database];"

            INDEXES = "&[index_file1];,&[index_file2];,&[index_file3];">

      <MvFILTER NAME = "&[dbname];" FILTER = "{NOT &[dbname];.d.deleted}">

 

      &[ON]<BLOCKQUOTE>&[OFF]

      <MvEVAL EXPR = TraverseTree(parm_admin_flag,parm_user,parm_pass)>

      <MvEVAL EXPR = Unindent()>

      <MvCLOSE NAME = "&[dbname];">

 

      &[ON];<hr width=90%><p>&[crlf];&[OFF];

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "ShowMessageFormIntro">

 

      &[ON];<a NAME = postfollowup><UL><center><H1>Post a Followup</H1></center></UL>&[crlf];&[OFF];

 

      <MvIF EXPR = "{show_preview EQ 'on'}">

            <MvASSIGN NAME = "postvar" VALUE = "{'parm_func=followuppreview'}">

      <MvELSE>

            <MvASSIGN NAME = "postvar" VALUE = "{'parm_func=post'}">

      </MvIF>

 

      <MvIF EXPR = "{parm_admin_flag EQ 'y'}">

            &[ON];<form method=POST action="&[documenturl];&[postvar];+parm_admin_flag=y+parm_user=&[parm_user];+parm_pass=&[parm_pass];">&[crlf];&[OFF];

      <MvELSE>

            &[ON];<form method=POST action="&[documenturl];&[postvar];">&[crlf];&[OFF];

      </MvIF>

 

      <MvIF EXPR = "{allow_html_subj EQ 'on'}">

            <MvASSIGN NAME = "subject" VALUE = "{ConvertTags(subject)}">

      </MvIF>

 

      &[ON];<input type=hidden name="parm_followup_to" value="&[parm_msgnum];"></INPUT>&[crlf];&[OFF];

      &[ON];<input type=hidden name="form_origname" value="&[name];"></INPUT>&[crlf];&[OFF];

      &[ON];<input type=hidden name="form_origemail" value="&[email];"></INPUT>&[crlf];&[OFF];

      &[ON];<input type=hidden name="form_origsubject" value="&[subject];"></INPUT>&[crlf];&[OFF];

      &[ON];<input type=hidden name="form_origdate" value="&[longdate];"></INPUT>&[crlf];&[OFF];

      &[ON];<CENTER><TABLE>&[crlf];&[OFF];

      &[ON];<TR><TH align="left">Name:</TH><TD><input type=text name="form_name" size=&[textwidth]; maxlength=&[textwidth];></INPUT></TD></TR>&[crlf];&[OFF];

      &[ON];<TR><TH align="left">E-Mail:</TH><TD><input type=text name="form_email" size=&[textwidth]; maxlength=&[textwidth];></INPUT></TD></TR>&[crlf];&[OFF];

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "ShowMessageFormSubject">

 

     

      <MvIF EXPR = "{subject_line EQ '0'}">

            <MvASSIGN NAME = "a1" VALUE = "{'Re:' IN subject}">

            <MvIF EXPR = "{a1 EQ '1'}">

                  &[ON];<TR><TH align="left">Subject:</TH><TD><b>&[crlf];&[OFF];

                  &[ON];<input type=text name="form_subject" size=&[textwidth]; maxlength=&[textwidth]; value="&[subject];"></INPUT></b></TD></TR>&[crlf];&[OFF];

            <MvELSE>

                  &[ON];<TR><TH align="left">Subject:</TH><TD><b>&[crlf];&[OFF];

                  &[ON];<input type=text name="form_subject" size=&[textwidth]; maxlength=&[textwidth]; value="Re: &[subject];"></INPUT></b></TD></TR>&[crlf];&[OFF];

            </MvIF>

      <MvELSE>

      <MvIF EXPR = "{subject_line EQ '1'}">

            <MvASSIGN NAME = "a1" VALUE = "{'Re:' IN subject}">

            <MvIF EXPR = "{a1 EQ '1'}">

                  &[ON];<input type=hidden name="form_subject" size=&[textwidth]; maxlength=&[textwidth]; value="&[subject];"></INPUT>&[crlf];&[OFF];

                  &[ON];<TR><TH align="left">Subject:</TH><TD><b>&[subject];</b></TD></TR>&[crlf];&[OFF];

            <MvELSE>

                  &[ON];<input type=hidden name="form_subject" size=&[textwidth]; maxlength=&[textwidth]; value="Re: &[subject];"></INPUT>&[crlf];&[OFF];

                  &[ON];<TR><TH align="left">Subject:</TH><TD><b>Re: &[subject];</b></TD></TR>&[crlf];&[OFF];

            </MvIF>

      <MvELSE>

      <MvIF EXPR = "{subject_line EQ '2'}">           

            &[ON];<TR><TH align="left">Subject:</TH><TD><input type=text name="form_subject" size=&[textwidth]; maxlength=&[textwidth];></INPUT></TD></TR>&[crlf];&[OFF];

      <MvELSE>

            <MvASSIGN NAME = "a1" VALUE = "{'Re:' IN subject}">

            <MvIF EXPR = "{a1 EQ '1'}">

                  &[ON];<TR><TH align="left">Subject:</TH><TD><input type=text name="form_subject" value="&[subject];" size=&[textwidth]; maxlength=&[textwidth];></INPUT></TD></TR>&[crlf];&[OFF];

            <MvELSE>

                  &[ON];<TR><TH align="left">Subject:</TH><TD><input type=text name="form_subject" value="Re: &[subject];" size=&[textwidth]; maxlength=&[textwidth];></INPUT></TD></TR>&[crlf];&[OFF];

            </MvIF>

      </MvIF>

      </MvIF>

      </MvIF>

 

      <MvIF EXPR = "{allow_html_subj EQ 'on'}">

            <MvASSIGN NAME = "subject" VALUE = "{ReconvertTags(subject)}">

      </MvIF>

 

</MvFUNCTION>

 

 

<MvFUNCTION NAME = "ShowMessageFormComments">

 

      &[ON];<TR><TH align="left">Comments:</TH><TD>&[crlf];&[OFF];

 

      <MvCOMMENT> If requested, add lines of the message to the reply comment area, preceded by colons.

          Produce one line until a <br>, newline, or <p> tag is seen.  If it's a <p>, also produce

          a blank line.

 

          Before processing body text to be quoted, convert any longforms of characters (i.e. &lt; for

          <, &gt; for >, and &quot; for ") to shortform, then reconvert when ready to display.

      </MvCOMMENT>

 

      <MvIF EXPR = "{quote_text EQ 'on'}">

            <MvIF EXPR = "{allow_html_body NE 'on'}">

                  <MvASSIGN NAME = "body" VALUE = "{ReconvertTags(body)}">

            </MvIF>

            <MvASSIGN NAME = "curr_pos" VALUE = "{'1'}">

            <MvASSIGN NAME = "lenny" VALUE = "{len(body)}">

            <MvASSIGN NAME = "a3" VALUE = "{crlf CIN body}">

            <MvIF EXPR = "{lenny GT 1 AND a3 EQ lenny - 1}">

                  <MvASSIGN NAME = "lenny" VALUE = "{lenny - 2}">

            </MvIF>

            <MvASSIGN NAME = "out_body" VALUE = "{''}">

            <MvWHILE EXPR = "{curr_pos LE lenny}">

                  <MvASSIGN NAME = "a1" VALUE = "{'<p>' CIN substring(body,curr_pos,lenny-curr_pos+1)}">

                  <MvASSIGN NAME = "a2" VALUE = "{'<br>' CIN substring(body,curr_pos,lenny-curr_pos+1)}">

                  <MvASSIGN NAME = "a3" VALUE = "{crlf CIN substring(body,curr_pos,lenny-curr_pos+1)}">

                  <MvIF EXPR = "{a1 GT '0'}">

                        <MvIF EXPR = "{((a2 EQ 0) OR (a2 GT a1)) AND ((a3 EQ 0) OR (a3 GT a1))}">

                              <MvIF EXPR = "{a1 GT textwidth - 2}">      <MvCOMMENT> Too big to fit with : </MvCOMMENT>

                                    <MvASSIGN NAME = "a4" VALUE = "{substring(body,curr_pos,textwidth - 2)}">

                                    <MvASSIGN NAME = "out_body" VALUE = "{out_body $ ': ' $ a4 $ crlf $ crlf}">

                                    <MvASSIGN NAME = "curr_pos" VALUE = "{curr_pos + textwidth - 2}">

                              <MvELSE>

                                    <MvASSIGN NAME = "a4" VALUE = "{substring(body,curr_pos,a1-1)}">

                                    <MvASSIGN NAME = "out_body" VALUE = "{out_body $ ': ' $ a4 $ crlf $ crlf}">

                                    <MvASSIGN NAME = "curr_pos" VALUE = "{curr_pos + a1-1 + 3}">

                              </MvIF>

                        <MvELSE>

                        <MvIF EXPR = "{((a2 NE 0) AND (a2 LT a1)) AND ((a3 EQ 0) OR (a3 GT a2))}">

                              <MvIF EXPR = "{a2 GT textwidth - 2}">      <MvCOMMENT> Too big to fit with : </MvCOMMENT>

                                    <MvASSIGN NAME = "a4" VALUE = "{substring(body,curr_pos,textwidth - 2)}">

                                    <MvASSIGN NAME = "out_body" VALUE = "{out_body $ ': ' $ a4 $ crlf}">

                                    <MvASSIGN NAME = "curr_pos" VALUE = "{curr_pos + textwidth - 2}">

                              <MvELSE>

                                    <MvASSIGN NAME = "a4" VALUE = "{substring(body,curr_pos,a2-1)}">

                                    <MvASSIGN NAME = "out_body" VALUE = "{out_body $ ': ' $ a4 $ crlf}">

                                    <MvASSIGN NAME = "curr_pos" VALUE = "{curr_pos + a2-1 + 4}">

                              </MvIF>

                        <MvELSE>

                        <MvIF EXPR = "{(a3 GT 0) AND (a3 LT a1)}">

                              <MvIF EXPR = "{a3 GT textwidth - 2}">      <MvCOMMENT> Too big to fit with : </MvCOMMENT>

                                    <MvASSIGN NAME = "a4" VALUE = "{substring(body,curr_pos,textwidth - 2)}">

                                    <MvASSIGN NAME = "out_body" VALUE = "{out_body $ ': ' $ a4 $ crlf}">

                                    <MvASSIGN NAME = "curr_pos" VALUE = "{curr_pos + textwidth - 2}">

                              <MvELSE>

                                    <MvASSIGN NAME = "a4" VALUE = "{substring(body,curr_pos,a3-1)}">

                                    <MvASSIGN NAME = "out_body" VALUE = "{out_body $ ': ' $ a4 $ crlf}">

                                    <MvASSIGN NAME = "curr_pos" VALUE = "{curr_pos + a3-1 + 2}">

                              </MvIF>

                        </MvIF>

                        </MvIF>

                        </MvIF>

                  <MvELSE>

                  <MvIF EXPR = "{(a2 GT 0) AND ((a3 EQ 0) OR (a3 GT a2))}">

                        <MvIF EXPR = "{a2 GT textwidth - 2}">      <MvCOMMENT> Too big to fit with : </MvCOMMENT>

                              <MvASSIGN NAME = "a4" VALUE = "{substring(body,curr_pos,textwidth - 2)}">

                              <MvASSIGN NAME = "out_body" VALUE = "{out_body $ ': ' $ a4 $ crlf}">

                              <MvASSIGN NAME = "curr_pos" VALUE = "{curr_pos + textwidth - 2}">

                        <MvELSE>

                              <MvASSIGN NAME = "a4" VALUE = "{substring(body,curr_pos,a2-1)}">

                              <MvASSIGN NAME = "out_body" VALUE = "{out_body $ ': ' $ a4 $ crlf}">

                              <MvASSIGN NAME = "curr_pos" VALUE = "{curr_pos + a2-1 + 4}">

                        </MvIF>

                  <MvELSE>

                  <MvIF EXPR = "{a3 GT '0'}">

                        <MvIF EXPR = "{a3 GT textwidth - 2}">      <MvCOMMENT> Too big to fit with : </MvCOMMENT>

                              <MvASSIGN NAME = "a4" VALUE = "{substring(body,curr_pos,textwidth - 2)}">

                              <MvASSIGN NAME = "out_body" VALUE = "{out_body $ ': ' $ a4 $ crlf}">

                              <MvASSIGN NAME = "curr_pos" VALUE = "{curr_pos + textwidth - 2}">

                        <MvELSE>

                              <MvASSIGN NAME = "a4" VALUE = "{substring(body,curr_pos,a3-1)}">

                              <MvASSIGN NAME = "out_body" VALUE = "{out_body $ ': ' $ a4 $ crlf}">

                              <MvASSIGN NAME = "curr_pos" VALUE = "{curr_pos + a3-1 + 2}">

                        </MvIF>

                  <MvELSE>

                        <MvIF EXPR = "{(lenny - curr_pos + 1) GT textwidth - 2}"><MvCOMMENT> Too big to fit with : </MvCOMMENT>

                              <MvASSIGN NAME = "a4" VALUE = "{substring(body,curr_pos,textwidth - 2)}">

                              <MvASSIGN NAME = "out_body" VALUE = "{out_body $ ': ' $ a4 $ crlf}">