int Menu(const char *title,MenuList& lst,int sel,int flags=MF_LABELS,const void* param=NULL) { Vector<FarMenuItem> menu; menu.Init(lst.Count()); static const char labels[]="1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"; static const int labelsCount=sizeof(labels)-1; int i=0; int j=0; char buf[16]; ZeroMemory(&menu[0],sizeof(FarMenuItem)*lst.Count()); if(!(flags&MF_FILTER)) { for(i=0;i<lst.Count();i++) { if((flags&MF_LABELS)) { if(i<labelsCount) { sprintf(buf,"&%c ",labels[i]); strcpy(menu[i].Text,buf); }else { strcpy(menu[i].Text," "); } strcat(menu[i].Text,lst[i].item.Substr(0,120)); }else { strcpy(menu[i].Text,lst[i].item.Substr(0,120)); } if(sel==i)menu[i].Selected=1; } String cnt; cnt.Sprintf(" %s%d ",GetMsg(MItemsCount),lst.Count()); int res=I.Menu(I.ModuleNumber,-1,-1,0,FMENU_WRAPMODE,title,flags&MF_SHOWCOUNT?cnt.Str():NULL, "content",NULL,NULL,&menu[0],lst.Count()); return res!=-1?lst[res].data:res; }else { String filter=param?(char*)param:""; Vector<int> idx; Vector<int> fk; static const char *filterkeys="1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$\\\x08-_=|;':\",./<>? []*&^%#@!~"; int shift; for(i=0;filterkeys[i];i++) { DWORD k=VkKeyScan(filterkeys[i]); if(k==0xffff) { fk.Push(0); continue; } shift=(k&0xff00)>>8; if(shift==1)shift=4; else if (shift==2)shift=1; else if (shift==4)shift=2; k=(k&0xff)|(shift<<16); fk.Push(k); } fk.Push(0); #ifdef DEBUG //DebugBreak(); #endif int mode=0; for(;;) { int oldj=j; j=0; String match=""; int minit=0; int fnd=-1,oldfnd=-1; idx.Clean(); for(i=0;i<lst.Count();i++) { lst[i].item.SetNoCase(!config.casesens); if(filter.Length() && (fnd=lst[i].item.Index(filter))==-1)continue; if(!minit && fnd!=-1) { match=lst[i].item.Substr(fnd); minit=1; } if(oldfnd!=-1 && oldfnd!=fnd) { oldj=-1; } if(fnd!=-1 && filter.Length()) { int xfnd=-1; while((xfnd=lst[i].item.Index(filter,xfnd+1))!=-1) { for(int k=0;k<match.Length();k++) { if(xfnd+k>=lst[i].item.Length() || (config.casesens && match[k]!=lst[i].item[xfnd+k]) || (!config.casesens && tolower(match[k])!=tolower(lst[i].item[xfnd+k])) ) { match.Delete(k); break; } } } } idx.Push(i); strcpy(menu[j].Text,lst[i].item.Substr(0,120)); if(sel==j)menu[j].Selected=1; j++; if(fnd!=-1)oldfnd=fnd; } if((mode==0 && j==0) || (mode==1 && j==oldj)) { if(filter.Length()) { //DebugBreak(); filter.Delete(-1); continue; } } if(sel>j) { menu[j-1].Selected=1; } if(match.Length()>filter.Length() && j>1 && mode!=1) { filter=match; } String cnt; cnt.Sprintf(" %s%d ",GetMsg(MItemsCount),j); int bkey; String ftitle=title; ftitle+=" ["+filter+"]"; int res=I.Menu(I.ModuleNumber,-1,-1,0,FMENU_WRAPMODE|FMENU_SHOWAMPERSAND,ftitle, flags&MF_SHOWCOUNT?cnt.Str():NULL,"content",&fk[0],&bkey,&menu[0],j); if(res==-1 && bkey==-1)return -1; if(bkey==-1) { return lst[idx[res]].data; } int key=filterkeys[bkey]; if(key==8) { filter.Delete(-1); mode=1; continue; } filter+=(char)key; mode=0; sel=res; } } }