TinTin++ Mud Client The TinTin++ message board

 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
TinTin++ Mud Client

BUG/PATCH: #MAP MAP {...} {FILENAME} not VALID HTML

 
Post new topic   Reply to topic    The TinTin++ message board Forum Index -> Bug Reports
View previous topic :: View next topic  
Author Message
Slysven



Joined: 10 Apr 2011
Posts: 365
Location: As "Jomin al'Bara" in WoTMUD or Wiltshire, UK

PostPosted: Tue Jul 31, 2012 4:59 pm    Post subject: BUG/PATCH: #MAP MAP {...} {FILENAME} not VALID HTML Reply with quote

A previous forum poster here had requested a way to produce maps to share on the web. Though the #MAP MAP option ought to produce something usable it does not convert the vt102 color codes into HTML (or strip them out for #CONFIG {LOG} {PLAIN}!). In addition, once I had got that working I found the HTML that was produced was deficient in that:
In write_html_header():
  • The header closing tag </head> appears *after* the body starting one <body ....>. I have repositioned it correctly.
  • There is no <!DOCTYPE ...> at beginning of file. I've put in an entry to make it HTML 4.01 Transitional.
  • There is no title <title>...</title> tag pair in the header section which the above mentioned DOCTYPE requires. I added one so that browsers will show a meaningful entry.
  • The HTML files that were produced had a fixed charset=iso-8859-1 even when #CONFIG {CHARSET} was UTF-8 (or BIG-5). I've made it follow the current #CONFIG value to be one of: "us-ascii", "UTF-8" or "BIG5" as appropriate.

Also:
  • No attempt is made to CLOSE HTML files correctly, i.e. to close off the open <html>, <body>, <pre>, and a pair of <span ...> tags. This is now done.
  • When multiple maps for example are sent to a single file there was no divider or separator between them. I now wrap each section with a <div>...</div> pair of tags, which should prove useful, especially if one attempts to print a file with multiple sections as it should help to show where to put page breaks? HOWEVER THIS REQUIRES REWINDING THE FILE POINTER TO OVERWRITE THE HTML FOOTER WHICH THE PREVIOUS POINT ADDRESSED. THIS MAY CAUSE PROBLEMS IF A PIPE OR OTHER EXOTIC FILE TYPE IS USED TO RECEIVE THE FILE...? Confused


Although there is the "despised" <blink>...</blink> tag pair which FireFox and some other browsers (but not Old versions of Internet Explorer) support the corresponding vt102 codes {<5##>} are not mapped to anything at present (the underline attribute {<4##>} also does not seem to be handled either Nope ) - I have used the flashing attribute in my UTF-8 maps to have flashing Skull & Crossbones symbols on Death-trap rooms and also to flash my location...!

Anyway here is the patch which I hope can be considered and incorporated...
Code:
--- ./src_original/buffer.c   2011-10-24 04:32:15.000000000 +0100
+++ ./src_modified/buffer.c   2012-07-29 20:47:29.598265200 +0100
@@ -991,7 +991,9 @@
 
          if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
          {
-            write_html_header(fp);
+            write_html_header(fp, (HAS_BIT(ses->flags,SES_FLAG_UTF8) ? "UTF-8":
+               (HAS_BIT(ses->flags,SES_FLAG_BIG5) ? "BIG5" :
+               "us-ascii")));
          }
 
          cnt = ses->scroll_row;
@@ -1030,6 +1032,11 @@
          }
          while (cnt != ses->scroll_row);
 
+         if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
+         {
+            write_html_footer(fp);
+         }
+
          fclose(fp);
       }
       else
--- ./src_original/line.c   2011-10-24 04:32:15.000000000 +0100
+++ ./src_modified/line.c   2012-07-31 21:22:23.470207700 +0100
@@ -82,13 +82,63 @@
       return ses;
    }
 
