static LRESULT WINAPI swellFileSelectProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  const int maxPathLen = 2048;
  const char *multiple_files = "(multiple files)";
  switch (uMsg)
  {
    case WM_CREATE:
      if (lParam)  // swell-specific
      {
        SetWindowLong(hwnd,GWL_WNDPROC,(LPARAM)SwellDialogDefaultWindowProc);
        SetWindowLong(hwnd,DWL_DLGPROC,(LPARAM)swellFileSelectProc);
        SetWindowLongPtr(hwnd,GWLP_USERDATA,lParam);
        BrowseFile_State *parms = (BrowseFile_State *)lParam;
        if (parms->caption) SetWindowText(hwnd,parms->caption);

        SWELL_MakeSetCurParms(1,1,0,0,hwnd,false,false);

        SWELL_MakeButton(0,
              parms->mode == BrowseFile_State::OPENDIR ? "Choose directory" :
              parms->mode == BrowseFile_State::SAVE ? "Save" : "Open",
              IDOK,0,0,0,0, 0);

        SWELL_MakeButton(0, "Cancel", IDCANCEL,0,0,0,0, 0);
        HWND edit = SWELL_MakeEditField(0x100, 0,0,0,0,  0);
        HWND dir = SWELL_MakeCombo(0x103, 0,0,0,0, CBS_DROPDOWNLIST);

        HWND list = SWELL_MakeControl("",0x104,"SysListView32",LVS_REPORT|LVS_SHOWSELALWAYS|
              (parms->mode == BrowseFile_State::OPENMULTI ? 0 : LVS_SINGLESEL)|
              LVS_OWNERDATA|WS_BORDER|WS_TABSTOP,0,0,0,0,0);
        if (list)
        {
          LVCOLUMN c={LVCF_TEXT|LVCF_WIDTH, 0, 280, (char*)"Filename" };
          ListView_InsertColumn(list,0,&c);
          c.cx = 120;
          c.pszText = (char*) "Size";
          ListView_InsertColumn(list,1,&c);
          c.cx = 140;
          c.pszText = (char*) "Date";
          ListView_InsertColumn(list,2,&c);
        }
        HWND extlist = (parms->extlist && *parms->extlist) ? SWELL_MakeCombo(0x105, 0,0,0,0, CBS_DROPDOWNLIST) : NULL;
        if (extlist)
        {
          const char *p = parms->extlist;
          while (*p)
          {
            const char *rd=p;
            p += strlen(p)+1;
            if (!*p) break;
            int a = SendMessage(extlist,CB_ADDSTRING,0,(LPARAM)rd);
            SendMessage(extlist,CB_SETITEMDATA,a,(LPARAM)p);
            p += strlen(p)+1;
          }
          SendMessage(extlist,CB_SETCURSEL,0,0);
        }

        SWELL_MakeLabel(-1,parms->mode == BrowseFile_State::OPENDIR ? "Directory: " : "File:",0x101, 0,0,0,0, 0); 
        
        if (BFSF_Templ_dlgid && BFSF_Templ_dlgproc)
        {
          HWND dlg = SWELL_CreateDialog(BFSF_Templ_reshead, BFSF_Templ_dlgid, hwnd, BFSF_Templ_dlgproc, 0);
          if (dlg) SetWindowLong(dlg,GWL_ID,0x102);
          BFSF_Templ_dlgproc=0;
          BFSF_Templ_dlgid=0;
        }

        SWELL_MakeSetCurParms(1,1,0,0,NULL,false,false);

        if (edit && dir)
        {
          char buf[maxPathLen];
          const char *filepart = "";
          if (parms->initialfile && *parms->initialfile && *parms->initialfile != '.') 
          { 
            lstrcpyn_safe(buf,parms->initialfile,sizeof(buf));
            char *p = (char *)WDL_get_filepart(buf);
            if (p > buf) { p[-1]=0; filepart = p; }
          }
          else if (parms->initialdir && *parms->initialdir) 
          {
            lstrcpyn_safe(buf,parms->initialdir,sizeof(buf));
          }
          else getcwd(buf,sizeof(buf));

          SetWindowText(edit,filepart);
          SendMessage(hwnd, WM_USER+100, 0x103, (LPARAM)buf);
        }

        SetWindowPos(hwnd,NULL,0,0,600, 400, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
        SendMessage(hwnd,WM_USER+100,1,0); // refresh list
      }
    break;
    case WM_USER+100:
      switch (wParam)
      {
        case 0x103: // update directory combo box -- destroys buffer pointed to by lParam
          if (lParam)
          {
            char *path = (char*)lParam;
            HWND combo=GetDlgItem(hwnd,0x103);
            SendMessage(combo,CB_RESETCONTENT,0,0);
            WDL_remove_trailing_dirchars(path);
            while (path[0]) 
            {
              SendMessage(combo,CB_ADDSTRING,0,(LPARAM)path);
              WDL_remove_filepart(path);
              WDL_remove_trailing_dirchars(path);
            }
            SendMessage(combo,CB_ADDSTRING,0,(LPARAM)"/");
            SendMessage(combo,CB_SETCURSEL,0,0);
          } 
        break;
        case 1:
        {
          BrowseFile_State *parms = (BrowseFile_State *)GetWindowLongPtr(hwnd,GWLP_USERDATA);
          if (parms)
          {
            char buf[maxPathLen];
            const char *filt = NULL;
            buf[0]=0;
            int a = (int) SendDlgItemMessage(hwnd,0x105,CB_GETCURSEL,0,0);
            if (a>=0) filt = (const char *)SendDlgItemMessage(hwnd,0x105,CB_GETITEMDATA,a,0);

            a = (int) SendDlgItemMessage(hwnd,0x103,CB_GETCURSEL,0,0);
            if (a>=0) SendDlgItemMessage(hwnd,0x103,CB_GETLBTEXT,a,(LPARAM)buf);

            if (buf[0]) parms->scan_path(buf, filt, parms->mode == BrowseFile_State::OPENDIR);
            else parms->viewlist.DeleteAll();
            HWND list = GetDlgItem(hwnd,0x104);
            ListView_SetItemCount(list, 0); // clear selection
            ListView_SetItemCount(list, parms->viewlist.GetSize());
            ListView_RedrawItems(list,0, parms->viewlist.GetSize());
          }
        }
        break;
      }
    break;
    case WM_GETMINMAXINFO:
      {
        LPMINMAXINFO p=(LPMINMAXINFO)lParam;
        p->ptMinTrackSize.x = 300;
        p->ptMinTrackSize.y = 300;
      }
    break;
    case WM_SIZE:
      {
        BrowseFile_State *parms = (BrowseFile_State *)GetWindowLongPtr(hwnd,GWLP_USERDATA);
        // reposition controls
        RECT r;
        GetClientRect(hwnd,&r);
        const int buth = 24, cancelbutw = 50, okbutw = parms->mode == BrowseFile_State::OPENDIR ? 120 : 50;
        const int xborder = 4, yborder=8;
        const int fnh = 20, fnlblw = parms->mode == BrowseFile_State::OPENDIR ? 70 : 50;

        int ypos = r.bottom - 4 - buth;
        int xpos = r.right;
        SetWindowPos(GetDlgItem(hwnd,IDCANCEL), NULL, xpos -= cancelbutw + xborder, ypos, cancelbutw,buth, SWP_NOZORDER|SWP_NOACTIVATE);
        SetWindowPos(GetDlgItem(hwnd,IDOK), NULL, xpos -= okbutw + xborder, ypos, okbutw,buth, SWP_NOZORDER|SWP_NOACTIVATE);

        HWND emb = GetDlgItem(hwnd,0x102);
        if (emb)
        {
          RECT sr;
          GetClientRect(emb,&sr);
          if (ypos > r.bottom-4-sr.bottom) ypos = r.bottom-4-sr.bottom;
          SetWindowPos(emb,NULL, xborder,ypos, xpos - xborder*2, sr.bottom, SWP_NOZORDER|SWP_NOACTIVATE);
          ShowWindow(emb,SW_SHOWNA);
        }

        HWND filt = GetDlgItem(hwnd,0x105);
        if (filt)
        {
          SetWindowPos(filt, NULL, xborder*2 + fnlblw, ypos -= fnh + yborder, r.right-fnlblw-xborder*3, fnh, SWP_NOZORDER|SWP_NOACTIVATE);
        }

        SetWindowPos(GetDlgItem(hwnd,0x100), NULL, xborder*2 + fnlblw, ypos -= fnh + yborder, r.right-fnlblw-xborder*3, fnh, SWP_NOZORDER|SWP_NOACTIVATE);
        SetWindowPos(GetDlgItem(hwnd,0x101), NULL, xborder, ypos, fnlblw, fnh, SWP_NOZORDER|SWP_NOACTIVATE);
        SetWindowPos(GetDlgItem(hwnd,0x103), NULL, xborder, 0, r.right-xborder*2, fnh, SWP_NOZORDER|SWP_NOACTIVATE);
  
        SetWindowPos(GetDlgItem(hwnd,0x104), NULL, xborder, fnh+yborder, r.right-xborder*2, ypos - (fnh+yborder) - yborder, SWP_NOZORDER|SWP_NOACTIVATE);
      }
    break;
    case WM_COMMAND:
      switch (LOWORD(wParam))
      {
        case 0x105:
          if (HIWORD(wParam) == CBN_SELCHANGE)
          {
            SendMessage(hwnd,WM_USER+100,1,0); // refresh list
          }
        return 0;
        case 0x103:
          if (HIWORD(wParam) == CBN_SELCHANGE)
          {
            SendMessage(hwnd,WM_USER+100,1,0); // refresh list
          }
        return 0;
        case IDCANCEL: EndDialog(hwnd,0); return 0;
        case IDOK: 
          {
            char buf[maxPathLen], msg[2048];
            buf[0]=0;

            int a = (int) SendDlgItemMessage(hwnd,0x103,CB_GETCURSEL,0,0);
            if (a>=0)
            {
              SendDlgItemMessage(hwnd,0x103,CB_GETLBTEXT,a,(LPARAM)buf);
              size_t buflen = strlen(buf);
              if (!buflen) strcpy(buf,"/");
              else
              {
                if (buflen > sizeof(buf)-2) buflen = sizeof(buf)-2;
                if (buf[buflen-1]!='/') { buf[buflen++] = '/'; buf[buflen]=0; }
              }
            }
            GetDlgItemText(hwnd,0x100,msg,sizeof(msg));

            BrowseFile_State *parms = (BrowseFile_State *)GetWindowLongPtr(hwnd,GWLP_USERDATA);
            int cnt;
            if (parms->mode == BrowseFile_State::OPENMULTI && (cnt=ListView_GetSelectedCount(GetDlgItem(hwnd,0x104)))>1 && (!*msg || !strcmp(msg,multiple_files)))
            {
              HWND list = GetDlgItem(hwnd,0x104);
              WDL_TypedBuf<char> fs;
              fs.Set(buf,strlen(buf)+1);
              int a = ListView_GetNextItem(list,-1,LVNI_SELECTED);
              while (a != -1 && fs.GetSize() < 4096*4096 && cnt--)
              {
                const char *fn = NULL;
                struct BrowseFile_State::rec *rec = parms->viewlist.EnumeratePtr(a,&fn);
                if (!rec) break;

                if (*fn) fn++; // skip type ident
                fs.Add(fn,strlen(fn)+1);
                a = ListView_GetNextItem(list,a,LVNI_SELECTED);
              }
              fs.Add("",1);

              parms->fnout = (char*)malloc(fs.GetSize());
              if (parms->fnout) memcpy(parms->fnout,fs.Get(),fs.GetSize());

              EndDialog(hwnd,1);
              return 0;
            }
            else 
            {
              if (msg[0] == '.' && (msg[1] == '.' || msg[1] == 0))
              {
                if (msg[1] == '.') SendDlgItemMessage(hwnd,0x103,CB_SETCURSEL,a+1,0);
                SetDlgItemText(hwnd,0x100,"");
                SendMessage(hwnd,WM_USER+100,1,0); // refresh list
                return 0;
              }
              else if (msg[0] == '/') lstrcpyn_safe(buf,msg,sizeof(buf));
              else lstrcatn(buf,msg,sizeof(buf));
            }

            switch (parms->mode)
            {
              case BrowseFile_State::OPENDIR:
                 if (!buf[0]) return 0;
                 else if (msg[0])
                 {
                   // navigate to directory if filepart set
                   DIR *dir = opendir(buf);
                   if (!dir) 
                   {
                     snprintf(msg,sizeof(msg),"Error opening directory:\r\n\r\n%s\r\n\r\nCreate?",buf);
                     if (MessageBox(hwnd,msg,"Create directory?",MB_OKCANCEL)==IDCANCEL) return 0;
                     CreateDirectory(buf,NULL);
                     dir=opendir(buf);
                   }
                   if (!dir) { MessageBox(hwnd,"Error creating directory","Error",MB_OK); return 0; }
                   closedir(dir);
                   SendMessage(hwnd, WM_USER+100, 0x103, (LPARAM)buf);
                   SetDlgItemText(hwnd,0x100,"");
                   SendMessage(hwnd,WM_USER+100,1,0); // refresh list

                   return 0;
                 }
                 else
                 {
                   DIR *dir = opendir(buf);
                   if (!dir) return 0;
                   closedir(dir);
                 }
              break;
              case BrowseFile_State::SAVE:
                 if (!buf[0]) return 0;
                 else  
                 {
                   struct stat st={0,};
                   DIR *dir = opendir(buf);
                   if (dir)
                   {
                     closedir(dir);
                     SendMessage(hwnd, WM_USER+100, 0x103, (LPARAM)buf);
                     SetDlgItemText(hwnd,0x100,"");
                     SendMessage(hwnd,WM_USER+100,1,0); // refresh list
                     return 0;
                   }
                   if (!stat(buf,&st))
                   {
                     snprintf(msg,sizeof(msg),"File exists:\r\n\r\n%s\r\n\r\nOverwrite?",buf);
                     if (MessageBox(hwnd,msg,"Overwrite file?",MB_OKCANCEL)==IDCANCEL) return 0;
                   }
                 }
              break;
              default:
                 if (!buf[0]) return 0;
                 else  
                 {
                   struct stat st={0,};
                   DIR *dir = opendir(buf);
                   if (dir)
                   {
                     closedir(dir);
                     SendMessage(hwnd, WM_USER+100, 0x103, (LPARAM)buf);
                     SetDlgItemText(hwnd,0x100,"");
                     SendMessage(hwnd,WM_USER+100,1,0); // refresh list
                     return 0;
                   }
                   if (stat(buf,&st))
                   {
                     snprintf(msg,sizeof(msg),"File does not exist:\r\n\r\n%s",buf);
                     MessageBox(hwnd,msg,"File not found",MB_OK);
                     return 0;
                   }
                 }
              break;
            }
            if (parms->fnout) 
            {
              lstrcpyn_safe(parms->fnout,buf,parms->fnout_sz);
            }
            else
            {
              size_t l = strlen(buf);
              parms->fnout = (char*)calloc(l+2,1);
              memcpy(parms->fnout,buf,l);
            }
          }
          EndDialog(hwnd,1);
        return 0;
      }
    break;
    case WM_NOTIFY:
      {
        LPNMHDR l=(LPNMHDR)lParam;
        if (l->code == LVN_GETDISPINFO)
        {
          BrowseFile_State *parms = (BrowseFile_State *)GetWindowLongPtr(hwnd,GWLP_USERDATA);
          NMLVDISPINFO *lpdi = (NMLVDISPINFO*) lParam;
          const int idx=lpdi->item.iItem;
          if (l->idFrom == 0x104 && parms && idx >=0 && idx < parms->viewlist.GetSize())
          {
            const char *fn = NULL;
            struct BrowseFile_State::rec *rec = parms->viewlist.EnumeratePtr(idx,&fn);
            if (rec && fn)
            {
              if (lpdi->item.mask&LVIF_TEXT) 
              {
                switch (lpdi->item.iSubItem)
                {
                  case 0:
                    if (fn[0]) lstrcpyn_safe(lpdi->item.pszText,fn+1,lpdi->item.cchTextMax);
                  break;
                  case 1:
                    if (fn[0] == 1) 
                    {
                      lstrcpyn_safe(lpdi->item.pszText,"<DIR>",lpdi->item.cchTextMax);
                    }
                    else
                    {
                      static const char *tab[]={ "bytes","KB","MB","GB" };
                      int lf=0;
                      WDL_INT64 s=rec->size;
                      if (s<1024)
                      {
                        snprintf(lpdi->item.pszText,lpdi->item.cchTextMax,"%d %s  ",(int)s,tab[0]);
                        break;
                      }
                      
                      int w = 1;
                      do {  w++; lf = (int)(s&1023); s/=1024; } while (s >= 1024 && w<4);
                      snprintf(lpdi->item.pszText,lpdi->item.cchTextMax,"%d.%d %s  ",(int)s,(int)((lf*10.0)/1024.0+0.5),tab[w-1]);
                    }
                  break;
                  case 2:
                    if (rec->date > 0 && rec->date < WDL_INT64_CONST(0x793406fff))
                    {
                      struct tm *a=localtime(&rec->date);
                      if (a)
                      {
                        char str[512];
                        strftime(str,sizeof(str),"%c",a);
                        lstrcpyn(lpdi->item.pszText, str,lpdi->item.cchTextMax);
                      }
                    }
                  break;
                }
              }
            }
          }
        }
        else if (l->code == LVN_ODFINDITEM)
        {
        }
        else if (l->code == LVN_ITEMCHANGED)
        {
          const int selidx = ListView_GetNextItem(l->hwndFrom, -1, LVNI_SELECTED);
          if (selidx>=0)
          {
            BrowseFile_State *parms = (BrowseFile_State *)GetWindowLongPtr(hwnd,GWLP_USERDATA);
            if (parms && parms->mode == BrowseFile_State::OPENMULTI && ListView_GetSelectedCount(l->hwndFrom)>1)
            {
              SetDlgItemText(hwnd,0x100,multiple_files);
            }
            else
            {
              const char *fn = NULL;
              struct BrowseFile_State::rec *rec = parms ? parms->viewlist.EnumeratePtr(selidx,&fn) : NULL;
              if (rec)
              {
                if (fn && fn[0]) SetDlgItemText(hwnd,0x100,fn+1);
              }
            }
          }
        }
        else if (l->code == NM_DBLCLK)
        {
          SendMessage(hwnd,WM_COMMAND,IDOK,0);
        }

      }
    break;
  }
  return 0;
}
Example #2
0
void MultiTab_Editor::draw_top_line()
{
  int ypos=0;
  if (m_top_margin > 1)
  {
    int xpos=0;
    int x;
    move(ypos++,0);
    const int cnt= GetTabCount();
    int tsz=16;
    // this is duplicated in onMouseMessage
    if (cnt>0) tsz=COLS/cnt;
    if (tsz>128)tsz=128;
    if (tsz<12) tsz=12;

    for (x= 0; x < cnt && xpos < COLS; x ++)
    {
      MultiTab_Editor *ed = GetTab(x);
      if (ed)
      {
        char buf[128 + 8];
        memset(buf,' ',tsz);
        const char *p = WDL_get_filepart(ed->GetFileName());
        const int lp=strlen(p);
        int skip=0;        
        if (x<9) 
        { 
          if (tsz>16)
          {
#ifdef __APPLE__
            memcpy(buf,"<Cmd+",skip=5);
#else
            memcpy(buf,"<Ctrl+",skip=6);
#endif
          }
          buf[skip++]='F'; 
          buf[skip++] = '1'+x; 
          buf[skip++] = '>';
          skip++;
        }
        memcpy(buf+skip,p,min(tsz-1-skip,lp));
        buf[tsz]=0;
        int l = tsz;
        if (l > COLS-xpos) l = COLS-xpos;
        if (ed == this)
        {
          attrset(SYNTAX_HIGHLIGHT2|A_BOLD);
        }
        else
        {
          attrset(A_NORMAL);
        }
        addnstr(buf,l);
        xpos += l;
      }
    }
    if (xpos < COLS) clrtoeol();
  }
  attrset(COLOR_TOPLINE|A_BOLD);
  bkgdset(COLOR_TOPLINE);
  const char *p=GetFileName();
  move(ypos,0);
  if (COLS>4)
  {
    const int pl = (int) strlen(p);
    if (pl > COLS-1 && COLS > 4)
    {
      addstr("...");
      p+=pl - (COLS-1) + 4;
    }
    addstr(p);
  }
  clrtoeol();
}
HFONT CreateFont(int lfHeight, int lfWidth, int lfEscapement, int lfOrientation, int lfWeight, char lfItalic, 
  char lfUnderline, char lfStrikeOut, char lfCharSet, char lfOutPrecision, char lfClipPrecision, 
         char lfQuality, char lfPitchAndFamily, const char *lfFaceName)
{
  HGDIOBJ__ *font=NULL;
#ifdef SWELL_FREETYPE
  FT_Face face=NULL;
  if (!s_freetype_failed && !s_freetype) s_freetype_failed = !!FT_Init_FreeType(&s_freetype);
  if (s_freetype)
  {
    if (!lfFaceName || !*lfFaceName) lfFaceName = "Arial";

    int fn_len = strlen(lfFaceName);

    const char *leadpath = "/usr/share/fonts/truetype/msttcorefonts"; // todo: scan subdirs?
    char tmp[1024];
    char bestmatch[512];
    bestmatch[0]=0;
    int x;
    for (x=0;x < s_registered_fonts.GetSize(); x ++)
    {
      const char *fn = s_registered_fonts.Get(x);
      if (fn)
      {
        const char *fnpart = WDL_get_filepart(fn);
        if (!strnicmp(fnpart,lfFaceName,strlen(lfFaceName)))
        {
          FT_New_Face(s_freetype,fn,0,&face);
          if (face) break;
        }
      }
    }

    if (!face)
    {
      snprintf(tmp,sizeof(tmp),"%s/%s.ttf",leadpath,lfFaceName);
      FT_New_Face(s_freetype,tmp,0,&face);
    }
    if (!face)
    {
      WDL_DirScan ds;
      if (!ds.First(leadpath)) do
      { 
        if (!strnicmp(ds.GetCurrentFN(),lfFaceName,fn_len))
        {
          if (!stricmp(ds.GetCurrentFN()+fn_len,".ttf"))
          {
            snprintf(tmp,sizeof(tmp),"%s/%s",leadpath,ds.GetCurrentFN());
            FT_New_Face(s_freetype,tmp,0,&face);
          }
          else 
          {
            // todo look for italic/bold/etc too
            int sl = strlen(ds.GetCurrentFN());
            if (sl > 4 && !stricmp(ds.GetCurrentFN() + sl - 4, ".ttf")  && (!bestmatch[0] || sl < strlen(bestmatch)))
            {
              lstrcpyn_safe(bestmatch,ds.GetCurrentFN(),sizeof(bestmatch));
            }
          }
        }
      } while (!face && !ds.Next());
      if (!face && bestmatch[0])
      {
        snprintf(tmp,sizeof(tmp),"%s/%s",leadpath,bestmatch);
        FT_New_Face(s_freetype,tmp,0,&face);
      }
    }
    if (!face) FT_New_Face(s_freetype,"/usr/share/fonts/truetype/freefont/FreeSans.ttf",0,&face);
    if (!face) FT_New_Face(s_freetype,"/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",0,&face);
  }
  
  if (face)
  {
    font = GDP_OBJECT_NEW();
    font->type=TYPE_FONT;
    font->fontface = face;
    font->alpha = 1.0f;
    ////unsure here
    if (lfWidth<0) lfWidth=-lfWidth;
    if (lfHeight<0) lfHeight=-lfHeight;
    FT_Set_Char_Size(face,lfWidth*64, lfHeight*64,0,0); // 72dpi
//    FT_Set_Pixel_Sizes(face,0,lfHeight);
  }
#else
  font->type=TYPE_FONT;
#endif
 
  return font;
}