===============================================================================
EDF Tokenizer String State:
===============================================================================

      case STATE_STRING: // reading a quoted string
         switch(c)
         {
         case '\t': // collapse hard tabs to spaces
            M_QStrPutc(&qstring, ' ');
            break;
         case '\f':
         case '\n': // free linebreak -- not allowed
            lexer_error(cfg, "unterminated string constant");
            return 0;
         case '\\': // escaped characters or line continuation
            {
               char s = *bufferpos++;

               if(s == '\0')
               {                  
                  lexer_error(cfg, "EOF in string constant");
                  return 0;
               }
               else
               {
                  switch(s)
                  {
                  case '\r':
                  case '\n':
                     // line continuance for quoted strings!
                     // increment the line
                     cfg->line++;

                     // loop until a non-whitespace char is found
                     while(isspace((s = *bufferpos++)));
                     
                     // better not be EOF!
                     if(s == '\0')
                     {
                        lexer_error(cfg, "EOF in string constant");
                        return 0;
                     }

                     // put back the last char
                     --bufferpos;
                     break;
                  case 'n':
                     M_QStrPutc(&qstring, '\n');
                     break;
                  case 't':
                     M_QStrPutc(&qstring, '\t');
                     break;
                  case 'a':
                     M_QStrPutc(&qstring, '\a');
                     break;
                  case 'b':
                     M_QStrPutc(&qstring, '\b');
                     break;                     
                  case '0':
                     M_QStrPutc(&qstring, '\0');
                     break;
                     // haleyjd 03/14/06: color codes
                  case 'K':
                     M_QStrPutc(&qstring, (char)128);
                     break;
                  case '1':
                  case '2':
                  case '3':
                  case '4':
                  case '5':
                  case '6':
                  case '7':
                  case '8':
                  case '9':
                     M_QStrPutc(&qstring, (char)((s - '0') + 128));
                     break;
                     // haleyjd 03/14/06: special codes
                  case 'T': // translucency
                     M_QStrPutc(&qstring, (char)138);
                     break;
                  case 'N': // normal
                     M_QStrPutc(&qstring, (char)139);
                     break;
                  case 'H': // hi
                     M_QStrPutc(&qstring, (char)140);
                     break;
                  case 'E': // error
                     M_QStrPutc(&qstring, (char)141);
                     break;
                  case 'S': // shadowed
                     M_QStrPutc(&qstring, (char)142);
                     break;
                  case 'C': // absCentered
                     M_QStrPutc(&qstring, (char)143);
                     break;
                  default:
                     M_QStrPutc(&qstring, s);
                     break;
                  }
                  continue;
               }
            }
            break;
         case '"':
            if(stringtype == 1) // double-quoted string, end it
            {
               mytext = M_QStrBuffer(&qstring);
               return CFGT_STR;
            }
            else
               M_QStrPutc(&qstring, c);
            continue;
         case '\'':
            if(stringtype == 2) // single-quoted string, end it
            {               
               mytext = M_QStrBuffer(&qstring);
               return CFGT_STR;
            }
            else
               M_QStrPutc(&qstring, c);
            continue;
         default:
            M_QStrPutc(&qstring, c);
            continue;
         }
         break;

===============================================================================         
EDF Tokenizer Heredoc State:
===============================================================================

      case STATE_HEREDOC: // heredoc string - read to next ["']@
         if((c == '"' || c == '\'') && *bufferpos == '@')
         {
            ++bufferpos; // move forward past @
            mytext = M_QStrBuffer(&qstring);
            return CFGT_STR;
         }
         else // normal characters -- everything is literal
         {
            if(c == '\n')
               cfg->line++; // still need to track line numbers

            M_QStrPutc(&qstring, c);
            continue;
         }
         break;

===============================================================================