home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1998 September / PCO_0998.ISO / filesbbs / dos / sbbs_src.exe / SBBS / LISTFILE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-13  |  21.6 KB  |  783 lines

  1. #line 1 "LISTFILE.C"
  2.  
  3. /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
  4.  
  5. #include "sbbs.h"
  6.  
  7. int listfile(char *fname, char HUGE16 *buf, uint dirnum
  8.     , char *search, char letter, ulong datoffset);
  9.  
  10. void clearline(void)
  11. {
  12.     int i;
  13.  
  14. outchar(CR);
  15. if(useron.misc&ANSI)
  16.     bputs("\x1b[K");
  17. else {
  18.     for(i=0;i<79;i++)
  19.         outchar(SP);
  20.     outchar(CR); }
  21. }
  22.  
  23. /****************************************************************************/
  24. /* Remove credits from uploader of file 'f'                                 */
  25. /****************************************************************************/
  26. void removefcdt(file_t f)
  27. {
  28.     char str[128];
  29.     int u;
  30.     long cdt;
  31.  
  32. if((u=matchuser(f.uler))==0) {
  33.    bputs(text[UnknownUser]);
  34.    return; }
  35. cdt=0L;
  36. if(dir[f.dir]->misc&DIR_CDTMIN && cur_cps) {
  37.     if(dir[f.dir]->misc&DIR_CDTUL)
  38.         cdt=((ulong)(f.cdt*(dir[f.dir]->up_pct/100.0))/cur_cps)/60;
  39.     if(dir[f.dir]->misc&DIR_CDTDL
  40.         && f.timesdled)  /* all downloads */
  41.         cdt+=((ulong)((long)f.timesdled
  42.             *f.cdt*(dir[f.dir]->dn_pct/100.0))/cur_cps)/60;
  43.     adjustuserrec(u,U_MIN,10,-cdt);
  44.     sprintf(str,"%lu minute",cdt);
  45.     sprintf(tmp,text[FileRemovedUserMsg]
  46.         ,f.name,cdt ? str : text[No]);
  47.     putsmsg(u,tmp); }
  48. else {
  49.     if(dir[f.dir]->misc&DIR_CDTUL)
  50.         cdt=(ulong)(f.cdt*(dir[f.dir]->up_pct/100.0));
  51.     if(dir[f.dir]->misc&DIR_CDTDL
  52.         && f.timesdled)  /* all downloads */
  53.         cdt+=(ulong)((long)f.timesdled
  54.             *f.cdt*(dir[f.dir]->dn_pct/100.0));
  55.     adjustuserrec(u,U_CDT,10,-cdt);
  56.     sprintf(tmp,text[FileRemovedUserMsg]
  57.         ,f.name,cdt ? ultoac(cdt,str) : text[No]);
  58.     putsmsg(u,tmp); }
  59.  
  60. adjustuserrec(u,U_ULB,10,-f.size);
  61. adjustuserrec(u,U_ULS,5,-1);
  62. }
  63.  
  64. /****************************************************************************/
  65. /* Move file 'f' from f.dir to newdir                                       */
  66. /****************************************************************************/
  67. void movefile(file_t f, int newdir)
  68. {
  69.     char str[256],path[256],fname[128],ext[1024];
  70.     int olddir=f.dir;
  71.  
  72. if(findfile(newdir,f.name)) {
  73.     bprintf(text[FileAlreadyThere],f.name);
  74.     return; }
  75. getextdesc(olddir,f.datoffset,ext);
  76. if(dir[olddir]->misc&DIR_MOVENEW)
  77.     f.dateuled=time(NULL);
  78. unpadfname(f.name,fname);
  79. removefiledat(f);
  80. f.dir=newdir;
  81. addfiledat(&f);
  82. bprintf(text[MovedFile],f.name
  83.     ,lib[dir[f.dir]->lib]->sname,dir[f.dir]->sname);
  84. sprintf(str,"Moved %s to %s %s",f.name
  85.     ,lib[dir[f.dir]->lib]->sname,dir[f.dir]->sname);
  86. logline(nulstr,str);
  87. if(!f.altpath) {    /* move actual file */
  88.     sprintf(str,"%s%s",dir[olddir]->path,fname);
  89.     if(fexist(str)) {
  90.         sprintf(path,"%s%s",dir[f.dir]->path,fname);
  91.         mv(str,path,0); } }
  92. if(f.misc&FM_EXTDESC)
  93.     putextdesc(f.dir,f.datoffset,ext);
  94. }
  95.  
  96. /****************************************************************************/
  97. /* Batch flagging prompt for download, extended info, and archive viewing    */
  98. /* Returns -1 if 'Q' or Ctrl-C, 0 if skip, 1 if [Enter], 2 otherwise        */
  99. /* or 3, backwards.                                                         */
  100. /****************************************************************************/
  101. char batchflagprompt(int dirnum, file_t bf[26], char total, long totalfiles)
  102. {
  103.     char ch,c,d,str[256],fname[128],*p,remcdt,remfile;
  104.     int i,j,u,ml,md,udir,ulib;
  105.     long cdt;
  106.     file_t f;
  107.  
  108. for(ulib=0;ulib<usrlibs;ulib++)
  109.     if(usrlib[ulib]==dir[dirnum]->lib)
  110.         break;
  111. for(udir=0;udir<usrdirs[ulib];udir++)
  112.     if(usrdir[ulib][udir]==dirnum)
  113.         break;
  114.  
  115. CRLF;
  116. while(online) {
  117.     bprintf(text[BatchFlagPrompt]
  118.         ,ulib+1
  119.         ,lib[dir[dirnum]->lib]->sname
  120.         ,udir+1
  121.         ,dir[dirnum]->sname
  122.         ,totalfiles);
  123.     ch=getkey(K_UPPER);
  124.     clearline();
  125.     if(ch=='?') {
  126.         menu("BATFLAG");
  127.         if(lncntr)
  128.             pause();
  129.         return(2); }
  130.     if(ch=='Q' || sys_status&SS_ABORT)
  131.         return(-1);
  132.     if(ch=='S')
  133.         return(0);
  134.     if(ch=='P')
  135.         return(3);
  136.     if(ch=='B') {    /* Flag for batch download */
  137.         if(useron.rest&FLAG('D')) {
  138.             bputs(text[R_Download]);
  139.             return(2); }
  140.         if(total==1) {
  141.             f.dir=dirnum;
  142.             strcpy(f.name,bf[0].name);
  143.             f.datoffset=bf[0].datoffset;
  144.             f.size=0;
  145.             getfiledat(&f);
  146.             addtobatdl(f);
  147.             CRLF;
  148.             return(2); }
  149.         bputs(text[BatchDlFlags]);
  150.         d=getstr(str,26,K_UPPER|K_LOWPRIO|K_NOCRLF);
  151.         lncntr=0;
  152.         if(sys_status&SS_ABORT)
  153.             return(-1);
  154.         if(d) {     /* d is string length */
  155.             CRLF;
  156.             lncntr=0;
  157.             for(c=0;c<d;c++) {
  158.                 if(batdn_total>=max_batdn) {
  159.                     bprintf(text[BatchDlQueueIsFull],str+c);
  160.                     break; }
  161.                 if(strchr(str+c,'.')) {     /* filename or spec given */
  162.                     f.dir=dirnum;
  163.                     p=strchr(str+c,SP);
  164.                     if(!p) p=strchr(str+c,',');
  165.                     if(p) *p=0;
  166.                     for(i=0;i<total;i++) {
  167.                         if(batdn_total>=max_batdn) {
  168.                             bprintf(text[BatchDlQueueIsFull],str+c);
  169.                             break; }
  170.                         padfname(str+c,tmp);
  171.                         if(filematch(bf[i].name,tmp)) {
  172.                             strcpy(f.name,bf[i].name);
  173.                             f.datoffset=bf[i].datoffset;
  174.                             f.size=0;
  175.                             getfiledat(&f);
  176.                             addtobatdl(f); } } }
  177.                 if(strchr(str+c,'.'))
  178.                     c+=strlen(str+c);
  179.                 else if(str[c]<'A'+total && str[c]>='A') {
  180.                     f.dir=dirnum;
  181.                     strcpy(f.name,bf[str[c]-'A'].name);
  182.                     f.datoffset=bf[str[c]-'A'].datoffset;
  183.                     f.size=0;
  184.                     getfiledat(&f);
  185.                     addtobatdl(f); } }
  186.             CRLF;
  187.             return(2); }
  188.         clearline();
  189.         continue; }
  190.  
  191.     if(ch=='E' || ch=='V') {    /* Extended Info */
  192.         if(total==1) {
  193.             f.dir=dirnum;
  194.             strcpy(f.name,bf[0].name);
  195.             f.datoffset=bf[0].datoffset;
  196.             f.dateuled=bf[0].dateuled;
  197.             f.datedled=bf[0].datedled;
  198.             f.size=0;
  199.             getfiledat(&f);
  200.             if(!viewfile(f,ch=='E'))
  201.                 return(-1);
  202.             return(2); }
  203.         bputs(text[BatchDlFlags]);
  204.         d=getstr(str,26,K_UPPER|K_LOWPRIO|K_NOCRLF);
  205.         lncntr=0;
  206.         if(sys_status&SS_ABORT)
  207.             return(-1);
  208.         if(d) {     /* d is string length */
  209.             CRLF;
  210.             lncntr=0;
  211.             for(c=0;c<d;c++) {
  212.                 if(strchr(str+c,'.')) {     /* filename or spec given */
  213.                     f.dir=dirnum;
  214.                     p=strchr(str+c,SP);
  215.                     if(!p) p=strchr(str+c,',');
  216.                     if(p) *p=0;
  217.                     for(i=0;i<total;i++) {
  218.                         padfname(str+c,tmp);
  219.                         if(filematch(bf[i].name,tmp)) {
  220.                             strcpy(f.name,bf[i].name);
  221.                             f.datoffset=bf[i].datoffset;
  222.                             f.dateuled=bf[i].dateuled;
  223.                             f.datedled=bf[i].datedled;
  224.                             f.size=0;
  225.                             getfiledat(&f);
  226.                             if(!viewfile(f,ch=='E'))
  227.                                 return(-1); } } }
  228.                 if(strchr(str+c,'.'))
  229.                     c+=strlen(str+c);
  230.                 else if(str[c]<'A'+total && str[c]>='A') {
  231.                     f.dir=dirnum;
  232.                     strcpy(f.name,bf[str[c]-'A'].name);
  233.                     f.datoffset=bf[str[c]-'A'].datoffset;
  234.                     f.dateuled=bf[str[c]-'A'].dateuled;
  235.                     f.datedled=bf[str[c]-'A'].datedled;
  236.                     f.size=0;
  237.                     getfiledat(&f);
  238.                     if(!viewfile(f,ch=='E'))
  239.                         return(-1); } }
  240.             return(2); }
  241.         clearline();
  242.         continue; }
  243.  
  244.     if((ch=='D' || ch=='M')     /* Delete or Move */
  245.         && !(useron.rest&FLAG('R'))
  246.         && (dir_op(dirnum) || useron.exempt&FLAG('R'))) {
  247.         if(total==1) {
  248.             strcpy(str,"A");
  249.             d=1; }
  250.         else {
  251.             bputs(text[BatchDlFlags]);
  252.             d=getstr(str,26,K_UPPER|K_LOWPRIO|K_NOCRLF); }
  253.         lncntr=0;
  254.         if(sys_status&SS_ABORT)
  255.             return(-1);
  256.         if(d) {     /* d is string length */
  257.             CRLF;
  258.             if(ch=='D') {
  259.                 if(noyes(text[AreYouSureQ]))
  260.                     return(2);
  261.                 remcdt=remfile=1;
  262.                 if(dir_op(dirnum)) {
  263.                     remcdt=!noyes(text[RemoveCreditsQ]);
  264.                     remfile=!noyes(text[DeleteFileQ]); } }
  265.             else if(ch=='M') {
  266.                 CRLF;
  267.                 for(i=0;i<usrlibs;i++)
  268.                     bprintf(text[MoveToLibLstFmt],i+1,lib[usrlib[i]]->lname);
  269.                 SYNC;
  270.                 bprintf(text[MoveToLibPrompt],dir[dirnum]->lib+1);
  271.                 if((ml=getnum(usrlibs))==-1)
  272.                     return(2);
  273.                 if(!ml)
  274.                     ml=dir[dirnum]->lib;
  275.                 else
  276.                     ml--;
  277.                 CRLF;
  278.                 for(j=0;j<usrdirs[ml];j++)
  279.                     bprintf(text[MoveToDirLstFmt]
  280.                         ,j+1,dir[usrdir[ml][j]]->lname);
  281.                 SYNC;
  282.                 bprintf(text[MoveToDirPrompt],usrdirs[ml]);
  283.                 if((md=getnum(usrdirs[ml]))==-1)
  284.                     return(2);
  285.                 if(!md)
  286.                     md=usrdirs[ml]-1;
  287.                 else md--;
  288.                 CRLF; }
  289.             lncntr=0;
  290.             for(c=0;c<d;c++) {
  291.                 if(strchr(str+c,'.')) {     /* filename or spec given */
  292.                     f.dir=dirnum;
  293.                     p=strchr(str+c,SP);
  294.                     if(!p) p=strchr(str+c,',');
  295.                     if(p) *p=0;
  296.                     for(i=0;i<total;i++) {
  297.                         padfname(str+c,tmp);
  298.                         if(filematch(bf[i].name,tmp)) {
  299.                             strcpy(f.name,bf[i].name);
  300.                             unpadfname(f.name,fname);
  301.                             f.datoffset=bf[i].datoffset;
  302.                             f.dateuled=bf[i].dateuled;
  303.                             f.datedled=bf[i].datedled;
  304.                             f.size=0;
  305.                             getfiledat(&f);
  306.                             if(f.opencount) {
  307.                                 bprintf(text[FileIsOpen]
  308.                                     ,f.opencount,f.opencount>1 ? "s":nulstr);
  309.                                 continue; }
  310.                             if(ch=='D') {
  311.                                 removefiledat(f);
  312.                                 if(remfile) {
  313.                                     sprintf(tmp,"%s%s",dir[f.dir]->path,fname);
  314.                                     remove(tmp); }
  315.                                 if(remcdt)
  316.                                     removefcdt(f); }
  317.                             else if(ch=='M')
  318.                                 movefile(f,usrdir[ml][md]); } } }
  319.                 if(strchr(str+c,'.'))
  320.                     c+=strlen(str+c);
  321.                 else if(str[c]<'A'+total && str[c]>='A') {
  322.                     f.dir=dirnum;
  323.                     strcpy(f.name,bf[str[c]-'A'].name);
  324.                     unpadfname(f.name,fname);
  325.                     f.datoffset=bf[str[c]-'A'].datoffset;
  326.                     f.dateuled=bf[str[c]-'A'].dateuled;
  327.                     f.datedled=bf[str[c]-'A'].datedled;
  328.                     f.size=0;
  329.                     getfiledat(&f);
  330.                     if(f.opencount) {
  331.                         bprintf(text[FileIsOpen]
  332.                             ,f.opencount,f.opencount>1 ? "s":nulstr);
  333.                         continue; }
  334.                     if(ch=='D') {
  335.                         removefiledat(f);
  336.                         if(remfile) {
  337.                             sprintf(tmp,"%s%s",dir[f.dir]->path,fname);
  338.                             remove(tmp); }
  339.                         if(remcdt)
  340.                             removefcdt(f); }
  341.                     else if(ch=='M')
  342.                         movefile(f,usrdir[ml][md]); } }
  343.             return(2); }
  344.         clearline();
  345.         continue; }
  346.  
  347.     return(1); }
  348.  
  349. return(-1);
  350. }
  351.  
  352. /*****************************************************************************/
  353. /* List files in directory 'dir' that match 'filespec'. Filespec must be      */
  354. /* padded. ex: FILE*   .EXT, not FILE*.EXT. 'mode' determines other critiria */
  355. /* the files must meet before they'll be listed. 'mode' bit FL_NOHDR doesn't */
  356. /* list the directory header.                                                */
  357. /* Returns -1 if the listing was aborted, otherwise total files listed         */
  358. /*****************************************************************************/
  359. int listfiles(uint dirnum, char *filespec, int tofile, char mode)
  360. {
  361.     uchar str[256],hdr[256],cmd[129],c,d,letter='A',*buf,*p,ext[513];
  362.     uchar HUGE16 *datbuf,HUGE16 *ixbbuf,flagprompt=0;
  363.     int i,j,file,found=0,lastbat=0,disp;
  364.     ulong l,m=0,n,length,anchor,next,datbuflen;
  365.     file_t f,bf[26];    /* bf is batch flagged files */
  366.  
  367. if(mode&FL_ULTIME) {
  368.     last_ns_time=now;
  369.     sprintf(str,"%s%s.DAB",dir[dirnum]->data_dir,dir[dirnum]->code);
  370.     if((file=nopen(str,O_RDONLY))!=-1) {
  371.         read(file,&l,4);
  372.         close(file);
  373.         if(ns_time>l)
  374.             return(0); } }
  375. sprintf(str,"%s%s.IXB",dir[dirnum]->data_dir,dir[dirnum]->code);
  376. if((file=nopen(str,O_RDONLY))==-1)
  377.     return(0);
  378. l=filelength(file);
  379. if(!l) {
  380.     close(file);
  381.     return(0); }
  382. if((ixbbuf=(char *)MALLOC(l))==NULL) {
  383.     close(file);
  384.     errormsg(WHERE,ERR_ALLOC,str,l);
  385.     return(0); }
  386. if(lread(file,ixbbuf,l)!=l) {
  387.     close(file);
  388.     errormsg(WHERE,ERR_READ,str,l);
  389.     FREE((char *)ixbbuf);
  390.     return(0); }
  391. close(file);
  392. sprintf(str,"%s%s.DAT",dir[dirnum]->data_dir,dir[dirnum]->code);
  393. if((file=nopen(str,O_RDONLY))==-1) {
  394.     errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
  395.     FREE((char *)ixbbuf);
  396.     return(0); }
  397. datbuflen=filelength(file);
  398. if((datbuf=MALLOC(datbuflen))==NULL) {
  399.     close(file);
  400.     errormsg(WHERE,ERR_ALLOC,str,datbuflen);
  401.     FREE((char *)ixbbuf);
  402.     return(0); }
  403. if(lread(file,datbuf,datbuflen)!=datbuflen) {
  404.     close(file);
  405.     errormsg(WHERE,ERR_READ,str,datbuflen);
  406.     FREE((char *)datbuf);
  407.     FREE((char *)ixbbuf);
  408.     return(0); }
  409. close(file);
  410. if(!tofile) {
  411.     action=NODE_LFIL;
  412.     getnodedat(node_num,&thisnode,0);
  413.     if(thisnode.action!=NODE_LFIL) {    /* was a sync */
  414.         getnodedat(node_num,&thisnode,1);
  415.         thisnode.action=NODE_LFIL;
  416.         putnodedat(node_num,thisnode); } }
  417. while(online && found<MAX_FILES) {
  418.     if(found<0)
  419.         found=0;
  420.     if(m>=l || flagprompt) {          /* End of list */
  421.         if(useron.misc&BATCHFLAG && !tofile && found && found!=lastbat
  422.             && !(mode&(FL_EXFIND|FL_VIEW))) {
  423.             flagprompt=0;
  424.             lncntr=0;
  425.             if((i=batchflagprompt(dirnum,bf,letter-'A',l/F_IXBSIZE))==2) {
  426.                 m=anchor;
  427.                 found-=letter-'A';
  428.                 letter='A'; }
  429.             else if(i==3) {
  430.                 if((long)anchor-((letter-'A')*F_IXBSIZE)<0) {
  431.                     m=0;
  432.                     found=0; }
  433.                 else {
  434.                     m=anchor-((letter-'A')*F_IXBSIZE);
  435.                     found-=letter-'A'; }
  436.                 letter='A'; }
  437.             else if(i==-1) {
  438.                 FREE((char *)ixbbuf);
  439.                 FREE((char *)datbuf);
  440.                 return(-1); }
  441.             else
  442.                 break;
  443.             getnodedat(node_num,&thisnode,0);
  444.             nodesync(); }
  445.         else
  446.             break; }
  447.  
  448.     if(letter>'Z')
  449.         letter='A';
  450.     if(letter=='A')
  451.         anchor=m;
  452.  
  453.     if(msgabort()) {         /* used to be !tofile && msgabort() */
  454.         FREE((char *)ixbbuf);
  455.         FREE((char *)datbuf);
  456.         return(-1); }
  457.     for(j=0;j<12 && m<l;j++)
  458.         if(j==8)
  459.             str[j]='.';
  460.         else
  461.             str[j]=ixbbuf[m++];        /* Turns FILENAMEEXT into FILENAME.EXT */
  462.     str[j]=0;
  463.     if(!(mode&(FL_FINDDESC|FL_EXFIND)) && filespec[0]
  464.         && !filematch(str,filespec)) {
  465.         m+=11;
  466.         continue; }
  467.     n=ixbbuf[m]|((long)ixbbuf[m+1]<<8)|((long)ixbbuf[m+2]<<16);
  468.     if(n>=datbuflen) {    /* out of bounds */
  469.         m+=11;
  470.         continue; }
  471.     if(mode&(FL_FINDDESC|FL_EXFIND)) {
  472.         getrec((char *)&datbuf[n],F_DESC,LEN_FDESC,tmp);
  473.         strupr(tmp);
  474.         p=strstr(tmp,filespec);
  475.         if(!(mode&FL_EXFIND) && p==NULL) {
  476.             m+=11;
  477.             continue; }
  478.         getrec((char *)&datbuf[n],F_MISC,1,tmp);
  479.         j=tmp[0];  /* misc bits */
  480.         if(j) j-=SP;
  481.         if(mode&FL_EXFIND && j&FM_EXTDESC) { /* search extended description */
  482.             getextdesc(dirnum,n,ext);
  483.             strupr(ext);
  484.             if(!strstr(ext,filespec) && !p) {    /* not in description or */
  485.                 m+=11;                         /* extended description */
  486.                 continue; } }
  487.         else if(!p) {             /* no extended description and not in desc */
  488.             m+=11;
  489.             continue; } }
  490.     if(mode&FL_ULTIME) {
  491.         if(ns_time>(ixbbuf[m+3]|((long)ixbbuf[m+4]<<8)|((long)ixbbuf[m+5]<<16)
  492.             |((long)ixbbuf[m+6]<<24))) {
  493.             m+=11;
  494.             continue; } }
  495.     if(useron.misc&BATCHFLAG && letter=='A' && found && !tofile
  496.         && !(mode&(FL_EXFIND|FL_VIEW))
  497.         && (!mode || !(useron.misc&EXPERT)))
  498.         bputs(text[FileListBatchCommands]);
  499.     m+=11;
  500.     if(!found && !(mode&(FL_EXFIND|FL_VIEW))) {
  501.         for(i=0;i<usrlibs;i++)
  502.             if(usrlib[i]==dir[dirnum]->lib)
  503.                 break;
  504.         for(j=0;j<usrdirs[i];j++)
  505.             if(usrdir[i][j]==dirnum)
  506.                 break;                        /* big header */
  507.         if((!mode || !(useron.misc&EXPERT)) && !tofile && (!filespec[0]
  508.             || (strchr(filespec,'*') || strchr(filespec,'?')))) {
  509.             sprintf(hdr,"%s%s.HDR",dir[dirnum]->data_dir,dir[dirnum]->code);
  510.             if(fexist(hdr))
  511.                 printfile(hdr,0);    /* Use DATA\DIRS\<CODE>.HDR */
  512.             else {
  513.                 if(useron.misc&BATCHFLAG)
  514.                     bputs(text[FileListBatchCommands]);
  515.                 else {
  516.                     CLS;
  517.                     d=strlen(lib[usrlib[i]]->lname)>strlen(dir[dirnum]->lname) ?
  518.                         strlen(lib[usrlib[i]]->lname)+17
  519.                         : strlen(dir[dirnum]->lname)+17;
  520.                     if(i>8 || j>8) d++;
  521.                     attr(color[clr_filelsthdrbox]);
  522.                     bputs("╔═");            /* use to start with \r\n */
  523.                     for(c=0;c<d;c++)
  524.                         outchar('═');
  525.                     bputs("╗\r\n║ ");
  526.                     sprintf(hdr,text[BoxHdrLib],i+1,lib[usrlib[i]]->lname);
  527.                     bputs(hdr);
  528.                     for(c=bstrlen(hdr);c<d;c++)
  529.                         outchar(SP);
  530.                     bputs("║\r\n║ ");
  531.                     sprintf(hdr,text[BoxHdrDir],j+1,dir[dirnum]->lname);
  532.                     bputs(hdr);
  533.                     for(c=bstrlen(hdr);c<d;c++)
  534.                         outchar(SP);
  535.                     bputs("║\r\n║ ");
  536.                     sprintf(hdr,text[BoxHdrFiles],l/F_IXBSIZE);
  537.                     bputs(hdr);
  538.                     for(c=bstrlen(hdr);c<d;c++)
  539.                         outchar(SP);
  540.                     bputs("║\r\n╚═");
  541.                     for(c=0;c<d;c++)
  542.                         outchar('═');
  543.                     bputs("╝\r\n"); } } }
  544.         else {                    /* short header */
  545.             if(tofile) {
  546.                 sprintf(hdr,"(%u) %s ",i+1,lib[usrlib[i]]->sname);
  547.                 write(tofile,crlf,2);
  548.                 write(tofile,hdr,strlen(hdr)); }
  549.             else {
  550.                 sprintf(hdr,text[ShortHdrLib],i+1,lib[usrlib[i]]->sname);
  551.                 bputs("\r\1>\r\n");
  552.                 bputs(hdr); }
  553.             c=bstrlen(hdr);
  554.             if(tofile) {
  555.                 sprintf(hdr,"(%u) %s",j+1,dir[dirnum]->lname);
  556.                 write(tofile,hdr,strlen(hdr)); }
  557.             else {
  558.                 sprintf(hdr,text[ShortHdrDir],j+1,dir[dirnum]->lname);
  559.                 bputs(hdr); }
  560.             c+=bstrlen(hdr);
  561.             if(tofile) {
  562.                 write(tofile,crlf,2);
  563.                 sprintf(hdr,"%*s",c,nulstr);
  564.                 strset(hdr,'─');
  565.                 strcat(hdr,crlf);
  566.                 write(tofile,hdr,strlen(hdr)); }
  567.             else {
  568.                 CRLF;
  569.                 attr(color[clr_filelstline]);
  570.                 while(c--)
  571.                     outchar('─');
  572.                 CRLF; } } }
  573.     next=m;
  574.     disp=1;
  575.     if(mode&(FL_EXFIND|FL_VIEW)) {
  576.         f.dir=dirnum;
  577.         strcpy(f.name,str);
  578.         m-=11;
  579.         f.datoffset=n;
  580.         f.dateuled=ixbbuf[m+3]|((long)ixbbuf[m+4]<<8)
  581.             |((long)ixbbuf[m+5]<<16)|((long)ixbbuf[m+6]<<24);
  582.         f.datedled=ixbbuf[m+7]|((long)ixbbuf[m+8]<<8)
  583.             |((long)ixbbuf[m+9]<<16)|((long)ixbbuf[m+10]<<24);
  584.         m+=11;
  585.         f.size=0;
  586.         getfiledat(&f);
  587.         if(!found)
  588.             bputs("\r\1>");
  589.         if(mode&FL_EXFIND) {
  590.             if(!viewfile(f,1)) {
  591.                 FREE((char *)ixbbuf);
  592.                 FREE((char *)datbuf);
  593.                 return(-1); } }
  594.         else {
  595.             if(!viewfile(f,0)) {
  596.                 FREE((char *)ixbbuf);
  597.                 FREE((char *)datbuf);
  598.                 return(-1); } } }
  599.  
  600.     else if(tofile)
  601.         listfiletofile(str,&datbuf[n],dirnum,tofile);
  602.     else if(mode&FL_FINDDESC)
  603.         disp=listfile(str,&datbuf[n],dirnum,filespec,letter,n);
  604.     else
  605.         disp=listfile(str,&datbuf[n],dirnum,nulstr,letter,n);
  606.     if(!disp && letter>'A') {
  607.         next=m-F_IXBSIZE;
  608.         letter--; }
  609.     else {
  610.         disp=1;
  611.         found++; }
  612.     if(sys_status&SS_ABORT) {
  613.         FREE((char *)ixbbuf);
  614.         FREE((char *)datbuf);
  615.         return(-1); }
  616.     if(mode&(FL_EXFIND|FL_VIEW))
  617.         continue;
  618.     if(useron.misc&BATCHFLAG && !tofile) {
  619.         if(disp) {
  620.             strcpy(bf[letter-'A'].name,str);
  621.             m-=11;
  622.             bf[letter-'A'].datoffset=n;
  623.             bf[letter-'A'].dateuled=ixbbuf[m+3]|((long)ixbbuf[m+4]<<8)
  624.                 |((long)ixbbuf[m+5]<<16)|((long)ixbbuf[m+6]<<24);
  625.             bf[letter-'A'].datedled=ixbbuf[m+7]|((long)ixbbuf[m+8]<<8)
  626.                 |((long)ixbbuf[m+9]<<16)|((long)ixbbuf[m+10]<<24); }
  627.         m+=11;
  628.         if(flagprompt || letter=='Z' || !disp ||
  629.             (filespec[0] && !strchr(filespec,'*') && !strchr(filespec,'?')
  630.             && !(mode&FL_FINDDESC))
  631.             || (useron.misc&BATCHFLAG && !tofile && lncntr>=rows-2)
  632.             ) {
  633.             flagprompt=0;
  634.             lncntr=0;
  635.             lastbat=found;
  636.             if((i=batchflagprompt(dirnum,bf,letter-'A'+1,l/F_IXBSIZE))<1) {
  637.                 FREE((char *)ixbbuf);
  638.                 FREE((char *)datbuf);
  639.                 if(i==-1)
  640.                     return(-1);
  641.                 else
  642.                     return(found); }
  643.             if(i==2) {
  644.                 next=anchor;
  645.                 found-=(letter-'A')+1; }
  646.             else if(i==3) {
  647.                 if((long)anchor-((letter-'A'+1)*F_IXBSIZE)<0) {
  648.                     next=0;
  649.                     found=0; }
  650.                 else {
  651.                     next=anchor-((letter-'A'+1)*F_IXBSIZE);
  652.                     found-=letter-'A'+1; } }
  653.             getnodedat(node_num,&thisnode,0);
  654.             nodesync();
  655.             letter='A';    }
  656.         else letter++; }
  657.     if(useron.misc&BATCHFLAG && !tofile
  658.         && lncntr>=rows-2) {
  659.         lncntr=0;        /* defeat pause() */
  660.         flagprompt=1; }
  661.     m=next;
  662.     if(mode&FL_FINDDESC) continue;
  663.     if(filespec[0] && !strchr(filespec,'*') && !strchr(filespec,'?') && m)
  664.         break; }
  665.  
  666. FREE((char *)ixbbuf);
  667. FREE((char *)datbuf);
  668. return(found);
  669. }
  670.  
  671. int cntlines(char *str)
  672. {
  673.     int i,lc,last;
  674.  
  675. for(i=lc=last=0;str[i];i++)
  676.     if(str[i]==LF || i-last>LEN_FDESC) {
  677.         lc++;
  678.         last=i; }
  679. return(lc);
  680. }
  681.  
  682. /****************************************************************************/
  683. /* Prints one file's information on a single line                           */
  684. /* Return 1 if displayed, 0 otherwise                                        */
  685. /****************************************************************************/
  686. int listfile(char *fname, char HUGE16 *buf, uint dirnum
  687.     , char *search, char letter, ulong datoffset)
  688. {
  689.     char str[256],ext[513]="",*ptr,*cr,*lf,exist=1;
  690.     uchar alt;
  691.     int i,j;
  692.     ulong cdt;
  693.  
  694. if(buf[F_MISC]!=ETX && (buf[F_MISC]-SP)&FM_EXTDESC && useron.misc&EXTDESC) {
  695.     getextdesc(dirnum,datoffset,ext);
  696.     if(useron.misc&BATCHFLAG && lncntr+cntlines(ext)>=rows-2)
  697.         return(0); }
  698. attr(color[clr_filename]);
  699. bputs(fname);
  700. if(buf[F_MISC]!=ETX && (buf[F_MISC]-SP)&FM_EXTDESC) {
  701.     if(!(useron.misc&EXTDESC))
  702.         outchar('+');
  703.     else
  704.         outchar(SP); }
  705. else
  706.     outchar(SP);
  707. if(useron.misc&BATCHFLAG) {
  708.     attr(color[clr_filedesc]);
  709.     bprintf("%c",letter); }
  710. getrec((char *)buf,F_ALTPATH,2,str);
  711. alt=(uchar)ahtoul(str);
  712. sprintf(str,"%s%s",alt>0 && alt<=altpaths ? altpath[alt-1]:dir[dirnum]->path
  713.     ,unpadfname(fname,tmp));
  714. if(dir[dirnum]->misc&DIR_FCHK && !fexist(str)) {
  715.     exist=0;
  716.     attr(color[clr_err]); }
  717. else
  718.     attr(color[clr_filecdt]);
  719. getrec((char *)buf,F_CDT,LEN_FCDT,str);
  720. cdt=atol(str);
  721. if(useron.misc&BATCHFLAG) {
  722.     if(!cdt) {
  723.         attr(curatr^(HIGH|BLINK));
  724.         bputs("  FREE"); }
  725.     else {
  726.         if(cdt<1024)    /* 1k is smallest size */
  727.             cdt=1024;
  728.         bprintf("%5luk",cdt/1024L); } }
  729. else {
  730.     if(!cdt) {  /* FREE file */
  731.         attr(curatr^(HIGH|BLINK));
  732.         bputs("   FREE"); }
  733.     else if(cdt>9999999L)
  734.         bprintf("%6luk",cdt/1024L);
  735.     else
  736.         bprintf("%7lu",cdt); }
  737. if(exist)
  738.     outchar(SP);
  739. else
  740.     outchar('-');
  741. getrec((char *)buf,F_DESC,LEN_FDESC,str);
  742. attr(color[clr_filedesc]);
  743. if(!ext[0]) {
  744.     if(search[0]) { /* high-light string in string */
  745.         strcpy(tmp,str);
  746.         strupr(tmp);
  747.         ptr=strstr(tmp,search);
  748.         i=strlen(search);
  749.         j=ptr-tmp;
  750.         bprintf("%.*s",j,str);
  751.         attr(color[clr_filedesc]^HIGH);
  752.         bprintf("%.*s",i,str+j);
  753.         attr(color[clr_filedesc]);
  754.         bprintf("%.*s",strlen(str)-(j+i),str+j+i); }
  755.     else
  756.         bputs(str);
  757.     CRLF; }
  758. ptr=ext;
  759. while(*ptr && ptr<ext+512 && !msgabort()) {
  760.     cr=strchr(ptr,CR);
  761.     lf=strchr(ptr,LF);
  762.     if(lf && (lf<cr || !cr)) cr=lf;
  763.     if(cr>ptr+LEN_FDESC)
  764.         cr=ptr+LEN_FDESC;
  765.     else if(cr)
  766.         *cr=0;
  767. //      bprintf("%.*s\r\n",LEN_FDESC,ptr);
  768.     sprintf(str,"%.*s\r\n",LEN_FDESC,ptr);
  769.     putmsg(str,P_NOATCODES|P_SAVEATR);
  770.     if(!cr) {
  771.         if(strlen(ptr)>LEN_FDESC)
  772.             cr=ptr+LEN_FDESC;
  773.         else
  774.             break; }
  775.     if(!(*(cr+1)) || !(*(cr+2)))
  776.         break;
  777.     bprintf("%21s",nulstr);
  778.     ptr=cr;
  779.     if(!(*ptr)) ptr++;
  780.     while(*ptr==LF || *ptr==CR) ptr++; }
  781. return(1);
  782. }
  783.