-   if ((ses->logline = fopen(left, "a")))
+   /* Have to test open file now as change of file opening mode from "a" to
+    * "r+" will fail if file does not exist */
+   ses->logline = fopen(left, "r+");
+   if (ses->logline==NULL)
+   { /*File does not exist (or can not be read*/
+      ses->logline = fopen(left, "w");
+      /* So we'll try to create an empty one */
+   }
+
+   if (ses->logline)
    {
+      fclose(ses->logline);
+   }
+
+   if ((ses->logline = fopen(left, "r+")))
+   { /*Was "a" but we may need to be able to rewind in file to overwrite */
       fseek(ses->logline, 0, SEEK_END);
 
-      if (ftell(ses->logline) == 0 && HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
+      /*Are we appending to a new file, then write header*/
+      if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
       {
-         write_html_header(ses->logline);
+         if (ftell(ses->logline) == 0)
+         {
+            write_html_header(ses->logline,
+               (HAS_BIT(ses->flags,SES_FLAG_UTF8) ? "UTF-8":
+               (HAS_BIT(ses->flags,SES_FLAG_BIG5) ? "BIG5" :
+               "us-ascii")));
+            if (ses->footer_size==0)
+            {
+               long start;
+
+               start=ftell(ses->logline);
+               write_html_footer(ses->logline);
+               ses->footer_size=(ftell(ses->logline)) - start;
+               fseek(ses->logline, -(ses->footer_size),
+                  SEEK_CUR);
+               /* Test write a footer onto new file so we also know how far
+                *to rewind logfile to remove it ... */
+            }
+         }
+         else
+         {
+            if (ses->footer_size==0)
+            {
+               long start;
+
+               start=ftell(ses->logline);
+               write_html_footer(ses->logline);
+               ses->footer_size=(ftell(ses->logline)) - start;
+               fseek(ses->logline, -(ses->footer_size),
+                  SEEK_CUR);
+               /* Test write a footer onto new file so we also know how far
+                *to rewind logfile to remove it ... */
+            }
+            fseek(ses->logline, -(ses->footer_size), SEEK_CUR);
+            write_html_divider(ses->logline);
+         }
       }
 
       if (*right)
@@ -97,6 +147,11 @@
 
          logit(ses, right, ses->logline, FALSE);
 
+         if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
+         {
+            write_html_footer(ses->logline);
+         }
+
          fclose(ses->logline);
          ses->logline = NULL;
       }
@@ -120,19 +175,76 @@
       return ses;
    }
 
