home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / ftp.vapor.com / microdot-1 / md1_src_02.lzx / brett.c < prev    next >
C/C++ Source or Header  |  1978-05-30  |  54KB  |  2,591 lines

  1. #include "microdot.h"
  2. #include "asyncio.h"
  3.  
  4. #include "ogre.h"
  5. #include "ogre_protos.h"
  6.  
  7. #include "md_rexx.h"
  8.  
  9. static void *brettmempool;
  10.  
  11. struct List brettlist;
  12. BOOL didsortin;
  13.  
  14. struct TagItem undertags[]={ RT_Underscore, '_', TAG_DONE, NULL };
  15.  
  16. extern struct Library *LocaleBase;
  17. extern ULONG checkprogramval;
  18.  
  19. extern int noreq;
  20. ULONG __stdargs askreq( char *txt, char *button, ... )
  21. {
  22.     if( noreq )
  23.         return( FALSE );
  24.  
  25. #ifndef MDV20
  26.     if( !LocaleBase )
  27.     {
  28.         replacebigd( txt );
  29.         replacebigd( button );
  30.     }
  31. #endif
  32.  
  33.     return( rtEZRequestA( txt, button, rinfo, (APTR)((long)(&button)+4), undertags ) );
  34. }
  35.  
  36. #define NOSS 8
  37. static char *schmeichelstrings[ NOSS ] = {
  38.     "unvergleichlichen",
  39.     "lieben",
  40.     "liebreizenden",
  41.     "umwerfenden",
  42.     "grandiosen",
  43.     "herrlichen",
  44.     "grazi÷sen",
  45.     "unbeschreiblichen"
  46. };
  47.  
  48. static char *schmeichel( void )
  49. {
  50.     return( schmeichelstrings[á(prefs.counter++) % NOSS ] );
  51.  
  52. }
  53.  
  54. static void doinfo(void)
  55. {
  56.     static struct TagItem tags[]={RTEZ_Flags,EZREQF_CENTERTEXT,TAG_DONE,0};
  57.     int rc;
  58.     //int isamosaic = (int)FindPort( "AMOSAIC.1" );
  59.     char but[á256 ];
  60.     char *mdinfotext = 
  61. #ifdef MDV20
  62.     "(╖) MicroDot020 (╖)\nV" MDVER " (" __DATE__ ")\n\n"
  63. #else
  64.     "(╖) MicroDot (╖)\nV" MDVER " (" __DATE__ ")\n\n"
  65. #endif
  66. "Geschrieben von Oliver Wagner\n"
  67. "<owagner@vapor.com>\n"
  68. "⌐ 1993-99, All Rights Reserved\n\n"
  69. "WWW: http://www.vapor.com/microdot-1/\n"
  70. "FTP: ftp.vapor.com, /pub/microdot-1/\n\n"
  71. "%s\n\n"
  72. "Benutzt \"reqtools.library\" ⌐ by Nico Franτois\n"
  73. "Benutzt \"ARexxBox\" ⌐ by Michael Balzer\n\n"
  74. "%lD Bytes freier Speicher\n"
  75. "Zeitverschiebung zur GMT: %lc%ld Stunde%s (%serzeit)\n\n"
  76. "Gewidmet der %s Claudia.";
  77.  
  78. #ifndef MDV20
  79.     if( !LocaleBase )
  80.         replacebigd( mdinfotext );
  81. #endif
  82.  
  83.     but[á0 ]á= 0;
  84.     if( !registerinfo.serie )
  85.         strcpy( but, "Registrieren|" );
  86.     /*if( isamosaic )
  87.         strcat( but, "Zur MicroDot-WWW-Page|" );*/
  88.     strcat( but, "Weiter" );
  89.  
  90.     rc = rtEZRequest( mdinfotext,
  91.         but,
  92.         rinfo, tags,
  93.         registerinfo.serie ? registerinfo.registriert_txt : "Unregistrierte Testversion",
  94.         AvailMem(0),
  95.         timezone_offset >= 0 ? '+' : '-',
  96.         abs( timezone_offset / 3600 ),
  97.         PLURALN( timezone_offset / 3600 ),
  98.         ( timezone_dst ) ? "Somm" : "Wint",
  99.         schmeichel()
  100.      );
  101.  
  102.     switch( rc )
  103.     {
  104.         case 1:
  105.             if( !registerinfo.serie )
  106.             {
  107.                 doregisterform();
  108.                 return;
  109.             }
  110.         /*case 2:
  111.             SystemTags( "rx \"address 'AMOSAIC.1'; 'show'; 'screen front'; 'activate'; 'jump url http://wade1.ab.umd.edu/support/microdot/'\"", TAG_DONE );
  112.             break;*/
  113.     }
  114. }
  115.  
  116. static int __stdargs sortbcmpf(struct mbrett **s1,struct mbrett **s2)
  117. {
  118.     return(stricmp((*s1)->b.name,(*s2)->b.name));
  119. }
  120.  
  121. static ULONG lastbrettcs;
  122.  
  123. static void calcbrettnamecrc( struct mbrett *mb )
  124. {
  125.     char tmp[á128 ];
  126.  
  127.     strcpy( tmp, mb->b.name );
  128.     strupr( tmp );
  129.  
  130.     mb->namecrc = crc32( tmp, strlen( tmp ) );
  131. }
  132.  
  133. void sortbrettlist( void )
  134. {
  135.     int c, c2, c3;
  136.     struct mbrett **array, *n;
  137.     struct List tl, tl2;
  138.  
  139.     NewList( &tl );
  140.     NewList( &tl2 );
  141.     
  142.     /* Move PM, Spool & Archiv to temporary list */
  143.     for( c=0; c<4; c++ )
  144.         AddTail( &tl, RemHead( &brettlist ) );
  145.  
  146.     c = GetNumEntries( &brettlist );
  147.     if( c )
  148.     {
  149.         array = myAllocVec( 4 * c, 0 );
  150.         if( !array )
  151.         {
  152.             displaybeep();
  153.             return;
  154.         }
  155.  
  156.         /* First, sort PM boards */
  157.         c = 0;
  158.         while((n=(struct mbrett*)RemHead(&brettlist)))
  159.         {
  160.             if( !( n->b.flags & BFLAG_EXTEND_PM ) ) 
  161.             {
  162.                 AddHead( &tl2, n );
  163.             }
  164.             else
  165.                 array[ c++ ] = n;
  166.         }
  167.         if( c )
  168.             qsort( array, c, 4, sortbcmpf);
  169.  
  170.         /* Sort Rest */
  171.  
  172.         c2 = 0;
  173.         while((n=(struct mbrett*)RemHead(&tl2)))
  174.             array[ c + c2++ ] = n;
  175.  
  176.         if( c2 )
  177.             qsort( &array[ c ], c2, 4, sortbcmpf );
  178.  
  179.         c+= c2;
  180.     }
  181.  
  182.     for( c2 = 0; c2 < 4; c2++ )
  183.         AddTail( &brettlist, RemHead( &tl ) );
  184.  
  185.     if( c )
  186.     {
  187.         for( c2 = 0; c2<c; c2++ )
  188.             AddTail( &brettlist, array[ c2 ] );
  189.         myFreeVec( array );
  190.     }
  191.  
  192.     makebrettview();
  193. }
  194.  
  195. static void addmvnode(void *pool,struct List *l,char *txt)
  196. {
  197.     struct mvnode *n=LibAllocPooled(pool,sizeof(struct mvnode));
  198.     n->txt=LibAllocPooled(pool,strlen(txt)+1);
  199.     strcpy(n->txt,txt);
  200.     AddTail(l,(struct Node*)n);
  201. }
  202.  
  203. static void freemvlist(void *pool)
  204. {
  205.     LibDeletePool(pool);
  206. }
  207.  
  208. static void procmapsmsg( char **msgbufp, int mode )
  209. {
  210.     if( isv37 )
  211.     {
  212.         char *mailbuf = *msgbufp;
  213.  
  214.         BPTR f = Open( "T:MD_MAPS.LST", MODE_NEWFILE );
  215.         if( f )
  216.         {
  217.             int rc;
  218.             Write( f, mailbuf, strlen( mailbuf ) );
  219.             Close( f );
  220.             execrexx( mode ? "MapsDel" : "MapsAdd" );
  221.             if( ( rc = getfilelen( "T:MD_MAPS.LST" ) ) > 0 )
  222.             {
  223.                 myFreeVec( mailbuf );
  224.                 mailbuf = myAllocVec( rc + 1, 0 );
  225.                 mailbuf[árc ]á= 0;
  226.                 f = Open( "T:MD_MAPS.LST", MODE_OLDFILE );
  227.                 Read( f, mailbuf, rc );
  228.                 Close( f );
  229.                 *msgbufp = mailbuf;
  230.             }
  231.             DeleteFile( "T:MD_MAPS.LST" );
  232.         }
  233.     }
  234. }
  235.  
  236. static void domapsadd(int mode)
  237. {
  238.     FILE *f;
  239.     struct mvnode *n;
  240.     struct List mvlist;
  241.     void *scs;
  242.     char buff[256];
  243.     struct IntuiMessage *mp,im;
  244.     int done=0,mailsize=0;
  245.     int markcount;
  246.     void *mvpool;
  247.     int rc;
  248.  
  249.     rtSetWaitPointer(w);
  250.  
  251.     f = fopen( "microdot.mapsblist", "r" );
  252.     if( !f )
  253.     {
  254.         if( askreq( "Keine Brettliste vorhanden!\nBestellen Sie zuerst per MAPS eine Brettliste und\nwarten Sie, bis diese eingelesen wurde.", "Brettliste bestellen|Abbruch" ) )
  255.         {
  256.             sendmapsreq( 1 );
  257.         }
  258.         ClearPointer( w );
  259.         return;
  260.     }
  261.  
  262.     mvpool=LibCreatePool(MEMF_CLEAR,4096,2048);
  263.     NewList(&mvlist);
  264.  
  265.     w->Flags |= WFLG_RMBTRAP;
  266.  
  267.     while((fgets(buff,256,f)))
  268.     {
  269.         clnl( buff );
  270.         addmvnode( mvpool, &mvlist, buff );
  271.     }
  272.     fclose(f);
  273.  
  274.     scs=pushscs();
  275.     setupscroller(&mvlist,3);
  276.     displayscroller();
  277.  
  278.     preport(0,1,"Bretter per MAPS %sbestellen: Markieren Sie die gewⁿnschten Bretter",(mode)?"ab":"");
  279.  
  280.     ClearPointer( w );
  281.  
  282.     while(!done)
  283.     {
  284.         while(!(mp=(struct IntuiMessage*)GetMsg(w->UserPort))) mWaitPort(w->UserPort);
  285.         im=*mp;
  286.         ReplyMsg(mp);
  287.  
  288.         switch(im.Class)
  289.         {
  290.             case IDCMP_REFRESHWINDOW:
  291.                 BeginRefresh( w );
  292.                 displayscroller();
  293.                 EndRefresh( w, TRUE );
  294.                 break;
  295.  
  296.             case IDCMP_CLOSEWINDOW:
  297.                 doaskquit();
  298.                 break;
  299.  
  300.             case MOUSEBUTTONS:
  301.                 rc = scrollerdoclick( &im );
  302.                 if( rc > 0 )
  303.                 {
  304.                     n=(struct mvnode*)GetEntry(&mvlist,getscrollercurrent());
  305.                     if(n) { n->sel^=~0; displaycurrentline(); }
  306.                 }
  307.                 else if( rc == -1 )
  308.                     done = 1;
  309.                 break;
  310.             case MOUSEMOVE: scrollerdomove(&im); break;
  311.             case GADGETDOWN: scrollerdogad(&im); break;
  312.             case RAWKEY: if(scrollerdokey(&im)<0) switch(im.Code) {
  313.                     case 0x5f:    showguide("maps_add");
  314.                                 break;
  315.  
  316.                     case 0x5d:
  317.                     case 0x0f:
  318.                     case 0x43:
  319.                     case 0x44:
  320.                     case 0x45:    done=1; break;
  321.  
  322.                      }
  323.                      break;
  324.  
  325.             case IDCMP_NEWSIZE:
  326.                 scrollerresize();
  327.                 break;
  328.         }
  329.  
  330.         markcount=mailsize=0; n=(struct mvnode*)mvlist.lh_Head;
  331.         while(n->n.mln_Succ)
  332.         {
  333.             if(n->sel)
  334.             {
  335.                 mailsize += strlen( n->txt ) + strlen( prefs.maps_addprefix ) + strlen( prefs.maps_delprefix ) + 1;
  336.                 markcount++;
  337.             }
  338.             n=(struct mvnode*)n->n.mln_Succ;
  339.         }
  340.         preport(1,1,"%lD Bretter markiert.",markcount);
  341.  
  342.     }
  343.  
  344.     if( markcount )
  345.     {
  346.         char *mailbuf;
  347.         if( !mode )
  348.             rc = askreq("%lD Brett%s bestellen?","Bestellen|Bestellen & _Eintragen|Abbruch",markcount,markcount==1 ? "":"er");
  349.         else
  350.             rc = askreq("%lD Brett%s abbestellen?","Abbestellen|Abbruch",markcount,markcount==1 ? "":"er");
  351.  
  352.         if( rc )
  353.         {
  354.             mailbuf = myAllocVec( mailsize + 512,0);
  355.             if(mailbuf)
  356.             {
  357.                 strcpy( mailbuf, prefs.maps_msgprefix );
  358.  
  359.                 n=(struct mvnode*)mvlist.lh_Head;
  360.                 while(n->n.mln_Succ)
  361.                 {
  362.                     if(n->sel)
  363.                     {
  364.                         strcpy( buff, &n->txt[ prefs.maps_list_boffs ]á);
  365.                         skillfirstspace( buff );
  366.                         asprintf( mailbuf, "%s%s\n", ( mode ) ? prefs.maps_delprefix : prefs.maps_addprefix, buff );
  367.                         if( rc == 2 )
  368.                         {
  369.                             char tmpbname[ 128 ];
  370.  
  371.                             strcpy( tmpbname, buff );
  372.                             if( (!ISRFC) && tmpbname[0]á!= '/'á)
  373.                                 strins( tmpbname, "/" );
  374.  
  375.                             findbrett( tmpbname, -1 );
  376.                         }
  377.  
  378.                     }
  379.                     n=(struct mvnode*)n->n.mln_Succ;
  380.                 }
  381.                 procmapsmsg( &mailbuf, mode );
  382.  
  383.                 sendshortmail( prefs.mapsname,(mode)?prefs.maps_del:prefs.maps_add,
  384.                     mailbuf,NULL,0,0,1);
  385.  
  386.                 myFreeVec(mailbuf);
  387.  
  388.                 if( rc == 2 )
  389.                 {
  390.                     sortbrettlist();
  391.                 }
  392.             }
  393.         }
  394.     }
  395.  
  396.     popscs(scs);
  397.     freemvlist(mvpool);
  398.  
  399.     w->Flags &= ~WFLG_RMBTRAP;
  400. }
  401.  
  402. #if 0
  403. static void donervsandro( void )
  404. {
  405.     char bet[á64 ];
  406.     int c, ml;
  407.     char mail[á256 ];
  408.  
  409.     srand( time( 0 ) );
  410.  
  411.     /* Bis zu 10 Leerzeilen */
  412.     ml = rand() % 10;
  413.     mail[á0 ]á= 0;
  414.     for( c = 0; c < ml; c++ )
  415.         strcat( mail, "\n" );
  416.  
  417.     ml = rand() % 30;
  418.     mail[á0 ]á= 0;
  419.     for( c = 0; c < ml; c++ )
  420.         strcat( mail, " " );
  421.  
  422.     if( rand() & 1 )
  423.         strcat( mail, "Wo bleibt der Guide?" );
  424.     else
  425.         strcat( mail, "Wo ist der Guide?" );
  426.     ml = rand() % 7;
  427.     for( c = 0; c < ml; c++ )
  428.         strcat( mail, "\n" );
  429.  
  430.     ml = rand() % 60;
  431.     for( c = 0; c < ml; c++ )
  432.         bet[ácá]á= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890 !"[ rand() % 64 ];
  433.     bet[ác ]á= 0;
  434.  
  435.     if( askreq( "Beschwerde ⁿber fehlenden MicroDot.guide\nan Sandro Paolini schicken?", "Verschicken|Abbruch" ) )
  436.     {
  437.         sendshortmail(
  438.             "s_paolini@aworld.aworld.de",
  439.             bet,
  440.             mail,
  441.             NULL,
  442.             NULL,
  443.             NULL,
  444.             NULL            
  445.         );
  446.     }
  447. }
  448. #endif 
  449.  
  450. void doaskquit( void )
  451. {
  452.     rtSetWaitPointer(w);
  453.     exit(0);
  454. }
  455.  
  456. LONG procmenu( USHORT code, ULONG quals )
  457. {
  458.     struct MenuItem *mit;
  459.     long itemnum = ITEMNUM( code );
  460.     long menunum = MENUNUM( code );
  461.     long subnum = SUBNUM( code );
  462.     UBYTE *rvp;
  463.     int rc;
  464.  
  465.     if(code==MENUNULL||itemnum==NOITEM) return(-1);
  466.     mit=ItemAddress(w->MenuStrip,code);
  467.     if(!mit) return(-1);
  468.     rvp=(UBYTE*)(((long)mit)+sizeof(struct MenuItem));
  469.  
  470.     if( ( !menunum ) && ( itemnum == 9 ) )
  471.     {
  472.         showguide( "main" );
  473.         return( -1 );
  474.     }
  475.  
  476.     if( *rvp )
  477.     {
  478.         return((LONG)(rvp[1]|((rvp[0]==0xff)?0x100:0)));
  479.     }
  480.     else if(!menunum) switch(itemnum)
  481.     {
  482.         case 0:
  483.         case 1:
  484.         case 2:
  485.         case 3:
  486.             lockwindow();
  487.             if( !dospool() )
  488.             {
  489.                 if( !donetcall( itemnum ) )
  490.                 {
  491.                     delspool();
  492.                     dosortin();
  493.                     didsortin = 1;
  494.                     sortbrettlist();
  495.                 }
  496.             }
  497.             else
  498.                 askreq( "Fehler beim Spoolen", "Abbruch" );
  499.             resetscroller();
  500.             unlockwindow();
  501.             break;
  502.         case 4: lockwindow(); sortinhand(); didsortin=1; sortbrettlist(); resetscroller(); unlockwindow();break;
  503.         case 6:
  504.             if( wbwindow )
  505.             {
  506.                 doterminal();
  507.                 resetscroller();
  508.             }
  509.             else
  510.             {
  511.                 lockwindow();
  512.                 doterminal();
  513.                 unlockwindow();
  514.             }
  515.             break;
  516.         /*case 4: lockwindow(); doanswermode(); unlockwindow(); break;*/
  517.         case 8: doinfo(); displayscroller(); break;
  518.         case 11: doiconify(); return( -1 );
  519.         case 12: selectpubscreen(); return( -1 );
  520.         case 14: doaskquit();
  521.                 break;
  522.     }
  523.     else if(menunum==3) switch(itemnum)
  524.     {
  525.         case 14:
  526.             switch( subnum )
  527.             {
  528.                 case 0: if(mit->Flags&CHECKED) prefs.flags|=MDF_SHOWREAL; else prefs.flags&=~MDF_SHOWREAL; break;
  529.                 case 1: if(mit->Flags&CHECKED) prefs.flags|=MDF_SHOWALL; else prefs.flags&=~MDF_SHOWALL; break;
  530.                 case 2: if(mit->Flags&CHECKED) prefs.flags|=MDF_SORTDATE; else prefs.flags&=~MDF_SORTDATE; break;
  531.                 case 3: if(mit->Flags&CHECKED) prefs.flags|=MDF_FILTERRE; else prefs.flags&=~MDF_FILTERRE; break;
  532.                 case 4: if(!(mit->Flags&CHECKED)) prefs.flags|=MDF_NOREADERSTYLES; else prefs.flags&=~MDF_NOREADERSTYLES; break;
  533.             }
  534.             break;
  535.  
  536.         case 22:
  537.             doscrollerclipboard();
  538.             break;
  539.     }
  540.     else if(menunum==4) switch( itemnum )
  541.     {
  542.         case 0: domapsadd( 0 ); makebrettview(); calcnumentries(); displayscroller(); break;
  543.         case 1: domapsadd( 1 ); break;
  544.  
  545.         case 2:
  546.             rc = askreq( "Ausfⁿhrliche Brettliste?", "Ausfⁿhrlich|_Kurz|Abbruch" );
  547.             if( rc )
  548.             {
  549.                 sendmapsreq( ( rc == 1 ) ? 1 : 0 );
  550.                 displayscroller();
  551.                 /*preport( 1,1, "Brettliste angefordert." );*/
  552.             }
  553.             break;
  554.         case  3: sendmapsreq( 2 ); displayscroller(); /*preport(1,1,"HILFE zu MAPS angefordert.");*/ break;
  555.         case  5: sendmapsreq( 3 ); displayscroller(); /*preport(1,1,"CLEARPM-Kommando verschickt.");*/ break;
  556.         case  7: sendmapsreq( 4 ); displayscroller(); break;
  557.         case 9: domailinglist();    displayscroller(); break;
  558.         case 10: dobugreport();    displayscroller(); break;
  559.         case 11: doregisterform(); displayscroller();    break;
  560.     }
  561.     else if(menunum==5) switch(itemnum)
  562.          {
  563.         case 0:
  564.             lockwindow();
  565.             dolanguagecfg();
  566.             unlockwindow();
  567.             break;
  568.  
  569.         case 2: lockwindow(); dopointcfg();        unlockwindow(); break;
  570.         case 3: lockwindow(); doserialcfg();    unlockwindow(); break;
  571.         case 4: lockwindow(); dosysopmodereq(); unlockwindow(); break;
  572.         case 5: lockwindow(); domapsprefs();     unlockwindow(); break;
  573.  
  574.         case 6: lockwindow(); donetcfg();        unlockwindow(); break;
  575.         case 7: lockwindow(); doulwin();         displayscroller(); unlockwindow(); break;
  576.         case 8: lockwindow(); douserkillwin();  unlockwindow(); break;
  577.  
  578.         case 10: lockwindow(); doexternprefs();  unlockwindow(); break;
  579.         case 11: if( isv37 )
  580.                 {
  581.                     dofontprefs();
  582.                 }
  583.                 else
  584.                 {
  585.                     dofontprefs13();
  586.                     /*if( mit->Flags & CHECKED )
  587.                         prefs.flags |= MDF_INTERLACE;
  588.                     else
  589.                         prefs.flags &= ~MDF_INTERLACE;
  590.                     closegui();
  591.                     opengui();*/
  592.                 }
  593.                 return( -1 );
  594.         
  595.         case 12: lockwindow(); dobed2prefs(); displayscroller(); unlockwindow(); break;
  596.         case 13: lockwindow(); dobedprefs(); unlockwindow(); setmenuescflag(); break;
  597.         case 14: lockwindow(); dobed3prefs(); unlockwindow(); setmenuescflag(); break;
  598.  
  599.         case 16: if( mit->Flags & CHECKED )
  600.                     prefs.flags |= MDF_PASSWORD;
  601.                  else
  602.                     prefs.flags &=~MDF_PASSWORD;
  603.                  break;
  604.  
  605.         case 17: lockwindow(); dochangepassword(); unlockwindow(); break;
  606.  
  607.     }
  608.     else if( menunum == 6 ) switch( itemnum )
  609.     {
  610.         case 0:
  611.             lockwindow();
  612.             pgp_prefs();
  613.             unlockwindow();
  614.             break;
  615.         case 1:
  616.             lockwindow();
  617.             pgp_setpassphrase();
  618.             unlockwindow();
  619.             break;
  620.         case 2:
  621.             lockwindow();
  622.             pgp_changepassphrase();
  623.             unlockwindow();
  624.             break;
  625.         case 3:
  626.             lockwindow();
  627.             pgp_rereadownkey();
  628.             unlockwindow();
  629.             break;
  630.         case 5:
  631.             lockwindow();
  632.             pgp_procincoming();
  633.             unlockwindow();
  634.             break;
  635.         case 6:
  636.             lockwindow();
  637.             pgp_showkeys( FALSE );
  638.             unlockwindow();
  639.             break;
  640.         case 7:
  641.             lockwindow();
  642.             pgp_showkeys( TRUE );
  643.             unlockwindow();
  644.             break;
  645.         case 8:
  646.             lockwindow();
  647.             pgp_checkkeys();
  648.             unlockwindow();
  649.             break;
  650.     }
  651.     else if( menunum == 7 ) switch( itemnum )
  652.     {
  653.         case 0:
  654.             lockwindow();
  655.             dorexxshell();
  656.             unlockwindow();
  657.             break;
  658.  
  659.         case 2:
  660.             dorexxcmd( 0, subnum );
  661.             break;
  662.  
  663.         case 3:
  664.             dorexxcmd( 1, subnum );
  665.             break;
  666.  
  667.         case 4:
  668.             dorexxcmd( 2, subnum );
  669.             break;
  670.  
  671.     }
  672.     return( -1 );
  673.     //return( procmenu( mit->NextSelect, quals ) );
  674. }
  675.  
  676. static ULONG brettcount,newmailcount,mailcount,markcount,unreadcount;
  677. void calcbcount(void)
  678. {
  679.     struct mbrett *n=(struct mbrett*)brettlist.lh_Head;
  680.  
  681.     brettcount=newmailcount=mailcount=markcount=unreadcount=0;
  682.  
  683.     while(n->n.ln_Succ)
  684.     {
  685.         brettcount++;
  686.         newmailcount += n->b.newmails;
  687.         mailcount += n->b.mails;
  688.         unreadcount += n->b.unreadmails;
  689.         if( n->n.ln_Type )
  690.             markcount++;
  691.         n = ( struct mbrett * ) n->n.ln_Succ;
  692.     }
  693.  
  694.     preport(0,1,(markcount)?"BRETTAUSWAHL: Insgesamt %lD Brett%s, %lD markiert":"BRETTAUSWAHL: Insgesamt %lD Brett%s",brettcount,(brettcount==1)?"":"er",markcount);
  695.     preport(1,1,"Insgesamt %lD Nachrichten, %lD neue, %lD ungelesene",mailcount,newmailcount,unreadcount);
  696.  
  697.     /* nur wenn markiert... */
  698.     if( markcount )
  699.         OnMenu( w, SHIFTITEM( 2 ) | SHIFTMENU( 1 ) );
  700.     else
  701.         OffMenu( w, SHIFTITEM( 2 ) | SHIFTMENU( 1 ) );
  702. }
  703.  
  704. static void strcatnum(char *string,long num)
  705. {
  706.     asprintf( string, "_%ld", num );
  707. }
  708.  
  709. void domenuhelp(char *menu,struct IntuiMessage *im)
  710. {
  711.     char buff[80];
  712.  
  713.     sprintf(buff,"menu_%s",menu);
  714.  
  715.     if(MENUNUM(im->Code)!=NOMENU && ITEMNUM(im->Code)!=NOITEM)
  716.     {
  717.         strcatnum(buff,MENUNUM(im->Code));
  718.         strcatnum(buff,ITEMNUM(im->Code));
  719.     }
  720.     if(SUBNUM(im->Code)!=NOSUB) strcatnum(buff,SUBNUM(im->Code));
  721.  
  722.     showguide(buff);
  723.  
  724. }
  725.  
  726. static void dodelback( char *path )
  727. {
  728.     char buff[ 256 ];
  729.     char *p;
  730.  
  731.     strcpy( buff, path );
  732.  
  733.     while( ( p = strrchr( buff, '/' ) ) )
  734.     {
  735.         *p = 0;
  736.         if( !DeleteFile( buff ) )
  737.             break;
  738.     }
  739. }
  740.  
  741. static void removeallmails( struct mbrett *mb )
  742. {
  743.     struct mindex *mix = loadbrettixquiet( mb );
  744.     struct mmail *mm, *next;
  745.  
  746.     if( mix )
  747.     {
  748.         mm = ( struct mmail * ) mix->maillist.lh_Head;
  749.         while( ( next = ( struct mmail * ) mm->n.mln_Succ ) )
  750.         {
  751.             if( !( mm->m.flags & MMF_ARCHIVE ) )
  752.             {
  753.                 Remove( mm );
  754.                 mix->changed = 1;
  755.             }
  756.             mm = next;
  757.         }
  758.         savebrettix( mix, mb );
  759.         freebrettix( mix );
  760.         calcmcount_mb( mix, mb );
  761.     }
  762. }
  763.  
  764. static void dodelbrett( struct mbrett *mbrett, int mode )
  765. {
  766.     char tmp[ 256 ];
  767.  
  768.     if( mode && ( !stricmp( mbrett->b.name, prefs.username ) || 
  769.                     !stricmp( mbrett->b.name, "/╗Archiv" ) ||
  770.                     !stricmp( mbrett->b.name, "/╗Protokoll" ) ||
  771.                     !stricmp( mbrett->b.name, "/╗Spool" ) ) )
  772.  
  773.     {
  774.         askreq( "Brett '%s' darf\nnicht gel÷scht werden", "Abbruch", mbrett->b.name );
  775.         return;
  776.     }
  777.  
  778.  
  779.     if( mode )
  780.     {
  781.         brettpfad( tmp, mbrett );
  782.         closeixfile( mbrett );
  783.         flushbrettix();
  784.         if( strlen( mbrett->b.name ) > 1 )
  785.         {
  786.             delpathcontents( tmp, 0, 0 );
  787.             dodelback( tmp );
  788.         }
  789.         Remove( mbrett );
  790.     }
  791.     else
  792.     {
  793.         removeallmails( mbrett );
  794.  
  795.         /*
  796.         delpathcontents( tmp, ".Brettinfo", ".Origin" );
  797.         mbrett->b.mails = mbrett->b.newmails = mbrett->b.unreadmails = 0;*/
  798.         /*mbrett->nextfreemsg = 0;*/
  799.     }
  800. }
  801.  
  802. static void procmapsmsg( char **msgbufp, int mode );
  803. static void dodelbretter( struct IntuiMessage *im )
  804. {
  805.     int dorem=ISSHIFT(im);
  806.     struct mbrett *mbrett,*n;
  807.     int rc;
  808.     char *delmsg=0;
  809.  
  810.     calcbcount();
  811.     if(!markcount)
  812.     {
  813.         mbrett=(struct mbrett*)GetEntry(&brettlist,getscrollercurrent());
  814.         if(!mbrett) return;
  815.         rc=askreq("%sBrett '%s' l÷schen?",dorem?"L÷schen|L÷_schen & Abbestellen|Nur Abbes_tellen|Abbruch":"L÷schen|Abbruch",(dorem)?"":"Inhalt von ",mbrett->b.name);
  816.         if(!rc) return;
  817.         lockwindow();
  818.         if( rc >= 2)
  819.             delmsg = myAllocVec( 1024, 0 );
  820.         if( rc <= 2 )
  821.             dodelbrett( mbrett, dorem );
  822.         if(delmsg)
  823.         {
  824.             sprintf( delmsg, "%s%s%s\n", prefs.maps_msgprefix, prefs.maps_delprefix, ISRFC ? &mbrett->b.name[á1 ]á: mbrett->b.name );
  825.             procmapsmsg( &delmsg, TRUE );
  826.             sendshortmail(prefs.mapsname,prefs.maps_del,delmsg,0,0,0,1);
  827.             myFreeVec( delmsg );
  828.         }
  829.         unlockwindow();
  830.     }
  831.     else
  832.     {
  833.         rc=askreq("%s%lD Bretter%s l÷schen?",dorem?"L÷schen|L÷_schen & Abbestellen|Nur Abbes_tellen|Abbruch":"L÷schen|Abbruch",(dorem)?"":"Inhalt von ",markcount,(dorem)?"":"n");
  834.         if(!rc) return;
  835.         lockwindow();
  836.         if( rc>=2 )
  837.             delmsg = myAllocVec( markcount * 128 + 512, 0 );
  838.         if( delmsg )
  839.         {
  840.             strcpy( delmsg, prefs.maps_msgprefix );
  841.         }
  842.         mbrett=(struct mbrett*)brettlist.lh_Head;
  843.         while(n=(struct mbrett*)mbrett->n.ln_Succ)
  844.         {
  845.             if(mbrett->n.ln_Type)
  846.             {
  847.                 if( delmsg )
  848.                     asprintf( delmsg, "%s%s\n", prefs.maps_delprefix, ISRFC ? &mbrett->b.name[á1 ]á: mbrett->b.name );
  849.                 if( rc <= 2 )
  850.                     dodelbrett( mbrett, dorem );
  851.             }
  852.             mbrett->n.ln_Type = 0;
  853.             mbrett = n;
  854.         }
  855.         if( delmsg )
  856.         {
  857.             if( delmsg[ 0 ] )
  858.             {
  859.                 procmapsmsg( &delmsg, TRUE );
  860.                 sendshortmail( prefs.mapsname, prefs.maps_del, delmsg, 0, 0, 0, 1 );
  861.             }
  862.             myFreeVec( delmsg );
  863.         }
  864.         unlockwindow();
  865.     }
  866.     makebrettview();
  867.     resetscroller();
  868. }
  869.  
  870. void brettpfad(char *path,struct mbrett *mb)
  871. {
  872.     char *p;
  873.  
  874.     strcpy(path,prefs.datadir);
  875.     p=mb->b.name;
  876.  
  877.     if(p[0]=='/') p++;
  878.     if(p[0]=='╗') p++;
  879.     addpart(path,p);
  880. }
  881.  
  882. /*void brettpfadfile(char *path,struct mbrett *mb,int num)
  883. {
  884.     char *p;
  885.     char nb[16];
  886.  
  887.     sprintf(nb,"%ld",num);
  888.  
  889.     strcpy(path,prefs.datadir);
  890.     p=mb->b.name;
  891.  
  892.     if(p[0]=='/') p++;
  893.     if(p[0]=='╗') p++;
  894.     addpart(path,p);
  895.     checkpath(path);
  896.     addpart(path,nb);
  897. }*/
  898.  
  899.  
  900. static void doeditbrett(struct mbrett *mb)
  901. {
  902.     char path[256];
  903.     int rc;
  904.     long wasnotthere;
  905.  
  906.     brettpfad(path,mb);
  907.     addpart(path,".origin");
  908.     DeleteFile("T:mdtemp.origin");
  909.     wasnotthere=copyfile(path,"T:mdtemp.origin");
  910.     rc=dobrettprefs(mb,0,"Brettparameter Σndern...");
  911.     if(rc) {
  912.         brettpfad(path,mb);
  913.         checkpath(path);
  914.         addpart(path,".origin");
  915.         DeleteFile(path);
  916.         copyfile("T:mdtemp.origin",path);
  917.     }
  918.     DeleteFile("T:mdtemp.origin");
  919. }
  920.  
  921.  
  922. static void doeditbretter(void)
  923. {
  924.     struct mbrett *mbrett,*n;
  925.     struct brett cmpbrett;
  926.     struct brettinfo cmpbi;
  927.  
  928.     calcbcount();
  929.     if( !markcount )
  930.     {
  931.         mbrett=(struct mbrett*)GetEntry(&brettlist,getscrollercurrent());
  932.         doeditbrett(mbrett);
  933.     }
  934.     else
  935.     {
  936.         memset( &cmpbrett, 0, sizeof( cmpbrett ) );
  937.         memset( &cmpbi, 0, sizeof( cmpbi ) );
  938.         if( !dobrettwildreq( &cmpbrett, &cmpbi, markcount ) )
  939.             return;
  940.         mbrett=(struct mbrett*)brettlist.lh_Head;
  941.         while(n=(struct mbrett*)mbrett->n.ln_Succ)
  942.         {
  943.             /* Brett Σndern? */
  944.             if(mbrett->n.ln_Type)
  945.             {
  946.                 mbrett->n.ln_Type=0;
  947.  
  948.                 if( cmpbrett.betreff[0]á)
  949.                     strcpy( mbrett->b.betreff, cmpbrett.betreff );
  950.  
  951.                 if( cmpbrett.days )
  952.                     mbrett->b.days = cmpbrett.days;
  953.  
  954.                 if( cmpbrett.language )
  955.                     mbrett->b.language = cmpbrett.language - 1;
  956.  
  957.                 if( cmpbrett.mails )
  958.                 {
  959.                     if( cmpbrett.flags & BFLAG_NOCRUNCH )
  960.                         mbrett->b.flags |= BFLAG_NOCRUNCH;
  961.                     else
  962.                         mbrett->b.flags &= ~BFLAG_NOCRUNCH;
  963.                 }
  964.  
  965.                 if( cmpbi.autoexpfad[0]á)
  966.                 {
  967.                     struct brettinfo *bi = getbrettinfo( mbrett );
  968.  
  969.                     strcpy( bi->autoexpfad, cmpbi.autoexpfad );
  970.                     setbrettinfo( mbrett, bi );
  971.                 }
  972.  
  973.             }
  974.             mbrett=n;
  975.         }
  976.     }
  977. }
  978.  
  979. static void donewbrett( int pm )
  980. {
  981.     struct mbrett mb, *new;
  982.     long rc;
  983.     BPTR testlock;
  984.  
  985.     memset(&mb,0,sizeof(struct mbrett));
  986.     if( pm )
  987.         mb.b.flags = BFLAG_EXTEND_PM;
  988.     mb.b.days = 14;
  989.  
  990.     DeleteFile( "T:mdtemp.origin" );
  991.     rc = dobrettprefs( &mb, TRUE, pm ? "Neues PM-Brett... " : "Neues Brett..." );
  992.  
  993.     if(rc)
  994.     {
  995.         if( pm )
  996.         {
  997.             mb.b.name[á78 - strlen( prefs.username ) ]á= 0;
  998.             strins( mb.b.name, prefs.username );
  999.             mb.b.flags |= BFLAG_EXTEND_PM;
  1000.         }
  1001.  
  1002.         new = LibAllocPooled( brettmempool, sizeof( struct mbrett ) );
  1003.         *new = mb;
  1004.  
  1005.         AddTail( &brettlist, new );
  1006.         calcbrettnamecrc( new );
  1007.  
  1008.         testlock = Lock( "T:mdtemp.origin", SHARED_LOCK );
  1009.         if( testlock )
  1010.         {
  1011.             char path[ 256 ];
  1012.  
  1013.             UnLock( testlock );
  1014.             brettpfad( path, new );
  1015.             checkpath( path );
  1016.             addpart( path, ".origin" );
  1017.             copyfile( "T:mdtemp.origin", path );
  1018.             DeleteFile( "T:mdtemp.origin" );
  1019.         }
  1020.         sortbrettlist();
  1021.         updateprop();
  1022.         displayscroller();
  1023.     }
  1024. }
  1025.  
  1026. static void domsg( int firstnew )
  1027. {
  1028.     struct mbrett *mb=(struct mbrett*)GetEntry(&brettlist,getscrollercurrent());
  1029.  
  1030.     if(mb)
  1031.     {
  1032.         rtSetWaitPointer( w );
  1033.         execrexx( "Board" );
  1034.         doinhalt( mb, firstnew );
  1035.     }
  1036. }
  1037.  
  1038. static void markall( void )
  1039. {
  1040.     struct mbrett *mbrett=(struct mbrett*)brettlist.lh_Head;
  1041.     int c = 0;
  1042.  
  1043.     while( mbrett->n.ln_Succ )
  1044.     {
  1045.         if( ++c > 4 )
  1046.             mbrett->n.ln_Type = 0xff;
  1047.         mbrett = (struct mbrett *) mbrett->n.ln_Succ;
  1048.     }
  1049. }
  1050.  
  1051. static void markbyname( void )
  1052. {
  1053.     struct mbrett *mbrett=(struct mbrett*)brettlist.lh_Head;
  1054.     struct mbrett *curr = ( struct mbrett * ) GetEntry( &brettlist, getscrollercurrent() );
  1055.     char match[á80 ], matchpat[á88 ];
  1056.     int rc;
  1057.  
  1058.     if( curr )
  1059.         strcpy( match, curr->b.name );
  1060.     else
  1061.         match[ 0 ]á= 0;    
  1062.  
  1063.     rc = rtGetString( match, 79, NULL, rinfo,
  1064.         RTGS_TextFmt, "Markieren nach Brettnamen\nMuster:",
  1065.         RTGS_Flags, GSREQF_CENTERTEXT,
  1066.         TAG_DONE
  1067.     );
  1068.  
  1069.     if( rc != TRUE )
  1070.         return;
  1071.  
  1072.     expandpattern( match, matchpat );
  1073.  
  1074.     while( mbrett->n.ln_Succ )
  1075.     {
  1076.         if( astcsma( mbrett->b.name, matchpat ) )
  1077.             mbrett->n.ln_Type = 0xff;
  1078.         mbrett = (struct mbrett *) mbrett->n.ln_Succ;
  1079.     }
  1080. }
  1081.  
  1082.  
  1083. void showguidegads( struct IntuiMessage *im, char *defguide )
  1084. {
  1085.     if( ( prefs.flags & MDF_GADGETS ) && ( im->MouseY >= gyoffs ) )
  1086.     {
  1087.         showguide( "fontprefs_16" );
  1088.     }
  1089.     else
  1090.     {
  1091.         showguide( defguide );
  1092.     }
  1093. }
  1094.  
  1095. // Datenbank scannen...
  1096.  
  1097. static void calcdbstatus( void )
  1098. {
  1099.     struct pindex *pixtab, *pix;
  1100.     ULONG dbfilecount = 0;
  1101.     ULONG dbfilemin = MAXINT, dbfilemax = 0;
  1102.     ULONG dbfileaccu = 0, dbfileixaccu = 0;
  1103.     ULONG dbfileixused = 0;
  1104.     ULONG dbmailcountused = 0;
  1105.     ULONG dbmailcountpack = 0, dbmailcountxpk = 0;
  1106.     struct FileInfoBlock *fib;
  1107.     BPTR lock, f;
  1108.     int cdblen, mc;
  1109.     char name[á64 ];
  1110.     int c;
  1111.  
  1112.     ixc_flush();
  1113.     closeallixfiles();
  1114.     sortbrettlist();
  1115.     fib = allocfib();
  1116.  
  1117.     // Zuerst Puffer scannen
  1118.  
  1119.     pushdir( prefs.datadir );
  1120.     lock = Lock( "", SHARED_LOCK );
  1121.     Examine( lock, fib );
  1122.  
  1123.     while( ExNext( lock, fib ) )
  1124.     {
  1125.         if( !astcsma( fib->fib_FileName, "MD_#?.Index" ) )
  1126.             continue;
  1127.  
  1128.         dbfilecount++;
  1129.         dbfileixaccu += fib->fib_Size;
  1130.  
  1131.         if( fib->fib_Size < sizeof( struct pindex ) )
  1132.             continue;
  1133.  
  1134.         pixtab = myAllocVec( fib->fib_Size, 0 );
  1135.         if( !pixtab )
  1136.             continue;
  1137.         f = Open( fib->fib_FileName, MODE_OLDFILE );
  1138.         if( !f )
  1139.         {
  1140.             myFreeVec( pixtab );
  1141.             continue;
  1142.         }
  1143.         Read( f, pixtab, fib->fib_Size );
  1144.         Close( f );
  1145.  
  1146.         mc = fib->fib_Size / sizeof( struct pindex );
  1147.  
  1148.         strcpy( name, fib->fib_FileName );
  1149.         strcpy( strrchr( name, '.' ), ".Data" );
  1150.         cdblen = getfilelen( name );
  1151.  
  1152.         if( cdblen >= 0 )
  1153.         {
  1154.             dbfileaccu += cdblen;
  1155.             if( cdblen < dbfilemin )
  1156.                 dbfilemin = cdblen;
  1157.             if( cdblen > dbfilemax )
  1158.                 dbfilemax = cdblen;
  1159.  
  1160.             for( c = 0, pix = pixtab; c < mc; c++, pix++ )
  1161.             {
  1162.                 if( ! ( pix->flags & PIF_KILLED ) )
  1163.                 {
  1164.                     dbfileixused += sizeof( struct pindex );
  1165.                     dbmailcountused++;
  1166.                     if( pix->flags & PIF_PACKED )
  1167.                     {
  1168.                         if( pix->flags & PIF_XPK )
  1169.                             dbmailcountxpk++;
  1170.                         else
  1171.                             dbmailcountpack++;
  1172.                     }
  1173.                 }
  1174.             }
  1175.         }
  1176.         myFreeVec( pixtab );
  1177.  
  1178.     }
  1179.     freefib( fib );
  1180.     UnLock( lock );
  1181.     popdir();
  1182.  
  1183.     if( !dbfilecount || !dbfileaccu )
  1184.     {
  1185.         askreq( "Keine Daten vorhanden.", "Ok" );
  1186.         return;
  1187.     }
  1188.  
  1189.     askreq( 
  1190. "Datenbank-Status:\n\n"
  1191. "%lD Nachrichten insgesamt, %lD Referenzen (%ld.%ld%%).\n"
  1192. "%lD Nachrichten (%ld.%ld%%) intern, %lD (%ld.%ld%%) mit XPK gepackt.\n\n"
  1193. "Datenbank besteht aus %lD Dateien mit insgesamt %lD Bytes.\n"
  1194. "Gr÷▀te Datei %lD Bytes, Kleinste %lD Bytes, ° %lD Bytes.\n\n"
  1195. "%lD Bytes Index, davon %lD benutzt (%ld.%ld%%)."
  1196. "%s%s",
  1197.         "Ok",
  1198.         dbmailcountused, mailcount, ( mailcount * 100 ) / dbmailcountused, ( ( mailcount * 1000 ) / dbmailcountused ) % 10, 
  1199.         dbmailcountpack, ( dbmailcountpack * 100 ) / dbmailcountused, ( ( dbmailcountpack * 1000 ) / dbmailcountused ) % 10,
  1200.         dbmailcountxpk, ( dbmailcountxpk * 100 ) / dbmailcountused, ( ( dbmailcountxpk * 1000 ) / dbmailcountused ) % 10,
  1201.  
  1202.         dbfilecount, dbfileaccu,
  1203.         dbfilemax, dbfilemin, dbfileaccu / dbfilecount,
  1204.         dbfileixaccu, dbfileixused, ( dbfileixused * 100 ) / dbfileixaccu, ( ( dbfileixused * 1000 ) / dbfileixaccu ) % 10,
  1205.         ( mailcount < ( dbmailcountused / 2 ) ) ? "\n\nSie sollten die Datenbank reorganisieren!" : "",
  1206.         ( ( dbfileaccu / dbfilecount ) < 65536 ) ? "\n\nSie sollten beim nΣchsten Reorganisieren\ndie Funktionen \"Zusammenfassen kleiner Files\" verwenden!" : ""
  1207.     );
  1208. }
  1209.  
  1210.  
  1211. /* Weiterschalten? */
  1212. extern int donextnewboard;
  1213.  
  1214. extern int scrollerenter;
  1215. void dobretter( void )
  1216. {
  1217.     struct IntuiMessage *mp,im;
  1218.     long rc;
  1219.     int oldflags;
  1220.     struct AppMessage *am;
  1221.     ULONG sig;
  1222.     int oldshowboardtree = prefs.showboardtree;
  1223.  
  1224.     if( donextnewboard )
  1225.     {
  1226.         struct mbrett *m;
  1227.         int nn = donextnewboard;
  1228.  
  1229.         rc = lastbrettcs & 0xffff;
  1230.         if( rc >= 0 && rc <= 2 )
  1231.             rc = 3;
  1232.         m =(struct mbrett*)GetEntry(&brettlist, rc + 1 );
  1233.  
  1234.         donextnewboard = FALSE;
  1235.  
  1236.         if( !m )
  1237.             m = ( struct mbrett * ) brettlist.lh_Head;
  1238.  
  1239.         while( m->n.ln_Succ )
  1240.         {
  1241.             if( m->b.newmails )
  1242.             {
  1243.                 /*setscrollercurrent(GetEntryNum(&brettlist,m));
  1244.                 showcurrentitem();
  1245.                 lastbrettcs = getscrollerstate();*/
  1246.                 lastbrettcs = GetEntryNum( &brettlist, m );
  1247.                 setscrollercurrent_internal( lastbrettcs );
  1248.                 if( lastbrettcs > 3 )
  1249.                     lastbrettcs |= ( ( lastbrettcs - 3 ) << 16 );
  1250.                 domsg( nn );
  1251.                 return;
  1252.             }
  1253.             m=(struct mbrett*)m->n.ln_Succ;
  1254.         }
  1255.         displaybeep();
  1256.     }
  1257.  
  1258.     //setupscroller( &brettlist, 0 );
  1259.     setupscroller( &brettlist, checkprogramval );
  1260.     setscrollerstate( lastbrettcs );
  1261.  
  1262.     /* Menus umschalten */
  1263.     OnMenu( w, SHIFTMENU( 1 ) | SHIFTITEM( NOITEM ) );
  1264.     OffMenu( w, SHIFTMENU( 2 ) | SHIFTITEM( NOITEM ) );
  1265.     OffMenu( w, SHIFTMENU( 3 ) | SHIFTITEM( NOITEM ) );
  1266.  
  1267.     if( rexxsig )
  1268.     {
  1269.         OnMenu( w, FULLMENUNUM( 7, 3, NOSUB ) );
  1270.         OffMenu( w, FULLMENUNUM( 7, 4, NOSUB  ) );
  1271.     }
  1272.  
  1273.     calcbcount();
  1274.  
  1275.     oldflags = prefs.flags & MDF_GADGETS;
  1276.  
  1277.     dorexx( 0 );
  1278.  
  1279.     ClearPointer(w);
  1280.  
  1281.     for(;;)
  1282.     {
  1283.         if( scrollerenter )
  1284.         {
  1285.             scrollerenter = FALSE;
  1286.             domsg( FALSE );
  1287.             return;
  1288.         }
  1289.  
  1290.         if( !( mp = (struct IntuiMessage *) GetMsg( w->UserPort ) ) )
  1291.         {
  1292.             sig = mWait( appwindowsig | ( 1 << w->UserPort->mp_SigBit ) | rexxsig );
  1293.  
  1294.             if( sig & appwindowsig )
  1295.             {
  1296.                 while( ( am = ( struct AppMessage *) GetMsg( appwindowmp ) ) )
  1297.                 {
  1298.                     if( am->am_NumArgs )
  1299.                     {
  1300.                         char name[ 256 ];
  1301.                         struct WBArg *wba = am->am_ArgList;
  1302.  
  1303.                         NameFromLock( wba->wa_Lock, name, 255 );
  1304.                         AddPart( name, wba->wa_Name, 255 );
  1305.                     
  1306.                         lockwindow();
  1307.                         DeleteFile(TMPMSGNAME);
  1308.                         dosendwin("Neue Nachricht verschicken...","","",NULL,NULL, 2, 0,0,0,0,NULL, name, NULL, NULL );
  1309.                         calcbcount();
  1310.                         displayscroller();
  1311.                         unlockwindow();
  1312.                     }
  1313.                     ReplyMsg( am );
  1314.                 }
  1315.             }
  1316.  
  1317.             if( rexxsig && ( sig & rexxsig ) )
  1318.                 dorexx( 0 );
  1319.  
  1320.             continue;
  1321.         }
  1322.         im = *mp;
  1323.         ReplyMsg( mp );
  1324.  
  1325.         switch(im.Class)
  1326.         {
  1327.             case IDCMP_REFRESHWINDOW:
  1328.                 BeginRefresh( w );
  1329.                 displayscroller();
  1330.                 EndRefresh( w, TRUE );
  1331.                 break;
  1332.  
  1333.             case IDCMP_CLOSEWINDOW:
  1334.                 doaskquit();
  1335.                 break;
  1336.  
  1337.             case IDCMP_NEWSIZE:
  1338.                 scrollerresize();
  1339.                 break;
  1340.  
  1341.             case MOUSEBUTTONS:
  1342.                 rc = scrollerdoclick(&im);
  1343.                 if( rc == 1 )
  1344.                 {
  1345.                     lastbrettcs = getscrollerstate();
  1346.                     domsg( FALSE );
  1347.                     return;
  1348.                 }
  1349.                 else if( rc == -2 )
  1350.                 {
  1351.                     im.Class        = RAWKEY;
  1352.                     im.Code         = 0x36;
  1353.                     im.Qualifier     = 0;
  1354.                     goto rawkey;
  1355.                 }
  1356.                 calcbcount();
  1357.                 break;
  1358.             case MOUSEMOVE:
  1359.                 scrollerdomove(&im);
  1360.                 break;
  1361.             case GADGETDOWN:
  1362.                 scrollerdogad(&im);
  1363.                 break;
  1364.  
  1365.             case GADGETUP:
  1366.                 rc = scrollerdogad( &im );
  1367.                 if( !rc )
  1368.                     break;
  1369.                 im.Class     = RAWKEY;
  1370.                 im.Code      = rc & 0xff;
  1371.                 im.Qualifier = ( rc & 0x100 ) ? QSHIFT : 0;
  1372.                 goto rawkey;
  1373.             case MENUPICK:
  1374.                 rc = procmenu( im.Code, im.Qualifier );
  1375.                 if( ( prefs.showboardtree != oldshowboardtree ) || ( oldflags != ( prefs.flags & MDF_GADGETS ) ) )
  1376.                 {
  1377.                     if( prefs.showboardtree != oldshowboardtree )
  1378.                         makebrettview();
  1379.                     rtSetWaitPointer( w );
  1380.                     return;
  1381.                 }
  1382.                 if( rc < 0 )
  1383.                 {
  1384.                     calcbcount();
  1385.                     break;
  1386.                 }
  1387.                 im.Code      = rc & 0xff;
  1388.                 im.Qualifier = ( rc & 0x100 ) ? IEQUALIFIER_LSHIFT : 0;
  1389. rawkey:
  1390.                     /* fallthrough */
  1391.             case RAWKEY:
  1392.                     rc = scrollerdokey( &im );
  1393.                     if( rc == 1 )
  1394.                         calcbcount();
  1395.                     else if( rc )
  1396.                       switch(im.Code)
  1397.                      {
  1398.                     case 0x5f:
  1399.                         showguidegads( &im, "brettauswahl" );
  1400.                         break;
  1401.  
  1402.                     case 0x18:    /* Brettindex wiederherstellen */
  1403.                         if( ISSHIFT( &im ) )
  1404.                         {
  1405.                             lockwindow();
  1406.                             restoremindex( (struct mbrett*) GetEntry( &brettlist, getscrollercurrent() ) );
  1407.                             displayscroller();
  1408.                             unlockwindow();
  1409.                         }
  1410.                         break;
  1411.  
  1412.                     case 0x43: 
  1413.                     case 0x44: lastbrettcs=getscrollerstate(); domsg( FALSE ); return;
  1414.  
  1415.                     case 0x19:  lockwindow();
  1416.                                 if( ISSHIFT( &im ) )
  1417.                                 {
  1418.                                     donewbrett( TRUE );
  1419.                                 }
  1420.                                 else
  1421.                                 {
  1422.                                     doeditbretter();
  1423.                                     displayscroller();
  1424.                                 }
  1425.                                 calcbcount();
  1426.                                 unlockwindow();
  1427.                                 break;
  1428.  
  1429.                     case 0x17:     lockwindow();
  1430.                                 if( ISSHIFT( &im ) )
  1431.                                     doreorg();
  1432.                                 else
  1433.                                     setallold();
  1434.                                 displayscroller();
  1435.                                 calcbcount();
  1436.                                 unlockwindow();
  1437.                                 break;
  1438.  
  1439.                     case 0x21:  // Datenbank-Status
  1440.                         lockwindow();
  1441.                         calcdbstatus();
  1442.                         unlockwindow();
  1443.                         break;
  1444.  
  1445.                     case 0x5e: /* zehner-tastatur + */
  1446.                     case 0x36: if(ISSHIFT(&im)) { lockwindow(); donewbrett( FALSE ); calcbcount(); unlockwindow(); break; }
  1447.                         else {
  1448.                             struct mbrett *m=(struct mbrett*)GetEntry(&brettlist,getscrollercurrent());
  1449.                             if(!m) m=(struct mbrett*)brettlist.lh_Head;
  1450.                             while(m->n.ln_Succ)
  1451.                             {
  1452.                                 if(m->b.newmails)
  1453.                                 {
  1454.                                     setscrollercurrent(GetEntryNum(&brettlist,m));
  1455.                                     showcurrentitem();
  1456.                                     lastbrettcs=getscrollerstate();
  1457.                                     domsg( TRUE );
  1458.                                     return;
  1459.                                 }
  1460.                                 m=(struct mbrett*)m->n.ln_Succ;
  1461.                             }
  1462.                             displaybeep();
  1463.                         }
  1464.                         break;
  1465.                             
  1466.                     case 0x46:
  1467.                         dodelbretter( &im );
  1468.                         if( getscrollercurrent() >= GetNumEntries( &brettlist ) )
  1469.                         {
  1470.                             setscrollercurrent( GetNumEntries( &brettlist ) - 1 );
  1471.                         }
  1472.                         findtopnode();
  1473.                         calcnumentries();
  1474.                         calcbcount();
  1475.                         showcurrentitem();
  1476.                         updateprop();
  1477.                         displayscroller();
  1478.                         break;
  1479.  
  1480.                     case 0x12:
  1481.                             lockwindow();
  1482.                             DeleteFile(TMPMSGNAME);
  1483.                             {
  1484.                                 FILE *f = fopen( TMPMSGNAME, "w" );
  1485.                                 if( f )
  1486.                                 {
  1487.                                     fprintf( f, "\n\n\n\n" );
  1488.                                     doorigin( f, 0, NULL );
  1489.                                     fclose( f );
  1490.                                 }
  1491.                             }
  1492.                             dosendwin( "Neue Nachricht verschicken...", "", "", NULL, NULL, 0, 0,0,0,0,NULL, NULL, NULL, NULL );
  1493.                             calcbcount();
  1494.                             displayscroller();
  1495.                             unlockwindow();
  1496.                             break;
  1497.  
  1498.                     case 0x37:
  1499.                                 if( ISSHIFT( &im ) )
  1500.                                     markall();
  1501.                                 else
  1502.                                     markbyname();
  1503.                                 calcbcount();
  1504.                                 displayscroller();
  1505.                                 break;
  1506.  
  1507.                     case 0x4a:
  1508.                     case 0x20: lockwindow(); docrunch((ISSHIFT(&im))?0:(struct mbrett*)GetEntry(&brettlist,getscrollercurrent()));
  1509.                             calcbcount(); displayscroller(); unlockwindow(); break;
  1510.  
  1511.                     case 0x27: lockwindow(); docrunchkillfile(); unlockwindow(); break;
  1512.  
  1513.  
  1514.                     case 0x50:
  1515.                     case 0x51:
  1516.                     case 0x52:
  1517.                     case 0x53:
  1518.                     case 0x54:
  1519.                         dorexxcmd( 0, ( im.Code - 0x50 ) + ( ISSHIFT( &im ) ? 5 : 0 ) );
  1520.                         break;
  1521.  
  1522.                     case 0x55:
  1523.                     case 0x56:
  1524.                     case 0x57:
  1525.                     case 0x58:
  1526.                     case 0x59:
  1527.                         dorexxcmd( 1, ( im.Code - 0x55 ) + ( ISSHIFT( &im ) ? 5 : 0 ) );
  1528.                         break;
  1529.  
  1530.                      }
  1531.                      break;
  1532.  
  1533.             case IDCMP_MENUHELP:
  1534.                 domenuhelp("brett",&im);
  1535.                 break;
  1536.         }
  1537.  
  1538.         if( didsortin )
  1539.         {
  1540.             updateprop();
  1541.             displayscroller();
  1542.             didsortin = 0;
  1543.         }
  1544.     }
  1545. }
  1546.  
  1547. static ULONG addbrett(char *name,char *betreff)
  1548. {
  1549.     struct mbrett *new = LibAllocPooled( brettmempool, sizeof( struct mbrett ) );
  1550.  
  1551.     if( !new )
  1552.         return( 0 );
  1553.     strcpy( new->b.name, name );
  1554.     strcpy( new->b.betreff, betreff );
  1555.     new->n.ln_Name = new->b.name;
  1556.     new->b.days = 14;
  1557.     calcbrettnamecrc( new );
  1558.  
  1559.     AddTail( &brettlist, new );
  1560.  
  1561.     return(-1);
  1562. }
  1563.  
  1564. static void newinit(void)
  1565. {
  1566.     struct mbrett *mapsbrett;
  1567.     struct brettinfo bi = { "", "", "MAPS", "ABS", "MAPS" };
  1568.     char buffer[á80 ];
  1569.  
  1570.     NewList( &brettlist );
  1571.     addbrett( prefs.username, "Pers÷nliche Nachrichten" );
  1572.     addbrett( "/╗SPOOL", "Ausgehende Nachrichten");
  1573.     addbrett( "/╗PROTOKOLL", "Netcall-Protokolle");
  1574.     addbrett( "/╗ARCHIV", "Archivierte Nachrichten");
  1575.  
  1576.     strcpy( buffer, prefs.username );
  1577.     strcat( buffer, "/MAPS" );
  1578.     addbrett( buffer, "MAPS-Nachrichten" );
  1579.  
  1580.     mapsbrett = ( struct mbrett * ) GetEntry( &brettlist, 4 );
  1581.     if( mapsbrett )
  1582.     {
  1583.         mapsbrett->b.flags |= BFLAG_EXTEND_PM;
  1584.         setbrettinfo( mapsbrett, &bi );
  1585.     }
  1586. }
  1587.  
  1588. static void findbrettbetreffinmapslist( char *bn, char *to )
  1589. {
  1590.     char buffer[ 256 ];
  1591.     char *p, *p2;
  1592.     FILE *f;
  1593.     int c = prefs.maps_list_offs, d;
  1594.  
  1595.     if( *bn == '/' )
  1596.         bn++;
  1597.  
  1598.     pushhomedir();
  1599.     f = fopen( "microdot.mapsblist" , "r" );
  1600.     popdir();
  1601.     if( !f )
  1602.         return;
  1603.     fsetbuf( f, 4096 );
  1604.  
  1605.     while( ( fgets( buffer, 256, f ) ) )
  1606.     {
  1607.         clnl( buffer );
  1608.         d = strlen( buffer );
  1609.         if( c >= d )
  1610.             continue;
  1611.         p = &buffer[áprefs.maps_list_boffs ];
  1612.         
  1613.         if( *p == '/'á)
  1614.             p++;
  1615.         p2 = p;
  1616.         while( *p2 && !isspace( *p2 ) )
  1617.             p2++;
  1618.         if( !p2[0] )
  1619.             continue;
  1620.         *p2++ = 0;
  1621.         if( !stricmp( bn, p ) )
  1622.         {
  1623.             if( !c )
  1624.             {
  1625.                 strncpy( to, stpblk( p2 ), 31 );
  1626.             }
  1627.             else
  1628.                 strncpy( to, &buffer[ c ], 31 );
  1629.             break; 
  1630.         }
  1631.     }
  1632.     fclose( f );
  1633. }
  1634.  
  1635. struct mbrett *findpmbrett( struct hlist *hlist )
  1636. {
  1637.     struct header *hl;
  1638.     int cmplen;
  1639.     struct mbrett *mb = ( struct mbrett * ) GetEntry( &brettlist, 4 );
  1640.     char *p;
  1641.     char buffer[á256 ];
  1642.  
  1643.     while( mb->n.ln_Succ && ( mb->b.flags & BFLAG_EXTEND_PM ) )
  1644.     {
  1645.         struct brettinfo *bi = getbrettinfo( mb );
  1646.  
  1647.         cmplen = strlen( bi->expm_data );
  1648.  
  1649.         if( cmplen && bi->expm_header[á0 ]á)
  1650.         {
  1651.             strcpy( buffer, bi->expm_header );
  1652.             p = strtok( buffer, "|, " );
  1653.  
  1654.             while( p )
  1655.             {
  1656.                 hl = hl_findheader( hlist, p );
  1657.  
  1658.                 while( hl )
  1659.                 {
  1660.                     if( !strnicmp( hl->data, bi->expm_data, cmplen ) || astcsma( hl->data, bi->expm_data ) )
  1661.                         return( mb );
  1662.                     hl = hl_findnextheader( hl );
  1663.                 }
  1664.                 p = strtok( NULL, "|, " );
  1665.             }
  1666.         }
  1667.  
  1668.         /* Keine Header-▄bereinstimmung; vielleicht EMP: ? */
  1669.         cmplen = strlen( bi->antwortan );
  1670.         if( cmplen )
  1671.         {
  1672.             hl = hl_findheader( hlist, "EMP" );
  1673.  
  1674.             while( hl )
  1675.             {
  1676.                 if( !strnicmp( hl->data, bi->antwortan, cmplen ) )
  1677.                     return( mb );
  1678.                 hl = hl_findnextheader( hl );
  1679.             }
  1680.         }
  1681.  
  1682.         mb = mb->n.ln_Succ;
  1683.     }
  1684.  
  1685.     /* Kein spezielles PM-Brett gefunden */
  1686.  
  1687.     return( ( struct mbrett * ) brettlist.lh_Head );
  1688. }
  1689.  
  1690. struct mbrett *findbrett(char *name,int create)
  1691. {
  1692.     struct mbrett *mb=(struct mbrett*)brettlist.lh_Head;
  1693.     char tmp[á128 ];
  1694.     ULONG crc;
  1695.  
  1696.     if( !name )
  1697.         return( mb );
  1698.  
  1699.     stccpy( tmp, name, sizeof( tmp ) );
  1700.     strupr( tmp );
  1701.     crc = crc32( tmp, strlen( tmp ) );
  1702.  
  1703.     while( mb->n.ln_Succ )
  1704.     {
  1705.         if( ( mb->namecrc == crc ) && !stricmp( name, mb->b.name ) )
  1706.             return( mb );
  1707.         mb=(struct mbrett*)mb->n.ln_Succ;
  1708.     }
  1709.     if( create && !strstr( name, "//" ) )
  1710.     {
  1711.         char betreff[40];
  1712.         sprintf( betreff, "Eingetragen %s", dat2str( time( 0 ) ) );
  1713.  
  1714.         findbrettbetreffinmapslist( name, betreff );
  1715.  
  1716.         addbrett( name, betreff );
  1717.         mb = findbrett( name, FALSE );
  1718.         if( mb )
  1719.             makembrettlastwrite( mb );
  1720.         return( mb );
  1721.     }
  1722.     return(0);
  1723. }
  1724.  
  1725. static int slcmp( char *s1, char *s2 )
  1726. {
  1727.     int c = 0, d = 0;
  1728.     int sc = '/';
  1729.     int sc2 = ( prefs.mode == MDM_RFC ) ? '.' : '/';
  1730.  
  1731.     if( *s1 == sc || *s1 == sc2 )
  1732.         s1++;
  1733.     if( *s2 == sc || *s2 == sc2  )
  1734.         s2++;
  1735.  
  1736.     while( *s1 && *s2 && ( *s1 == *s2 ) )
  1737.     {
  1738.         s1++;
  1739.         s2++;
  1740.         c++;
  1741.     }
  1742.  
  1743.     if( *s1 == scá|| *s1 == sc2 )
  1744.         s1--;
  1745.     if( *s2 == sc || *s2 == sc2á)
  1746.         s2--;
  1747.  
  1748.     while( ( c > 0 ) )
  1749.     {
  1750.         if( *s1 == scá|| *s1 == sc2 )
  1751.             d++;
  1752.         s1--;
  1753.         c--;
  1754.     }
  1755.  
  1756.     return( d );
  1757. }
  1758.  
  1759. static char *bnind( char *bn, int ind )
  1760. {
  1761.     int sc = '/';
  1762.     int sc2 = ( prefs.mode == MDM_RFC ) ? '.' : '/';
  1763.  
  1764.     while( *bn && ind )
  1765.     {
  1766.         if( *bn == sc || *bn == sc2 )
  1767.             ind--;
  1768.         bn++;
  1769.     }
  1770.     if( *bn )
  1771.         return( bn );
  1772.     else
  1773.         return( NULL );
  1774. }
  1775.  
  1776. static void convbn( char *bn )
  1777. {
  1778.     char *bn2 = bn;
  1779.  
  1780.     while( ( bn = strchr( bn, '/' ) ) )
  1781.         *bn++ = 3;
  1782.  
  1783.     if( prefs.mode == MDM_RFC )
  1784.     {
  1785.         while( ( bn2 = strchr( bn2, '.' ) ) )
  1786.             *bn2++ = 3;
  1787.     }
  1788. }
  1789.  
  1790. static struct mbrett * attachbl( struct mbrett *n, int indent, char *indentspace )
  1791. {
  1792.     char *bn = n->b.name;
  1793.     int cmp;
  1794.     char *p;
  1795.     int offsl;
  1796.  
  1797.     memset( indentspace, 32, 127 );
  1798.  
  1799.     if( *bn == '/' || ( prefs.mode == MDM_RFC && *bn == '.'á) )
  1800.         bn++;
  1801.  
  1802.     /* Aktuellen Eintrag erzeugen */
  1803.     p = bnind( bn, indent );
  1804.     if( p )
  1805.     {
  1806.         offsl = ( p - bn ) + 1;
  1807.         strcpy( &indentspace[ offsl ], p );
  1808.     }
  1809.     else
  1810.     {
  1811.         strcpy( indentspace, bn );
  1812.     }
  1813.     /*Printf("ACTUAL: %ld, %s\n", offsl, p );*/
  1814.     strncpy( n->viewname, indentspace, 80 );
  1815.     convbn( n->viewname );
  1816.  
  1817.     n = (struct mbrett *) n->n.ln_Succ;
  1818.     while( n->n.ln_Succ )
  1819.     {
  1820.         /* ▄bereinstimmung mit nΣchstem Eintrag? */
  1821.         cmp = slcmp( bn, n->b.name );
  1822.         if( cmp <= indent )
  1823.             break;
  1824.         n = attachbl( n, cmp, indentspace );
  1825.  
  1826.     }
  1827.     return( n );
  1828. }
  1829.  
  1830. static void rollbv( struct mbrett *n )
  1831. {
  1832.     char cmp[ 84 ];
  1833.     UBYTE *p;
  1834.     int c;
  1835.  
  1836.     cmp[ 0 ] = cmp[ 83 ] = 0;
  1837.  
  1838.     while( n->n.ln_Pred )
  1839.     {
  1840.         for( c = 0; n->viewname[ c ] && cmp[ cá]; c++ )
  1841.         {
  1842.             if( ( n->viewname[ c ] == 3 ) && ( cmp[ cá] == 2 ) )
  1843.                 n->viewname[ c ] = 6;
  1844.  
  1845.         }
  1846.  
  1847.         p = strchr( n->viewname, 0 );
  1848.         while( p >= n->viewname && *p != 32 )
  1849.             p--;
  1850.         memcpy( n->viewname, cmp, min( strlen( cmp ), p - n->viewname + 1 ) );
  1851.  
  1852.         if( *p == 32 )
  1853.             *p = 4;
  1854.         else if( *p == 2 )
  1855.             *p = 1;
  1856.  
  1857.         strcpy( cmp, n->viewname );
  1858.  
  1859.         p = cmp;
  1860.         while( *p )
  1861.         {
  1862.             if( *p == 4 || *p == 1 )
  1863.                 *p = 2;
  1864.             else if( *p == 3 || *p > 5 )
  1865.                 *p = 32;
  1866.  
  1867.             p++;
  1868.         }
  1869.  
  1870.         n = ( struct mbrett * ) n->n.ln_Pred;
  1871.     }
  1872. }
  1873.  
  1874. #define BLR_ID 1
  1875.  
  1876. int bl_maxname, bl_maxcomment;
  1877.  
  1878. static void calcblmaxes( void )
  1879. {
  1880.     struct mbrett *n = (struct mbrett *) brettlist.lh_Head;
  1881.  
  1882.     bl_maxname = bl_maxcomment = 0;
  1883.  
  1884.     while( n->n.ln_Succ )
  1885.     {
  1886.         bl_maxname = max( strlen( n->viewname ), bl_maxname );
  1887.         bl_maxcomment = max( strlen( n->b.betreff ), bl_maxcomment );
  1888.         n = (struct mbrett *) n->n.ln_Succ;
  1889.     }
  1890. }
  1891.  
  1892. void makebrettview( void )
  1893. {
  1894.     struct mbrett *n = (struct mbrett *) brettlist.lh_Head;
  1895.     char indentspace[ 128 ];
  1896.  
  1897.     if( !prefs.showboardtree )
  1898.     {
  1899.         while( n->n.ln_Succ )
  1900.         {
  1901.             strcpy( n->viewname, n->b.name );
  1902.             n = (struct mbrett *) n->n.ln_Succ;
  1903.         }
  1904.         calcblmaxes();
  1905.         return;
  1906.     }
  1907.     /* Brettbaum aufbauen */
  1908.     indentspace[á127 ]á= 0;
  1909.     while( n->n.ln_Succ )
  1910.     {
  1911.         n = attachbl( n, 0, indentspace );
  1912.     }
  1913.     rollbv( ( struct mbrett * ) brettlist.lh_TailPred );
  1914.     (( struct mbrett * ) brettlist.lh_Head)->viewname[0] = 7;
  1915.     calcblmaxes();
  1916. }
  1917.  
  1918. static void blscandir( struct ogwin *ogw, struct brett *b, FILE *f, char *name )
  1919. {
  1920.     char tmp[ 256 ];
  1921.     BPTR lock;
  1922.     struct FileInfoBlock *fib;
  1923.  
  1924.     strcpy( tmp, prefs.datadir );
  1925.     addpart( tmp, name );
  1926.     ogreSetStringValue( ogw, BLR_ID, tmp );
  1927.  
  1928.     lock = Lock( tmp, SHARED_LOCK );
  1929.     if( !lock )
  1930.         return;
  1931.  
  1932.     fib = allocfib();
  1933.     if( !fib )
  1934.     {
  1935.         UnLock( lock );
  1936.         return;
  1937.     }
  1938.  
  1939.     if( !Examine( lock, fib ) )
  1940.     {
  1941.         UnLock( lock );
  1942.         freefib( fib );
  1943.         return;
  1944.     }
  1945.  
  1946.     /* Gut, nun Liste durchgehen. Falls .index, dann Brett
  1947.        anhΣngen, falls Dir, dann weitersuchen */
  1948.  
  1949.     while( ExNext( lock, fib ) )
  1950.     {
  1951.         if( !stricmp( fib->fib_FileName, ".mindex" ) )
  1952.         {
  1953.             if( !stricmp( name, "PROTOKOLL" ) ||
  1954.                 !stricmp( name, "ARCHIV" ) ||
  1955.                 !stricmp( name, "SPOOL" ) ||
  1956.                 !stricmp( name, prefs.username ) )
  1957.             
  1958.             {
  1959.                 continue;
  1960.             }
  1961.  
  1962.             tmp[á0 ] = '/';
  1963.             strcpy( &tmp[1], name );
  1964.             strupr( tmp );
  1965.             strcpy( b->name, tmp );
  1966.             strcpy( b->betreff, "<gerettet>" );
  1967.             findbrettbetreffinmapslist( tmp, b->betreff );
  1968.             fwrite( b, sizeof( *b ), 1, f );
  1969.  
  1970.         }
  1971.         else if( fib->fib_DirEntryType > 0 )
  1972.         {
  1973.             strcpy( tmp, name );
  1974.             addpart( tmp, fib->fib_FileName );
  1975.             blscandir( ogw, b, f, tmp );
  1976.         }
  1977.     }
  1978.  
  1979.     UnLock( lock );
  1980.     freefib( fib );
  1981. }
  1982.  
  1983.  
  1984.  
  1985. static void doblrecover( void )
  1986. {
  1987.     FILE *f;
  1988.     struct ogwin *ogw;
  1989.     struct brett b;
  1990.  
  1991.     f = fopen( "microdot.boardix", "w" );
  1992.  
  1993.     if( !f )
  1994.     {
  1995.         displaybeep();
  1996.         return;
  1997.     }
  1998.  
  1999.     memset( &b, 0, sizeof( b ) );
  2000.     b.flags |= BFLAG_HASBINFO;
  2001.     strcpy( b.name, prefs.username );
  2002.     strcpy( b.betreff, "Pers÷nliche Nachrichten" );
  2003.     fwrite( &b, sizeof( b ), 1, f );
  2004.     strcpy( b.betreff, "Ausgehende Nachrichten" );
  2005.     strcpy( b.name, "/╗SPOOL" );
  2006.     fwrite( &b, sizeof( b ), 1, f );
  2007.     strcpy( b.betreff, "Netcall-Protokolle" );
  2008.     strcpy( b.name, "/╗PROTOKOLL" );
  2009.     fwrite( &b, sizeof( b ), 1, f );
  2010.     strcpy( b.betreff, "Archivierte Nachrichten" );
  2011.     strcpy( b.name, "/╗ARCHIV" );
  2012.     fwrite( &b, sizeof( b ), 1, f );
  2013.  
  2014.     ogw = ogreInitWindow( scr, 0, 0, "Brettlistenrestauration" );
  2015.     ogreAddGroup( ogw, 0, OGFRAME_NONE, NULL );
  2016.     ogreAddText( ogw, 0, "Untersuche:", BLR_ID, "", 44, 1 );
  2017.     if( !ogreOpenWindow( ogw ) )
  2018.         return;
  2019.  
  2020.     blscandir( ogw, &b, f, "" );
  2021.     fclose( f );
  2022.  
  2023.     ogreExitWindow( ogw );
  2024. }
  2025.  
  2026. /* MicroDot-1.x-Daten wandeln... */
  2027.  
  2028. //#define copytilleof(f1,f2) {while(((ch=fgetc(f1))!=EOF))fputc(ch,f2);}
  2029.  
  2030. static void copytilleof( BPTR f1, BPTR f2 )
  2031. {
  2032.     char buffer[á1024 ];
  2033.     int rc;
  2034.  
  2035.     while( ( rc = Read( f1, buffer, 1024 ) ) > 0 ) 
  2036.         Write( f2, buffer, rc );
  2037. }
  2038.  
  2039. static void copy1xbrett( int puffer, struct brett *b )
  2040. {
  2041.     struct mbrett mb;
  2042.     char path[á256 ];
  2043.     int mc = 0;
  2044.     struct pindex pix;
  2045.     struct mail newmail;
  2046.     struct oldmail oldmail;
  2047.     BPTR oldix;
  2048.     BPTR newix;
  2049.     BPTR puf;
  2050.     BPTR pufix;
  2051.     BPTR md;
  2052.     int ml;
  2053.  
  2054.     mb.b = *b;
  2055.     brettpfad( path, &mb );
  2056.     addpart( path, ".index" );
  2057.     oldix = Open( path, MODE_OLDFILE );
  2058.     if( !oldix )
  2059.         return;
  2060.  
  2061.     brettpfad( path, &mb );
  2062.     addpart( path, ".MIndex" );
  2063.     newix = Open( path, MODE_NEWFILE );
  2064.     if( !newix )
  2065.         return;
  2066.  
  2067.     sprintf( path, "%sMD_%lx.Data", prefs.datadir, puffer );
  2068.     puf = Open( path, MODE_NEWFILE );
  2069.     if( !puf )
  2070.         return;
  2071.  
  2072.     sprintf( path, "%sMD_%lx.Index", prefs.datadir, puffer );
  2073.     pufix = Open( path, MODE_NEWFILE );
  2074.     if( !pufix )
  2075.         return;
  2076.  
  2077.     /* Alten index ⁿberspringen */
  2078.     Seek( oldix, sizeof( struct index ), OFFSET_BEGINNING );
  2079.  
  2080.     brettpfad( path, &mb );
  2081.     pushdir( path );
  2082.  
  2083.     /* Nachrichten durchgehen */
  2084.     while( ( Read( oldix, &oldmail, sizeof( oldmail ) ) ) == sizeof( oldmail ) )
  2085.     {
  2086.         memset( &newmail, 0, sizeof( newmail ) );
  2087.         memset( &pix, 0, sizeof( pix ) );
  2088.  
  2089.         sprintf( path, "%ld", mc );
  2090.         ml = getfilelen( path );
  2091.         md = Open( path, MODE_OLDFILE );
  2092.         if( !md )
  2093.             break;
  2094.  
  2095.         Read( md, &pix.headersize, 4 );
  2096.         pix.offset = Seek( puf, 0, OFFSET_CURRENT );
  2097.         pix.datasize = ml - pix.headersize;
  2098.         pix.headersize -= 8;
  2099.         Seek( md, 4, OFFSET_CURRENT );
  2100.  
  2101.         copytilleof( md, puf );
  2102.         Close( md );
  2103.  
  2104.         DeleteFile( path );
  2105.  
  2106.         Write( pufix, &pix, sizeof( pix ) );
  2107.  
  2108.         /* Mail-Struktur erstellen */
  2109.         newmail.time = oldmail.time;
  2110.         newmail.pufferID = puffer;
  2111.         newmail.mailID = mc++;
  2112.         newmail.flags = oldmail.flags;
  2113.         newmail.maillen = pix.datasize;
  2114.         newmail.midcrc = oldmail.midcrc;
  2115.         newmail.bezcrc = oldmail.bezcrc;
  2116.         newmail.incomtime = oldmail.incomtime;
  2117.         strcpy( newmail.betreff, oldmail.betreff );
  2118.         strcpy( newmail.absender, oldmail.absender);
  2119.         strcpy( newmail.absenderreal, oldmail.absenderreal );
  2120.  
  2121.         Write( newix, &newmail, sizeof( newmail ) );
  2122.     }
  2123.  
  2124.     popdir();
  2125.  
  2126.     Close( oldix );
  2127.     Close( newix );
  2128.     Close( puf );
  2129.     Close( pufix );
  2130.  
  2131.     brettpfad( path, &mb );
  2132.     addpart( path, ".index" );
  2133.  
  2134.     DeleteFile( path );
  2135.  
  2136. }
  2137.  
  2138. #define FPS(x) Write(outwin,x,strlen(x))
  2139.  
  2140. static void convertmd1( void )
  2141. {
  2142.     BPTR outwin;
  2143.     BPTR f1, f2;
  2144.     ULONG headoffs;
  2145.     struct brett newbrett;
  2146.     struct oldbrett oldbrett;
  2147.     int puffer = 0;
  2148.     char buffer[ 128 ];
  2149.  
  2150.     prefs.pointxfer = 0;
  2151.  
  2152.     outwin = Open( "RAW:////Konvertiere MicroDot-1.6-Konfiguration", MODE_NEWFILE );
  2153.  
  2154.     /* Maps-Liste */
  2155.     f1 = Open( "microdot.mbl", MODE_OLDFILE );
  2156.     if( f1 )
  2157.     {
  2158.         FPS( "MAPS-Brettliste...\n" );
  2159.         f2 = Open( "MicroDot.mapsblist", MODE_NEWFILE );
  2160.         Read( f1, &headoffs, 4 );
  2161.         Seek( f1, headoffs, OFFSET_BEGINNING );
  2162.         copytilleof( f1, f2 );
  2163.         Close( f2 );
  2164.         Close( f1 );
  2165.         DeleteFile( "microdot.mbl" );
  2166.     }
  2167.  
  2168.     f1 = Open( "microdot.bix", MODE_OLDFILE );
  2169.     if( !f1 )
  2170.         return;
  2171.  
  2172.     f2 = Open( "microdot.boardix", MODE_NEWFILE );
  2173.     if( !f2 )
  2174.         return;
  2175.  
  2176.     FPS( "Konvertiere Brettdaten...\n" );
  2177.  
  2178.     /* Bretter... */
  2179.     while( ( Read( f1, &oldbrett, sizeof( oldbrett ) ) ) == sizeof( oldbrett ) )
  2180.     {
  2181.         memset( &newbrett, 0, sizeof( newbrett ) );
  2182.  
  2183.         sprintf( buffer, "Brett %s nach MD_%lx.Data\n", oldbrett.name, puffer );
  2184.         FPS( buffer );
  2185.  
  2186.         /* Neue Brettstruktur */
  2187.         strcpy( newbrett.name, oldbrett.name );
  2188.         strcpy( newbrett.betreff, oldbrett.betreff );
  2189.         newbrett.flags = oldbrett.flags;
  2190.         newbrett.unreadmails = oldbrett.unreadmails;
  2191.         newbrett.mails = oldbrett.mails;
  2192.         newbrett.newmails = oldbrett.newmails;
  2193.         newbrett.days = oldbrett.days;
  2194.         Write( f2, &newbrett, sizeof( newbrett ) );
  2195.  
  2196.         /* Inhalt... */
  2197.         copy1xbrett( puffer++, &newbrett );
  2198.     }
  2199.  
  2200.     FPS( "Konvertierung abgeschlossen\n" );
  2201.  
  2202.     Close( f1 );
  2203.     Close( f2 );
  2204.  
  2205.     DeleteFile( "microdot.bix.bak" );
  2206.     Rename( "microdot.bix", "microdot.bix.bak" );
  2207.     
  2208.     Delay( 350 );
  2209.  
  2210.     Close( outwin );
  2211.  
  2212. }
  2213.  
  2214. void loadbretter( void )
  2215. {
  2216.     struct AsyncFile *f;
  2217.     BPTR f2;
  2218.     char path[256];
  2219.     struct mbrett *n, *mb;
  2220.     struct brett b;
  2221.     struct brettinfo *binfo;
  2222.     int ml;
  2223.     struct List templist;
  2224.  
  2225.     NewList( &brettlist );
  2226.     NewList( &templist );
  2227.     brettmempool = LibCreatePool( MEMF_CLEAR, sizeof( struct mbrett ) * 32, sizeof( struct mbrett ) * 8 );
  2228.  
  2229. retry:
  2230.     ml = getfilelen( "microdot.boardix" );
  2231.     f = OpenAsync( "microdot.boardix", MODE_READ, sizeof( struct brett ) * 128 );
  2232.     if( !f || ml < sizeof( struct brett ) )
  2233.     {
  2234.         if( f )
  2235.             CloseAsync( f );
  2236.  
  2237.         /* Vielleicht altinstallation? */
  2238.         if( exists( "microdot.bix" ) )
  2239.         {
  2240.             ml = askreq( "M÷chten Sie ihre MicroDot 1.0/1.6-Installation\nin das neue Datenbankformat umwandeln lassen?\n\nACHTUNG!\nDie Wandlung kann nicht mehr rⁿckgΣngig gemacht werden!",
  2241.                 "Umwandeln|Abbruch" );
  2242.  
  2243.             if( ml )
  2244.             {
  2245.                 convertmd1();
  2246.                 goto retry;
  2247.             }
  2248.             exit( 0 );
  2249.         }
  2250.  
  2251.  
  2252.         /* Brettliste kaputt? */
  2253.  
  2254.         if( prefs.flags2 & MDF2_PREFSLOADED )
  2255.         {
  2256.             if( ( ml = getfilelen( "microdot.boardix.bak" ) ) > ( int ) sizeof( struct brett ) )
  2257.             {
  2258.                 ml = askreq( "Die Brettliste \"microdot.boardix\" ist defekt.\nEs existiert aber eine wahrscheinlich\nintakte Sicherheitskopie der Liste mit %lD EintrΣgen.\nSoll die Sicherheitskopie installiert werden?",
  2259.                     "Ja|Nein",
  2260.                     ml / sizeof( struct brett )
  2261.                 );
  2262.  
  2263.                 if( ml )
  2264.                 {
  2265.                     Rename( "microdot.boardix", "microdot.boardix.error" );
  2266.                     DeleteFile( "microdot.boardix" );
  2267.                     Rename( "microdot.boardix.bak", "microdot.boardix" );
  2268.                     goto retry;
  2269.                 }
  2270.             }
  2271.  
  2272.             /* Nun gut, Recovery versuchen? */
  2273.             ml = askreq( "Die Brettliste \"microdot.boardix\" ist defekt.\nSoll eine Restauration versucht werden?",
  2274.                 "Rettungsversuch|Ignorieren"
  2275.             );
  2276.             if( ml )
  2277.             {
  2278.                 Rename( "microdot.boardix", "microdot.boardix.error" );
  2279.                 DeleteFile( "microdot.boardix" );
  2280.                 doblrecover();
  2281.                 goto retry;
  2282.             }
  2283.         }
  2284.  
  2285.         newinit();
  2286.         return;
  2287.     }
  2288.     mb = NULL;
  2289.     while( ( ReadAsync( f, &b, sizeof( struct brett ) ) == sizeof( struct brett ) ) )
  2290.     {
  2291.         if( !*( stpblk( b.name ) ) )
  2292.             continue;
  2293.  
  2294.         n = LibAllocPooled( brettmempool, sizeof( struct mbrett ) );
  2295.         if( !n )
  2296.         {
  2297.             displaybeep();
  2298.             break;
  2299.         }
  2300.         n->b = b;
  2301.         calcbrettnamecrc( n );
  2302.         if( b.flags & BFLAG_HASBINFO )
  2303.         {
  2304.             brettpfad( path, n );
  2305.             addpart( path, ".Brettinfo" );
  2306.             f2 = Open( path, MODE_OLDFILE );
  2307.             if( f2 )
  2308.             {
  2309.                 binfo = LibAllocPooled( brettmempool, sizeof( struct brettinfo ) );
  2310.                 if( !binfo )
  2311.                 {
  2312.                     displaybeep();
  2313.                     break;
  2314.                 }
  2315.                 Read( f2, binfo, sizeof( struct brettinfo ) );
  2316.                 Close( f2 );
  2317.                 n->brettinfo = binfo;
  2318.             }
  2319.         }
  2320.  
  2321.         makembrettlastwrite( n );
  2322.  
  2323.         /* Hm... */
  2324.         if( b.flags & BFLAG_EXTEND_PM )
  2325.         {
  2326.             AddTail( &templist, n );
  2327.         }
  2328.         else
  2329.         {
  2330.             if( n->b.name[á0 ]á== '/' && n->b.name[á1 ]á== '╗' )
  2331.                 Insert( &brettlist, n, mb );
  2332.             else
  2333.                 AddTail( &brettlist, n );
  2334.         }
  2335.         mb = n;
  2336.  
  2337.     }
  2338.  
  2339.     mb = GetEntry( &brettlist, 3 );
  2340.  
  2341.     while( n = RemTail( &templist ) )
  2342.         Insert( &brettlist, n, mb );
  2343.  
  2344.     CloseAsync( f );
  2345. }
  2346.  
  2347. void freebretter(void)
  2348. {
  2349.     struct mbrett *n;
  2350.  
  2351.     if( !brettlist.lh_Head )
  2352.         return;
  2353.  
  2354.     while( ( n = ( struct mbrett * ) RemHead( &brettlist ) ) )
  2355.     {
  2356.         if( n->ixfile )
  2357.             CloseAsync( n->ixfile );
  2358.     }
  2359.  
  2360.     if( brettmempool )
  2361.         LibDeletePool( brettmempool );
  2362.  
  2363. }
  2364.  
  2365. static void checkixcache( void )
  2366. {
  2367.     struct mbrett *mb = ( struct mbrett * ) brettlist.lh_Head;
  2368.     int cachesize = 0;
  2369.  
  2370.     while( mb->n.ln_Succ )
  2371.     {
  2372.         if( mb->ixfile )
  2373.             cachesize++;
  2374.         mb = ( struct mbrett * ) mb->n.ln_Succ;
  2375.     }
  2376.  
  2377.     if( ( cachesize > 32 ) || ( cachesize > 4 && AvailMem( MEMF_LARGEST | MEMF_FAST ) < 128000 ) )
  2378.     {
  2379.         mb = ( struct mbrett * ) brettlist.lh_Head;
  2380.         while( mb->n.ln_Succ && ( cachesize > 5 ) )
  2381.         {
  2382.             if( mb->ixfile )
  2383.             {
  2384.                 CloseAsync( mb->ixfile );
  2385.                 mb->ixfile = NULL;
  2386.                 cachesize--;
  2387.             }
  2388.             mb = ( struct mbrett * ) mb->n.ln_Succ;
  2389.         }
  2390.     }
  2391. }
  2392.  
  2393.  
  2394. struct AsyncFile *getixfile( struct mbrett *mb, int rw )
  2395. {
  2396.     char buf[á256 ];
  2397.  
  2398.     if( mb->rw == MODE_WRITE )
  2399.         mb->rw = 42;
  2400.  
  2401.     if( mb->ixfile && ( ( mb->rw == rw ) ) )
  2402.     {
  2403.         if( rw == MODE_READ )
  2404.             SeekAsync( mb->ixfile, 0, MODE_START );
  2405.         return( mb->ixfile );
  2406.     }
  2407.  
  2408.     if( mb->ixfile )
  2409.         CloseAsync( mb->ixfile );
  2410.     mb->ixfile = NULL;
  2411.     checkixcache();
  2412.  
  2413.     mb->rw = rw;
  2414.  
  2415.     brettpfad( buf, mb );
  2416.     checkpath( buf );
  2417.     addpart( buf, ".MIndex" );
  2418.  
  2419.     mb->ixfile = OpenAsync( buf, rw, sizeof( struct mail ) * 32 );
  2420.  
  2421.     return( mb->ixfile );
  2422. }
  2423.  
  2424. void closeixfile( struct mbrett *mb )
  2425. {
  2426.     if( mb->ixfile )
  2427.     {
  2428.         CloseAsync( mb->ixfile );
  2429.         if( mb->rw )
  2430.         {
  2431.             char buf[á256 ];
  2432.  
  2433.             brettpfad( buf, mb );
  2434.             checkpath( buf );
  2435.             addpart( buf, ".MIndex" );
  2436.  
  2437.             if( !getfilelen( buf ) )
  2438.                 DeleteFile( buf );
  2439.         }
  2440.  
  2441.         mb->ixfile = NULL;
  2442.     }
  2443. }
  2444.  
  2445. void closeallixfiles( void )
  2446. {
  2447.     struct mbrett *mb = ( struct mbrett * ) brettlist.lh_Head;
  2448.  
  2449.     while( mb->n.ln_Succ )
  2450.     {
  2451.         if( mb->ixfile )
  2452.         {
  2453.             CloseAsync( mb->ixfile );
  2454.             mb->ixfile = NULL;
  2455.         }
  2456.  
  2457.         mb = ( struct mbrett * ) mb->n.ln_Succ;
  2458.     }
  2459. }
  2460.  
  2461. void closeallwriteixfiles( void )
  2462. {
  2463.     struct mbrett *mb = ( struct mbrett * ) brettlist.lh_Head;
  2464.  
  2465.     while( mb->n.ln_Succ )
  2466.     {
  2467.         if( mb->rw && mb->ixfile )
  2468.         {
  2469.             CloseAsync( mb->ixfile );
  2470.             mb->ixfile = NULL;
  2471.         }
  2472.  
  2473.         mb = ( struct mbrett * ) mb->n.ln_Succ;
  2474.     }
  2475. }
  2476.  
  2477.  
  2478. void savebretter(void)
  2479. {
  2480.     struct AsyncFile *f;
  2481.     BPTR f2;
  2482.     struct mbrett *mb;
  2483.     char path[256];
  2484.     int rc;
  2485.  
  2486.     mb=(struct mbrett*)brettlist.lh_Head;
  2487.     if(!mb || IsListEmpty(&brettlist))
  2488.         return;
  2489.     pushhomedir();
  2490.     DeleteFile( "microdot.boardix.bak" );
  2491.     Rename( "microdot.boardix", "microdot.boardix.bak" );
  2492.     f = OpenAsync( "microdot.boardix", MODE_WRITE, sizeof( struct brett ) * 64 );
  2493.     popdir();
  2494.     if( !f )
  2495.     {
  2496.         rc = IoErr();
  2497.         askreq("Kann Brettliste nicht\nabspeichern (%ld)\n%s","Abbruch",rc, errorstring( rc ) );
  2498.         return;
  2499.     }
  2500.     while( mb->n.ln_Succ )
  2501.     {
  2502.         if( mb->ixfile )
  2503.         {
  2504.             CloseAsync( mb->ixfile );
  2505.             mb->ixfile = NULL;
  2506.         }
  2507.  
  2508.         if( mb->brettinfo )
  2509.         {
  2510.             brettpfad(path,mb);
  2511.             checkpath(path);
  2512.             addpart(path,".Brettinfo");
  2513.             f2=Open(path,MODE_NEWFILE);
  2514.             if(f2)
  2515.             {
  2516.                 Write(f2,mb->brettinfo,sizeof(struct brettinfo));
  2517.                 Close(f2);
  2518.             }
  2519.             else displaybeep();
  2520.             mb->b.flags|=BFLAG_HASBINFO;
  2521.         }
  2522.         else
  2523.             mb->b.flags &= ~BFLAG_HASBINFO;
  2524.  
  2525.         WriteAsync(f,&mb->b,sizeof(struct brett));
  2526.  
  2527.         mb=(struct mbrett*)mb->n.ln_Succ;
  2528.     }
  2529.     CloseAsync( f );
  2530. }
  2531.  
  2532.  
  2533. struct brettinfo *getbrettinfo(struct mbrett *mb)
  2534. {
  2535.     static struct brettinfo fakebi={0};
  2536.  
  2537. /*    Printf("getbrettinfo mb %lx\n",mb);*/
  2538.  
  2539.     if(mb->brettinfo) return(mb->brettinfo);
  2540.     else return( &fakebi );
  2541.  
  2542. }
  2543.  
  2544. void setbrettinfo(struct mbrett *mb,struct brettinfo *bi)
  2545. {
  2546.     if( !bi->diskussionin[0] && !bi->autoexpfad[0] && !( mb->b.flags & BFLAG_EXTEND_PM ) )
  2547.     {
  2548.         if( mb->brettinfo )
  2549.         {
  2550.             char path[256];
  2551.             /*FreeMem(mb->brettinfo,sizeof(struct brettinfo));*/
  2552.             mb->brettinfo = 0;
  2553.             brettpfad(path,mb);
  2554.             addpart(path,".Brettinfo");
  2555.             DeleteFile(path);
  2556.         }
  2557.         return;
  2558.     }
  2559.     if( !mb->brettinfo )
  2560.         mb->brettinfo = LibAllocPooled( brettmempool, sizeof(struct brettinfo) );
  2561.     *mb->brettinfo=*bi;
  2562. }
  2563.  
  2564. /*static int tstmail(struct mbrett *b,int m)
  2565. {
  2566.     BPTR lck;
  2567.     char path[256];
  2568.     
  2569.     brettpfadfile( path, b, m );
  2570.     lck = Lock( path, SHARED_LOCK );
  2571.     if( lck )
  2572.         UnLock( lck );
  2573.     return( ( int ) lck );
  2574. }
  2575. */
  2576.  
  2577. /*int getbrettnextfree(struct mbrett *mb)
  2578. {
  2579.     return( -1 );
  2580. }
  2581. */
  2582.  
  2583. void makembrettlastwrite( struct mbrett *mb )
  2584. {
  2585.     char x[á6 ];
  2586.  
  2587.     utunpk( mb->b.lastwrite, x );
  2588.     sprintf( mb->lastwritedate, "%02ld.%02ld", x[á2 ], x[á1 ]á);
  2589.  
  2590. }
  2591.