home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mksmvp10.zip / MKSRCMSG.DOC < prev    next >
Text File  |  1994-12-10  |  25KB  |  710 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.   ╔═══════════════════════════╦═══════════════════════════════════════════╗
  14.   ║ Mythical Kingdom Software ║           MK Msg Access Source            ║
  15.   ║      ▄ ▄         ▄ ▄      ║    Squish, Jam, *.Msg, Hudson, and Ezy    ║
  16.   ║      ███  ▐▀ ▐▀  ███      ║                                           ║
  17.   ║      ███████████████      ║     Copyright 1992-1994 by Mark May       ║
  18.   ║      ██████░░░██████      ║            All Rights Reserved            ║
  19.   ║  ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒  ║                                           ║
  20.   ╚═══════════════════════════╩═══════════════════════════════════════════╝
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.         The products mentioned in this documentation are trademarks
  35.                           of their individual owners.
  36.  
  37.         (See MKMsgJam.Pas for copyright/credit for the JAM message
  38.         base developers)
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.   ───────────────────────────────[  USAGE  ]──────────────────────────────
  46.  
  47.         The included programs make up a library of routines to allow you
  48.     to easily access various message base types in a very generic manner.
  49.     (I am hopeful that others will extend this to include even more
  50.     message base types).  To accomplish this a generic AbsMsgObj was created
  51.     and the Hudson, JAM, Squish, *.Msg, and Ezy objects were descended from it.
  52.  
  53.     In the MKMsgAbs.Pas file there are comments which explain what the various
  54.     methods were intended to accomplish.
  55.  
  56.     To write new messages to the message bases, you need to be sure to call
  57.     StartNewMsg prior to setting any of the message fields or adding any
  58.     text.  Text may be added to the message via DoChar, DoString, and
  59.     DoStringLn calls.  When the message is finished call WriteMsg to save
  60.     the message to the message base (nothing is updated until this is done).
  61.  
  62.     The various methods you can call are explained further in the sections
  63.     below, marked "Reading Messages" and "Writing Messages".  You also
  64.     may want to examine the included sample applications (MsgExprt, MsgImprt,
  65.     and MKMsgCvt to see how they used the message objects).
  66.  
  67.     If anyone develops support for added message base formats, that you
  68.     will make freely available (for any purpose) to other developers,
  69.     please contact me about including it in a future release.  The
  70.     advantage to BBS developers is that this will make it very easy for
  71.     utility authors to support your message base format.
  72.  
  73.  
  74.  
  75.  
  76.   ──────────────────────────[  Examples Included  ]────────────────────────
  77.  
  78.  
  79.     MsgExprt - Exports a message area to a text file
  80.  
  81.     Example: MsgExprt Out.Txt H007C:\RA\Msg
  82.  
  83.     A sample application has been included to show how these routines can
  84.     be used.  MsgExprt will export messages from the various message base
  85.     formats into a text file.  It requires two command line paramaters.  The
  86.     first is the name of the text file to use for output.  The second is the
  87.     message area identifier of the message base to be exported.
  88.  
  89.  
  90.                          -----------------------
  91.  
  92.     MsgImprt - Imports a text file into a message base.
  93.  
  94.     Example: MsgImprt MK.Log /TMark_May /P /E /ASC:\Msg\Logs /SBBS_Log
  95.  
  96.     An application like this could be used to import log files or other
  97.     information into your message base.  It is an example of how to
  98.     write new messages using the MKMsg routines. To use it you give it
  99.     a command line paramater of the text file to use and various options,
  100.     the options must be preceeded by either a '/' or a '-'.  You can also
  101.     embed options in the text file by starting a line with a percent % sign
  102.     followed by the option.  The following options are supported:
  103.  
  104.     /FFrom_Name               /TTo_Name            /SSubject_Of_Message
  105.     /AMsgAreaId               /DDestAddress        /OOrigAddress
  106.     /P (private)              /E (Erase file afterward)
  107.  
  108.  
  109.                          -----------------------
  110.  
  111.     MKMsgCvt - Converts (copies) messages from one msg base to another
  112.  
  113.     Example: MKMsgCvt H007C:\RA\Msg SC:\Msg\General
  114.  
  115.     This application allows you to quickly convert a message base from
  116.     one format to another.  It displays a "banner" screen as it converts,
  117.     to show its progress.  An application like this could be useful when
  118.     converting to a new message base format.
  119.  
  120.  
  121.  
  122.  
  123.   ──────────────────────────[  Message Area Id's  ]────────────────────────
  124.  
  125.     To identify message areas, I use something I call a MsgAreaId.  It
  126.     identifies both the type of message base and the path/area that it
  127.     is in.  With a MsgAreaId, a program can open the message base without
  128.     needing to look up anything in the BBS config files.  I encourage others
  129.     to adopt them as well, so that people who use your program can get
  130.     used to a common way of specifying the message areas.
  131.  
  132.     Message area identifiers have the following formats:
  133.  
  134.     Squish:  S followed by the path\filename of the message area
  135.        Example:  SC:\Max\Msg\Muffin
  136.  
  137.     Hudson   H followed by a 3 digit area number follow by the msg base path
  138.        Example:  H007C:\Quick\MsgBase\
  139.  
  140.     Fido(*.Msg) F followed by the message path
  141.        Example:  FD:\FD\Mail\
  142.  
  143.     JAM J followed by the path\filename of the message area
  144.        Example: JC:\RA2\MSG\RA_UTIL
  145.  
  146.     Ezycom E followed by the 4 digit area number followed by the msg base path
  147.        Example: E0001F:\EZY\MSG
  148.  
  149.     It you use the MKOpen unit to init/open your message areas, your
  150.     actual application should only need to know about the abstract message
  151.     object.  This may allow you to incorporate future message base types with
  152.     absolutely no changes to your code.
  153.  
  154.  
  155.  
  156.  
  157.  
  158.  
  159.   ──────────────────────────[  Reading Messages ]──────────────────────────
  160.  
  161.    First create a variable that is an abstract message pointer (type
  162.    AbsMsgPtr).  This can either be local to a procedure or a global
  163.    variable.
  164.  
  165.         Var
  166.           MsgOut: AbsMsgPtr;
  167.  
  168.    Next allocate the message object and initialize it.  I generally use
  169.    a case statement to handle multiple message base types.
  170.  
  171.         MsgBaseType := UpCase(AreaId[1]);
  172.         Case MsgBaseType of
  173.           'H': MsgOut := New(HudsonMsgPtr, Init);
  174.           'S': MsgOut := New(SqMsgPtr, Init);
  175.           'F': MsgOut := New(FidoMsgPtr, Init);
  176.           'E': MsgOut := New(EzyMsgPtr, Init);
  177.         Else
  178.           Begin
  179.           WriteLn('Invalid message base type');
  180.           Halt(1);
  181.           End;
  182.  
  183.    The next step is to set the message base path (which for some message
  184.    base types may also include an area number).
  185.  
  186.         MsgPath := Copy(AreaId,2,128);
  187.         MsgOut^.SetMsgPath(Copy(MsgPath);
  188.  
  189.    After setting the message base path, you are now ready to open the
  190.    message base.
  191.  
  192.         If MsgOut^.OpenMsgBase <> 0 Then
  193.           Begin
  194.           WriteLn('Error opening message base');
  195.           Halt(2);
  196.           End;
  197.  
  198.    Next we would seek to our starting message number.
  199.  
  200.         StartingNumber := 1;
  201.         MsgOut^.SeekFirst(StartingNumber);
  202.  
  203.  
  204.  
  205.  
  206.   ──────────────────────────[  Reading Messages ]──────────────────────────
  207.  
  208.    After the seek we would check whether a message was found and often
  209.    loop until we run out of messages.
  210.  
  211.  
  212.         While MsgOut^.SeekFound Do
  213.  
  214.  
  215.   Before using any of the message header fields we need to call MsgStartUp
  216.   which reads in the message header and initializes for that message.
  217.  
  218.  
  219.           Begin
  220.           MsgOut^.MsgStartUp;
  221.  
  222.   Next we would get various items of information about the message and do
  223.   whatever processing we needed to with them.
  224.  
  225.          WriteLn('Msg Number: ', MsgOut^.GetMsgNum);
  226.          WriteLn('From: ', MsgOut^.GetFrom);
  227.          WriteLn('To: ', MsgOut^.GetTo);
  228.  
  229.   Before starting to process the message text itself we need to call the
  230.   MsgTxtStartUp procedure (this reads in the message text, which may not
  231.   have been done when MsgStartUp was called to speed up processing when
  232.   only the message header information was needed).
  233.  
  234.          MsgOut^.MsgTxtStartUp;
  235.  
  236.   Next we get a word-wrapped string out of the message text (you can also
  237.   use GetChar to get the text one character at a time).
  238.  
  239.         StLen := 78;
  240.         TmpStr := MsgOut^.GetString(StLen);
  241.  
  242.   We use the EOM (end of message) function to see if there is more text
  243.   left in the message to process.
  244.  
  245.         While (Not MsgOut^.EOM) Do
  246.           Begin
  247.           WriteLn(TmpStr);
  248.           TmpStr := MsgOut^.GetString(StLen);
  249.           End;
  250.  
  251.   We then seek the next message.
  252.  
  253.         MsgOut^.SeekNext;
  254.         End;
  255.  
  256.   Finally we close the message base and dispose of the message object.
  257.  
  258.       If MsgOut^.CloseMsgBase <> 0 Then;
  259.       Dispose(MsgOut, Done);
  260.  
  261.  
  262.  
  263.  
  264.   ──────────────────────────[  Writing Messages ]──────────────────────────
  265.  
  266.   We use a similar set of methods when we want to write a new message to the
  267.   message base.
  268.  
  269.   First we again initialize the message object, set the message base path,
  270.   and open the message base.
  271.  
  272.         MsgWriteError := 0;
  273.         Case UpCase(AreaId[1]) of
  274.           'S': TMsg := New(SqMsgPtr, Init);       {Squish area}
  275.           'H': TMsg := New(HudsonMsgPtr, Init);   {Hudson area}
  276.           'F': TMsg := New(FidoMsgPtr, Init);     {*.Msg area}
  277.           'E': TMsg := New(EzyMsgPtr, Init);      {Ezy msg area}
  278.           Else
  279.             MsgWriteError := 10;
  280.           End;
  281.         If MsgWriteError = 0 Then
  282.           Begin
  283.           TMsg^.SetMsgPath(Copy(AreaId, 2, 128);  {Set msg base path}
  284.           MsgWriteError := TMsg^.OpenMsgBase;
  285.           End;
  286.  
  287.   Next we tell the message object what type of mail is kept in this
  288.   message area (this is done since some message base types keep
  289.   different flags set on echomail and netmail areas).
  290.  
  291.         If MsgWriteError = 0 Then
  292.           Begin
  293.           Case Config^.GetMsgType(Area) of        {set type of message}
  294.             Normal: TMsg^.SetMailType(mmtNormal);
  295.             EchoMail: TMsg^.SetMailType(mmtEchoMail);
  296.             NetMail: TMsg^.SetMailType(mmtNetMail);
  297.             End;
  298.  
  299.   Then we call StartNewMsg to get everything setup for adding a new
  300.   message (sets all the fields to default values).
  301.  
  302.  
  303.           TMsg^.StartNewMsg;       {initialize for adding msg}
  304.           End;
  305.  
  306.   We then set the various message header fields.
  307.  
  308.         If MsgWriteError = 0 Then
  309.           Begin
  310.           TMsg^.SetFrom('From Name');           {Set from name}
  311.           TMsg^.SetTo('To Name');               {Set to name}
  312.           TMsg^.SetSubj('Subject goes here');   {Set message subject}
  313.           TMsg^.SetDate(DateStr(GetDosDate));   {Set msg date mm-dd-yy}
  314.           TMsg^.SetTime(TimeStr(GetDosDate));   {Set msg time hh:mm}
  315.           TMsg^.SetEcho(True);                  {Should msg be echoed}
  316.           TMsg^.SetRefer(ReferenceNumber);      {Set reference #, often 0)
  317.  
  318.  
  319.  
  320.  
  321.   ──────────────────────────[  Writing Messages ]──────────────────────────
  322.  
  323.   We then add our message text using DoStringLn, DoString, and/or DoChar.
  324.   If we are creating a Fido echomail message we should also add a tear and
  325.   origin line.
  326.  
  327.           TMsg^.DoStringLn('Message text string 1');
  328.           TMsg^.DoStringLn('Message text string 2');
  329.             {Add msg text using the String StringLn or Char methods}
  330.             {make sure that a #13 occurs before the tearline}
  331.  
  332.  
  333.   Next we write the message to the message base (up until this time
  334.   nothing has been saved and you could safely abort the message
  335.   without harm).
  336.  
  337.           MsgWriteError := TMsg^.WriteMsg;    {Save the message}
  338.           End;
  339.  
  340.   Often you will then want to check what message number was given to
  341.   your newly created message.
  342.  
  343.         NewMsgNum := TMsg^.GetMsgNum;   {Check what number was assigned to it}
  344.  
  345.   And finally we again close the message base and deallocate memory.
  346.  
  347.         If TMsg^.CloseMsgBase <> 0 Then; {Close msg base}
  348.         Dispose(TMsg, Done); {Dispose of the object pointer}
  349.         End.
  350.  
  351.  
  352.  
  353.  
  354.   ─────────────────────────[  Method Descriptions ]────────────────────────
  355.  
  356.   Constructor Init;
  357.     Initializes the message object and allocates the memory that the message
  358.     object will use.
  359.  
  360.   Destructor Done;
  361.     Deallocates the memory the message object uses and does general clean up
  362.  
  363.   Procedure SetMsgPath(MsgPath: String)
  364.     Sets the path to the message base.  Note that some types of message bases
  365.     will need an area number included as part of the message path.
  366.  
  367.   Function OpenMsgBase: Word;
  368.     Opens the message base.  A zero is returned if the open is successful
  369.     otherwise an error number is returned.
  370.  
  371.   Function CloseMsgBase: Word;
  372.     Closes the message base and returns zero for success, otherwise it
  373.     returns an error number.
  374.  
  375.   Function CreateMsgBase(MaxMsg: Word; MaxDays: Word): Word;
  376.     Used to create a new message base.  Some message base types use the
  377.     maximum messages and/or maximum days to enable them to do automatic
  378.     message purging.  Again a zero is returned for success.
  379.  
  380.   Function  MsgBaseExists: Boolean;
  381.     Used to check whether a message base actually exists.
  382.  
  383.   Function  LockMsgBase: Boolean;
  384.     Used to lock the message base so that other programs cannot write
  385.     messages to it.  Note that you don't every need to call this yourself
  386.     as the WriteMsg function will call it itself.  If you are writing a
  387.     large number of messages at a time though, you can improve speed by
  388.     locking before you start and unlocking after you finish.
  389.  
  390.  
  391.   Function  UnLockMsgBase: Boolean;
  392.     Releases the lock that was put on the message base by LockMsgBase.
  393.  
  394.   Procedure SetDest(Var Addr: AddrType);
  395.     Sets the destination address (zone:net/node.point) for the message.
  396.  
  397.   Procedure SetOrig(Var Addr: AddrType);
  398.     Sets the originating address for the message.
  399.  
  400.   Procedure SetFrom(Name: String);
  401.     Sets the name of the author of the message.  Generally passed as a
  402.     mixed case string, with the message object converting it if another
  403.     format is needed.
  404.  
  405.   Procedure SetTo(Name: String);
  406.     Sets the name of the person the message was written to.
  407.  
  408.   Procedure SetSubj(Str: String);
  409.     Sets the subject of the message.
  410.  
  411.  
  412.  
  413.   ─────────────────────────[  Method Descriptions ]────────────────────────
  414.  
  415.   Procedure SetCost(SCost: Word);
  416.     Sets the netmail cost of the message.
  417.  
  418.   Procedure SetRefer(SRefer: LongInt);
  419.     Sets the message number of the message that the current message
  420.     was replying to.
  421.  
  422.   Procedure SetSeeAlso(SAlso: LongInt);
  423.     Sets the reply message number of the message that is replying to the
  424.     current message.
  425.  
  426.   Procedure SetDate(SDate: String);
  427.     Sets the date the message was written in MM-DD-YY format.
  428.  
  429.   Procedure SetTime(STime: String);
  430.     Sets the time the message was written in HH:MM format.
  431.  
  432.   Procedure SetLocal(LS: Boolean);
  433.   Procedure SetRcvd(RS: Boolean);
  434.   Procedure SetPriv(PS: Boolean);
  435.   Procedure SetCrash(SS: Boolean);
  436.   Procedure SetKillSent(SS: Boolean);
  437.   Procedure SetSent(SS: Boolean);
  438.   Procedure SetFAttach(SS: Boolean);
  439.   Procedure SetReqRct(SS: Boolean);
  440.   Procedure SetReqAud(SS: Boolean);
  441.   Procedure SetRetRct(SS: Boolean);
  442.   Procedure SetFileReq(SS: Boolean);
  443.     These procedures set the various message flags for local, received,
  444.     private, crash netmail, kill/sent, sent, file attach, request receipt,
  445.     request audit, return receipt, file request.
  446.  
  447.   Procedure DoString(Str: String);
  448.     Adds a string to the text of the message.
  449.  
  450.   Procedure DoChar(Ch: Char);
  451.     Adds a character to the text of the message.
  452.  
  453.   Procedure DoStringLn(Str: String);
  454.     Adds a string and newline to the text of the message.
  455.  
  456.   Function  WriteMsg: Word;
  457.     Writes the message you are creating to the message base.  A zero is
  458.     returned if the process was successful.
  459.  
  460.  
  461.  
  462.  
  463.   ─────────────────────────[  Method Descriptions ]────────────────────────
  464.  
  465.   Function  GetChar: Char;
  466.     Get a character from the message text.  This is valid only when reading
  467.     messages not when creating them.
  468.  
  469.   Function  EOM: Boolean;
  470.     Used to check whether we are at EOM (End Of Message) which would mean
  471.     that no more characters remain in the text of the current message.
  472.  
  473.   Function  GetString(MaxLen: Word): String;
  474.     Gets a word-wrapped string from the text of the message that can be
  475.     up to MaxLen characters long.
  476.  
  477.   Function  WasWrap: Boolean;
  478.     Tells us whether the last message text line we retrieved was word-
  479.     wrapped or whether and actual newline character was found.
  480.  
  481.   Function  GetFrom: String;
  482.   Function  GetTo: String;
  483.   Function  GetSubj: String;
  484.   Function  GetCost: Word;
  485.   Function  GetDate: String;
  486.   Function  GetTime: String;
  487.   Function  GetRefer: LongInt;
  488.   Function  GetSeeAlso: LongInt;
  489.   Procedure GetOrig(Var Addr: AddrType);
  490.   Procedure GetDest(Var Addr: AddrType);
  491.     These functions allow us to retrieve information from the message
  492.     header.  The information retrieved is in the same format as the
  493.     corresponding Set procedure.
  494.  
  495.   Function  GetMsgNum: LongInt;
  496.     Gets the message number of the current message we are reading.  It
  497.     will also return the created message number after WriteMsg has been
  498.     called (undefined prior to that time on created messages).
  499.  
  500.   Function  IsLocal: Boolean;
  501.   Function  IsCrash: Boolean;
  502.   Function  IsKillSent: Boolean;
  503.   Function  IsSent: Boolean;
  504.   Function  IsFAttach: Boolean;
  505.   Function  IsReqRct: Boolean;
  506.   Function  IsReqAud: Boolean;
  507.   Function  IsRetRct: Boolean;
  508.   Function  IsFileReq: Boolean;
  509.   Function  IsRcvd: Boolean;
  510.   Function  IsPriv: Boolean;
  511.   Function  IsDeleted: Boolean;
  512.   Function  IsEchoed: Boolean;
  513.     A series of functions that returns the status of the various message
  514.     flags for Local, Crash NetMail, Kill/Sent, Sent, File Attach, Request
  515.     Receipt, Request Audit, Return Receipt, File Request, Received,
  516.     Private, Deleted, and Echoed.
  517.  
  518.  
  519.  
  520.   ─────────────────────────[  Method Descriptions ]────────────────────────
  521.  
  522.   Function  GetMsgLoc: LongInt;
  523.   Procedure SetMsgLoc(ML: LongInt);
  524.     This pair of methods allos you to get a longint that represents the
  525.     current message location (which may be a message number, seek position,
  526.     etc) that you can store.  Later you can call SetMsgLoc with this value
  527.     to again make that message the current message.  In some message base
  528.     types this may be much quicker than doing a seekfirst to re-find it.
  529.  
  530.   Procedure MsgStartUp;
  531.     Reads in the message header of a message so that you have access to
  532.     its contents.
  533.  
  534.   Procedure MsgTxtStartUp;
  535.     Reads in the text of a message so that you have access to it.
  536.  
  537.   Procedure StartNewMsg;
  538.     Initializes fields to default values prior to starting to create a
  539.     new message.
  540.  
  541.   Procedure SeekFirst(MsgNum: LongInt);
  542.     Finds the first message number greater than or equal to the message
  543.     number you pass it.  You should use SeekFound to see if this was
  544.     successful.
  545.  
  546.   Procedure SeekNext;
  547.     Finds the next message after the current message.
  548.  
  549.   Procedure SeekPrior;
  550.     Finds the message prior to the current message.
  551.  
  552.   Function  SeekFound: Boolean;
  553.     Tells whether the SeekFirst, SeekNext, or SeekPrior request was
  554.     successful.
  555.  
  556.   Procedure YoursFirst(Name: String; Handle: String);
  557.   Procedure YoursNext;
  558.   Function  YoursFound: Boolean;
  559.     These three methods are similar to the seek methods, but instead
  560.     search for unreceived mail to an individual.  You may pass both
  561.     a name and a handle to search for both at once.
  562.  
  563.   Function  GetHighMsgNum: LongInt;
  564.     Returns the highest message number in the message base.
  565.  
  566.   Procedure SetMailType(MT: MsgMailType);
  567.     Sets the type of mail in the area (local, echo, or net).
  568.  
  569.   Function  GetSubArea: Word;
  570.     Gets the subarea number in a Hudson message base to allow one pass
  571.     with YoursFirst/YoursNext so that your mail searches are quicker.
  572.  
  573.  
  574.  
  575.  
  576.   ─────────────────────────[  Method Descriptions ]────────────────────────
  577.  
  578.   Procedure ReWriteHdr;
  579.     Rewrites the message header of the current message.  This is generally
  580.     done after changing a message flag (such as the "received" flag).  The
  581.     flags are safe to assume as part of the message header.  The
  582.     To/From/Subject information may not be part of the header in all future
  583.     message base types.
  584.  
  585.   Procedure DeleteMsg;
  586.     A procedure that deletes the current message.
  587.  
  588.   Procedure SetEcho(ES: Boolean);
  589.     Determines whether the message is flagged as waiting to be exported.
  590.  
  591.   Function  NumberOfMsgs: LongInt; Virtual;
  592.     Gets the number of messages in a message area.
  593.  
  594.   Function  GetLastRead(UNum: LongInt): LongInt;
  595.   Procedure SetLastRead(UNum: LongInt; LR: LongInt);
  596.     Gets and sets the last read pointers for the message area for a
  597.     specified user number.  The user numbers are zero-based (ie the
  598.     sysop is generally user number zero).
  599.  
  600.   Function  GetMsgDisplayNum: LongInt;
  601.     This function will either return the message number itself, or on
  602.     some message base types may return a smaller message number more
  603.     suitable for user display.
  604.  
  605.   Function  GetTxtPos: LongInt;
  606.   Procedure SetTxtPos(TP: LongInt);
  607.     These two methods allow you to get and later restore the current
  608.     position in the message text.  You should not make any other
  609.     assumptions about the value used by these methods other than
  610.     that.
  611.  
  612.  
  613.  
  614.   ───────────────────────────[  PRODUCT SUPPORT  ]─────────────────────────
  615.  
  616.  
  617.     Help or suggestions can be submitted in a variety of ways.
  618.  
  619.     *  Through the FidoNet EchoMail MK Conference (AreaTag MK).
  620.         -   This is a product support area for all Mythical Kingdom
  621.         -   Software.
  622.  
  623.     *  If the MK Echo is not available in your area, it is available from
  624.        the following addresses:
  625.  
  626.        1:110/290       1:3625/457       1:151/1000       1:151/1003
  627.  
  628.     *  Through RIME (RelayNet) at address ->MYTHKING.
  629.  
  630.     *  Via NetMail to Mark May (Author) at address 1:110/290.
  631.         -   You will have to poll for your reply after two days due to the
  632.         -   product being free.  An answer should be waiting for you by
  633.         -   then.  If you do not receive a reply within 5 days, please
  634.         -   re-send your message.  If you don't pick up your reply, it will
  635.         -   be deleted in a week or two.
  636.  
  637.     *  Call the Mythical Kingdom Tech BBS directly:
  638.         -   DataLine : 513-237-7737 (9600 Baud HST/V32)
  639.  
  640.     *  Or, mail your questions/suggestions to:
  641.  
  642.             Mark May
  643.             Mythical Kingdom Software
  644.             P.O. Box 24808
  645.             Huber Heights, OH  45424
  646.  
  647.   ───────────────────────[  WARRANTY AND DISCLAIMER  ]─────────────────────
  648.  
  649.         The only thing the author can guarantee is that MKSrcMsg will take up
  650.     space on your hard drive.  Beyond that, you use the program at your own
  651.     risk.   MKSrcMsg has been tested in many different environments with no
  652.     damage, loss of data, or compromised security, and we cannot guarantee
  653.     how it will work in your environment.  The author will not be held
  654.     responsible for any damage to your system.
  655.  
  656.  
  657.  
  658.  
  659.   ────────────────────────────[  REGISTRATION  ]───────────────────────────
  660.  
  661.         A registration fee is not required for these programs.
  662.     If you are a shareware author, consider sending me a registered
  663.     version of your program in exchange for your use of this program.
  664.  
  665.         I would appreciate it if you would either fill in the form
  666.     below and return it to me, or to drop me a postcard.  This will
  667.     help in measuring the usefulness of MK Msg Src and help in
  668.     determining how time is allocated between this and other projects.
  669.  
  670.         Registration Information:                  MKSrcMsg v1.06
  671.  
  672.  
  673.         Name:         ____________________________________________
  674.  
  675.         Address:      ____________________________________________
  676.  
  677.                       ____________________________________________
  678.  
  679.         City, ST Zip  ____________________________________________
  680.  
  681.  
  682.         BBS Name:     ____________________________________________
  683.  
  684.  
  685.         BBS Phone Number  (     )        -
  686.  
  687.  
  688.         Applicable NetWork Address(es) (IE: FidoNet, Etc.)
  689.  
  690.         __________________________________________________________
  691.  
  692.         __________________________________________________________
  693.  
  694.  
  695.         Any suggestions or comments ______________________________
  696.  
  697.         __________________________________________________________
  698.  
  699.         __________________________________________________________
  700.  
  701.  
  702.         Registrations should be mailed to:
  703.  
  704.               Mark May
  705.               Mythical Kingdom Software
  706.               P.O. Box 24808
  707.               Huber Heights, OH  45424
  708.  
  709.  
  710.