home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / ftp.vapor.com / microdot-1 / md1_src_02.lzx / crunch.c < prev    next >
C/C++ Source or Header  |  2014-05-19  |  36KB  |  1,629 lines

  1. #include "microdot.h"
  2.  
  3. #include "asyncio.h"
  4.  
  5. #include "ogre.h"
  6. #include "ogre_protos.h"
  7.  
  8. extern BOOL do_autoreorg, do_autocrunch;
  9.  
  10. void calcmcount_mb( struct mindex *mix, struct mbrett *mb )
  11. {
  12.     struct mmail *mm=(struct mmail*)mix->maillist.lh_Head;
  13.     long newcount=0/*,delcount=0*/,mailcount=0,/*foldcount=0,*/unreadcount=0;
  14.  
  15.     while( mm->n.mln_Succ )
  16.     {
  17.         if( ! ( mm->m.flags & MMF_KILL ) )
  18.         {
  19.             mailcount++;
  20.             /*if(mm->m.flags & MMF_DEL ) delcount++;
  21.             if(mm->m.flags & MMF_FOLD) foldcount++;*/
  22.             if(mm->m.flags & (MMF_UNSEEN|MMF_SHOW)) newcount++;
  23.             if(!(mm->m.flags & MMF_READ)) unreadcount++;
  24.         }
  25.         mm=(struct mmail*)mm->n.mln_Succ;
  26.     }
  27.     mb->b.mails          = mailcount;
  28.     mb->b.newmails    = newcount;
  29.     mb->b.unreadmails = unreadcount;
  30. }
  31.  
  32. #define CGID_CRUNCH_DAT 9
  33. #define CGID_CRUNCH_NEW 1
  34. #define CGID_CRUNCH_READ 2
  35. #define CGID_START 3
  36. #define CGID_END 4
  37. #define CGID_FG 5
  38. #define CGID_FG2 10
  39. #define CGID_FG3 11
  40.  
  41. #define CGID_FG3T 12
  42.  
  43. #define CGID_DUPEKILL 13
  44.  
  45. #define CGID_L0 6
  46. #define CGID_L1 7
  47. #define CGID_L2 8
  48.  
  49. static int Done,datedel,newdel,readdel,dupedel;
  50. static struct ogwin *ogw;
  51. static int abscount,delcount,remcount;
  52.  
  53. static void removemsgs(struct mbrett *mb,struct mindex *mix)
  54. {
  55.     struct mmail *m=(struct mmail*)mix->maillist.lh_Head,*nm;
  56.     int currentcount = 0,
  57.         ptr = 0,
  58.         mmcount;
  59.  
  60.     mmcount = mix->mailcount;
  61.  
  62.     ogreSetMaxVal( ogw, CGID_FG, mmcount + 1 );
  63.     ogreSetValue( ogw, CGID_FG, 0 );
  64.  
  65.     while((nm=(struct mmail*)m->n.mln_Succ))
  66.     {
  67.         ptr++;
  68.  
  69.         ogreSetValue( ogw, CGID_FG, ptr );
  70.  
  71.         /* Nachricht erhalten */
  72.         if( ( !newdel && ( m->m.flags & MMF_UNSEEN ) ) ||
  73.               ( m->m.flags & ( MMF_ARCHIVE | MMF_SHOW ) ) ||
  74.               ( !( m->m.flags & ( MMF_KILL | MMF_DEL ) ) ) )
  75.         {
  76.             currentcount++;
  77.         }
  78.         else
  79.         {
  80.             mix->changed=1;
  81.             remcount++;
  82.             Remove((struct Node*)m); /* Nachricht wech! */
  83.         }
  84.         m=nm;
  85.     }
  86.  
  87.     mix->mailcount = currentcount;
  88.  
  89. }
  90.  
  91. static void crunchkillfile( void )
  92. {
  93.     char buffer[1024];
  94.     long t, cmpt;
  95.     FILE *midin, *midout;
  96.     int count = 0, delcount = 0;
  97.     int maxlen, currentpos;
  98.     int kftimeout;
  99.     int rc;
  100.  
  101.     kftimeout = ( prefs.killfile_hold ) ? prefs.killfile_hold : 30;
  102.     kftimeout *= 3600 * 24;
  103.  
  104.     maxlen = getfilelen( "microdot.kill" );
  105.     if( maxlen < 1 )
  106.         return;
  107.  
  108.     midin = fopen( "microdot.kill", "r" );
  109.     if( !midin )
  110.         return;
  111.  
  112.     midout = fopen( "microdot.newkill", "w" );
  113.     if( !midout )
  114.     {
  115.         displaybeep();
  116.         fclose( midin );
  117.         return;
  118.     }
  119.  
  120.     time( &cmpt );
  121.  
  122.     ogreSetMaxVal( ogw, CGID_FG, maxlen );
  123.  
  124.     for( ;; )
  125.     {
  126.         currentpos = ftell( midin );
  127.  
  128.         ogreSetValue( ogw, CGID_FG, currentpos );
  129.  
  130.         sprintf( buffer, "%lD EintrΣge, %lD gel÷scht",
  131.             count++, delcount );
  132.  
  133.         ogreSetStringValue( ogw, CGID_L1, buffer );
  134.  
  135.         if( fread( &t, 4, 1, midin ) != 1 )
  136.             break;
  137.         fgets( buffer, 1024, midin );
  138.  
  139.         /* Alter prⁿfen */
  140.         if( t + kftimeout < cmpt )
  141.         {
  142.             delcount ++;
  143.             continue;
  144.         }
  145.  
  146.         /* Rest Kopieren */
  147.         fwrite( &t, 4, 1, midout );
  148.         fwrite( buffer, strlen( buffer ), 1, midout );
  149.  
  150.         while( ( rc = fread( buffer, 1, 1024, midin ) ) > 0 )
  151.             fwrite( buffer, rc, 1, midout );
  152.  
  153.         break;
  154.     }
  155.  
  156.     fclose( midin );
  157.     fclose( midout );
  158.     DeleteFile( "microdot.kill.bak" );
  159.     Rename( "microdot.kill", "microdot.kill.bak" );
  160.     Rename( "microdot.newkill", "microdot.kill" );
  161.  
  162. }
  163.  
  164. void docrunchkillfile( void )
  165. {
  166.     struct Window *iw;
  167.     struct IntuiMessage *im;
  168.     int Done = FALSE;
  169.     int l;
  170.     char buffer[á64 ];
  171.  
  172.     Done = FALSE;
  173.  
  174.     ogw = ogreInitWindow( scr, WFLG_RMBTRAP, NULL, "Killfile aufrΣumen..." );
  175.     ogreAddGroup( ogw, 0, OGFRAME_NONE, NULL );
  176.     ogreAddText( ogw, 0, "Status:", CGID_L1, "", 46, 1 );
  177.     ogreAddFuelGauge( ogw, 1, CGID_FG, 100 );
  178.     ogreAddInteger( ogw, 2, 'h', "_Haltezeit in Tagen:", CGID_L0, prefs.killfile_hold ? prefs.killfile_hold : 30, 1, 2000, 10, 10 );
  179.  
  180.     ogreAddGroup( ogw, 1, OGFRAME_NONE, NULL );
  181.     ogreAddButton( ogw, 0 | OGB_ONENTER, 's', "_Start", CGID_START );
  182.     ogreAddHelp( ogw, 0 );
  183.     ogreAddButton( ogw, 0 | OGB_ONESC, 'a', "_Abbruch", CGID_END );
  184.  
  185.     iw = ogreOpenWindow( ogw );
  186.     if( !iw )
  187.         return;
  188.  
  189.     pushhomedir();
  190.  
  191.     l = getfilelen( "microdot.kill" );
  192.     if( l < 0 )
  193.         l = 0;
  194.  
  195.     sprintf( buffer, "KillfilelΣnge %lD Bytes", l );
  196.     ogreSetStringValue( ogw, CGID_L1, buffer );
  197.  
  198.     while( !Done )
  199.     {
  200.         im = ogreWaitIM( ogw );
  201.  
  202.         if( im->Class == IDCMP_GADGETHELP)
  203.             showguidenum( "crunchkill_gads", im->Code );
  204.         else if( im->Class == IDCMP_GADGETUP )
  205.         {
  206.             if( im->Code == CGID_START )
  207.                 Done = 2;
  208.             else if( im->Code == CGID_END )
  209.                 Done = 1;
  210.         }
  211.         ogreIMReply( ogw, im );
  212.     }
  213.  
  214.     prefs.killfile_hold = ogreValue( ogw, CGID_L0 );
  215.  
  216.     if( Done == 2 )
  217.     {
  218.         ogreEnable( ogw, FALSE, CGID_START, CGID_END, CGID_L0, 0 );
  219.         crunchkillfile();
  220.     }
  221.  
  222.     popdir();
  223.     ogreExitWindow( ogw );
  224. }
  225.  
  226.  
  227. static struct mmail * testdupe( struct mmail *cm )
  228. {
  229.     struct mmail *ml = ( struct mmail * ) cm->n.mln_Succ;
  230.  
  231.     while( ml && ml->n.mln_Succ )
  232.     {
  233.         if( cm->m.midcrc == ml->m.midcrc )
  234.         {
  235.             return( ml );
  236.         }
  237.         ml = ( struct mmail * ) ml->n.mln_Succ;
  238.     }
  239.     return( NULL );
  240. }
  241.  
  242. static void crunchbrett(struct mbrett *mb)
  243. {
  244.     struct mindex *mix;
  245.     struct mmail *m, *dupe;
  246.     char tmp[128];
  247.     long t,timeout;
  248.  
  249.     ogreSetValue( ogw, CGID_FG, 0 );
  250.  
  251.     ogreSetStringValue( ogw, CGID_L0,mb->b.name);
  252.     ogreSetStringValue( ogw, CGID_L2, "Lade Brettindex..." );
  253.  
  254.     mix=loadbrettixquiet(mb);
  255.     if(!mix)
  256.     {
  257.         mb->b.unreadmails     = 0;
  258.         mb->b.mails         = 0;
  259.         mb->b.newmails        = 0;
  260.         return;
  261.     }
  262.  
  263. /*    mb->nextfreemsg=0;*/
  264.  
  265.     time( &t );
  266.     timeout = mb->b.days * ( 3600 * 24 );
  267.  
  268.     m=(struct mmail*)mix->maillist.lh_Head;
  269.     ogreSetStringValue( ogw, CGID_L2,"L÷sche Nachrichten...");
  270.     while(m->n.mln_Succ)
  271.     {
  272.         abscount++;
  273.  
  274.         if( !( mb->b.flags & BFLAG_NOCRUNCH ) )
  275.         {
  276.             if( !( m->m.flags & MMF_DEL ) )
  277.             {
  278.                 if( datedel )
  279.                 {
  280.                     if( ( t - ( m->m.incomtime ) > timeout ) && !( m->m.flags & ( MMF_SHOW | MMF_ARCHIVE ) ) )
  281.                     {
  282.                         if( newdel || !( m->m.flags & MMF_UNSEEN ) )
  283.                         {
  284.                             mix->changed = 1;
  285.                             m->m.flags  |= MMF_DEL;
  286.                             delcount++;
  287.                         }
  288.                     }
  289.                 }
  290.             }
  291.             if( !( m->m.flags & MMF_DEL ) )
  292.             {
  293.                 if( readdel ) 
  294.                 {
  295.                     if( ( m->m.flags & MMF_READ ) && ( !( m->m.flags & ( MMF_SHOW | MMF_ARCHIVE ) ) ) )
  296.                     {
  297.                         if( newdel || !( m->m.flags & MMF_UNSEEN ) )
  298.                         {
  299.                             mix->changed = 1;
  300.                             m->m.flags  |= MMF_DEL;
  301.                             delcount++;
  302.                         }
  303.                     }
  304.                 }
  305.             }
  306.         }
  307.  
  308.         if( !( m->m.flags & MMF_DEL ) )
  309.         {
  310.             /* gegen Killfile testen */
  311.             if((!(m->m.flags&MMF_DEL)) && testcrcidmke(m->m.midcrc))
  312.             {
  313.                 struct header *hl;
  314.                 struct msghandle *msg;
  315.                 struct hlist *hlist;
  316.                 msg = msg_open( m->m.pufferID, m->m.mailID );
  317.                 if( msg )
  318.                 {
  319.                     hlist = msg_loadheader( msg );
  320.                     hl = hl_findheader( hlist, "MID" );
  321.                     if(hl && testidmke(hl->data)) { mix->changed=1; delcount++; m->m.flags|=MMF_DEL; }
  322.                     hl_freeheader( hlist );
  323.                     msg_close( msg );
  324.                 }
  325.             }
  326.         }
  327.         /* Dupe? */
  328.         if( dupedel )
  329.         {
  330.             //Printf( "testing for %lx\n", m );
  331.             if( dupe = testdupe( m ) )
  332.             {
  333.                 //Printf( "found dupe %lx\n", dupe );
  334.                 if( !( dupe->m.flags & MMF_DEL ) )
  335.                 {
  336.                     mix->changed = 1;
  337.                     dupe->m.flags = MMF_DEL;
  338.                     delcount++;
  339.                 }
  340.             }
  341.         }
  342.  
  343.         m=(struct mmail*)m->n.mln_Succ;
  344.     }
  345.     ogreSetStringValue( ogw, CGID_L2, "Entferne Nachrichten..." );
  346.     removemsgs( mb, mix );
  347.     sprintf( tmp, "%lD insgesamt, %lD gel÷scht, %lD entfernt", abscount, delcount, remcount );
  348.     ogreSetStringValue( ogw, CGID_L1, tmp );
  349.     ogreSetStringValue( ogw, CGID_L2, "Speichere Brettindex..." );
  350.     calcmcount_mb( mix, mb );
  351.     savebrettix( mix, mb );
  352.     freebrettix( mix );
  353.     ogreSetStringValue( ogw, CGID_L2, "" );
  354.     closeallixfiles();
  355.     flushbrettix();
  356. /*    mb->nextfreemsg = 0;*/
  357. }
  358.  
  359. static void startcrunch( struct mbrett *cmb )
  360. {
  361.     struct IntuiMessage *im;
  362.     long class, code;
  363.  
  364.     datedel = ogreValue( ogw, CGID_CRUNCH_DAT );
  365.     newdel  = ogreValue( ogw, CGID_CRUNCH_NEW );
  366.     readdel = ogreValue( ogw, CGID_CRUNCH_READ );
  367.     dupedel = ogreValue( ogw, CGID_DUPEKILL );
  368.  
  369.     ogreEnable( ogw, FALSE, CGID_CRUNCH_DAT, CGID_CRUNCH_NEW, CGID_CRUNCH_READ, CGID_START, CGID_DUPEKILL, OGID_HELP, 0 );
  370.  
  371.     delcount=0;
  372.     remcount=0;
  373.     abscount=0;
  374.  
  375.     if( !cmb )
  376.     {
  377.         crunchkillfile();
  378.         doinfofg();
  379.     }
  380.  
  381.     ogreSetStringValue( ogw, CGID_L1, "" );
  382.     ogreSetStringValue( ogw, CGID_L2, "Lade Killfile..." );
  383.     loadmke();
  384.  
  385.     if( cmb ) crunchbrett( cmb );
  386.     else
  387.     {
  388.         int bc = 0;
  389.         cmb=(struct mbrett*)brettlist.lh_Head;
  390.         while(cmb->n.ln_Succ)
  391.         {
  392.             if( stricmp( cmb->b.name, "/╗SPOOL" ) )
  393.                 crunchbrett( cmb );
  394.             ogreSetValue( ogw, CGID_FG2, bc++ );
  395.             cmb=(struct mbrett*)cmb->n.ln_Succ;
  396.             if((im=(struct IntuiMessage*)ogreIM(ogw)))
  397.             {
  398.                 class=im->Class; code=im->Code;
  399.                 ogreIMReply(ogw, im);
  400.                 if(class==GADGETUP)
  401.                     break;
  402.             }
  403.             doinfofg();
  404.         }
  405.     }
  406.  
  407.     doinfofg();
  408.     freemke();
  409.     savebretter();
  410. }
  411.  
  412. void docrunch( struct mbrett *mb )
  413. {
  414.     struct Window *iw;
  415.     struct IntuiMessage *im;
  416.  
  417.     Done = FALSE;
  418.  
  419.     if( mb == (struct mbrett*)-1 )
  420.     {
  421.         mb = NULL;
  422.         Done = 2;
  423.     }
  424.  
  425.     if( mb && !stricmp( mb->b.name, "/╗SPOOL" ) )
  426.     {
  427.         askreq( "Das /╗SPOOL-Brett wird automatisch nach dem\nNetcall aufgerΣumt. Gel÷schte Nachrichten werden grundsΣtzlich\nnicht verschickt.", "OK" );
  428.         return;
  429.     }
  430.  
  431.  
  432.     ogw = ogreInitWindow( scr, WFLG_RMBTRAP, NULL, "AufrΣumen" );
  433.     ogreAddGroup( ogw, 0, OGFRAME_OUTLINE, " Parameter " );
  434.     ogreAddCheckbox( ogw, 0, 'd', "nach _Datum l÷schen", CGID_CRUNCH_DAT, prefs.flags2 & MDF2_CRUNCH_DAT );
  435.     ogreAddCheckbox( ogw, 0, 'n', "     auch _Neue", CGID_CRUNCH_NEW, prefs.flags2 & MDF2_CRUNCH_NEW );
  436.     ogreAddCheckbox( ogw, 1, 'g', "    Alle _Gelesenen", CGID_CRUNCH_READ, prefs.flags2 & MDF2_CRUNCH_ALLREAD );
  437.     ogreAddCheckbox( ogw, 1, 'p', "Alle Do_ppelten", CGID_DUPEKILL, prefs.flags2 & MDF2_CRUNCH_DUPES );
  438.  
  439.     ogreAddGroup( ogw, 1, OGFRAME_OUTLINE, " Status " );
  440.     ogreAddText( ogw, 0, " Brett:", CGID_L0, "", 46, 1 );
  441.     ogreAddText( ogw, 1, " Mails:", CGID_L1, "", 46, 1 );
  442.     ogreAddText( ogw, 2, "Status:", CGID_L2, "", 46, 1 );
  443.     ogreAddFuelGauge( ogw, 3, CGID_FG, 100 );
  444.  
  445.     if( !mb )
  446.     {
  447.         ogreAddFuelGauge( ogw, 4, CGID_FG2, GetNumEntries( &brettlist ) );
  448.         ogreAddText( ogw, 5, "Belegter Festplattenplatz:", CGID_FG3T, "", 1, 0 );
  449.         ogreAddFuelGauge( ogw, 5, CGID_FG3, 100 );
  450.     }
  451.  
  452.     ogreAddGroup( ogw, 2, OGFRAME_NONE, NULL );
  453.     ogreAddButton( ogw, 0 | OGB_ONENTER, 's', "_Start", CGID_START );
  454.     ogreAddHelp( ogw, 0 );
  455.     ogreAddButton( ogw, 0 | OGB_ONESC, 'a', "_Abbruch", CGID_END );
  456.  
  457.     iw = ogreOpenWindow( ogw );
  458.     if( !iw )
  459.         return;
  460.  
  461.     if( mb && ( mb->b.flags & BFLAG_NOCRUNCH ) )
  462.     {
  463.         ogreSetValue( ogw, CGID_CRUNCH_DAT, FALSE );
  464.         ogreSetValue( ogw, CGID_CRUNCH_READ, FALSE );
  465.         //ogreSetValue( ogw, CGID_CRUNCH_NEW, FALSE );
  466.         ogreEnable( ogw, FALSE, CGID_CRUNCH_DAT, CGID_CRUNCH_READ, 0 );
  467.     }
  468.  
  469.     setupinfofg( prefs.datadir,  ogw, CGID_FG3 );
  470.     doinfofg();
  471.  
  472.     while( !Done )
  473.     {
  474.         im = ogreWaitIM( ogw );
  475.  
  476.         if( im->Class == IDCMP_GADGETHELP)
  477.             showguidenum( "crunch_gads", im->Code );
  478.         else if( im->Class == IDCMP_GADGETUP )
  479.         {
  480.             if( im->Code == CGID_START )
  481.                 Done = 2;
  482.             else if( im->Code == CGID_END )
  483.                 Done = 1;
  484.         }
  485.         ogreIMReply( ogw, im );
  486.     }
  487.  
  488.     if( ogreValue( ogw, CGID_CRUNCH_DAT ) )
  489.         prefs.flags2 |= MDF2_CRUNCH_DAT;
  490.     else
  491.         prefs.flags2 &= ~MDF2_CRUNCH_DAT;
  492.  
  493.     if( ogreValue( ogw, CGID_CRUNCH_NEW ) )
  494.         prefs.flags2 |= MDF2_CRUNCH_NEW;
  495.     else
  496.         prefs.flags2 &= ~MDF2_CRUNCH_NEW;
  497.  
  498.     if( ogreValue( ogw, CGID_CRUNCH_READ ) )
  499.         prefs.flags2 |= MDF2_CRUNCH_ALLREAD;
  500.     else
  501.         prefs.flags2 &= ~MDF2_CRUNCH_ALLREAD;
  502.  
  503.     if( ogreValue( ogw, CGID_DUPEKILL ) )
  504.         prefs.flags2 |= MDF2_CRUNCH_DUPES;
  505.     else
  506.         prefs.flags2 &= ~MDF2_CRUNCH_DUPES;
  507.  
  508.     if( Done == 2 )
  509.         startcrunch( mb );
  510.  
  511.     freeinfofg();
  512.  
  513.     ogreExitWindow( ogw );
  514. }
  515.  
  516. #define IX_T 1
  517. #define IX_F 2
  518. #define IX_X 3
  519.  
  520. void setallold( void )
  521. {
  522.     struct Window *iw;
  523.     struct IntuiMessage *im;
  524.     struct mbrett *mb = (struct mbrett *) brettlist.lh_Head;
  525.     struct mindex *mix;
  526.     int bcount = 0;
  527.     int Abort = FALSE;
  528.     struct mmail *mm;
  529.  
  530.     if( !askreq( "Wirklich ALLE Nachrichten auf 'Alt' setzen?", "Ja|Abbruch" ) )
  531.         return;
  532.  
  533.     ogw = ogreInitWindow( scr, 0, NULL, "Alle Nachrichten auf 'Alt' setzen..." );
  534.     ogreAddGroup( ogw, 0, OGFRAME_NONE, NULL );
  535.     ogreAddText( ogw, 0, "Brett:", IX_T, "", 46, 1 );
  536.     ogreAddFuelGauge( ogw, 1, IX_F, GetNumEntries( &brettlist ) );
  537.     ogreAddButton( ogw, 2 | OGB_ONESC, 'a', "_Abbruch", IX_X );
  538.  
  539.     iw = ogreOpenWindow( ogw );
  540.     if( !iw )
  541.         return;
  542.  
  543.     sortbrettlist();
  544.  
  545.     while( mb->n.ln_Succ && !Abort )
  546.     {
  547.         ogreSetStringValue( ogw, IX_T, mb->b.name );
  548.         mix = loadbrettixquiet( mb );
  549.         if( !mix )
  550.             break;
  551.         calcmcount_mb( mix, mb );
  552.         mm = ( struct mmail * ) mix->maillist.lh_Head;
  553.         while( mm->n.mln_Succ )
  554.         {
  555.             mm->m.flags &= ~ MMF_UNSEEN;
  556.             mm = ( struct mmail * ) mm->n.mln_Succ;            
  557.         }
  558.         mix->changed = 1;
  559.         savebrettix( mix, mb );
  560.         freebrettix( mix );
  561.         mb->b.flags &= ~ BFLAG_TOUCHED;
  562.         ogreSetValue( ogw, IX_F, bcount++ );
  563.  
  564.         im = ogreIM( ogw );
  565.         if( im )
  566.         {
  567.             if( im->Class == GADGETUP )
  568.                 Abort = TRUE;
  569.             ogreIMReply( ogw, im );
  570.         }
  571.  
  572.         mb = ( struct mbrett * ) mb->n.ln_Succ;
  573.     }
  574.  
  575.     ogreExitWindow( ogw );
  576. }
  577.  
  578. #define RID_ABBRUCH 1
  579. #define RID_I1 2
  580. #define RID_I2 3
  581. #define RID_FG 4
  582. #define RID_GFG 5
  583. #define RID_GFGTXT 6
  584.  
  585. static struct msgmove
  586. {
  587.     struct msgmove *n;
  588.     ULONG spID;
  589.     ULONG smID;
  590.     ULONG dpID;
  591.     ULONG dmID;
  592. } *msgmovelist;
  593.  
  594. struct ixinfo
  595. {
  596.     struct MinNode n;
  597.     ULONG pID;
  598.     ULONG count;
  599.     UBYTE *mark;
  600.     ULONG newlen;
  601. };
  602.  
  603. static struct MinList ixlist;
  604. static int ixignoreall;
  605.  
  606. static int markix( struct mmail *mm, struct mindex *mix )
  607. {
  608.     struct ixinfo *ix = ( struct ixinfo * ) ixlist.mlh_Head;
  609.     int dowhat = 0;
  610.     ULONG mID = mm->m.mailID, pID = mm->m.pufferID;
  611.  
  612.     while( ix->n.mln_Succ )
  613.     {
  614.         if( ix->pID == pID )
  615.         {
  616.             if( mID >= ix->count )
  617.             {
  618.                 if( !ixignoreall )
  619.                 {
  620.                     dowhat = askreq( "Fehler bei der Reorganisation:\nNachricht %lD im Puffer %lx (max %lD) existiert nicht!",
  621.                         "Diese Nachricht entfernen|Alle Defekten entfernen|Ignorieren",
  622.                         mID, pID, ix->count
  623.                     );
  624.                 }
  625.                 else
  626.                     dowhat = 1;
  627.  
  628.                 switch( dowhat )
  629.                 {
  630.                     case 2:
  631.                         ixignoreall = TRUE;
  632.                         // Fallthrough
  633.  
  634.                     case 1:
  635.                         mm->m.flags |= MMF_KILL;
  636.                         mix->changed = TRUE;
  637.                         break;
  638.                 }
  639.             }
  640.             else
  641.                 setbit( ix->mark, mID );
  642.             return( 0 );
  643.         }
  644.  
  645.         ix = ( struct ixinfo * ) ix->n.mln_Succ;
  646.     }
  647.  
  648.     if( !ixignoreall )
  649.         dowhat = askreq( "Fehler bei der Reorganisation:\nPuffer %lx existiert nicht!",
  650.             "Diese Nachricht entfernen|Alle Defekten entfernen|Ignorieren",
  651.         pID
  652.     );
  653.     else
  654.         dowhat = 1;
  655.  
  656.     switch( dowhat )
  657.     {
  658.         case 2:
  659.             ixignoreall = TRUE;
  660.             // Fallthrough
  661.  
  662.         case 1:
  663.             mm->m.flags |= MMF_KILL;
  664.             mix->changed = TRUE;
  665.             break;
  666.     }
  667.  
  668.     return( 0 );
  669. }
  670.  
  671. static void copyfh2async( BPTR from, struct AsyncFile *to, int size )
  672. {
  673.     void *bufmem;
  674.     int rc;
  675.     int bs;
  676.  
  677.     if( size < 1 )
  678.         return;
  679.  
  680.     bufmem = allocbuffmem( size, &bs );
  681.  
  682.     while( size )
  683.     {
  684.         rc = Read( from, bufmem, bs );
  685.         if( rc > 0 )
  686.             WriteAsync( to, bufmem, rc );
  687.         else
  688.             break;
  689.         size -= rc;
  690.     }
  691.  
  692.     freebuffmem();
  693. }
  694.  
  695. static int procmsgmovelist( struct mmail *m )
  696. {
  697.     ULONG pID = m->m.pufferID, mID = m->m.mailID;
  698.     struct msgmove *mm = msgmovelist;
  699.  
  700.     while( mm )
  701.     {
  702.         if( ( mm->spID == pID ) && ( mm->smID == mID ) )
  703.         {
  704.             m->m.pufferID = mm->dpID;
  705.             m->m.mailID = mm->dmID;
  706.             return( TRUE );
  707.         }
  708.         mm = mm->n;
  709.     }
  710.     return( FALSE );
  711. }
  712.  
  713. //
  714. //    HΣngt einen Puffer an einen anderen an
  715. //  und erzeugt msgmove-Nodes
  716. //
  717.  
  718. static void moveerr( ULONG fid, ULONG tid, char *filename )
  719. {
  720.     askreq( "Fehler beim Verschieben von ID %lx nach %lx:\nDatei %s lΣ▀t sich nicht ÷ffnen!\n(DOS-Fehler %ld)",
  721.         "Abbruch",
  722.         fid, tid, filename, IoErr()
  723.     );        
  724. }
  725.  
  726. static int movepuffer( APTR pool, ULONG fpID, ULONG tpID )
  727. {
  728.     struct pindex *pix, *scan;
  729.     struct msgmove *newmm;
  730.     char oixname[á32 ], sixname[á32 ];
  731.     char odname[á32 ], sdname[á32 ];
  732.     struct AsyncFile *oldix, *olddata;
  733.     BPTR six, sd;
  734.     ULONG sixsize;
  735.     ULONG poffset, midoffset;
  736.     int ixcount, c, maillen;
  737.  
  738.     sprintf( sixname, "MD_%lx.Index", fpID );
  739.     sprintf( sdname, "MD_%lx.Data", fpID );
  740.     sprintf( oixname, "MD_%lx.Index", tpID );
  741.     sprintf( odname, "MD_%lx.Data", tpID );
  742.  
  743.     sixsize = getfilelen( sixname );
  744.     ixcount = sixsize / sizeof( struct pindex );
  745.     poffset = getfilelen( odname );
  746.     midoffset = getfilelen( oixname ) / sizeof( struct pindex );
  747.  
  748.     oldix = OpenAsync( oixname, MODE_APPEND, sizeof( struct pindex ) * 64 );
  749.  
  750.     if( !oldix )
  751.     {
  752.         moveerr( fpID, tpID, oixname );
  753.         return( 1 );
  754.     }
  755.  
  756.     pix = LibAllocPooled( miscmempool, sixsize );
  757.     if( !pix )
  758.         return( 1 );
  759.  
  760.     olddata = OpenAsync( odname, MODE_APPEND, 32768 );
  761.     if( !olddata )
  762.     {
  763.         CloseAsync( oldix );
  764.         moveerr( fpID, tpID, odname );
  765.         return( 1 );
  766.     }
  767.  
  768.     six = Open( sixname, MODE_OLDFILE );
  769.     if( !six )
  770.     {
  771.         CloseAsync( oldix );
  772.         CloseAsync( olddata );
  773.         moveerr( fpID, tpID, sixname );
  774.         return( 1 );
  775.     }
  776.     Read( six, pix, sixsize );
  777.     Close( six );
  778.  
  779.     sd = Open( sdname, MODE_OLDFILE );
  780.     if( !sd )
  781.     {
  782.         CloseAsync( oldix );
  783.         CloseAsync( olddata );
  784.         moveerr( fpID, tpID, sdname );
  785.         return( 1 );
  786.     }
  787.  
  788.     for( c = 0, scan = pix; c < ixcount; scan++, c++ )
  789.     {
  790.         if( scan->flags & PIF_KILLED )
  791.             continue;
  792.  
  793.         maillen = scan->headersize + scan->commentsize + scan->datasize;
  794.  
  795.         // Data kopieren
  796.         Seek( sd, scan->offset, OFFSET_BEGINNING );
  797.         copyfh2async( sd, olddata, maillen );
  798.  
  799.         // Index korrigieren
  800.         scan->offset = poffset;
  801.         poffset += maillen;
  802.         WriteAsync( oldix, scan, sizeof( *scan ) );
  803.  
  804.         newmm = LibAllocPooled( pool, sizeof( *newmm ) );
  805.         if( !newmm )
  806.         {
  807.             LibFreePooled( miscmempool, pix, sixsize );
  808.             askreq( "Fehler: Kein Speicher fⁿr Nachrichtenverschiebetabelle!", "Abbruch" );
  809.             Close( sd );
  810.             DeleteFile( sixname );
  811.             DeleteFile( sdname );
  812.             CloseAsync( oldix );
  813.             CloseAsync( olddata );
  814.             return( 1 );
  815.         }
  816.         newmm->n = msgmovelist;
  817.         msgmovelist = newmm;
  818.         newmm->spID = fpID;
  819.         newmm->smID = c;
  820.         newmm->dpID = tpID;
  821.         newmm->dmID = midoffset++;
  822.     }
  823.  
  824.     LibFreePooled( miscmempool, pix, sixsize );
  825.     Close( sd );
  826.     DeleteFile( sixname );
  827.     DeleteFile( sdname );
  828.     CloseAsync( oldix );
  829.     CloseAsync( olddata );
  830.  
  831.     return( 0 );
  832. }
  833.  
  834. static void reworkpuffer( struct ogwin *ogw, struct ixinfo *ix )
  835. {
  836.     char f1[ 128 ];
  837.     char f2[á128 ];
  838.     char fo1[ 128 ];
  839.     BPTR oldp;
  840.     struct AsyncFile *newp;
  841.     struct pindex *pix, *pixp;
  842.     LONG pixsize = ix->count * sizeof( struct pindex );
  843.     LONG curoffs = 0, maillen = 0;
  844.     int changed = 0;
  845.     int c;
  846.  
  847.     sprintf( fo1,  "MD_%lx.Data", ix->pID );
  848.     sprintf( f1, "MD_%lx.Data.New", ix->pID );
  849.     sprintf( f2,  "MD_%lx.Index", ix->pID );
  850.  
  851.  
  852.     /* Entgⁿltige Entsorgung... */
  853.     if( !ix->count || !tstbitfield( ix->mark, ix->count ) )
  854.     {
  855.         prefs.nextfreepuf = 0;
  856.         DeleteFile( fo1 );
  857.         DeleteFile( f2 );
  858.         return;
  859.     }
  860.  
  861.     ogreSetMaxVal( ogw, RID_FG, ix->count );
  862.  
  863.     pix = LibAllocPooled( miscmempool, pixsize );
  864.     if( !pix )
  865.     {
  866.         askreq( "Fehler beim Reorganisieren:\nKein Speicher fⁿr Index.", "Abbruch" );
  867.         return;
  868.     }
  869.     /* Indizies einlesen */
  870.     oldp = Open( f2, MODE_OLDFILE );
  871.     Read( oldp, pix, pixsize );
  872.     Close( oldp );
  873.  
  874.     /* Prⁿfen, ob gⁿltiger Eintrag entfernt wurde */
  875.     for( pixp = pix, c = 0; c < ix->count; c++, pixp++ )
  876.     {
  877.         if( !tstbit( ix->mark, cá)á&& ( ! ( pixp->flags & PIF_KILLED ) ) )
  878.         {
  879.             pixp->flags |= PIF_KILLED;
  880.             pixp->offset = ~0;
  881.             changed = 1;
  882.         }
  883.     }
  884.  
  885.     /* Keine ─nderungen */
  886.     if( !changed )
  887.     {
  888. exnodo:
  889.         LibFreePooled( miscmempool, pix, pixsize );
  890.         return;
  891.     }
  892.     
  893.     oldp = Open( fo1, MODE_OLDFILE );
  894.     newp = OpenAsync( f1, MODE_WRITE, 65536 );
  895.     if( !oldp )
  896.     {
  897.         askreq( "Fehler bei der Reorganisation:\nDatei %s lΣ▀t sich nicht ÷ffnen (%ld)",
  898.             "Abbruch",
  899.             fo1,
  900.             IoErr()
  901.         );
  902.         goto exnodo;
  903.     }
  904.  
  905.     if( !newp )
  906.     {
  907.         Close( oldp );
  908.         askreq( "Fehler bei der Reorganisation:\nDatei %s lΣ▀t sich nicht beschreiben (%ld)",
  909.             "Abbruch",
  910.             f1,
  911.             IoErr()
  912.         );
  913.         goto exnodo;
  914.     }
  915.  
  916.     /* Nun verbleibende Daten umkopieren */
  917.     for( pixp = pix, c = 0; c < ix->count; c++, pixp++ )
  918.     {
  919.         ogreSetValue( ogw, RID_FG, c );
  920.         if( ! ( pixp->flags & PIF_KILLED ) )
  921.         {
  922.             maillen = pixp->headersize + pixp->commentsize + pixp->datasize;
  923. reseek:
  924.             if( Seek( oldp, pixp->offset, OFFSET_BEGINNING ) < 0 )
  925.             {
  926.                 if( askreq( "Fehler bei der Reorganisation:\nDos-Fehler %ld bei Seek() zu Offset %ld\nin Datei \"%s\"",
  927.                         "Wiederholen|Abbruch",
  928.                         IoErr(),
  929.                         pixp->offset,
  930.                         fo1
  931.                     ) )
  932.                     goto reseek;
  933.                 Close( oldp );
  934.                 CloseAsync( newp );
  935.                 LibFreePooled( miscmempool, pix, pixsize );
  936.                 return;
  937.             }
  938.             pixp->offset = curoffs;
  939.             curoffs += maillen;
  940.             copyfh2async( oldp, newp, maillen );            
  941.         }
  942.     }
  943.  
  944.     Close( oldp );
  945.     CloseAsync( newp );
  946.  
  947.     /* Indizies zurⁿckschreiben */
  948.     oldp = Open( f2, MODE_NEWFILE );
  949.     if( !oldp )
  950.     {
  951.         askreq( "Fehler bei der Reorganisation:\nBrettindex \"%s\" konnte nicht neu\ngeschrieben werden (%ld)",
  952.             "Abbruch",
  953.             f2, IoErr()
  954.         );
  955.     }
  956.     else
  957.     {
  958.         Write( oldp, pix, pixsize );
  959.         Close( oldp );
  960.         /* Puffer umkopieren */
  961.         DeleteFile( fo1 );
  962.         Rename( f1, fo1 );
  963.     }
  964.  
  965.     LibFreePooled( miscmempool, pix, pixsize );
  966. }
  967.  
  968. static int abortreorg( void )
  969. {
  970.     return( ( int ) askreq( "Reorganisation abbrechen?", "Reorganisation abbrechen|Fortsetzen" ) );
  971. }
  972.  
  973. static int abortrestore( void )
  974. {
  975.     return( ( int ) askreq( "Wiederherstellung des Brettindex abbrechen?", "Wiederherstellung abbrechen|Fortsetzen" ) );
  976. }
  977.  
  978. static struct direntry {
  979.     struct direntry *next;
  980.     char name[ 256 ];
  981. } *first;
  982.  
  983. static void adddir( struct ogwin *ogw, APTR pool, char *dir )
  984. {
  985.     struct FileInfoBlock *fib;
  986.     BPTR lock, oldcd;
  987.     struct direntry *new;
  988.     char path[ 256 ];
  989.  
  990.     ogreSetStringValue( ogw, RID_I1, dir );
  991.  
  992.     lock = Lock( dir, SHARED_LOCK );
  993.     if( !lock )
  994.         return;
  995.  
  996.     new = LibAllocPooled( pool, sizeof( *new ) );
  997.     if( !new )
  998.     {
  999.         UnLock( lock );
  1000.         return;
  1001.     }
  1002.  
  1003.     strcpy( new->name, dir );
  1004.  
  1005.     new->next = first;
  1006.     first = new;
  1007.  
  1008.     oldcd = CurrentDir( lock );
  1009.     fib = allocfib();
  1010.  
  1011.     Examine( lock, fib );
  1012.  
  1013.     while( ExNext( lock, fib ) )
  1014.     {
  1015.         if( fib->fib_DirEntryType > 0 )
  1016.         {
  1017.             strcpy( path, dir );
  1018.             addpart( path, fib->fib_FileName );
  1019.             adddir( ogw, pool, path );
  1020.         }            
  1021.     }
  1022.  
  1023.     freefib( fib );
  1024.     UnLock( CurrentDir( oldcd ) );
  1025. }
  1026.  
  1027. static void doremovedirs( struct ogwin *ogw )
  1028. {
  1029.     APTR pool;
  1030.  
  1031.     first = NULL;
  1032.     pool = LibCreatePool( 0, sizeof( struct direntry ) * 16, sizeof( struct direntry ) * 8 );
  1033.  
  1034.     ogreSetStringValue( ogw, RID_I2, "Suche ⁿberflⁿssige Verzeichnisse..." );
  1035.     adddir( ogw, pool, prefs.datadir );
  1036.     ogreSetStringValue( ogw, RID_I2, "Entferne ⁿberflⁿssige Verzeichnisse..." );
  1037.     ogreSetStringValue( ogw, RID_I1, "-" );
  1038.     while( first )
  1039.     {
  1040.         DeleteFile( first->name );
  1041.         first = first->next;
  1042.     }
  1043.     
  1044.     LibDeletePool( pool );
  1045. }
  1046.  
  1047. void doreorg2( int merge )
  1048. {
  1049.     struct Window *iw;
  1050.     struct IntuiMessage *im;
  1051.     struct mbrett *mb = (struct mbrett *) brettlist.lh_Head;
  1052.     struct mindex *mix;
  1053.     int bcount = 5;
  1054.     int Abort = FALSE;
  1055.     struct mmail *mm;
  1056.     struct FileInfoBlock *fib;
  1057.     BPTR lock;
  1058.     struct ixinfo *new;
  1059.     APTR pool;
  1060.     char tmp[á128 ], tmp2[ 128 ];
  1061.     int c, d;
  1062.     ULONG olddbsize = 0, newdbsize = 0;
  1063.     int dbfilecount;
  1064.     struct MinList mergelist;
  1065.     
  1066.     ixignoreall = FALSE;
  1067.     NewList( ( struct List * ) &ixlist );
  1068.     NewList( ( struct List * ) &mergelist );
  1069.  
  1070.     ogw = ogreInitWindow( scr, 0, NULL, "Reorganisation..." );
  1071.     ogreAddGroup( ogw, 0, OGFRAME_NONE, NULL );
  1072.     ogreAddText( ogw, 0, "Aktion:", RID_I2, "", 46, 1 );
  1073.     ogreAddText( ogw, 1, "Status:", RID_I1, "", 46, 1 );
  1074.     ogreAddFuelGauge( ogw, 2, RID_FG, GetNumEntries( &brettlist ) );
  1075.     ogreAddFuelGauge( ogw, 3, RID_GFG, 100 );
  1076.     ogreAddText( ogw, 4, "Belegter Festplattenplatz:", RID_GFGTXT, "", 1, 0 );
  1077.     ogreAddFuelGauge( ogw, 4, CGID_FG3, 100 );
  1078.     ogreAddButton( ogw, 5 | OGB_ONESC, 'a', "_Abbruch", RID_ABBRUCH );
  1079.  
  1080.     iw = ogreOpenWindow( ogw );
  1081.     if( !iw )
  1082.         return;
  1083.  
  1084.     setupinfofg( prefs.datadir,  ogw, CGID_FG3 );
  1085.     doinfofg();
  1086.  
  1087.     ixc_flush();
  1088.     closeallixfiles();
  1089.  
  1090.     sortbrettlist();
  1091.     fib = allocfib();
  1092.     pool = LibCreatePool( MEMF_CLEAR, 8192, 4096 );
  1093.  
  1094.     ogreSetStringValue( ogw, RID_I2, "Untersuche Datenfiles..." );
  1095.     lock = Lock( prefs.datadir, SHARED_LOCK );
  1096.     Examine( lock, fib );
  1097.  
  1098.     openlogmsg( "Reorganisations-Protokoll" );
  1099.  
  1100.     while( ExNext( lock, fib ) && !Abort )
  1101.     {
  1102.         if( !astcsma( fib->fib_FileName, "MD_#?.Index" ) )
  1103.             continue;
  1104.  
  1105.         ogreSetStringValue( ogw, RID_I1, fib->fib_FileName );
  1106.  
  1107.         new = LibAllocPooled( pool, sizeof( *new ) );
  1108.         if( !new )
  1109.             continue;
  1110.  
  1111.         new->count = fib->fib_Size / sizeof( struct pindex );
  1112.  
  1113.         if( fib->fib_Size % sizeof( struct pindex ) )
  1114.         {
  1115.             Abort = !askreq( "Warnung: Indexdatei %s hat\nungⁿltige LΣnge %lD (~%lD/%lD)",
  1116.                     "Weiter|Abbruch",
  1117.                     fib->fib_FileName,
  1118.                     fib->fib_Size,
  1119.                     new->count * sizeof( struct pindex ),
  1120.                     new->count
  1121.                  );
  1122.         }
  1123.  
  1124.         if( new->count )
  1125.         {
  1126.             new->mark = LibAllocPooled( pool, ( new->count + 31 ) / 8 );
  1127.             if( !new->mark )
  1128.             {
  1129.                 askreq( "Fehler bei der Reorganisation:\nKein Speicher fⁿr Tabellen.", "Abbruch" );
  1130.                 Abort = TRUE;
  1131.             }
  1132.         }
  1133.         stch_l( &fib->fib_FileName[3], ( LONG * ) &new->pID );
  1134.         AddTail( ( struct List * ) &ixlist, ( struct Node * ) new );
  1135.  
  1136.         im = ogreIM( ogw );
  1137.         if( im )
  1138.         {
  1139.             if( im->Class == GADGETUP )
  1140.                 Abort = abortreorg();
  1141.             ogreIMReply( ogw, im );
  1142.         }
  1143.     }
  1144.     freefib( fib );
  1145.     UnLock( lock );
  1146.  
  1147.     ogreSetStringValue( ogw, RID_I2, "Untersuche Bretter..." );
  1148.     ogreSetMaxVal( ogw, RID_GFG, GetNumEntries( &brettlist ) + ( GetNumEntries( ( struct List * ) &ixlist ) * 10 ) + 5 );
  1149.     ogreSetValue( ogw, RID_GFG, bcount );
  1150.     while( mb->n.ln_Succ && !Abort )
  1151.     {
  1152.         ogreSetStringValue( ogw, RID_I1, mb->b.name );
  1153.  
  1154.         mix = loadbrettixquiet( mb );
  1155.         if( !mix )
  1156.         {
  1157.             Abort = TRUE;
  1158.             break;
  1159.         }
  1160.         calcmcount_mb( mix, mb );
  1161.         mm = ( struct mmail * ) mix->maillist.lh_Head;
  1162.         while( mm->n.mln_Succ )
  1163.         {
  1164.             markix( mm, mix );
  1165.             mm = ( struct mmail * ) mm->n.mln_Succ;            
  1166.         }
  1167.         savebrettix( mix, mb );
  1168.         freebrettix( mix );
  1169.         closeallixfiles();
  1170.         flushbrettix();
  1171.         ogreSetValue( ogw, RID_GFG, bcount++ );
  1172.  
  1173.         im = ogreIM( ogw );
  1174.         if( im )
  1175.         {
  1176.             if( im->Class == GADGETUP )
  1177.                 Abort = abortreorg();
  1178.             ogreIMReply( ogw, im );
  1179.         }
  1180.  
  1181.         mb = ( struct mbrett * ) mb->n.ln_Succ;
  1182.     }
  1183.  
  1184.     closeallixfiles();
  1185.     ixc_flush();
  1186.  
  1187.     ogreSetStringValue( ogw, RID_I2, "Bearbeite Datenfiles..." );
  1188.  
  1189.     pushdir( prefs.datadir );
  1190.  
  1191.     printlog( "▄berarbeiten der Datenfiles:\n---------------------------------------------------\n" );
  1192.     dbfilecount = GetNumEntries( ( struct List * ) &ixlist );
  1193.  
  1194.     while( !Abort && ( new = ( struct ixinfo * ) RemHead( ( struct List * ) &ixlist ) ) )
  1195.     {
  1196.         sprintf( tmp, "MD_%lx.Data", new->pID );
  1197.         sprintf( tmp2, "%s, %lD Bytes", tmp, d = getfilelen( tmp ) );
  1198.         ogreSetStringValue( ogw, RID_I1, tmp2 );
  1199.         reworkpuffer( ogw, new );
  1200.         doinfofg();
  1201.         olddbsize += d;
  1202.         c = getfilelen( tmp );
  1203.         if( c < 1 )
  1204.             strcat( tmp2,": gel÷scht!" );
  1205.         else
  1206.         {
  1207.             asprintf( tmp2, "-> %lD Bytes", c );
  1208.             newdbsize += c;
  1209.         }
  1210.         ogreSetStringValue( ogw, RID_I1, tmp2 );
  1211.         new->newlen = c;
  1212.  
  1213.         printlog( "%-16.16s: %10lD -> %10lD Bytes (%ld%%)\n",
  1214.             tmp,
  1215.             d,
  1216.             ( c > 1 ) ? c : 0,
  1217.             ( c > 1 && d ) ? ( ( c * 100 ) / d ) : 0
  1218.         );
  1219.  
  1220.         ogreSetValue( ogw, RID_GFG, bcount );
  1221.         bcount += 10;
  1222.         ogreSetValue( ogw, RID_FG, 0 );
  1223.  
  1224.         im = ogreIM( ogw );
  1225.         if( im )
  1226.         {
  1227.             if( im->Class == GADGETUP )
  1228.                 Abort = abortreorg();
  1229.             ogreIMReply( ogw, im );
  1230.         }
  1231.  
  1232.         if( c > 0 )
  1233.             AddTail( ( struct List *) &mergelist, new );
  1234.     }
  1235.  
  1236.     if( !Abort )
  1237.         printlog( "-------------------\n%10lD Files, %10lD -> %10lD Bytes (%ld%%)\n\n",
  1238.             dbfilecount,
  1239.             olddbsize,
  1240.             newdbsize,
  1241.             ( olddbsize > 100 ) ? ( newdbsize ) / ( olddbsize / 100 ) : 0
  1242.         );
  1243.     else
  1244.         printlog( "\n*** Reorganisation abgebrochen!\n\n" );
  1245.  
  1246.     // Eventuell mergen?
  1247.     if( merge )
  1248.     {
  1249.         int destsize = prefs.reorg_destsize * 1024;
  1250.  
  1251.         msgmovelist = NULL;
  1252.  
  1253.         printlog( "\nZusammenfassen kleiner Datenfiles:\n---------------------------------------------------\n" );
  1254.         ogreSetStringValue( ogw, RID_I2, "Zusammenfassung kleiner Datenfiles..." );
  1255.  
  1256.         while( !Abort && ( new = ( struct ixinfo * ) RemHead( ( struct List * ) &mergelist ) ) )
  1257.         {
  1258.             while( new->newlen < destsize )
  1259.             {
  1260.                 struct ixinfo *from = ( struct ixinfo * ) mergelist.mlh_Head;
  1261.  
  1262.                 while( from->n.mln_Succ )
  1263.                 {
  1264.                     if( ( from->newlen + new->newlen ) < ( destsize + ( destsize / 5 ) ) )
  1265.                     {
  1266.                         sprintf( tmp, "MD_%lx an MD_%lx", from->pID, new->pID );
  1267.                         ogreSetStringValue( ogw, RID_I1, tmp );
  1268.                         printlog( "MD_%lx (%lD) an MD_%lx (%lD); neue LΣnge %lD Bytes\n",
  1269.                             from->pID, from->newlen,
  1270.                             new->pID, new->newlen,
  1271.                             from->newlen + new->newlen
  1272.                         );
  1273.                         if( movepuffer( pool, from->pID, new->pID ) )
  1274.                             Abort = TRUE;
  1275.                         new->newlen += from->newlen;
  1276.                         Remove( from );
  1277.                         break;
  1278.                     }
  1279.                     from = ( struct ixinfo * ) from->n.mln_Succ;
  1280.                 }
  1281.  
  1282.                 if( !from->n.mln_Succ )
  1283.                     break;
  1284.  
  1285.             }
  1286.             im = ogreIM( ogw );
  1287.             if( im )
  1288.             {
  1289.                 if( im->Class == GADGETUP )
  1290.                     Abort = abortreorg();
  1291.                 ogreIMReply( ogw, im );
  1292.             }
  1293.         }
  1294.  
  1295.         if( msgmovelist )
  1296.         {
  1297.             ogreSetStringValue( ogw, RID_I2, "Korrigiere Brettindizes..." );
  1298.             mb = (struct mbrett *) brettlist.lh_Head;
  1299.             while( mb->n.ln_Succ && !Abort )
  1300.             {
  1301.                 ogreSetStringValue( ogw, RID_I1, mb->b.name );
  1302.  
  1303.                 mix = loadbrettixquiet( mb );
  1304.                 if( !mix )
  1305.                 {
  1306.                     Abort = TRUE;
  1307.                     break;
  1308.                 }
  1309.                 mm = ( struct mmail * ) mix->maillist.lh_Head;
  1310.                 while( mm->n.mln_Succ )
  1311.                 {
  1312.                     if( procmsgmovelist( mm ) )
  1313.                         mix->changed = TRUE;
  1314.                     mm = ( struct mmail * ) mm->n.mln_Succ;            
  1315.                 }
  1316.                 savebrettix( mix, mb );
  1317.                 freebrettix( mix );
  1318.                 closeallixfiles();
  1319.                 flushbrettix();
  1320.  
  1321.                 mb = ( struct mbrett * ) mb->n.ln_Succ;
  1322.             }
  1323.         }
  1324.     }
  1325.  
  1326.     if( !Abort )
  1327.     {
  1328.         doremovedirs( ogw );
  1329.     }
  1330.  
  1331.     closelogmsg();
  1332.  
  1333.     popdir();
  1334.     freeinfofg();
  1335.     LibDeletePool( pool );
  1336.     ogreExitWindow( ogw );
  1337. }
  1338.  
  1339. #define REOID_START 1
  1340. #define REOID_CANCEL 2
  1341. #define REOID_L1 3
  1342. #define REOID_L2 4
  1343. #define REOID_MERGE 5
  1344. #define REOID_MAX 6
  1345.  
  1346. static long nummsgs(void)
  1347. {
  1348.     struct mbrett *n=(struct mbrett*)brettlist.lh_Head;
  1349.     long count = 0;
  1350.  
  1351.     while(n->n.ln_Succ)
  1352.     {
  1353.         count += n->b.mails;
  1354.         n=(struct mbrett*)n->n.ln_Succ;
  1355.     }
  1356.     return( count );
  1357. }
  1358.  
  1359.  
  1360. void doreorg( void )
  1361. {
  1362.     struct Window *iw;
  1363.     struct IntuiMessage *im;
  1364.     int v;
  1365.     char buffer[ 40 ];
  1366.     int num = nummsgs();
  1367.  
  1368.     Done = FALSE;
  1369.  
  1370.     if( !prefs.reorg_destsize )
  1371.         prefs.reorg_destsize = 256;
  1372.  
  1373.     ogw = ogreInitWindow( scr, WFLG_RMBTRAP, NULL, "Reorganisation der Nachrichtendatenbank" );
  1374.     ogreAddGroup( ogw, 0, OGFRAME_OUTLINE, " Parameter " );
  1375.     ogreAddText( ogw, 0, "", REOID_L1, "Die Reorganisation kann lΣngere Zeit in Anspruch nehmen!", 56, 0 );
  1376.     ogreAddText( ogw, 1, "UngefΣhrer Speicherbedarf:", REOID_L2, "", 20, 0 );
  1377.     ogreAddCheckbox( ogw, 2, 'z', "_Zusammenfassen kleiner Puffer:", REOID_MERGE, prefs.reorg_merge );
  1378.     ogreAddInteger( ogw, 3, 'g', "Ziel_gr÷▀e KByte:", REOID_MAX, prefs.reorg_destsize, 8, MAXINT, 10, 10 );
  1379.  
  1380.     ogreAddGroup( ogw, 1, OGFRAME_NONE, NULL );
  1381.     ogreAddButton( ogw, 0 | OGB_ONENTER, 's', "_Start", REOID_START );
  1382.     ogreAddHelp( ogw, 0 );
  1383.     ogreAddButton( ogw, 0 | OGB_ONESC, 'a', "_Abbruch", REOID_CANCEL );
  1384.  
  1385.     iw = ogreOpenWindow( ogw );
  1386.     if( !iw )
  1387.         return;
  1388.  
  1389.     while( !Done )
  1390.     {
  1391.         v = ogreValue( ogw, REOID_MERGE );
  1392.         ogreEnable( ogw, v, REOID_MAX, 0 );
  1393.         sprintf( buffer, "%lD Bytes", 160749 + ( ( num + 7 ) / 8 ) + ( v ? num * 20 : 0 ) );
  1394.         ogreSetStringValue( ogw, REOID_L2, buffer );
  1395.  
  1396.         im = ogreWaitIM( ogw );
  1397.  
  1398.         if( im->Class == IDCMP_GADGETHELP )
  1399.             showguidenum( "reorgprefs_gads", im->Code );
  1400.         else if( im->Class == IDCMP_GADGETUP )
  1401.         {
  1402.             if( im->Code == REOID_START )
  1403.                 Done = 2;
  1404.             else if( im->Code == REOID_CANCEL )
  1405.                 Done = 1;
  1406.         }
  1407.         ogreIMReply( ogw, im );
  1408.     }
  1409.  
  1410.     if( Done == 1 )
  1411.     {
  1412.         ogreExitWindow( ogw );
  1413.         return;
  1414.     }
  1415.  
  1416.     prefs.reorg_destsize = ogreValue( ogw, REOID_MAX );
  1417.     prefs.reorg_merge = ogreValue( ogw, REOID_MERGE );
  1418.     ogreExitWindow( ogw );
  1419.  
  1420.     doreorg2( v );
  1421. }
  1422.  
  1423. #define RGID_L0 1
  1424. #define RGID_L1 2
  1425. #define RGID_L2 3
  1426. #define RGID_FG 4
  1427. #define RGID_START 5
  1428. #define RGID_END 6
  1429.  
  1430.  
  1431. void restoremindex( struct mbrett *mb )
  1432. {
  1433.     struct Window *iw;
  1434.     struct IntuiMessage *im;
  1435.     char buffer[ 128 ], buffer2[á128 ];
  1436.     BPTR lock;
  1437.     struct AsyncFile *newmindex;
  1438.     struct FileInfoBlock *fib;
  1439.     int Abort = FALSE;
  1440.     int mailcount = 0;
  1441.     ULONG pID, mID;
  1442.     struct msghandle *msg;
  1443.     struct hlist *hlist;
  1444.     struct header *hl;
  1445.     struct mail mail;
  1446.     int pmc;
  1447.     struct mindex *mix;
  1448.     int ispm;
  1449.  
  1450.     Done = FALSE;
  1451.  
  1452.     ispm = mb->b.name[á0 ]á!= '/';
  1453.  
  1454.     if( !stricmp( mb->b.name, "/╗SPOOL" ) )
  1455.     {
  1456.         askreq( "Wiederherstellung des /╗SPOOL-Brettes\nist nicht m÷glich.", "Abbruch" );
  1457.         return;
  1458.     }
  1459.  
  1460.     if( !stricmp( mb->b.name, "/╗ARCHIV" ) )
  1461.     {
  1462.         askreq( "Wiederherstellung des /╗ARCHIV-Brettes\nist nicht m÷glich.", "Abbruch" );
  1463.         return;
  1464.     }
  1465.  
  1466.     ogw = ogreInitWindow( scr, WFLG_RMBTRAP, NULL, "Brettindex wiederherstellen" );
  1467.     ogreAddGroup( ogw, 0, OGFRAME_OUTLINE, " Status " );
  1468.     ogreAddText( ogw, 0, " Brett:", RGID_L0, mb->b.name, 46, 1 );
  1469.     ogreAddText( ogw, 1, " Mails:", RGID_L1, "", 46, 1 );
  1470.     ogreAddText( ogw, 2, "Status:", RGID_L2, "", 46, 1 );
  1471.     ogreAddFuelGauge( ogw, 3, RGID_FG, 100 );
  1472.  
  1473.     ogreAddGroup( ogw, 1, OGFRAME_NONE, NULL );
  1474.     ogreAddButton( ogw, 0 | OGB_ONENTER, 's', "_Start", RGID_START );
  1475.     ogreAddHelp( ogw, 0 );
  1476.     ogreAddButton( ogw, 0 | OGB_ONESC, 'a', "_Abbruch", RGID_END );
  1477.  
  1478.     iw = ogreOpenWindow( ogw );
  1479.     if( !iw )
  1480.         return;
  1481.  
  1482.     while( !Done )
  1483.     {
  1484.         im = ogreWaitIM( ogw );
  1485.  
  1486.         if( im->Class == IDCMP_GADGETHELP)
  1487.             showguidenum( "restoremindex_gads", im->Code );
  1488.         else if( im->Class == IDCMP_GADGETUP )
  1489.         {
  1490.             if( im->Code == RGID_START )
  1491.                 Done = 2;
  1492.             else if( im->Code == RGID_END )
  1493.                 Done = 1;
  1494.         }
  1495.         ogreIMReply( ogw, im );
  1496.     }
  1497.  
  1498.     if( Done == 1 )
  1499.     {
  1500.         ogreExitWindow( ogw );
  1501.         return;
  1502.     }
  1503.  
  1504.     if( !askreq( "Wollen Sie wirklich den Index von\nBrett %s\nrestaurieren?\n\n*** ACHTUNG!\n*** SΣmtliche Flags bestehender Nachrichten gehen verloren!", "Wiederherstellen|Abbruch", mb->b.name ) )
  1505.     {
  1506.         ogreExitWindow( ogw );
  1507.         return;
  1508.     }
  1509.  
  1510.     ogreEnable( ogw, FALSE, RGID_START, OGID_HELP, NULL );
  1511.  
  1512.     /* Es geht los */
  1513.     flushbrettix();
  1514.     closeallixfiles();
  1515.  
  1516.     brettpfad( buffer, mb );
  1517.     addpart( buffer, ".Mindex-new" );
  1518.     newmindex = OpenAsync( buffer, MODE_WRITE, sizeof( struct mail ) * 32 );
  1519.     if( !newmindex )
  1520.     {
  1521.         askreq( "Fehler bei der Wiederherstellung:\nDatei \"%s\" lΣ▀t sich nicht beschreiben (%ld).",
  1522.             "Abbruch",
  1523.             buffer,
  1524.             IoErr()
  1525.         );
  1526.         ogreExitWindow( ogw );
  1527.         return;
  1528.     }
  1529.  
  1530.     fib = allocfib();
  1531.     lock = Lock( prefs.datadir, SHARED_LOCK );
  1532.     Examine( lock, fib );
  1533.  
  1534.     while( ExNext( lock, fib ) && !Abort )
  1535.     {
  1536.         if( !astcsma( fib->fib_FileName, "MD_#?.Index" ) )
  1537.             continue;
  1538.  
  1539.         sprintf( buffer, "Untersuche %s...", fib->fib_FileName );
  1540.         ogreSetStringValue( ogw, RGID_L2, buffer );
  1541.  
  1542.         stch_l( &fib->fib_FileName[á3 ], &pID );
  1543.  
  1544.         pmc = fib->fib_Size / sizeof( struct pindex );
  1545.  
  1546.         ogreSetMaxVal( ogw, RGID_FG, pmc );
  1547.  
  1548.         for( mID = 0; mID < pmc && !Abort; mID++ )
  1549.         {
  1550.             ogreSetValue( ogw, RGID_FG, mID );
  1551.             msg = msg_open( pID, mID );
  1552.             if( !msg )
  1553.                 break;
  1554.             if( msg->pix.flags & PIF_KILLED )
  1555.             {
  1556.                 msg_close( msg );
  1557.                 continue;
  1558.             }
  1559.  
  1560.             hlist = msg_loadheader( msg );
  1561.             if( !hlist )
  1562.             {
  1563.                 askreq( "Fehler bei der Wiederherstellung:\nHeader von Nachricht %lx:%lx konnte\nnicht geladen werden.", "Abbruch", pID, mID );
  1564.                 msg_close( msg );
  1565.                 break;
  1566.             }
  1567.  
  1568.             /* In hlist steht die Headerliste */
  1569.  
  1570.             hl = hl_findheader( hlist, "EMP" );
  1571.             while( hl )
  1572.             {
  1573.                 /* Gefunden! */
  1574.                 if( ( ispm && hl->data[ 0 ]á!= '/' ) || !stricmp( hl->data, mb->b.name ) )
  1575.                 {
  1576.                     memset( &mail, 0, sizeof( mail ) );
  1577.                     mail.pufferID = pID;
  1578.                     mail.mailID = mID;
  1579.                     header2mail( hlist, &mail );
  1580.                     if( !mail.maillen )
  1581.                         mail.maillen = msg_getsize( msg, MC_HEADER ) + msg_getsize( msg, MC_COMMENT ) + msg_getsize( msg, MC_DATA );
  1582.                     WriteAsync( newmindex, &mail, sizeof( mail ) );
  1583.                     mailcount++;
  1584.                     break;
  1585.                 }
  1586.                 hl = hl_findnextheader( hl );
  1587.             }
  1588.             hl_freeheader( hlist );
  1589.             msg_close( msg );
  1590.             sprintf( buffer, "%lD Nachricht%s gefunden", mailcount, mailcount == 1 ? "en" : "" );
  1591.             ogreSetStringValue( ogw, RGID_L1, buffer );
  1592.         }
  1593.  
  1594.         im = ogreIM( ogw );
  1595.         if( im )
  1596.         {
  1597.             if( im->Class == GADGETUP )
  1598.                 Abort = abortrestore();
  1599.             ogreIMReply( ogw, im );
  1600.         }
  1601.     }
  1602.  
  1603.     freefib( fib );
  1604.     UnLock( lock );
  1605.  
  1606.     CloseAsync( newmindex );
  1607.     brettpfad( buffer, mb );
  1608.     addpart( buffer, ".Mindex-new" );
  1609.  
  1610.     if( !Abort )
  1611.     {
  1612.         brettpfad( buffer2, mb );
  1613.         addpart( buffer2, ".Mindex" );
  1614.         DeleteFile( buffer2 );
  1615.         Rename( buffer, buffer2 );
  1616.     }
  1617.     else
  1618.         DeleteFile( buffer );
  1619.  
  1620.     ogreExitWindow( ogw );
  1621.  
  1622.     mix = loadbrettixquiet( mb );
  1623.     if( mix )
  1624.     {
  1625.         calcmcount_mb( mix, mb );
  1626.         freebrettix( mix );
  1627.     }
  1628. }
  1629.