#include "common.h"
#include <libgen.h>

ALLOCATED string_obj* extend_macro(char* in, RESULT bool* ruby_mode, RESULT bool* ruby_mode_nonoutput, RESULT bool* output, RESULT bool* quick, RESULT bool* shell_mode, RESULT bool* shell_mode2, RESULT bool* xterm_mode, RESULT bool* reset_marks,  bool flg, bool convert)
{
    sFile* cursor = ActiveDir()->CursorFile();
    *ruby_mode = false;
    *ruby_mode_nonoutput = false;
    *output = true;
    *shell_mode = false;
    *shell_mode2 = false;
    *quick = false;
    *xterm_mode = false;
    *reset_marks = true;

    string_obj* out = string_new("");

    char* p = in;
    bool squote = false;
    bool dquote = false;
    while(*p) {
        if(*p == '\'') {
            p++;

            if(!dquote) squote = !squote;

            string_push_back(out, "\'");
        }
        else if(*p == '"') {
            p++;

            if(!squote) dquote = !dquote;

            string_push_back(out, "\"");
        }
        else if(!squote && *p == '%') {
        //else if(!squote && !dquote && *p == '%') {
            p++;

            switch(*p) {
                case '%':
                    p++;

                    if(flg) {
                        string_push_back(out, "%");
                    }
                    else {
                        string_push_back(out, "%%");
                    }
                    break;

                case 'r':
                    p++;

                    if(flg) {
                        *ruby_mode = true;
                    }
                    else {
                        string_push_back(out, "%r");
                    }
                    break;

                case 'R':
                    p++;

                    if(flg) {
                        *ruby_mode_nonoutput = true;
                    }
                    else {
                        string_push_back(out, "%R");
                    }
                    break;

                case 'q':
                    p++;

                    if(flg) {
                        *output = false;
                    }
                    else {
                        string_push_back(out, "%q");
                    }
                    break;

                case 'Q':
                    p++;

                    if(flg) {
                        *quick = true;
                    }
                    else {
                        string_push_back(out, "%Q");
                    }
                    break;

                case 's':
                    p++;

                    if(flg) {
                        *shell_mode = true;
                    }
                    else {
                        string_push_back(out, "%s");
                    }
                    break;

                case 'S':
                    p++;

                    if(flg) {
                        *shell_mode2 = true;
                    }
                    else {
                        string_push_back(out, "%S");
                    }
                    break;

                case 't':
                    p++;

                    if(flg) {
                        *xterm_mode = true;
                    }
                    else {
                        string_push_back(out, "%t");
                    }
                    break;

                case 'o':
                    p++;
                    if(flg) {
                        *reset_marks = false;
                    }
                    else {
                        string_push_back(out, "%o");
                    }
                    break;

                case 'M':
                    p++;

                    if(*p == '2') {
                        p++;

                        if(flg) {
                            string_obj* str = SleepDir()->MarkFilesSQuoteFullPath();
                            string_push_back(out, string_c_str(str));
                            string_delete(str);
                        }
                        else {
                            string_push_back(out, "%M2");
                        }
                    }
                    else {
                        if(flg) {
                            string_obj* str = ActiveDir()->MarkFilesSQuoteFullPath();
                            string_push_back(out, string_c_str(str));
                            string_delete(str);
                        }
                        else {
                            string_push_back(out, "%M");
                        }
                    }
                    break;

                case 'f': {
                    p++;

                    if(convert) {
                        const int len = strlen(cursor->mName);
      
                        bool squote_name = false;
                        for(int i=0; i<len; i++) {
                            if(cursor->mName[i] == '\'') {
                                squote_name = true;
                                break;
                            }
                        }
      
                        if(squote_name) {
                            string_push_back(out, "\"");
#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
                            string_obj* str = string_new(cursor->mName);
                            string_obj* str2 = string_new("");
                            if(kanji_convert2(str, str2, gKanjiCodeFileName, gKanjiCode) == -1) {
                                string_push_back(out, cursor->mName);
                            }
                            else {
                                string_push_back(out, string_c_str(str2));
                            }
                            string_delete(str);
                            string_delete(str2);
#else
                            string_push_back(out, cursor->mName);
#endif
                            string_push_back(out, "\"");
                        }
                        else {
                            string_push_back(out, "'");
#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
                            string_obj* str = string_new(cursor->mName);
                            string_obj* str2 = string_new("");
                            if(kanji_convert2(str, str2, gKanjiCodeFileName, gKanjiCode) == -1) {
                                string_push_back(out, cursor->mName);
                            }
                            else {
                                string_push_back(out, string_c_str(str2));
                            }
                            string_delete(str);
                            string_delete(str2);
#else
                            string_push_back(out, cursor->mName);
#endif
                            string_push_back(out, "'");
                        }
                    }
                    else {
                        const int len = strlen(cursor->mName);
      
                        bool squote_name = false;
                        for(int i=0; i<len; i++) {
                            if(cursor->mName[i] == '\'') {
                                squote_name = true;
                                break;
                            }
                        }
      
                        if(squote_name) {
                            string_push_back(out, "\"");
                            string_push_back(out, cursor->mName);
                            string_push_back(out, "\"");
                        }
                        else {
                            string_push_back(out, "'");
                            string_push_back(out, cursor->mName);
                            string_push_back(out, "'");
                        }
                    }
                }
                break;

                case 'F': {
                    p++;

                    if(convert) {
                        char* name = ActiveDir()->Path();
                        char* name2 = cursor->mName;
      
                        const int len = strlen(ActiveDir()->Path());
                        const int len2 = strlen(cursor->mName);
          
                        bool squote_name = false;
                        for(int i=0; i<len; i++) {
                            if(name[i] == '\'') {
                                squote_name = true;
                                break;
                            }
                        }
                        for(int i=0; i<len2; i++) {
                            if(name2[i] == '\'') {
                                squote_name = true;
                                break;
                            }
                        }
      
                        if(squote_name) {
                            string_push_back(out, "\"");
#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
                            string_obj* str = string_new(name);
                            string_push_back(str, name2);
                            string_obj* str2 = string_new("");
                            if(kanji_convert2(str, str2, gKanjiCodeFileName, gKanjiCode) == -1) {
                                string_push_back(out, name);
                                string_push_back(out, name2);
                            }
                            else {
                                string_push_back(out, string_c_str(str2));
                            }
                            string_delete(str);
                            string_delete(str2);
#else
                            string_push_back(out, name);
                            string_push_back(out, name2);
#endif
                            string_push_back(out, "\"");
                        }
                        else {
                            string_push_back(out, "'");

#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
                            string_obj* str = string_new(name);
                            string_push_back(str, name2);
                            string_obj* str2 = string_new("");
                            if(kanji_convert2(str, str2, gKanjiCodeFileName, gKanjiCode) == -1) {
                                string_push_back(out, name);
                                string_push_back(out, name2);
                            }
                            else {
                                string_push_back(out, string_c_str(str2));
                            }
                            string_delete(str);
                            string_delete(str2);
#else
                            string_push_back(out, name);
                            string_push_back(out, name2);
#endif
                            string_push_back(out, "'");
                        }
                    }
                    else {
                        char* name = ActiveDir()->Path();
                        char* name2 = cursor->mName;
      
                        const int len = strlen(ActiveDir()->Path());
                        const int len2 = strlen(cursor->mName);
          
                        bool squote_name = false;
                        for(int i=0; i<len; i++) {
                            if(name[i] == '\'') {
                                squote_name = true;
                                break;
                            }
                        }
                        for(int i=0; i<len2; i++) {
                            if(name2[i] == '\'') {
                                squote_name = true;
                                break;
                            }
                        }
      
                        if(squote_name) {
                            string_push_back(out, "\"");
                            string_push_back(out, name);
                            string_push_back(out, name2);
                        }
                        else {
                            string_push_back(out, "'");

                            string_push_back(out, name);
                            string_push_back(out, name2);
                            string_push_back(out, "'");
                        }
                    }
                }
                break;

                case 'x': {
                    p++;
 
                    if(convert) {
                        char* extension = extname(cursor->mName);
                        const int len = strlen(extension);
     
                        bool squote_name = false;
                        for(int i=0; i<len; i++) {
                            if(extension[i] == '\'') {
                                squote_name = true;
                                break;
                            }
                        }
      
                        if(squote_name) {
                            string_push_back(out, "\"");
#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
                            string_obj* str = string_new(extension);
                            string_obj* str2 = string_new("");
                            if(kanji_convert2(str, str2, gKanjiCodeFileName, gKanjiCode) == -1) {
                                string_push_back(out, extension);
                            }
                            else {
                                string_push_back(out, string_c_str(str2));
                            }
                            string_delete(str);
                            string_delete(str2);
#else
                            string_push_back(out, extension);
#endif
                            string_push_back(out, "\"");
                        }
                        else {
                            string_push_back(out, "'");
#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
                            string_obj* str = string_new(extension);
                            string_obj* str2 = string_new("");
                            if(kanji_convert2(str, str2, gKanjiCodeFileName, gKanjiCode) == -1) {
                                string_push_back(out, extension);
                            }
                            else {
                                string_push_back(out, string_c_str(str2));
                            }
                            string_delete(str);
                            string_delete(str2);
#else
                            string_push_back(out, extension);
#endif
                            string_push_back(out, "'");
                        }
      
                        FREE(extension);
                    }
                    else {
                        char* extension = extname(cursor->mName);
                        const int len = strlen(extension);
     
                        bool squote_name = false;
                        for(int i=0; i<len; i++) {
                            if(extension[i] == '\'') {
                                squote_name = true;
                                break;
                            }
                        }
      
                        if(squote_name) {
                            string_push_back(out, "\"");
                            string_push_back(out, extension);
                            string_push_back(out, "\"");
                        }
                        else {
                            string_push_back(out, "'");
                            string_push_back(out, extension);
                            string_push_back(out, "'");
                        }
      
                        FREE(extension);
                    }
                }
                break;

                case 'X': {
                    p++;
 
                    if(convert) {
                        char* nwe = noextname(cursor->mName);
                        const int len = strlen(nwe);
      
                        bool squote_name = false;
                        for(int i=0; i<len; i++) {
                            if(nwe[i] == '\'') {
                                squote_name = true;
                                break;
                            }
                        }
      
                        if(squote_name) {
                            string_push_back(out, "\"");
#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
                            string_obj* str = string_new(nwe);
                            string_obj* str2 = string_new("");
                            if(kanji_convert2(str, str2, gKanjiCodeFileName, gKanjiCode) == -1) {
                                string_push_back(out, nwe);
                            }
                            else {
                                string_push_back(out, string_c_str(str2));
                            }
                            string_delete(str);
                            string_delete(str2);
#else
                            string_push_back(out, nwe);
#endif
                            string_push_back(out, "\"");
                        }
                        else {
                            string_push_back(out, "'");
#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
                            string_obj* str = string_new(nwe);
                            string_obj* str2 = string_new("");
                            if(kanji_convert2(str, str2, gKanjiCodeFileName, gKanjiCode) == -1) {
                                string_push_back(out, nwe);
                            }
                            else {
                                string_push_back(out, string_c_str(str2));
                            }
                            string_delete(str);
                            string_delete(str2);
#else
                            string_push_back(out, nwe);
#endif
                            string_push_back(out, "'");
                        }
      
                        FREE(nwe);
                    }
                    else {
                        char* nwe = noextname(cursor->mName);
                        const int len = strlen(nwe);
      
                        bool squote_name = false;
                        for(int i=0; i<len; i++) {
                            if(nwe[i] == '\'') {
                                squote_name = true;
                                break;
                            }
                        }
      
                        if(squote_name) {
                            string_push_back(out, "\"");
                            string_push_back(out, nwe);
                            string_push_back(out, "\"");
                        }
                        else {
                            string_push_back(out, "'");
                            string_push_back(out, nwe);
                            string_push_back(out, "'");
                        }
      
                        FREE(nwe);
                    }
                }
                break;

                case 'd': {
                    p++;
  
                    if(*p == '2') {
                        p++;
 
                        if(convert) {
                            char* tmp = STRDUP(SleepDir()->Path());
                            tmp[strlen(tmp)-1] = 0;
                            char* name = basename(tmp);
                            FREE(tmp);
                            const int len = strlen(name);
      
                            bool squote_name = false;
                            for(int i=0; i<len; i++) {
                                if(name[i] == '\'') {
                                    squote_name = true;
                                    break;
                                }
                            }
      
                            if(squote_name) {
                                string_push_back(out, "\"");
#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
                                string_obj* str = string_new(name);
                                string_obj* str2 = string_new("");
                                if(kanji_convert2(str, str2, gKanjiCodeFileName, gKanjiCode) == -1) {
                                    string_push_back(out, name);
                                }
                                else {
                                    string_push_back(out, string_c_str(str2));
                                }
                                string_delete(str);
                                string_delete(str2);
#else
                                string_push_back(out, name);
#endif
                                string_push_back(out, "/");
                                string_push_back(out, "\"");
                            }
                            else {
                                string_push_back(out, "'");
#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
                                string_obj* str = string_new(name);
                                string_obj* str2 = string_new("");
                                if(kanji_convert2(str, str2, gKanjiCodeFileName, gKanjiCode) == -1) {
                                    string_push_back(out, name);
                                }
                                else {
                                    string_push_back(out, string_c_str(str2));
                                }
                                string_delete(str);
                                string_delete(str2);
#else
                                string_push_back(out, name);
#endif
                                string_push_back(out, "/");
                                string_push_back(out, "'");
                            }
                        }
                        else {
                            char* tmp = STRDUP(SleepDir()->Path());
                            tmp[strlen(tmp)-1] = 0;
                            char* name = basename(tmp);
                            FREE(tmp);
                            const int len = strlen(name);
      
                            bool squote_name = false;
                            for(int i=0; i<len; i++) {
                                if(name[i] == '\'') {
                                    squote_name = true;
                                    break;
                                }
                            }
      
                            if(squote_name) {
                                string_push_back(out, "\"");
                                string_push_back(out, name);
                                string_push_back(out, "/");
                                string_push_back(out, "\"");
                            }
                            else {
                                string_push_back(out, "'");
                                string_push_back(out, name);
                                string_push_back(out, "/");
                                string_push_back(out, "'");
                            }
                        }
                    }
                    else {
                        if(convert) {
                            char* tmp = STRDUP(ActiveDir()->Path());
                            tmp[strlen(tmp)-1] = 0;
                            char* name = basename(tmp);
                            FREE(tmp);
                            const int len = strlen(name);
      
                            bool squote_name = false;
                            for(int i=0; i<len; i++) {
                                if(name[i] == '\'') {
                                    squote_name = true;
                                    break;
                                }
                            }
      
                            if(squote_name) {
                                string_push_back(out, "\"");
#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
                                string_obj* str = string_new(name);
                                string_obj* str2 = string_new("");
                                if(kanji_convert2(str, str2, gKanjiCodeFileName, gKanjiCode) == -1) {
                                    string_push_back(out, name);
                                }
                                else {
                                    string_push_back(out, string_c_str(str2));
                                }
                                string_delete(str);
                                string_delete(str2);
#else
                                string_push_back(out, name);
#endif
                                string_push_back(out, "/");
                                string_push_back(out, "\"");
                            } else {
                                string_push_back(out, "'");
#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
                                string_obj* str = string_new(name);
                                string_obj* str2 = string_new("");
                                if(kanji_convert2(str, str2, gKanjiCodeFileName, gKanjiCode) == -1) {
                                    string_push_back(out, name);
                                }
                                else {
                                    string_push_back(out, string_c_str(str2));
                                }
                                string_delete(str);
                                string_delete(str2);
#else
                                string_push_back(out, name);
#endif
                                string_push_back(out, "/");
                                string_push_back(out, "'");
                            }
                        }
                        else {
                            char* tmp = STRDUP(ActiveDir()->Path());
                            tmp[strlen(tmp)-1] = 0;
                            char* name = basename(tmp);
                            FREE(tmp);
                            const int len = strlen(name);
      
                            bool squote_name = false;
                            for(int i=0; i<len; i++) {
                                if(name[i] == '\'') {
                                    squote_name = true;
                                    break;
                                }
                            }
      
                            if(squote_name) {
                                string_push_back(out, "\"");
                                string_push_back(out, name);
                                string_push_back(out, "/");
                                string_push_back(out, "\"");
                            } else {
                                string_push_back(out, "'");
                                string_push_back(out, name);
                                string_push_back(out, "/");
                                string_push_back(out, "'");
                            }
                        }
                    }
                }
                break;

                case 'D': {
                      p++;

                      if(*p == '2') {
                          p++;

                          if(convert) {
                              const char* name = SleepDir()->Path();
                              const int len = strlen(name);

                              bool squote_name = false;
                              for(int i=0; i<len; i++) {
                                  if(name[i] == '\'') {
                                      squote_name = true;
                                      break;
                                  }
                              }

                              char tmp[PATH_MAX];
                              strcpy(tmp, name);
                              tmp[strlen(tmp)-1] = 0;

                              if(squote_name) {
                                  string_push_back(out, "\"");
#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
                                  string_obj* str = string_new(tmp);
                                  string_obj* str2 = string_new("");
                                  if(kanji_convert2(str, str2, gKanjiCodeFileName, gKanjiCode) == -1) {
                                      string_push_back(out, tmp);
                                  }
                                  else {
                                      string_push_back(out, string_c_str(str2));
                                  }
                                  string_delete(str);
                                  string_delete(str2);
#else
                                  string_push_back(out, tmp);
#endif
                                  string_push_back(out, "/");
                                  string_push_back(out, "\"");
                              }
                              else {
                                  string_push_back(out, "'");
#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
                                  string_obj* str = string_new(tmp);
                                  string_obj* str2 = string_new("");
                                  if(kanji_convert2(str, str2, gKanjiCodeFileName, gKanjiCode) == -1) {
                                      string_push_back(out, tmp);
                                  }
                                  else {
                                      string_push_back(out, string_c_str(str2));
                                  }
                                  string_delete(str);
                                  string_delete(str2);
#else
                                  string_push_back(out, tmp);
#endif
                                  string_push_back(out, "/");
                                  string_push_back(out, "'");
                              }
                          }
                          else {
                              const char* name = SleepDir()->Path();
                              const int len = strlen(name);

                              bool squote_name = false;
                              for(int i=0; i<len; i++) {
                                  if(name[i] == '\'') {
                                      squote_name = true;
                                      break;
                                  }
                              }

                              char tmp[PATH_MAX];
                              strcpy(tmp, name);
                              tmp[strlen(tmp)-1] = 0;

                              if(squote_name) {
                                  string_push_back(out, "\"");
                                  string_push_back(out, tmp);
                                  string_push_back(out, "/");
                                  string_push_back(out, "\"");
                              }
                              else {
                                  string_push_back(out, "'");
                                  string_push_back(out, tmp);
                                  string_push_back(out, "/");
                                  string_push_back(out, "'");
                              }
                          }
                      }
                      else {
                          if(convert) {
                              const char* name = ActiveDir()->Path();
                              const int len = strlen(ActiveDir()->Path());

                              bool squote_name = false;
                              for(int i=0; i<len; i++) {
                                  if(name[i] == '\'') {
                                      squote_name = true;
                                      break;
                                  }
                              }

                              char tmp[PATH_MAX];
                              strcpy(tmp, name);
                              tmp[strlen(tmp)-1] = 0;

                              if(squote_name) {
                                  string_push_back(out, "\"");
#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
                                  string_obj* str = string_new(tmp);
                                  string_obj* str2 = string_new("");
                                  if(kanji_convert2(str, str2, gKanjiCodeFileName, gKanjiCode) == -1) {
                                      string_push_back(out, tmp);
                                  }
                                  else {
                                      string_push_back(out, string_c_str(str2));
                                  }
                                  string_delete(str);
                                  string_delete(str2);
#else
                                  string_push_back(out, tmp);
#endif
                                  string_push_back(out, "/");
                                  string_push_back(out, "\"");
                              }
                              else {
                                  string_push_back(out, "'");
#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
                                  string_obj* str = string_new(tmp);
                                  string_obj* str2 = string_new("");
                                  if(kanji_convert2(str, str2, gKanjiCodeFileName, gKanjiCode) == -1) {
                                      string_push_back(out, tmp);
                                  }
                                  else {
                                      string_push_back(out, string_c_str(str2));
                                  }
                                  string_delete(str);
                                  string_delete(str2);
#else
                                  string_push_back(out, tmp);
#endif
                                  string_push_back(out, "/");
                                  string_push_back(out, "'");
                              }
                          }
                          else {
                              const char* name = ActiveDir()->Path();
                              const int len = strlen(ActiveDir()->Path());

                              bool squote_name = false;
                              for(int i=0; i<len; i++) {
                                  if(name[i] == '\'') {
                                      squote_name = true;
                                      break;
                                  }
                              }

                              char tmp[PATH_MAX];
                              strcpy(tmp, name);
                              tmp[strlen(tmp)-1] = 0;

                              if(squote_name) {
                                  string_push_back(out, "\"");
                                  string_push_back(out, tmp);
                                  string_push_back(out, "/");
                                  string_push_back(out, "\"");
                              }
                              else {
                                  string_push_back(out, "'");
                                  string_push_back(out, tmp);
                                  string_push_back(out, "/");
                                  string_push_back(out, "'");
                              }
                          }
                      }

                  }
                  break;

                case 'm':
                    p++;
      
                    if(*p == '2') {
                        p++;
      
                        if(flg) {
                            string_obj* str = SleepDir()->MarkFilesSQuote();
                            string_push_back(out, string_c_str(str));
                            string_delete(str);
                        }
                        else {
                            string_push_back(out, "%m2");
                        }
                    }
                    else {
                        if(flg) {
                            string_obj* str = ActiveDir()->MarkFilesSQuote();
                            string_push_back(out, string_c_str(str));
                            string_delete(str);
                        }
                        else {
                            string_push_back(out, "%m");
                        }
                    }
                    break;
  
                default:
                    gErrMsgCancel = false; 
                    err_msg("illeagal macro char");
                    break;
            }
        }
        else {
            char tmp[2];
            tmp[0] = *p++;
            tmp[1] = 0;
            string_push_back(out, tmp);
        }
    }

    return out;
}
