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

  1. #include "microdot.h"
  2.  
  3. #include <proto/gadtools.h>
  4.  
  5. #include "ogre_protos.h"
  6.  
  7. extern struct Gadget scrollgad;
  8. extern struct PropInfo propinfo;
  9.  
  10. static int scrollermode;
  11.  
  12. static struct List *currentlist;
  13. static long currenttop, currentsel, nopropupdate;
  14. static APTR topnode;
  15. static ULONG numentries;
  16. static int lastdir = -1;
  17.  
  18. #define LDU 0
  19. #define LDD 1
  20.  
  21. #define swap(a,b){int t;t=a;a=b;b=t;}
  22.  
  23. static ULONG scrollerhistory[ 128 ];
  24.  
  25. // Fⁿr ALT-F1/F10
  26. static ULONG posarray[á4 * 10 ];
  27.  
  28. static void scrollerup( void );
  29. static void scrollerdown( void );
  30.  
  31. static void scrolleruplines( int );
  32. static void scrollerdownlines( int );
  33.  
  34. static int mark_xs, mark_ys, mark_xe, mark_ye;
  35.  
  36. void updateprop(void)
  37. {
  38.     ULONG    total        =    numentries;
  39.     ULONG    hidden,top    =    currenttop;
  40.  
  41.     if( nopropupdate )
  42.         return;
  43.  
  44.     hidden = max( total - screenlines, 0 );
  45.     if(top>hidden) top=hidden;
  46.     propinfo.VertPot=(hidden>0)?(((ULONG)top*MAXPOT)/hidden):0;
  47.     NewModifyProp( &scrollgad, w, 0, propinfo.Flags,
  48.         propinfo.HorizPot, propinfo.VertPot,
  49.         propinfo.HorizBody, propinfo.VertBody, 1
  50.     );
  51. }
  52.  
  53.  
  54. static char gadt[ 16 * 32];
  55. static struct Gadget gads[16];
  56. static struct IntuiText gadit[32];
  57. static UBYTE gscs[32];
  58. static int gads_active, gadsize;
  59. static struct Gadget *gtglist;
  60. static struct VisualInfo *gtvi;
  61.  
  62. static struct TextAttr microfontta, microfontta_underlined; 
  63.  
  64. #define SETXY(b,n,x,y) b[(n)*2]=x;b[((n)*2)+1]=y;
  65.  
  66. void removescrollgads( void )
  67. {
  68.     if( gads_active )
  69.     {
  70.         if( gtglist )
  71.         {
  72.             RemoveGList( w, gtglist, gads_active );
  73.             FreeGadgets( gtglist );
  74.             FreeVisualInfo( gtvi );
  75.             gtglist = NULL;
  76.         }
  77.         else
  78.         {
  79.             RemoveGList( w, &gads[0], gads_active );
  80.         }
  81.         gads_active = 0;
  82.     }
  83. }
  84.  
  85. static void scrollgads( int maxentries, char **entries, UWORD *codes )
  86. {
  87.     int c;
  88.     int gadxsize, gadysize;
  89.     int halfmaxentries = maxentries / 2;
  90.     ULONG    posarray[8];
  91.     ULONG    sizearray[8];
  92.     char    *p;
  93.     int     labeloffs, labelchar;
  94.     int        fys, cml;
  95.     struct TextFont *gtf;
  96.     struct Border *gb, *sb;
  97.     struct NewGadget ng;
  98.     struct Gadget *gtlg = NULL, *g;
  99.     static char **oldentries;
  100.     static UWORD *oldcodes;
  101.     static ULONG oldwidth;
  102.  
  103.  
  104.     if( ! ( prefs.flags & MDF_GADGETS ) /*&& !wbwindow */ )
  105.     {
  106.         removescrollgads();
  107.         return;
  108.     }
  109.  
  110.     if( gads_active && ( entries == oldentries ) && ( codes == oldcodes ) && ( oldwidth == w->Width ) )
  111.     {
  112.         if( !wbwindow )
  113.             screenlines = (scr->Height - topoffs - gadsize ) / fontysize;
  114.         return;
  115.     }
  116.  
  117.     oldentries = entries;
  118.     oldcodes = codes;
  119.     oldwidth = w->Width;
  120.  
  121.     removescrollgads();
  122.  
  123.     microfontta.ta_Name = prefs.gadfontname;
  124.     microfontta.ta_YSize = fys = prefs.gadfontheight;
  125.     microfontta_underlined = microfontta;
  126.     microfontta_underlined.ta_Style |= FSF_UNDERLINED;
  127.     gtf = OpenDiskFont( µfontta );
  128.  
  129.     memset( &gads[0], 0, sizeof( struct Gadget ) * 16 );
  130.     memset( &gadit[0], 0, sizeof( struct IntuiText ) * 16 );
  131.  
  132.     gadsize = ( fys + 2 ) * 2 + 4;
  133.     gadysize = fys + 2;
  134.  
  135.     if( !wbwindow )
  136.     {
  137.         gyoffs = scr->Height - gadsize;
  138.         screenlines = (scr->Height - topoffs - gadsize ) / fontysize;
  139.         SetAPen(rp, screenpens[ SHADOWPEN ] );
  140.         Move(rp,0,gyoffs);
  141.         Draw(rp,screenxsize-17,rp->cp_y);
  142.         SetAPen(rp, screenpens[ SHINEPEN ] );
  143.         Move(rp,0,rp->cp_y+1);
  144.         Draw(rp,screenxsize-17,rp->cp_y);
  145.         SetAPen( rp, 0 );
  146.         RectFill( rp, 0, gyoffs + 2, screenxsize - 17, scr->Height - 1 );
  147.     }
  148.     else
  149.     {
  150.         gyoffs = - ( ( ( fys + 4 ) * 2 ) + 1 );
  151.     }
  152.  
  153.     /* Setup Positions */
  154.     if( wbwindow )
  155.     {
  156.         c = w->Width - w->BorderLeft - w->BorderRight - 4;
  157.         gadxsize = ( c / halfmaxentries ) - 2;
  158.         for( c = 0; c < halfmaxentries; c++ )
  159.             posarray[c] = ( ( gadxsize + 2 ) * c ) + w->BorderLeft + 2;
  160.     }
  161.     else
  162.     {
  163.         gadxsize = ( ( screenxsize - 20) / halfmaxentries ) - 2;
  164.         for( c = 0; c < halfmaxentries; c++ )
  165.             sizearray[c] = gadxsize;
  166.         rtSpread( posarray, sizearray, gadxsize*halfmaxentries, 8, screenxsize - 24, halfmaxentries );
  167.  
  168.         if( isv37 )
  169.         {
  170.             gtvi = GetVisualInfo( scr, TAG_DONE );
  171.             gtlg = CreateContext( >glist );
  172.  
  173.             ng.ng_TextAttr = µfontta;
  174.             ng.ng_Width = gadxsize;
  175.             ng.ng_Height = gadysize;
  176.             ng.ng_Flags = 0;
  177.             ng.ng_VisualInfo = gtvi;
  178.         }
  179.     }
  180.  
  181.     if( !gtlg )
  182.     {
  183.         gb = makebevelborder( gadxsize, gadysize, FALSE );
  184.         sb = makebevelborder( gadxsize, gadysize, TRUE );
  185.     }
  186.  
  187.     /* Setup Gadgets */
  188.     for( c = 0; c < maxentries; c++ )
  189.     {
  190.         if( gtlg )
  191.         {
  192.             ng.ng_GadgetText     = entries[ cá];
  193.             ng.ng_LeftEdge         = posarray[ c % halfmaxentries ];
  194.             ng.ng_TopEdge        = ( c >= halfmaxentries ) ? gyoffs + gadysize + 4 : gyoffs + 3;
  195.             ng.ng_GadgetID        = 256 + c;
  196.             ng.ng_UserData        = ( void * ) codes[ác ];
  197.             gtlg = CreateGadget( BUTTON_KIND, gtlg, &ng, GT_Underscore, '_', TAG_DONE );
  198.         }
  199.         else
  200.         {
  201.             if( c != ( maxentries - 1 ) )
  202.                 gads[c].NextGadget    = &gads[ác + 1];
  203.  
  204.             gads[c].LeftEdge     = posarray[ c % halfmaxentries ];
  205.             gads[c].TopEdge        = ( c >= halfmaxentries ) ? gyoffs + gadysize + 4 : gyoffs + 3;
  206.             gads[c].Width        = gadxsize;
  207.             gads[c].Height        = gadysize;
  208.             gads[c].Flags        = GFLG_GADGHIMAGE;
  209.             gads[c].Activation    = GACT_RELVERIFY;
  210.             gads[c].GadgetType    = GTYP_BOOLGADGET;
  211.             gads[c].GadgetRender= gb;
  212.             gads[c].SelectRender= sb;
  213.             gads[c].GadgetID    = 256 + c;
  214.             gads[c].GadgetText    = &gadit[c];
  215.             gads[c].UserData    = (void *) codes[c];
  216.  
  217.             if( wbwindow )
  218.             {
  219.                 gads[c].Activation |= GACT_BOTTOMBORDER;
  220.                 gads[c].GadgetType |= GTYP_GZZGADGET;
  221.                 gads[c].Flags      |= GFLG_RELBOTTOM;
  222.             }
  223.  
  224.             gadit[c].FrontPen    = 1;
  225.             gadit[c].TopEdge    = 1;
  226.             gadit[c].IText        = &gadt[c*32];
  227.             gadit[c].ITextFont    = µfontta;
  228.  
  229.             strcpy( &gadt[c*32], entries[c]);
  230.             p = strchr( &gadt[c*32], '_' );
  231.             if( p )
  232.             {
  233.                 *p = 0;
  234.                 gscs[ c * 2 ] = p[ 1 ];
  235.                 labeloffs = IntuiTextLength( &gadit[c] );
  236.                 labelchar = ( ( int ) p ) - ( ( int )( &gadt[ c * 32 ] ) );
  237.                 strcpy( p, &p[1] );
  238.             }
  239.             gadit[c].LeftEdge     = ( gadxsize - IntuiTextLength( &gadit[c] ) ) / 2;
  240.  
  241.             /* Gadget-Text Kⁿrzen? */
  242.             if( gadit[c].LeftEdge < 2 )
  243.             {
  244.                 cml = ogreTextFit( gtf, &gadt[ c * 32 ], gadxsize - 4 );
  245.                 gadt[ ( c * 32 ) + cml ] = 0;
  246.  
  247.                 /* Shortcut wech? */
  248.                 if( cml <= labelchar )
  249.                     p = NULL;
  250.  
  251.                 gadit[c].LeftEdge     = ( gadxsize - IntuiTextLength( &gadit[c] ) ) / 2;
  252.             }
  253.  
  254.             if( p )
  255.             {
  256.                 gadit[ c + 16]             = gadit[c];
  257.                 gadit[c].NextText        = &gadit[ c + 16 ];
  258.                 gadit[c+16].IText        = &gscs[ c * 2 ];
  259.                 gadit[c+16].ITextFont    = µfontta_underlined;
  260.                 gadit[c+16].LeftEdge    += labeloffs;
  261.             }
  262.         }
  263.     }
  264.  
  265.     gads_active = maxentries;
  266.  
  267.     if( gtglist )
  268.     {
  269.         /* Gadtools-Gadgets zΣhlen */
  270.         g = gtglist;
  271.         gads_active = 0;
  272.         while( g )
  273.         {
  274.             gads_active++;
  275.             g = g->NextGadget;
  276.         }
  277.  
  278.         AddGList( w, gtglist, 0, gads_active, NULL );
  279.         RefreshGList( gtglist, w, NULL, gads_active + 1 );
  280.         GT_RefreshWindow( w, NULL );
  281.     }
  282.     else
  283.     {
  284.         AddGList( w, &gads[0], 0, gads_active, NULL );
  285.         if( wbwindow )
  286.             RefreshWindowFrame( w );
  287.         else
  288.             RefreshGList( &gads[0], w, NULL, gads_active );
  289.  
  290.     }
  291.     CloseFont( gtf );
  292. }
  293.  
  294. static char *sg_brett[12] = {
  295.     "WΣhlen",
  296.     "Markieren",
  297.     "Alle Demarkieren",
  298.     "_nΣchste Neue",
  299.     "_Neues Brett",
  300.     "_aufrΣumen",
  301.     "_Alles AufrΣumen",
  302.     "Brettinhalt l÷schen",
  303.     "Brett l÷schen",
  304.     "Brett_parameter",
  305.     "Nachricht schr_eiben",
  306.     "Hilfe" };
  307.  
  308. static UWORD sg_brett_codes[12] = {
  309.     0x44,
  310.     0x40,
  311.     0x0  | 0x100,
  312.     0x36,
  313.     0x36 | 0x100,
  314.     0x20,
  315.     0x20 | 0x100,
  316.     0x46,
  317.     0x46 | 0x100,
  318.     0x19,
  319.     0x12,
  320.     0x5f };
  321.  
  322. static char *sg_inhalt[14]á= {
  323.     "Lesen",
  324.     "_Antwort",
  325.     "_Private Antwort",
  326.     "_Weiterleiten",
  327.     "Markieren",
  328.     "_Drucken",
  329.     "Auslagern",
  330.     "Thread _falten",
  331.     "Alle fal_ten",
  332.     "Alle entfal_Ten",
  333.     "Schr_eiben",
  334.     "L÷schen",
  335.     "Zurⁿck/Neu l÷schen",
  336.     "Zurⁿck",
  337. };
  338.  
  339. static UWORD sg_inhalt_codes[14] = {
  340.     0x44,
  341.     0x20 | 0x100,
  342.     0x19 | 0x100,
  343.     0x11,
  344.     0x40,
  345.     0x22,
  346.     0x32 /*| 0x100*/,
  347.     0x23, 
  348.     0x14,
  349.     0x14 | 0x100,
  350.     0x12,
  351.     0x46,
  352.     0x200,
  353.     0x201
  354. };
  355.  
  356. static char *sg_msg[14]á= {
  357.     "Extern anzeigen",
  358.     "_Antwort",
  359.     "_Private Antwort",
  360.     "_Weiterleiten",
  361.     "Markieren",
  362.     "_Drucken",
  363.     "Auslagern",
  364.  
  365.     "Halten",
  366.     "Wiedervorlage",
  367.     "L÷schen",
  368.     "Thread _Killen",
  369.     "Absender speichern",
  370.     "_nΣchste Neue",
  371.     "Zurⁿck",
  372. };
  373.  
  374. static UWORD sg_msg_codes[14] = {
  375.     0x34,
  376.     0x20 | 0x100,
  377.     0x19 | 0x100,
  378.     0x11,
  379.     0x40,
  380.     0x22,
  381.     0x32 /*| 0x100*/,
  382.  
  383.     0x25,
  384.     0x01 | 0x100,
  385.     0x46,
  386.     0x27 | 0x100,
  387.     0x21 | 0x100,
  388.     0x36,
  389.     0x45,
  390. };
  391.  
  392. void makescrollergads( void )
  393. {
  394.     switch( scrollermode )
  395.     {
  396.         case 0:
  397.             scrollgads( 12, sg_brett, sg_brett_codes );
  398.             break;
  399.  
  400.         case 1:
  401.             scrollgads( 14, sg_inhalt, sg_inhalt_codes );
  402.             break;
  403.  
  404.         case 2:
  405.             scrollgads( 14, sg_msg, sg_msg_codes );
  406.             break;
  407.  
  408.         default:
  409.             removescrollgads();
  410.             SetAPen( rp, 0 );
  411.             RectFill( rp, 0, topoffs, scr->Width - 17, scr->Height - 1 );
  412.             break;
  413.     }
  414. }
  415.  
  416. void __inline findtopnode( void )
  417. {
  418.     topnode = GetEntry( currentlist, currenttop );
  419. }
  420.  
  421. static void __inline findtopnode_next( int n )
  422. {
  423.     topnode = GetEntryFromHere( topnode, n );
  424. }
  425.  
  426. static void __inline findtopnode_before( int n )
  427. {
  428.     while( n-- )
  429.         topnode = ( ( struct Node * ) topnode )->ln_Pred;
  430. }
  431.  
  432. void setupscroller(struct List *l,int mode)
  433. {
  434.     UWORD total,hidden;
  435.  
  436.     OffMenu( w, FULLMENUNUM( 3, 22, NOSUB ) );    // Clipboard...
  437.  
  438.     mark_xs = mark_ys = mark_xe = mark_ye = -1;
  439.  
  440.     memset( &scrollerhistory[á0 ], 0xff, 128 * 4 );
  441.  
  442.     scrollermode=mode;
  443.  
  444.     currenttop=currentsel=0;
  445.     currentlist=l;
  446.     findtopnode();
  447.  
  448.     numentries = total = GetNumEntries(currentlist);
  449.     hidden = max( total - screenlines, 0 );
  450.  
  451.     propinfo.VertBody=(hidden>0)?(UWORD)(((ULONG)(screenlines-1)*MAXBODY)/(total-1)):MAXBODY;
  452.     updateprop();
  453.  
  454.     SetAPen( rp, 0 );
  455.     RectFill( rp, 0, topoffs, scr->Width-17, topoffs + ( fontysize * screenlines ) - 1 );
  456.  
  457.     if( mode > 1 )
  458.         memset( &posarray[ámode * 10 ], 0, 10 * 4 );
  459.  
  460.     /*screenlines=(scr->Height-topoffs)/fontysize;*/
  461.  
  462.     recalcwindowsize();
  463.     scrollerdoclick( 0 );
  464.     makescrollergads();
  465. }
  466.  
  467. /*static void formatbrettline( char *buff, struct mbrett *n )
  468. {
  469.     char x[ 6 ];
  470.  
  471.     utunpk(n->b.lastwrite,x);
  472.     sprintf(buff,"%-39.39s\x05%4ld\x05%4ld\x05%4ld\x05%02ld.%02ld\x05%s",
  473.         n->viewname,
  474.         n->b.mails,
  475.         n->b.newmails,
  476.         n->b.unreadmails,
  477.         x[á1 ], x[á2 ],
  478.         n->b.betreff
  479.     );
  480. }*/
  481.  
  482. extern __asm formatbrettline( register __a0 char *, register __a1 struct mbrett * );
  483.  
  484. void displayscrollerbrett(void)
  485. {
  486.     ULONG c;
  487.     struct mbrett *n=(struct mbrett*)topnode;
  488.     char buff[ 512 ];
  489.     int p;
  490.  
  491.     for(c=0; c<screenlines; c++)
  492.     {
  493.         if(n && n->n.ln_Succ)
  494.         {
  495.             if( c == currentsel - currenttop )
  496.             {
  497.                 if( n->n.ln_Type )
  498.                     p = PEN_MARKSEL;
  499.                 else
  500.                     p = PEN_SEL;
  501.             }
  502.             else
  503.             {
  504.                 if( n->n.ln_Type )
  505.                     p = PEN_MARK;
  506.                 else
  507.                     p = PEN_TEXT;
  508.             }
  509.             formatbrettline( buff, n );
  510.             qf_ws( c, p, buff );
  511.             n=(struct mbrett*)n->n.ln_Succ;
  512.         }
  513.         else
  514.         {
  515.             qf_ws( c, 0, "" );
  516.         }
  517.     }
  518. }
  519.  
  520. static void countmailstree(struct mmail *n,int *new,int *count)
  521. {
  522.     *count=(*count)+1;
  523.     if(n->m.flags&MMF_UNSEEN) *new=(*new)+1;
  524.     if(n->bezlink) countmailstree(n->bezlink,new,count);
  525.     if(n->firstbez) countmailstree(n->firstbez,new,count);
  526. }
  527.  
  528. extern int ml_bet, ml_kb;
  529. static void __inline fmtmsgline(struct vmail *vn,char *to)
  530. {
  531.     struct mmail *n=vn->m;
  532.     int ind;
  533.     char fch1,fch2;
  534.     char *bet = n->m.betreff;
  535.     char *p;
  536.     int len;
  537.  
  538.     /* Betreff RE:s filtern? */
  539.     if( prefs.flags & MDF_FILTERRE )
  540.         bet = &bet[ávn->m->reoffset ];
  541.     len = strlen( bet );
  542.  
  543.     fch1='-';
  544.     if(n->m.flags&MMF_ARCHIVE) fch1='H';
  545.     else if(n->m.flags&MMF_DEL) fch1='L';
  546.     //if(n->m.flags&MMF_KILL) fch1='K';
  547.  
  548.     fch2='-';
  549.     if(n->m.flags&MMF_UNSEEN) fch2='N';
  550.     if(n->m.flags&MMF_SHOW) fch2='!';
  551.     if(n->m.flags&MMF_OUT) fch2='>';
  552.  
  553.     p = &to[áml_bet ];
  554.     *p++á= 5;
  555.     *p++á= fch2;
  556.     *p++á= (n->m.flags&MMF_GOTEB)?'E':((n->m.flags&MMF_READ)?'G':'-');
  557.     *p++á= ( n->m.flags & MMF_BIN ) ? 'B'á: '-';
  558.     *p++á= fch1;
  559.     *p++ = 5;
  560.     memcpy( p, vn->kb, ml_kb );
  561.     p += ml_kb;
  562.     *p++ = 5;
  563.     strcpy( p, vn->date );
  564.     p = strchr( p, 0 );
  565.     *p++ = 5;
  566.     strcpy( p, (n->m.absenderreal[0]&&prefs.flags&MDF_SHOWREAL)?n->m.absenderreal:n->m.absender );
  567.  
  568. /*    sprintf( &to[áml_bet ],"\x05%lc%lc%lc%lc\x05%s\x05%s\x05%s",
  569.         fch2,
  570.         (n->m.flags&MMF_GOTEB)?'E':((n->m.flags&MMF_READ)?'G':'-'),
  571.         fch3,
  572.         fch1,
  573.         vn->kb,
  574.         vn->date,
  575.         (n->m.absenderreal[0]&&prefs.flags&MDF_SHOWREAL)?n->m.absenderreal:n->m.absender
  576.     );*/
  577.  
  578.     ind = vn->indent;
  579.     if( ind > ( ml_bet - 1 ) )
  580.     {
  581.         memcpy( to, vn->indentspace, ml_bet - 1 );
  582.         to[áml_bet - 1 ]á= '╗';
  583.     }
  584.     else if( ind )
  585.     {
  586.         len = min( len, ml_bet - ind );
  587.         memcpy( to, vn->indentspace, ind );
  588.         memcpy( &to[áind ], bet, len );
  589.         memset( &to[ len + ind ], 32, ( ml_bet - ind ) - len );
  590.     }
  591.     else
  592.     {
  593.         len = min( len, ml_bet );
  594.         memcpy( to, bet, len );
  595.         memset( &to[ len ], 32, ml_bet - len );
  596.     }
  597.  
  598.     if( n->m.flags & MMF_FOLD )
  599.     {
  600.         int v1=0,v2=0;
  601.         char x[á32 ];
  602.  
  603.         if(n->firstbez)
  604.             countmailstree(n->firstbez,&v1,&v2);
  605.         sprintf(x," {F:%ld/%ld}",v1,v2);
  606.         memcpy( &to[ ml_bet - strlen( x ) ], x, strlen( x ) );
  607.     }
  608. }
  609.  
  610.  
  611. static void __inline displayscrollermsg(void)
  612. {
  613.     ULONG c;
  614.     struct vmail *n=(struct vmail*)topnode;
  615.     char buff[ 512 ];
  616.     int p;
  617.  
  618.     for(c=0; c<screenlines; c++)
  619.     {
  620.         if( n && n->n.mln_Succ )
  621.         {
  622.             if( c == currentsel - currenttop )
  623.             {
  624.                 if( n->sel )
  625.                     p = PEN_MARKSEL;
  626.                 else
  627.                     p = PEN_SEL;
  628.             }
  629.             else
  630.             {
  631.                 if( n->sel )
  632.                     p = PEN_MARK;
  633.                 else
  634.                     p = PEN_TEXT;
  635.             }
  636.     
  637.             fmtmsgline(n,buff);
  638.             qf_ws( c, p, buff );
  639.             n=(struct vmail*)n->n.mln_Succ;
  640.         }
  641.         else
  642.         {
  643.             qf_ws( c, 0, "" );
  644.         }
  645.     }
  646. }
  647.  
  648. static void markscrollerline( int line, int linelen )
  649. {
  650.     int mxs = -1, mye = linelen;
  651.     int m_ys = mark_ys;
  652.     int m_xs = mark_xs;
  653.     int m_ye = mark_ye;
  654.     int m_xe = mark_xe;
  655.  
  656.     if( m_ys > m_ye )
  657.     {
  658.         swap( m_ys, m_ye );
  659.         swap( m_xs, m_xe );
  660.     }        
  661.     if( m_ys == m_ye )
  662.     {
  663.         if( m_xs > m_xe )
  664.             swap( m_xs, m_xe );
  665.     }
  666.  
  667.     line += currenttop;
  668.  
  669.     if( line == m_ys )
  670.     {
  671.         if( m_ys == m_ye )
  672.             mye = m_xe;
  673.         mxs = m_xs;
  674.     }
  675.     else if( line > m_ys && line < m_ye )
  676.         mxs = 0;
  677.     else if( line == m_ye )
  678.     {
  679.         mxs = 0;
  680.         mye = m_xe;
  681.     }    
  682.  
  683.     if( mxs >= 0 )
  684.     {
  685.         //Printf( "qf_inv %ld, %ld, %ld\n", line - currenttop, mxs, mye );
  686.         qf_inv( line - currenttop, mxs, mye );
  687.     }
  688.  
  689. }
  690.  
  691. static void __inline displayscrollertxt(void)
  692. {
  693.     ULONG c;
  694.     struct dnode *n=(struct dnode*)topnode;
  695.     //UWORD pen[]á= { PEN_READ, PEN_QUOTE, PEN_HEAD };
  696.  
  697.     for(c=0; c<screenlines; c++)
  698.     {
  699.         if(n && n->n.mln_Succ)
  700.         {
  701.             qf_wt( c, n );
  702.             markscrollerline( c, strlen( n->txt ) );
  703.             n=(struct dnode*)n->n.mln_Succ;
  704.         }
  705.         else
  706.         {
  707.             qf_clr( c );
  708.         }
  709.     }
  710. }
  711.  
  712. static void __inline displayscrollermaps(void)
  713. {
  714.     ULONG c;
  715.     struct mvnode *n=(struct mvnode*)topnode;
  716.     int p;
  717.  
  718.     for(c=0; c<screenlines; c++) {
  719.         if(n && n->n.mln_Succ)
  720.         {
  721.             if( c == currentsel - currenttop )
  722.             {
  723.                 if( n->sel )
  724.                     p = PEN_MARKSEL;
  725.                 else
  726.                     p = PEN_SEL;
  727.             }
  728.             else
  729.             {
  730.                 if( n->sel )
  731.                     p = PEN_MARK;
  732.                 else
  733.                     p = PEN_TEXT;
  734.             }
  735.  
  736.             qf_ws( c, p, n->txt );
  737.             n=(struct mvnode*)n->n.mln_Succ;
  738.         }
  739.         else
  740.         {
  741.             qf_clr( c );
  742.         }
  743.     }
  744. }
  745.  
  746. void displayscroller(void)
  747. {
  748.     switch(scrollermode) {
  749.         case 0: displayscrollerbrett(); break;
  750.         case 1: displayscrollermsg(); break;
  751.         case 2: displayscrollertxt(); break;
  752.         case 3: displayscrollermaps(); break;
  753.     }
  754. }
  755.  
  756.  
  757. static void __inline displayscrollerlinebrett(int c)
  758. {
  759.     struct mbrett *n;
  760.     char buff[ 512 ];
  761.     int p;
  762.  
  763.     if(c<0||c>=screenlines) return;
  764.     n=(struct mbrett*)GetEntryFromHere( topnode, c );
  765.  
  766.     if( n && n->n.ln_Succ )
  767.     {
  768.         if( c == currentsel - currenttop )
  769.         {
  770.             if( n->n.ln_Type )
  771.                 p = PEN_MARKSEL;
  772.             else
  773.                 p = PEN_SEL;
  774.         }
  775.         else
  776.         {
  777.             if( n->n.ln_Type )
  778.                 p = PEN_MARK;
  779.             else
  780.                 p = PEN_TEXT;
  781.         }
  782.  
  783.         formatbrettline( buff, n );
  784.         qf_ws( c, p, buff );
  785.         /*n=(struct mbrett*)n->n.ln_Succ;*/
  786.     }
  787.     else
  788.     {
  789.         qf_ws( c, 0, "" );
  790.     }
  791. }
  792.  
  793. static void __inline displayscrollerlinemsg(int c)
  794. {
  795.     struct vmail *n;
  796.     char buff[ 512 ];
  797.     int p;
  798.  
  799.     if(c<0||c>=screenlines||!topnode) return;
  800.     n=(struct vmail*)GetEntryFromHere( topnode, c );
  801.  
  802.     if(n && n->n.mln_Succ)    
  803.     {
  804.         if( c == currentsel - currenttop )
  805.         {
  806.             if( n->sel )
  807.                 p = PEN_MARKSEL;
  808.             else
  809.                 p = PEN_SEL;
  810.         }
  811.         else
  812.         {
  813.             if( n->sel )
  814.                 p = PEN_MARK;
  815.             else
  816.                 p = PEN_TEXT;
  817.         }
  818.  
  819.         fmtmsgline(n,buff);
  820.         qf_ws( c, p, buff );
  821.         /*n=(struct vmail*)n->n.mln_Succ;*/
  822.     }
  823.     else
  824.     {
  825.         qf_ws( c, 0, "" );
  826.     }
  827. }
  828.  
  829. static void __inline displayscrollerlinetxt(int c)
  830. {
  831.     struct dnode *n;
  832.     //UWORD pen[]á= { PEN_READ, PEN_QUOTE, PEN_HEAD };
  833.  
  834.     if(c<0||c>=screenlines) return;
  835.     n=(struct dnode*)GetEntryFromHere( topnode, c );
  836.  
  837.     if( n && n->n.mln_Succ )
  838.     {
  839.         qf_wt( c, n );
  840.         /*n=(struct vmail*)n->n.mln_Succ;*/
  841.         markscrollerline( c, strlen( n->txt ) );
  842.     }
  843.     else
  844.     {
  845.         qf_clr( c );
  846.     }
  847. }
  848.  
  849. static void __inline displayscrollerlinemaps(int c)
  850. {
  851.     struct mvnode *n;
  852.     int p;
  853.  
  854.     if(c<0||c>=screenlines) return;
  855.     n=(struct mvnode*)GetEntryFromHere( topnode, c );
  856.  
  857.     if(n && n->n.mln_Succ)
  858.     {
  859.         if( c == currentsel - currenttop )
  860.         {
  861.             if( n->sel )
  862.                 p = PEN_MARKSEL;
  863.             else
  864.                 p = PEN_SEL;
  865.         }
  866.         else
  867.         {
  868.             if( n->sel )
  869.                 p = PEN_MARK;
  870.             else
  871.                 p = PEN_TEXT;
  872.         }
  873.  
  874.         qf_ws( c, p, n->txt );
  875.     }
  876.     else
  877.     {
  878.         qf_ws( c, 0, "" );
  879.     }
  880. }
  881.  
  882. void displayscrollerline( int c )
  883. {
  884.     switch( scrollermode )
  885.     {
  886.         case 0: displayscrollerlinebrett(c); break;
  887.         case 1: displayscrollerlinemsg(c); break;
  888.         case 2: displayscrollerlinetxt(c); break;
  889.         case 3: displayscrollerlinemaps(c); break;
  890.     }
  891. }
  892.  
  893. extern void __asm storeselsup( register __a0 APTR from, register __d0 ULONG new );
  894. static void storecurrentsel( void )
  895. {
  896.     storeselsup( &scrollerhistory[á128 ], getscrollerstate() );
  897. /*    memmove( &scrollerhistory[ 1 ], &scrollerhistory[á0 ], 127 * 4 );
  898.     scrollerhistory[á0 ]á= getscrollerstate();*/
  899. }
  900.  
  901. static void scrollerhis( void )
  902. {
  903.     ULONG s = scrollerhistory[á0 ];
  904.  
  905.     if( s == ~0 )
  906.     {
  907.         displaybeep();
  908.         return;
  909.     }
  910.     scrollerhistory[ 127 ]á= ~0;
  911.     memcpy( &scrollerhistory[á0 ], &scrollerhistory[á1 ], 127 * 4 );
  912.     setscrollerstate( s );
  913. }
  914.  
  915. void setscrollercurrent_internal( int num )
  916. {
  917.     if( num != currentsel )
  918.         storecurrentsel();
  919.     currentsel = num;
  920. }
  921.  
  922. void setscrollercurrent( int num )
  923. {
  924.     int oldsel=currentsel;
  925.  
  926.     if( scrollermode == 2 )
  927.     {
  928.         if(num<0) num=0;
  929.         if( num > ( numentries - screenlines ) )
  930.             num = numentries - screenlines;
  931.         /*currentsel = num;*/
  932.         if( num < oldsel )
  933.             scrolleruplines( oldsel - num );
  934.         else
  935.             scrollerdownlines( num - oldsel );
  936.         /*setscrollertop( num );*/
  937.         return;
  938.     }
  939.  
  940.     if( num < 0 )
  941.         num = 0;
  942.     if( num >= numentries )
  943.         num = numentries - 1;
  944.  
  945.     if( num != oldsel )
  946.         storecurrentsel();
  947.  
  948.     currentsel=num;
  949.  
  950.     displayscrollerline(oldsel-currenttop);
  951.     displayscrollerline(currentsel-currenttop);
  952.  
  953. }
  954.  
  955. void setscrollercurrent2( int num )
  956. {
  957.     int oldsel=currentsel;
  958.  
  959.     if( scrollermode == 2 )
  960.     {
  961.         if(num<0) num=0;
  962.         if(num>(numentries-screenlines)) num=numentries-screenlines;
  963.         /*currentsel=num;*/
  964.         if( num < oldsel )
  965.             scrolleruplines( oldsel - num );
  966.         else
  967.             scrollerdownlines( num - oldsel );
  968.         /*setscrollertop(num);*/
  969.         return;
  970.     }
  971.  
  972.     if( num < 0 )
  973.         num = 0;
  974.     if( num >= numentries )
  975.         num = numentries - 1;
  976.  
  977.     if( num != oldsel )
  978.         storecurrentsel();
  979.  
  980.     currentsel = num;
  981.     /* Alte demarkieren */
  982.     displayscrollerline( oldsel - currenttop );
  983. }
  984.  
  985. void displaycurrentline( void )
  986. {
  987.     displayscrollerline( currentsel - currenttop );
  988. }
  989.  
  990. static void scrollerup( void )
  991. {
  992.     if( scrollermode == 2 )
  993.     {
  994.         if( currentsel > 0 )
  995.         {
  996.             setscrollercurrent( currentsel - 1 );
  997.             //findtopnode_before( 1 );
  998.         }
  999.         return;
  1000.     }
  1001.  
  1002.     if( currenttop )
  1003.     {
  1004.         currenttop--;
  1005.         findtopnode_before( 1 );
  1006.         ClipBlit( rp, 0, topoffs, rp, 0, topoffs+fontysize, screenxsize-16,(screenlines-1)*fontysize, 0xc0 );
  1007.         displayscrollerline( 0 );
  1008.         updateprop();
  1009.     }
  1010. }
  1011.  
  1012. static void scrollerdown(void)
  1013. {
  1014.     int x;
  1015.  
  1016.     if( scrollermode == 2 )
  1017.     {
  1018.         if( currentsel < ( numentries - screenlines ) )
  1019.         {
  1020.             setscrollercurrent( currentsel + 1 );
  1021.             //findtopnode_next( 1 );
  1022.         }
  1023.         return;
  1024.     }
  1025.  
  1026.     x=max(numentries-screenlines,0);
  1027.     if(currenttop<x)
  1028.     {
  1029.         currenttop++;
  1030.         findtopnode_next( 1 );
  1031.         ClipBlit( rp,0,topoffs+fontysize, rp,0,topoffs, screenxsize-16,(screenlines-1)*fontysize, 0xc0 );
  1032.         displayscrollerline( screenlines - 1);
  1033.         updateprop();
  1034.     }
  1035. }
  1036.  
  1037.  
  1038.  
  1039. void showcurrentitem( void )
  1040. {
  1041.     int total;
  1042.     int sj;
  1043.     int newct;
  1044.     int delta;
  1045.     int ld = lastdir;
  1046.  
  1047.     lastdir = -1;
  1048.  
  1049.     if( scrollermode == 2 )
  1050.         return;
  1051.  
  1052.     if( currenttop < 0 )
  1053.     {
  1054.         currenttop = 0;
  1055.         findtopnode();
  1056.         displayscroller();
  1057.         updateprop();
  1058.     }
  1059.  
  1060.     sj = ( ( prefs.flags2 & MDF2_SCROLLJUMP ) && ( scrollermode != 2 ) ) ? 5 : 1;
  1061.  
  1062.     /* Prⁿfen, ob Cursor im Fenster ist */
  1063.  
  1064.     switch( ld )
  1065.     {
  1066.         case LDD:
  1067.             if( currentsel < ( currenttop + screenlines - sj ) )
  1068.                 return;
  1069.             break;
  1070.  
  1071.         case LDU:
  1072.             if( currentsel >= currenttop + sj )
  1073.                 return;
  1074.             break;
  1075.  
  1076.         default:
  1077.             if( currentsel >= currenttop &&
  1078.                 currentsel < ( currenttop + screenlines ) )
  1079.                     return;
  1080.             break;
  1081.  
  1082.     }
  1083.  
  1084.     if( ( currentsel <= currenttop ) || ( ld == LDU ) )
  1085.     {
  1086.         newct = max( currentsel - sj + 1, 0 );
  1087.         delta = currenttop - newct;
  1088.         scrolleruplines( delta );
  1089.         return;
  1090.     }
  1091.     else
  1092.     {
  1093.         total = numentries;
  1094.         newct = min( currentsel - screenlines + sj, total - screenlines );
  1095.         delta = currenttop - newct;
  1096.         scrollerdownlines( -delta );
  1097.         return;
  1098.     }
  1099. }
  1100.  
  1101. int getscrollercurrent(void)
  1102. {
  1103.     return(currentsel);
  1104. }
  1105.  
  1106. void setscrollertop(int top)
  1107. {
  1108.     UWORD total = numentries;
  1109.     UWORD hidden;
  1110.  
  1111.     hidden = max( total - screenlines, 0 );
  1112.     if( top > hidden )
  1113.         top = hidden;
  1114.     if( top == currenttop )
  1115.         return;
  1116.     currenttop = top;
  1117.     findtopnode();
  1118.     propinfo.VertPot=(hidden>0)?(((ULONG)top*MAXPOT)/hidden):0;
  1119.     updateprop();
  1120.     displayscroller();
  1121. }
  1122.  
  1123. void normalizescroller( void )
  1124. {
  1125.     if( currentsel < 0 )
  1126.         return;
  1127.     if( currentsel < currenttop )
  1128.     {
  1129.         currenttop = currentsel;
  1130.         findtopnode();
  1131.     }
  1132.     if( currentsel >= currenttop + screenlines )
  1133.     {
  1134.         currenttop = currentsel - screenlines + 1;
  1135.         findtopnode();
  1136.     }
  1137. }
  1138.  
  1139.  
  1140. ULONG getscrollerstate(void)
  1141. {
  1142.     ULONG r=(currentsel|(currenttop<<16));
  1143.     return(r);
  1144. }
  1145.  
  1146. void setscrollerstate( ULONG r )
  1147. {
  1148.     currenttop=~0;
  1149.     currentsel= r & 0xffff;
  1150.     setscrollertop( r >> 16 );
  1151. }
  1152.  
  1153. struct si {
  1154.     struct List *l;
  1155.     ULONG mode;
  1156.     USHORT currenttop,currentsel;
  1157. };
  1158.  
  1159. void *pushscs(void)
  1160. {
  1161.     struct si *si=LibAllocPooled(miscmempool,sizeof(struct si));
  1162.  
  1163.     if(!si) return(0);
  1164.     si->mode=scrollermode;
  1165.     si->currenttop=currenttop;
  1166.     si->currentsel=currentsel;
  1167.     si->l=currentlist;
  1168.     return(si);
  1169. }
  1170.  
  1171. void popscs(void *sip)
  1172. {
  1173.     struct si *si=sip;
  1174.  
  1175.     if(!si) return;
  1176.     setupscroller(si->l,si->mode);
  1177.     currentsel=si->currentsel;
  1178.     currenttop=~0;
  1179.     setscrollertop(si->currenttop);
  1180.     LibFreePooled(miscmempool,si,sizeof(struct si));
  1181. }
  1182.  
  1183. void popscsnv(void *sip)
  1184. {
  1185.     struct si *si=sip;
  1186.  
  1187.     if(!si) return;
  1188. //    setupscroller(si->l,si->mode);
  1189.     currentlist = si->l;
  1190.     scrollermode = si->mode; 
  1191.     currentsel = si->currentsel;
  1192.     currenttop = si->currenttop;
  1193.     findtopnode();
  1194.     LibFreePooled(miscmempool,si,sizeof(struct si));
  1195. }
  1196.  
  1197. void scrollerresize( void )
  1198. {
  1199.     static UWORD lastwinx, lastwiny;
  1200.  
  1201.     if( wbwindow && ( w->Height != lastwiny || w->Width != lastwinx ) )
  1202.     {
  1203.         recalcwindowsize();
  1204.         if( w->Width != lastwinx )
  1205.             makescrollergads();
  1206.         lastwinx = w->Width;
  1207.         lastwiny = w->Height;
  1208.         updateprop();
  1209.         sabd( rp, 0, 0, JAM1 );
  1210.         RectFill( rp, 0, topoffs, screenxsize, w->GZZHeight );
  1211.  
  1212.         if( scrollermode == 1 )
  1213.             makevnodemlist( currentlist );
  1214.  
  1215.         displayscroller();
  1216.     }
  1217. }
  1218.  
  1219. static void resetmark( void )
  1220. {
  1221.     if( mark_xs >= 0 )
  1222.     {
  1223.         mark_xs = mark_ys = mark_xe = mark_ye = -1;
  1224.         OffMenu( w, FULLMENUNUM( 3, 22, NOSUB ) );
  1225.         displayscrollertxt();
  1226.     }
  1227. }
  1228.  
  1229. void doscrollerclipboard( void )
  1230. {
  1231.     struct dnode *n;
  1232.     int t;
  1233.     int len = 0, la = 0, c;
  1234.     char *p;
  1235.     static struct IOClipReq *iocr;
  1236.     struct MsgPort *iop;
  1237.     static ULONG iffheader[]á= {
  1238.         MAKE_ID('F','O','R','M'), 0,
  1239.         MAKE_ID('F','T','X','T'),
  1240.         MAKE_ID('C','H','R','S'), 0
  1241.     };
  1242.  
  1243.     if( scrollermode != 2 && mark_xs < 0 )
  1244.     {
  1245.         displaybeep();
  1246.         return;
  1247.     }
  1248.  
  1249.     if( !iocr )
  1250.         iocr = LibAllocPooled( miscmempool, sizeof( *iocr ) );
  1251.     else
  1252.         memset( iocr, 0, sizeof( *iocr ) );
  1253.  
  1254.     if( mark_ys > mark_ye )
  1255.     {
  1256.         t = mark_ys;
  1257.         mark_ys = mark_ye;
  1258.         mark_ye = t;
  1259.  
  1260.         t = mark_xs;
  1261.         mark_xs = mark_xe;
  1262.         mark_xe = t;
  1263.     }
  1264.     if( mark_ys == mark_ye )
  1265.     {
  1266.         if( mark_xs > mark_xe )
  1267.         {
  1268.             t = mark_xs;
  1269.             mark_xs = mark_xe;
  1270.             mark_xe = t;
  1271.         }
  1272.     }
  1273.  
  1274.     for( c = mark_ys; c <= mark_ye; c++ )
  1275.     {
  1276.         n = ( struct dnode * ) GetEntry( currentlist, c );
  1277.         if( n )
  1278.             p = n->txt;
  1279.         else
  1280.             p = "";
  1281.  
  1282.         len += strlen( p ) + 1;
  1283.         if( c == mark_ys )
  1284.             len -= mark_xs;
  1285.         if( c == mark_ye )
  1286.             len -= strlen( p ) - mark_xe;
  1287.     }
  1288.  
  1289.     if( len & 1 )
  1290.         la = 1;
  1291.  
  1292.     // Open Clipboard
  1293.     iop = CreatePort( NULL, 0 );
  1294.     iocr->io_Message.mn_ReplyPort = iop;
  1295.  
  1296.     if( OpenDevice( "clipboard.device", 0, iocr, 0 ) )
  1297.     {
  1298.         askreq( "\"clipboard.device\" konnte nicht\nge÷ffnet werden.", "Abbruch" );
  1299.         DeletePort( iop );
  1300.         return;
  1301.     }
  1302.  
  1303.     iffheader[á1 ]á= len + la + 12;
  1304.     iffheader[á4 ]á= len;
  1305.  
  1306.     iocr->io_Command = CMD_WRITE;
  1307.     iocr->io_Data = iffheader;
  1308.     iocr->io_Length = 20;
  1309.     DoIO( iocr );
  1310.  
  1311.     for( c = mark_ys; c <= mark_ye; c++ )
  1312.     {
  1313.         n = ( struct dnode * ) GetEntry( currentlist, c );
  1314.         if( n )
  1315.             p = n->txt;
  1316.         else
  1317.             p = "";
  1318.  
  1319.         len = strlen( p );
  1320.         if( c == mark_ye )
  1321.             len -= strlen( p ) - mark_xe;
  1322.         if( c == mark_ys )
  1323.         {
  1324.             p = &p[ámark_xs ];
  1325.             len -= mark_xs;
  1326.         }
  1327.  
  1328.         if( strlen( p ) )
  1329.         {
  1330.             iocr->io_Command = CMD_WRITE;
  1331.             iocr->io_Data = p;
  1332.             iocr->io_Length = strlen( p );
  1333.             DoIO( iocr );
  1334.         }
  1335.         iocr->io_Command = CMD_WRITE;
  1336.         iocr->io_Data = "\n";
  1337.         iocr->io_Length = 1;
  1338.         DoIO( iocr );
  1339.     }
  1340.  
  1341.     iocr->io_Command = CMD_UPDATE;
  1342.     DoIO( iocr );
  1343.  
  1344.     CloseDevice( iocr );
  1345.     DeletePort( iop );
  1346.  
  1347.     resetmark();
  1348. }
  1349.  
  1350. static void handletxtsel( struct IntuiMessage *im, int startline )
  1351. {
  1352.     int startcol;
  1353.     int Done = FALSE;
  1354.     struct IntuiMessage cim;
  1355.     int mousex = im->MouseX, mousey = im->MouseY;
  1356.     int cx, cy;
  1357.     int oldcy = -1, oldcx = -1;
  1358.     struct dnode *n;
  1359.  
  1360.     if( wbwindow )
  1361.     {
  1362.         mousex -= w->BorderLeft;
  1363.         mousey -= w->BorderTop;
  1364.     }
  1365.     startcol = mousex / fontxsize;
  1366.  
  1367.     n = ( struct dnode * ) GetEntryFromHere( topnode, startline );
  1368.  
  1369.     if( !n || !n->txt )
  1370.         startcol = 0;
  1371.     else
  1372.         startcol = min( startcol, strlen( n->txt ) - 1 );
  1373.  
  1374.     resetmark();
  1375.     OnMenu( w, FULLMENUNUM( 3, 22, NOSUB ) );
  1376.     mark_xs = mark_xe = startcol;
  1377.     mark_ys = mark_ye = startline + currenttop;
  1378.  
  1379.     displayscrollerlinetxt( startline );
  1380.  
  1381.     ReportMouse( TRUE, w );
  1382.     w->Flags |= WFLG_RMBTRAP;
  1383.  
  1384.     while( !Done )
  1385.     {
  1386.         while( !( im = GetIMsg( w->UserPort ) ) )
  1387.             WaitPort( w->UserPort );
  1388.         cim = *im;
  1389.         ReplyMsg( im );
  1390.  
  1391.         if( cim.Class == MOUSEBUTTONS )
  1392.         {
  1393.             if( cim.Code == SELECTUP )
  1394.                 Done = TRUE;
  1395.             else if( cim.Code == MENUDOWN )
  1396.                 Done = 2;
  1397.         }
  1398.         else if( cim.Class == MOUSEMOVE )
  1399.         {
  1400.             mousex = cim.MouseX;
  1401.             mousey = cim.MouseY;
  1402.             if( wbwindow )
  1403.             {
  1404.                 mousex -= w->BorderLeft;
  1405.                 mousey -= w->BorderTop;
  1406.             }
  1407.         }
  1408.         if( cim.Class == INTUITICKS || cim.Class == MOUSEMOVE )
  1409.         {
  1410.             cx = mousex / fontxsize;
  1411.             cy = ( mousey - (int)topoffs ) / (int)fontysize;
  1412.  
  1413.             if( cx >= screencols )
  1414.                 cx = screencols - 1;
  1415.  
  1416.             if( cy < 0 )
  1417.             {
  1418.                 scrollerup();
  1419.                 cy = 0;
  1420.             }
  1421.             else if( cy >= screenlines )
  1422.             {
  1423.                 scrollerdown();
  1424.                 cy = screenlines - 1;
  1425.             }
  1426.             n = ( struct dnode * ) GetEntryFromHere( topnode, cy );
  1427.             if( n && n->txt )
  1428.             {
  1429.                 mark_xe = min( cx, strlen( n->txt ) );
  1430.             }
  1431.             else
  1432.                 mark_xe = 0;
  1433.             mark_ye = cy + currenttop;
  1434.  
  1435.             if( mark_xe != oldcx || mark_ye != oldcy )
  1436.             {
  1437.                 if( mark_ye != oldcy )
  1438.                 {
  1439.                     displayscrollertxt();
  1440.                 }
  1441.                 else
  1442.                 {
  1443.                     displayscrollerlinetxt( oldcy - currenttop );
  1444.                 }
  1445.             }
  1446.             oldcx = mark_xe;
  1447.             oldcy = mark_ye;            
  1448.         }
  1449.     }
  1450.  
  1451.     w->Flags &= ~WFLG_RMBTRAP;
  1452.     ReportMouse( FALSE, w );
  1453.  
  1454.     if( Done == 2 )
  1455.         resetmark();
  1456.  
  1457. }
  1458.  
  1459. int scrollerdoclick( struct IntuiMessage *im )
  1460. {
  1461.     int l;
  1462.     static int lastline;
  1463.     static ULONG seconds,micros;
  1464.     struct Node *n;
  1465.     int rc=0;
  1466.     UWORD mousex, mousey;
  1467.  
  1468.     if( !im )
  1469.     {
  1470.         seconds = micros = 0;
  1471.         return(0);
  1472.     }
  1473.  
  1474.     mousex = im->MouseX;
  1475.     mousey = im->MouseY;
  1476.  
  1477.     if( wbwindow )
  1478.     {
  1479.         mousex -= w->BorderLeft;
  1480.         mousey -= w->BorderTop;
  1481.  
  1482.         if( mousex < 0 || mousey < 0 || mousex >= screenxsize || mousey >= w->GZZHeight )
  1483.             return( 0 );
  1484.     }
  1485.  
  1486.     if( im->Code == MIDDLEDOWN )
  1487.     {
  1488.         im->Code = SELECTDOWN;
  1489.         im->Qualifier = QSHIFT;
  1490.     }
  1491.  
  1492.     if( im->Code == SELECTDOWN )
  1493.     {
  1494.         if(scrollermode>=1 && scrollermode<=3 && mousex<2 && mousey>22)
  1495.             return( -1 );
  1496.         if(scrollermode>=0 && scrollermode<=3 && mousey >= scr->Height - 2 )
  1497.             return( -2 );
  1498.  
  1499.         l= ( mousey - topoffs ) / fontysize;
  1500.         if( l < 0 || l>=screenlines )
  1501.             return( 0 );
  1502.  
  1503.         /* Markieren */
  1504.         if( scrollermode == 2 )
  1505.         {
  1506.             handletxtsel( im, l );
  1507.         }
  1508.         else
  1509.         {
  1510.             if( im->Qualifier & QSHIFT )
  1511.             {
  1512.                 n=GetEntryFromHere( topnode,l );
  1513.                 if(n)
  1514.                 {
  1515.                     if(scrollermode && scrollermode !=3 )
  1516.                          ((struct vmail*)n)->sel^=0xff;
  1517.                     else
  1518.                         n->ln_Type^=~0;
  1519.                     displayscrollerline(l);
  1520.                 }
  1521.             }
  1522.             else
  1523.             {
  1524.                 setscrollercurrent( currenttop + l );
  1525.                 if( DoubleClick( seconds, micros, 
  1526.                          im->Seconds,
  1527.                          im->Micros ) && l == lastline ) rc=1;
  1528.             }
  1529.             lastline=l;
  1530.             seconds    = im->Seconds;
  1531.             micros    = im->Micros;
  1532.         }
  1533.     }
  1534.     return(rc);
  1535. }
  1536.  
  1537. void scrollerdomove( struct IntuiMessage *im )
  1538. {
  1539.     UWORD total=numentries;
  1540.     UWORD new, hidden;
  1541.     int delta, dir = 0;
  1542.  
  1543.     hidden=max(total-screenlines,0);
  1544.     new=(((ULONG)hidden*propinfo.VertPot)+(MAXPOT/2))>>16;
  1545.  
  1546.     delta = currenttop - new;
  1547.     if( !delta )
  1548.         return;
  1549.     else if( delta < 0 )
  1550.     {
  1551.         dir = 1;
  1552.         delta = -delta;
  1553.     }
  1554.  
  1555.     nopropupdate = 1;
  1556.  
  1557.     if( dir )
  1558.         scrollerdownlines( delta );
  1559.     else
  1560.         scrolleruplines( delta );
  1561.  
  1562.     nopropupdate = 0;
  1563. }
  1564.  
  1565. /* called on GADGETDOWN */
  1566. int scrollerdogad(struct IntuiMessage *im)
  1567. {
  1568.     struct Gadget *g=im->IAddress;
  1569.     long doup,class,tickcount=4;
  1570.  
  1571.     if( g->GadgetID >= 256 )
  1572.     {
  1573.         if( im->Class == GADGETUP )
  1574.             return( (int) g->UserData );
  1575.         else
  1576.             return( 0 );
  1577.     }
  1578.  
  1579.     doup = g->GadgetID - 2;
  1580.     if( doup < 0 )
  1581.     {
  1582.         scrollerdomove( im );
  1583.         return( 0 );
  1584.     }
  1585.  
  1586.     if( doup )
  1587.         scrollerup();
  1588.     else
  1589.         scrollerdown();
  1590.  
  1591.     for(;;)
  1592.     {
  1593.         while(!(im=(struct IntuiMessage*)GetMsg(w->UserPort)))
  1594.             mWaitPort(w->UserPort);
  1595.         class=im->Class;
  1596.         ReplyMsg(im);
  1597.         if( class != INTUITICKS )
  1598.             break;
  1599.         if( ! ( --tickcount ) )
  1600.         {
  1601.             tickcount = 1;
  1602.             if( doup )
  1603.                 scrollerup();
  1604.             else
  1605.                 scrollerdown();
  1606.         }
  1607.     }
  1608.     return( 0 );
  1609. }
  1610.  
  1611. extern long mmcount;
  1612. static int disableinc;
  1613.  
  1614. void xscroller( void )
  1615. {
  1616.     disableinc = mmcount;    
  1617. }
  1618.  
  1619. void incscroller( void )
  1620. {
  1621.     if( disableinc )
  1622.     {
  1623.         disableinc = FALSE;
  1624.         return;
  1625.     }
  1626.  
  1627.     if( !( prefs.flags2 & MDF2_AUTOLF ) )
  1628.         return;
  1629.  
  1630.     setscrollercurrent( currentsel + 1 );
  1631.     lastdir = LDD;
  1632.     showcurrentitem();
  1633. }
  1634.  
  1635. extern void savesel( void );
  1636.  
  1637. static void mb_findscrollerentrybyrawkey( char key, int dir )
  1638. {
  1639.     struct mbrett *mb = ( struct mbrett * ) GetEntry( currentlist, currentsel );
  1640.     struct mbrett *oldmb = mb;
  1641.  
  1642.     if( key >= '1' && key <= '4'á)
  1643.     {
  1644.         setscrollercurrent( key - '1' );
  1645.         showcurrentitem();
  1646.         return;
  1647.     }
  1648.  
  1649.     mb = ( struct mbrett * ) ( dir ? mb->n.ln_Pred : mb->n.ln_Succ );
  1650.     if( !dir && !mb->n.ln_Succ )
  1651.         mb = ( struct mbrett * ) currentlist->lh_Head;
  1652.     else if( dir && !mb->n.ln_Pred )
  1653.         mb = ( struct mbrett * ) currentlist->lh_TailPred;
  1654.  
  1655.     while( mb != oldmb )
  1656.     {
  1657.         /* NΣchster gefunden! */
  1658.         if( mb->b.name[ 0 ]á== key || 
  1659.             ( ( mb->b.name[á0 ]á== '/' ) && mb->b.name[á1 ]á== key ) )
  1660.         {
  1661.             setscrollercurrent( GetEntryNum( currentlist, mb ) );
  1662.             showcurrentitem();
  1663.             return;
  1664.         }
  1665.  
  1666.         mb = ( struct mbrett * ) ( dir ? mb->n.ln_Pred : mb->n.ln_Succ );
  1667.         if( !dir && !mb->n.ln_Succ )
  1668.             mb = ( struct mbrett * ) currentlist->lh_Head;
  1669.         else if( dir && !mb->n.ln_Pred )
  1670.             mb = ( struct mbrett * ) currentlist->lh_TailPred;
  1671.     }
  1672. }
  1673. static void maps_findscrollerentrybyrawkey( char key, int dir )
  1674. {
  1675.     struct mvnode *mb = ( struct mvnode * ) GetEntry( currentlist, currentsel );
  1676.     struct mvnode *oldmb = mb;
  1677.  
  1678.     mb = ( struct mvnode * ) ( dir ? mb->n.mln_Pred : mb->n.mln_Succ );
  1679.     if( !dir && !mb->n.mln_Succ )
  1680.         mb = ( struct mvnode * ) currentlist->lh_Head;
  1681.     else if( dir && !mb->n.mln_Pred )
  1682.         mb = ( struct mvnode * ) currentlist->lh_TailPred;
  1683.  
  1684.     while( mb != oldmb )
  1685.     {
  1686.         /* NΣchster gefunden! */
  1687.         if( mb->txt[ prefs.maps_list_boffs ]á== key || 
  1688.             ( ( mb->txt[áprefs.maps_list_boffs ]á== '/' ) && mb->txt[áprefs.maps_list_boffs + 1 ]á== key ) )
  1689.         {
  1690.             setscrollercurrent( GetEntryNum( currentlist, mb ) );
  1691.             showcurrentitem();
  1692.             return;
  1693.         }
  1694.  
  1695.         mb = ( struct mvnode * ) ( dir ? mb->n.mln_Pred : mb->n.mln_Succ );
  1696.         if( !dir && !mb->n.mln_Succ )
  1697.             mb = ( struct mvnode * ) currentlist->lh_Head;
  1698.         else if( dir && !mb->n.mln_Pred )
  1699.             mb = ( struct mvnode * ) currentlist->lh_TailPred;
  1700.     }
  1701. }
  1702.  
  1703. static void findscrollerentrybyrawkey( char key, int dir )
  1704. {
  1705.     switch( scrollermode )
  1706.     {
  1707.         case 0:
  1708.             mb_findscrollerentrybyrawkey( key, dir );
  1709.             break;
  1710.  
  1711.         case 3:
  1712.             maps_findscrollerentrybyrawkey( key, dir );
  1713.             break;
  1714.     }
  1715. }
  1716.  
  1717. int scrollerdokey(struct IntuiMessage *im)
  1718. {
  1719.     struct mbrett *n;
  1720.     int scrolljump = ( ( prefs.flags2 & MDF2_SCROLLJUMP ) && ( scrollermode != 2 ) ) ? 5 : 1;
  1721.  
  1722.     //
  1723.     // <alt>-Buchstabe springt zum entsprechenden Eintrag
  1724.     //
  1725.  
  1726.     if( im->Qualifier & ( IEQUALIFIER_LALT | IEQUALIFIER_RALT ) )
  1727.     {
  1728.         char *vankey;
  1729.         struct IntuiMessage im2 = *im;
  1730.         int isshift = im->Qualifier & QSHIFT;
  1731.  
  1732.         /* Funktionstasten */
  1733.         if( im2.Code >= 0x50 && im2.Code <= 0x59 )
  1734.         {
  1735.             ULONG *cp = &posarray[á( scrollermode * 10 ) + im2.Code - 0x50 ];
  1736.  
  1737.             if( im->Qualifier & IEQUALIFIER_LALT )
  1738.             {
  1739.                 setscrollerstate( *cp );
  1740.             }
  1741.             else
  1742.             {
  1743.                 *cp = getscrollerstate();
  1744.             }
  1745.             return( 0 );
  1746.         }
  1747.  
  1748.         im2.Qualifier = 0;
  1749.         vankey = rawkeyconvert( &im2 );
  1750.  
  1751.         if( *vankey && !isspace( *vankey ) ) 
  1752.             findscrollerentrybyrawkey( toupper( *vankey ), isshift );
  1753.  
  1754.         return( 0 );    // Event gefressen...
  1755.     }
  1756.  
  1757.     switch(im->Code)
  1758.     {
  1759.         case 0: /* deselect */
  1760.             if(scrollermode==2) break;
  1761.             if(scrollermode==1) {
  1762.                 struct vmail *m=(struct vmail*)currentlist->lh_Head;
  1763.                 savesel();
  1764.                 while(m->n.mln_Succ)
  1765.                 {
  1766.                     m->sel=0;
  1767.                     m=(struct vmail*)m->n.mln_Succ;
  1768.                 }
  1769.             }
  1770.             else
  1771.             {
  1772.                 n=(struct mbrett*)currentlist->lh_Head;
  1773.                 while(n->n.ln_Succ)
  1774.                 {
  1775.                     n->n.ln_Type=0;
  1776.                     n=(struct mbrett*)n->n.ln_Succ;
  1777.                 }
  1778.             }
  1779.  
  1780.             displayscroller();
  1781.             break;
  1782.  
  1783.         case 0x5d:    // History
  1784.             scrollerhis();
  1785.             return( 0 );
  1786.  
  1787.         case 0x41: /* Backspace */ im->Qualifier|=QSHIFT;
  1788.  
  1789.         case 0x3d:
  1790.         case 0x3e:
  1791.         case 0x3f:
  1792.         case 0x4c: /* up */
  1793.             if(im->Qualifier&QSHIFT || im->Code==0x3f) setscrollercurrent2(currentsel-screenlines+scrolljump);
  1794.             else if(im->Qualifier&QCTRL || im->Code==0x3d) setscrollercurrent2(0);
  1795.             else setscrollercurrent2(currentsel-1); 
  1796.             lastdir = LDU;
  1797.             showcurrentitem();
  1798.             displaycurrentline();
  1799.             return(0);
  1800.         
  1801.         case 0x1d:
  1802.         case 0x1e:
  1803.         case 0x1f:
  1804.         case 0x4d: /* down */
  1805.             if((im->Qualifier&QSHIFT) || im->Code==0x1f) setscrollercurrent2(currentsel+screenlines-scrolljump);
  1806.             else if( ( im->Qualifier&QCTRL ) || im->Code==0x1d) setscrollercurrent2(numentries-1);
  1807.             else setscrollercurrent2( currentsel + 1 );
  1808.             lastdir = LDD;
  1809.             showcurrentitem();
  1810.             displaycurrentline();
  1811.             return(0);
  1812.  
  1813.         case 0x40: /* space */
  1814.             if(scrollermode==2) break;
  1815.             n=(struct mbrett*)GetEntry(currentlist,currentsel);
  1816.             if(n && n->n.ln_Succ) {
  1817.                 if(scrollermode&&scrollermode!=3) ((struct vmail*)n)->sel^=0xff;
  1818.                 else n->n.ln_Type^=~0;
  1819.                 displaycurrentline();
  1820.                 incscroller();
  1821.             }
  1822.             return(1);
  1823.     }
  1824.  
  1825.     return(-1);
  1826. }
  1827.  
  1828. void calcnumentries( void )
  1829. {
  1830.     numentries = GetNumEntries( currentlist );
  1831. }
  1832.  
  1833. void resetscroller( void )
  1834. {
  1835.     numentries = GetNumEntries( currentlist );
  1836.     if( currenttop + screenlines >= numentries )
  1837.         currenttop = max( 0, numentries - screenlines );
  1838.     recalcwindowsize();
  1839.     makescrollergads();
  1840.     findtopnode();
  1841.     updateprop();
  1842.     displayscroller();
  1843. }
  1844.  
  1845. static void scrolleruplines( int l )
  1846. {
  1847.     int remain;
  1848.  
  1849.     l = min( currenttop, l );
  1850.     if( l < 1 ) 
  1851.         return;
  1852.     remain = screenlines - l;
  1853.  
  1854.     if( scrollermode == 2 )
  1855.     {
  1856.         storecurrentsel();
  1857.         currentsel -= l;
  1858.     }
  1859.  
  1860.     if( remain < 9 )
  1861.     {
  1862.         setscrollertop( currenttop - l );
  1863.         return;
  1864.     }
  1865.  
  1866.     ClipBlit( rp, 0, topoffs,
  1867.               rp, 0, topoffs + ( fontysize * ( screenlines - remain ) ),
  1868.                   screenxsize - 16,
  1869.                   ( remain ) * fontysize,
  1870.                 0xc0
  1871.     );
  1872.  
  1873.     currenttop -= l;
  1874.     findtopnode_before( l );
  1875.  
  1876.     /* Redraw missing entries */
  1877.     while( l-- )
  1878.         displayscrollerline( l );
  1879.  
  1880.     updateprop();
  1881. }
  1882.  
  1883. static void scrollerdownlines( int l )
  1884. {
  1885.     int remain;
  1886.     int c;
  1887.  
  1888.     c = max( numentries - screenlines, 0 );
  1889.     if( currenttop + l > c )
  1890.         l = c - currenttop;
  1891.  
  1892.     if( l < 1 ) 
  1893.         return;
  1894.  
  1895.     remain = screenlines - l;
  1896.  
  1897.     if( scrollermode == 2 )
  1898.     {
  1899.         storecurrentsel();
  1900.         currentsel += l;
  1901.     }
  1902.  
  1903.     if( remain < 5 )
  1904.     {
  1905.         setscrollertop( currenttop + l );
  1906.         return;
  1907.     }
  1908.  
  1909.     currenttop += l;
  1910.     findtopnode_next( l );
  1911.  
  1912.     ClipBlit( rp, 0, topoffs + ( fontysize * ( screenlines - remain ) ),
  1913.               rp, 0, topoffs,
  1914.                   screenxsize - 16,
  1915.                   ( remain ) * fontysize,
  1916.     0xc0 );
  1917.  
  1918.     /* Redraw missing entries */
  1919.     while( l-- )
  1920.         displayscrollerline( screenlines - l - 1 );
  1921.  
  1922.     updateprop();
  1923.  
  1924. }
  1925.  
  1926. /*int getscrollertop( void )
  1927. {
  1928.     return( currenttop );
  1929. }
  1930. */
  1931.  
  1932. int getscrollerselect( void )
  1933. {
  1934.     struct Node *obj = GetEntry( currentlist, currentsel );
  1935.  
  1936.     if( !obj )
  1937.         return( FALSE );
  1938.  
  1939.     if( !scrollermode )
  1940.         return( obj->ln_Type );
  1941.     else
  1942.         return( ( ( struct vmail * ) obj) -> sel );
  1943.  
  1944. }
  1945.  
  1946. void scrollerselect( int mode, int which )
  1947. {
  1948.     struct Node *obj;
  1949.     UBYTE flg = which ? 0xff : 0;
  1950.  
  1951.     if( !mode )
  1952.         obj = GetEntry( currentlist, currentsel );
  1953.     else
  1954.         obj = currentlist->lh_Head;
  1955.  
  1956.     while( obj->ln_Succ )
  1957.     {
  1958.         if( scrollermode )
  1959.             ((struct vmail*)obj)->sel = flg;
  1960.         else
  1961.             obj->ln_Type = flg;
  1962.  
  1963.         if( mode )
  1964.             obj = obj->ln_Succ;
  1965.         else
  1966.             break;
  1967.     }
  1968.  
  1969.     if( mode )
  1970.         displayscroller();
  1971.     else
  1972.         displaycurrentline();
  1973. }
  1974.