-   if ((ses->logline = fopen(left, "a")))
+   /* Have to test open file now as change of file opening mode from "a" to
+    * "r+" will fail if file does not exist. */
+   ses->logline = fopen(left, "r+");
+   if (ses->logline==NULL)
+   {
+      /* File does not exist (or can not be read. */
+      ses->logline = fopen(left, "w");
+      /* So we'll try to create an empty one. */
+   }
+
+   if (ses->logline)
+   {
+      fclose(ses->logline);
+   }
+
+   if ((ses->logline = fopen(left, "r+")))
+   /* Was "a" but we may need to be able to rewind in file to overwrite. */
    {
       fseek(ses->logline, 0, SEEK_END);
 
-      if (ftell(ses->logline) == 0 && HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
+      /* Are we appending to a new file, then write header. */
+      if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
       {
-         write_html_header(ses->logline);
+         if (ftell(ses->logline) == 0)
+         {
+            write_html_header(ses->logline,
+               (HAS_BIT(ses->flags,SES_FLAG_UTF8) ? "UTF-8":
+               (HAS_BIT(ses->flags,SES_FLAG_BIG5) ? "BIG5" :
+               "us-ascii")));
+            if (ses->footer_size==0)
+            {
+               long start;
+
+               start=ftell(ses->logline);
+               write_html_footer(ses->logline);
+               ses->footer_size=(ftell(ses->logline)) - start;
+               fseek(ses->logline, -(ses->footer_size),
+                  SEEK_CUR);
+               /* Test write a footer onto new file so we also know how far
+                * to rewind logfile to remove it ... */
+            }
+         }
+         else
+         {
+            if (ses->footer_size==0)
+            {
+               long start;
+
+               start=ftell(ses->logline);
+               write_html_footer(ses->logline);
+               ses->footer_size=(ftell(ses->logline)) - start;
+               fseek(ses->logline, -(ses->footer_size),
+                  SEEK_CUR);
+               /* Test write a footer onto new file so we also know how far
+                * to rewind logfile to remove it ... */
+            }
+            fseek(ses->logline, -(ses->footer_size), SEEK_CUR);
+            write_html_divider(ses->logline);
+         }
       }
 
       if (*right)
       {
+
          logit(ses, right, ses->logline, TRUE);
 
+         if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
+         {
+            write_html_footer(ses->logline);
+         }
          fclose(ses->logline);
          ses->logline = NULL;
       }
--- ./src_original/log.c   2011-10-24 04:32:15.000000000 +0100
+++ ./src_modified/log.c   2012-07-31 21:08:14.911000100 +0100
@@ -73,38 +73,103 @@
    {
       if (ses->logfile)
       {
+         if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
+         {
+            write_html_footer(ses->logfile);
+         }
+
          fclose(ses->logfile);
       }
 
-      if ((ses->logfile = fopen(right, "a")))
+      /* Have to test open file now as change of file opening mode from "a" to
+       * "r+" will fail if file does not exist. */
+      ses->logfile = fopen(right, "r+");
+      if (ses->logfile==NULL)
+      {
+      /* File does not exist (or can not be read) */
+         show_message(ses, -1, "#WARNING: #LOG {APPEND} {%s} - COULDN'T OPEN FILE FOR APPENDING, TRYING TO CREATE NEW FILE.", right);
+         ses->logfile = fopen(right, "w");
+         /* So we'll try to create an empty one. */
+      }
+      fclose(ses->logfile);
+
+      if ((ses->logfile = fopen(right, "r+")))
+      /* Can't use "a" anymore as may need to write before end of file. */
       {
          fseek(ses->logfile, 0, SEEK_END);
 
-         if (ftell(ses->logfile) == 0 && HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
+         if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
          {
-            write_html_header(ses->logfile);
+            if (ftell(ses->logfile) == 0)
+            {
+               write_html_header(ses->logfile, (HAS_BIT(ses->flags,SES_FLAG_UTF8)
+                  ? "UTF-8" : (HAS_BIT(ses->flags,SES_FLAG_BIG5) ? "BIG5" : "us-ascii")));
+               if (ses->footer_size==0)
+               {
+                  long start;
+
+                  start=ftell(ses->logfile);
+                  write_html_footer(ses->logfile);
+                  ses->footer_size=(ftell(ses->logfile)) - start;
+                  fseek(ses->logfile, -(ses->footer_size), SEEK_CUR);
+               }
+               /* Find out how long the *FIXED* footer is for future use,
+                * then rewind to its start. */
+            }
+            else
+            {
+               fseek(ses->logfile, -(ses->footer_size), SEEK_CUR);
+               write_html_divider(ses->logfile);
+               /* Rewind before last footer and replace with divider for
+                * next batch of information. */
+            }
          }
-         show_message(ses, -1, "#LOG: LOGGING OUTPUT TO '%s' FILESIZE: %ld", right, ftell(ses->logfile));
+         show_message(ses, -1, "#LOG {APPEND}: LOGGING OUTPUT TO '%s' FILESIZE: %ld", right, ftell(ses->logfile));
       }
       else
       {
-         tintin_printf2(ses, "#ERROR: #LOG {%s} {%s} - COULDN'T OPEN FILE.", left, right);
+         tintin_printf2(ses, "#ERROR: #LOG {APPEND} {%s} - COULDN'T OPEN FILE.", right);
       }
    }
    else if (is_abbrev(left, "OVERWRITE") && *right != 0)
    {
       if (ses->logfile)
       {
+         if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
+         {
+            write_html_footer(ses->logfile);
+         }
+         /* Probably redundent as about to overwrite it anyhow - but if
+          * switching to a new file (seems possible) then better close old
+          * one properly.*/
          fclose(ses->logfile);
       }
 
-      if ((ses->logfile = fopen(right, "w")))
+      if ((ses->logfile = fopen(right, "w+")))
+      /* Changed from "w" to allow writing at position not at end of file.*/
       {
+         fseek(ses->logfile, 0, SEEK_END);
+         /* Actually as this must be a new file this is probably redundent!*/
          if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
          {
-            write_html_header(ses->logfile);
+            write_html_header(ses->logfile, (HAS_BIT(ses->flags,SES_FLAG_UTF8)
+               ? "UTF-8": (HAS_BIT(ses->flags,SES_FLAG_BIG5)
+               ? "BIG5" : "us-ascii")));
+
+            if (ses->footer_size==0)
+            {
+               long start;
+
+               start=ftell(ses->logfile);
+               write_html_footer(ses->logfile);
+               ses->footer_size=(ftell(ses->logfile)) - start;
+               fseek(ses->logfile, -(ses->footer_size), SEEK_CUR);
+            }
+            /* Find out how long the *FIXED* footer is for future use, then
+             * rewind to its start. */
+
          }
-         show_message(ses, -1, "#LOG: LOGGING OUTPUT TO '%s'", right);
+         show_message(ses, -1, "#LOG {OVERWRITE}: LOGGING OUTPUT TO '%s'", right);
       }
       else
       {
@@ -115,6 +180,10 @@
    {
       if (ses->logfile)
       {
+         if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
+         {
+            write_html_footer(ses->logfile);
+         }
          fclose(ses->logfile);
          ses->logfile = NULL;
          show_message(ses, -1, "#LOG: LOGGING TURNED OFF.");
@@ -131,13 +200,20 @@
    return ses;
 }
 
-void write_html_header(FILE *fp)
+/* Added DOCTYPE entry at start; put REQUIRED title in heading;
+ * changed "<meta http-equiv='content-type' content='type=text/html charset=UTF-8'>\n"
+ * to allow it to be externally controlled...*/
+void write_html_header(FILE *fp, char *charset)
 {
-   char *header =
+   char *headerA =
+      "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">"
       "<html>\n"
       "<head>\n"
-      "<meta http-equiv='content-type' content='text/html; charset=iso-8859-1'>\n"
-      "<meta name='description' content='Generated by TinTin++ "CLIENT_VERSION" - http://tintin.sourceforge.net'>\n"
+      "<meta http-equiv='content-type' content='text/html; charset=";
+   char *headerB =
+      "'>\n"
+      "<meta name='generator' content='"CLIENT_NAME" "CLIENT_VERSION" - http://tintin.sourceforge.net'>\n"
+      "<title>"CLIENT_NAME" "CLIENT_VERSION" file</title>\n"
       "<style type='text/css'>\n"
       "{\n\tfont-family: Courier;\n\tfont-size: 10pt;\n}\n"
       ".d30{ color: #000; } .l30{ color: #555; } .b40{ background-color: #000; } .b50{ background-color: #555 }\n"
@@ -151,13 +227,30 @@
       ".d38{ color: #FFF; } .l38{ color: #FFF; } .b48{ background-color: #000; } .b58{ background-color: #000 }\n"
       ".d39{ color: #FFF; } .l39{ color: #FFF; } .b49{ background-color: #000; } .b59{ background-color: #000 }\n"
       "</style>\n"
-      "<body bgcolor='#000000'>\n"
       "</head>\n"
-      "<pre>\n"
-      "<span class='b49'><span class='d39'>\n";
-   fputs(header, fp);
+      "<body bgcolor='#000000'>\n"
+      "<div><pre><span class='b49'><span class='d39'>";
+   fputs(headerA, fp);
+   fputs(charset, fp);
+   fputs(headerB, fp);
 }
 
+void write_html_divider(FILE *fp)
+{
+   char *divider =
+      "</span></span></pre></div>\n"
+      "<div><pre><span class='b49'><span class='d39'>";
+   fputs(divider, fp);
+}
+
+void write_html_footer(FILE *fp)
+{
+   char *footer =
+      "</span></span></pre></div>\n"
+      "</body>\n"
+      "</html>";
+   fputs(footer, fp);
+}
 
 void vt102_to_html(struct session *ses, char *txt, char *out)
 {
--- ./src_original/mapper.c   2012-04-04 03:22:14.000000000 +0100
+++ ./src_modified/mapper.c   2012-07-31 21:24:15.447501500 +0100
@@ -1088,11 +1088,88 @@
       {
          if (tolower((int) *arg3) == 'a')
          {
-            logfile = fopen(arg2, "a");
+            /* Have to test open file now as change of file opening mode
+             * from "a" to "r+" will fail if file does not exist. */
+            logfile = fopen(arg2, "r+");
+            if (logfile==NULL)
+            {
+               /* File does not exist (or can not be read) */
+               show_message(ses, -1, "#WARNING: #MAP MAP {%s} {APPEND}"
+                  " {%s} - COULDN'T OPEN FILE FOR APPENDING, TRYING TO "
+                  "CREATE NEW FILE.", arg1, arg2);
+               logfile = fopen(arg2, "w");
+               /* So we'll try to create an empty one. */
+            }
+            fclose(logfile);
+
+            logfile = fopen(arg2, "r+");
+            /* Cannot use "a" as we may need to write before the end of an
+             * existing file*/
+            fseek(logfile, 0, SEEK_END);
+            /* Have to make sure we set file pointer to END of file :) */
+            if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
+            {
+               if (ftell(logfile) == 0)
+               {
+                  /* Empty file so write header */
+                  write_html_header(logfile,
+                     (HAS_BIT(ses->flags,SES_FLAG_UTF8)
+                     ? "UTF-8": (HAS_BIT(ses->flags,SES_FLAG_BIG5)
+                     ? "BIG5" : "us-ascii")));
+
+                  if (ses->footer_size==0)
+                  {
+                     long start;
+
+                     start=ftell(logfile);
+                     write_html_footer(logfile);
+                     ses->footer_size=ftell(logfile) - start;
+                     fseek(logfile, -(ses->footer_size), SEEK_CUR);
+                  }
+               /* Find out how long the *FIXED* footer is for future use,
+                * then rewind to its start. */
+               }
+               else
+               {
+               /* Non-empty file so if footer size is unknown write
+                * it once and rewind twice...
+                * (won't work if footer has changed size but what the heck). */
+                  if (ses->footer_size==0)
+                  {
+                     long start;
+
+                     start=ftell(logfile);
+                     write_html_footer(logfile);
+                     ses->footer_size=ftell(logfile) - start;
+                     fseek(logfile, -(ses->footer_size), SEEK_CUR);
+                  }
+                  fseek(logfile, -(ses->footer_size), SEEK_CUR);
+                  /* Rewind to erase existing footer and put divider in...*/
+                  write_html_divider(logfile);
+               }
+            }
          }
          else
          {
-            logfile = fopen(arg2, "w");
+            logfile = fopen(arg2, "w+");
+            if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
+            {
+               write_html_header(logfile,
+                  (HAS_BIT(ses->flags,SES_FLAG_UTF8)
+                  ? "UTF-8": (HAS_BIT(ses->flags,SES_FLAG_BIG5)
+                  ? "BIG5" : "us-ascii")));
+
+               if (ses->footer_size==0)
+               {
+                  long start;
+
+                  start=ftell(logfile);
+                  write_html_footer(logfile);
+                  ses->footer_size=ftell(logfile) - start;
+                  fseek(logfile, -(ses->footer_size), SEEK_CUR);
+               } /* Find out how long the *FIXED* footer is for future use,
+                  * then rewind to its start. */
+            }
          }
       }
 
@@ -1157,6 +1234,21 @@
 
             if (logfile)
             {
+               if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
+               {
+                  char tmp[BUFFER_SIZE];
+
+                  strcpy(tmp, out);
+                  vt102_to_html(ses, tmp, out);
+               }
+               else if (HAS_BIT(ses->flags, SES_FLAG_LOGPLAIN))
+               {
+                  char tmp[BUFFER_SIZE];
+
+                  strcpy(tmp, out);
+                  strip_vt102_codes(tmp, out);
+               }
+
                fprintf(logfile, "%s\n", out);
             }
             else
@@ -1191,6 +1283,21 @@
 
          if (logfile)
          {
+            if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
+            {
+               char tmp[BUFFER_SIZE];
+
+               strcpy(tmp, out);
+               vt102_to_html(ses, tmp, out);
+            }
+            else if (HAS_BIT(ses->flags, SES_FLAG_LOGPLAIN))
+            {
+               char tmp[BUFFER_SIZE];
+
+               strcpy(tmp, out);
+               strip_vt102_codes(tmp, out);
+            }
+
             fprintf(logfile, "%s\n", out);
          }
          else
@@ -1202,6 +1309,9 @@
 
    if (logfile)
    {
+      if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
+         write_html_footer(logfile);
+
       fclose(logfile);
    }
 
@@ -1334,7 +1444,7 @@
 
             delete_map(ses);
 
-            return;            
+            return;
       }
    }
 
--- ./src_original/tintin.h   2012-04-04 01:11:01.000000000 +0100
+++ ./src_modified/tintin.h   2012-07-31 21:29:36.667171700 +0100
@@ -576,6 +577,7 @@
    char                  * group;
    FILE                  * logfile;
    FILE                  * logline;
+   long                    footer_size;
    struct listroot       * list[LIST_MAX];
    struct listroot       * history;
    int                     rows;
@@ -1488,7 +1491,9 @@
 
 extern void logit(struct session *ses, char *txt, FILE *file, int newline);
 extern DO_COMMAND(do_log);
-extern void write_html_header(FILE *fp);
+extern void write_html_header(FILE *fp, char *charset);
+extern void write_html_divider(FILE *fp);
+extern void write_html_footer(FILE *fp);
 extern void vt102_to_html(struct session *ses, char *txt, char *out);
 #endif
 

Further developments:
  • It may be useful to separate the #CONFIG {LOG} {PLAIN|RAW|HTML} option for the #MAP MAP case from the #LINE LOG/#LOG /#BUFFER WRITE cases - I run stuff to a second XTerm window (on a second monitor) running a "tail -f files" when I'm MUDding and RAW mode is useful for that, but if I switch to HTML mode to produce a map it'll foul that up - at present I'll have to do it off-line which is no great problem at present but might be nice to avoid by leaving a #CONFIG {MAP} option at {HTML}.
  • I have found it is possible to use <span style='cursor:pointer' title='text'>...</span> around the symbols in an HTML map file so that hovering over a room in a browser such as FireFox changes the pointer and brings up, say, the Room Name / Area / Description in a tooltip box. I need to establish a way for the user to choose which options are displayed this way and in what order, not exactly sure yet how to do that. The text does bloat the file but for small to medium size maps it really adds to the interactivity and information carrying capability! Some similar mechanisms might also make it possible to jump to other map files or to a different level on a multilevel map by clicking on an exit or room.
  • I'm also thinking that a #CONFIG {HIDEMEINMAP} option so that the symbol indicating where the User is (the centre of the map) can be switched off while producing a HTML (or indeed other) format map would be useful for HTML map production.
  • The fixed character set: "iso-8859-1" which was being used in HTML files is relevant for the English speaking American area and I suspect many MUDs do not actually go beyond plain 7-bit ASCII however for parts of the World with other iso-8859-## 8-bit character sets do we need to allow them to be selected instead within TinTin++ - or do we just do what I do and work in UTF-8 wherever I can.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    The TinTin++ message board Forum Index -> Bug Reports All times are GMT - 5 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
Get TinTin++ Mud Client at SourceForge.net. Fast, secure and Free Open Source software downloads Get TinTin++ Mud Client at SourceForge.net. Fast, secure and Free Open Source software downloads
TinTin++ Homepage

Powered by phpBB © 2001, 2002 phpBB Group