home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 3 / AACD03.BIN / AACD / Programming / Triton / Source / classes / listview.c < prev    next >
C/C++ Source or Header  |  1998-05-23  |  19KB  |  614 lines

  1. /*
  2.  *  OpenTriton -- A free release of the triton.library source code
  3.  *  Copyright (C) 1993-1998  Stefan Zeiger
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  */
  20.  
  21.  
  22. /****** triton.library/class_Listview ******
  23. *
  24. *   NAME
  25. *    class_Listview -- A GadTools Listview gadget
  26. *
  27. *   SUPERCLASS
  28. *    class_DisplayObject
  29. *
  30. *   SYNOPSIS
  31. *    TROB_Listview
  32. *
  33. *   ATTRIBUTES
  34. *    <Default>        : struct List *entries
  35. *                       [create, set]
  36. *    TRAT_Flags       : ULONG flags
  37. *                       - Listview type (mutually exclusive):
  38. *                         - TRLV_READONLY     : A read-only list
  39. *                         - TRLV_SELECT       : You may select an entry
  40. *                         - TRLV_SHOWSELECTED : Show selected entry
  41. *                       - TRLV_NOCURSORKEYS   : Don't use arrow keys
  42. *                       - TRLV_NONUMPADKEYS   : Don't use keypad keys
  43. *                       - TRLV_FWFONT         : Use the fixed-width font
  44. *                       - TRLV_NOGAP (V2)     : Leave no gap below the
  45. *                                               list but instead at the
  46. *                                               end of the group.
  47. *                       [create, set]
  48. *    TRAT_Value       : ULONG selected        : Currently selected entry
  49. *                                               (TRLV_SHOWSELECTED only)
  50. *                       [create, set, get]
  51. *    TRLV_Top         : ULONG top
  52. *                       [create, set, get]
  53. *    TRLV_VisibleLines: ULONG visiblelines    : Number of visible lines
  54. *                       [get]
  55. *    TRAT_MinWidth    : ULONG minwidth        : Minimum width
  56. *                                               (Default: 10 characters)
  57. *                       [create, set]
  58. *    TRAT_MinHeight   : ULONG minheight       : Minimum height
  59. *                                               (Default: 4 lines)
  60. *                       [create, set]
  61. *
  62. *   APPLICATION MESSAGES
  63. *    'Select' listviews send TRMS_ACTION messages. 'ShowSelected' lists
  64. *    send TRMS_NEWVALUE messages. trm_Data contains the ordinal number
  65. *    of the selected entry. trm_Qualifier&IEQUALIFIER_REPEAT is set if
  66. *    the user has double-clicked the specified listview entry.
  67. *
  68. ******/
  69.  
  70.  
  71. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  72. //////////////////////////////////////////////////////////////////////////////////////// Include our stuff //
  73. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  74.  
  75. #define TR_THIS_IS_TRITON
  76.  
  77. #include <libraries/triton.h>
  78. #include <clib/triton_protos.h>
  79. #include "/internal.h"
  80. #include "listview.def"
  81.  
  82.  
  83. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  84. ////////////////////////////////////////////////////////////////////////////////////////////// Object data //
  85. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  86.  
  87. #define OBJECT (&(object->DO.O))
  88. #define DISPLAYOBJECT (&(object->DO))
  89. #define LISTVIEW object
  90.  
  91.  
  92. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  93. //////////////////////////////////////////////////////////////////////////////////////// Helping functions //
  94. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  95.  
  96. #ifdef TR_OS39
  97.  
  98. LONG __regargs __inline TR_ListViewPos(struct Gadget *gadget, struct Window *window)
  99. {
  100.   LONG top;
  101.  
  102.   GT_GetGadgetAttrs(gadget, window, NULL, GTLV_Top, &top, TAG_END);
  103.   return top;
  104. }
  105.  
  106. ULONG __regargs __inline TR_GetBetterListviewHeight(struct TROD_Listview *object, ULONG oheight)
  107. {
  108.   ULONG bheight;
  109.  
  110.   LISTVIEW->DispLines=(oheight-4)/LISTVIEW->FontHeight;
  111.   bheight=LISTVIEW->FontHeight*LISTVIEW->DispLines+4;
  112.   return bheight;
  113. }
  114.  
  115. #else
  116.  
  117. LONG __regargs TR_ListViewPos(struct Gadget *gadget, struct Window *window)
  118. {
  119.   LONG top;
  120.  
  121.   if(TR_Global.trg_OSVersion<39) top=(LONG)(*(short *)(((char *)gadget)+sizeof(struct Gadget)+4));
  122.   else GT_GetGadgetAttrs(gadget, window, NULL, GTLV_Top, &top, TAG_END);
  123.   return top;
  124. }
  125.  
  126. ULONG __regargs TR_GetBetterListviewHeight(struct TROD_Listview *object, ULONG oheight)
  127. {
  128.   ULONG bheight;
  129.  
  130.   if(TR_Global.trg_OSVersion>=39) LISTVIEW->DispLines=(oheight-4)/LISTVIEW->FontHeight;
  131.   else LISTVIEW->DispLines=((oheight-8)/LISTVIEW->FontHeight)-1;
  132.   bheight=LISTVIEW->FontHeight*LISTVIEW->DispLines+4;
  133.   if(TR_Global.trg_OSVersion<39)
  134.     if(LISTVIEW->ShowSelected) bheight+=LISTVIEW->FontHeight;
  135.   return bheight;
  136. }
  137.  
  138. #endif
  139.  
  140.  
  141. void __regargs TR_ReadListviewPos(struct TROD_Listview *object)
  142. {
  143.   LISTVIEW->Top=
  144.     TR_ListViewPos((struct Gadget *)DISPLAYOBJECT->PrivData,OBJECT->Project->trp_Window);
  145. }
  146.  
  147.  
  148. BOOL __regargs TR_RethinkListview(struct TROD_Listview *object)
  149. {
  150.   BOOL newtop=FALSE;
  151.  
  152.   if(LISTVIEW->Value<LISTVIEW->Top)
  153.     {
  154.       LISTVIEW->Top=LISTVIEW->Value;
  155.       newtop=TRUE;
  156.     }
  157.   else if(LISTVIEW->Value>LISTVIEW->Top+LISTVIEW->DispLines-1)
  158.     {
  159.       LISTVIEW->Top=LISTVIEW->Value-LISTVIEW->DispLines+1;
  160.       newtop=TRUE;
  161.     }
  162.  
  163.   if(DISPLAYOBJECT->Installed) if(newtop)
  164.     GT_SetGadgetAttrs((struct Gadget *)DISPLAYOBJECT->PrivData,
  165.               OBJECT->Project->trp_Window,NULL,GTLV_Top,LISTVIEW->Top,TAG_END);
  166.  
  167.   return newtop;
  168. }
  169.  
  170.  
  171. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  172. ////////////////////////////////////////////////////////////////////////////////////////////////// Methods //
  173. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  174.  
  175. TR_METHOD(Listview,NEW,NewData)
  176. {
  177.   if(!TRDP_DisplayObject_NEW(object,messageid,data,metaclass->trc_SuperClass)) return NULL;
  178.  
  179.   if(!(LISTVIEW->MinWidth)) LISTVIEW->MinWidth=10;
  180.   if(!(LISTVIEW->MinHeight)) LISTVIEW->MinHeight=4;
  181.   LISTVIEW->LastEntry=0;
  182.   LISTVIEW->LastSeconds=0;
  183.   LISTVIEW->LastMicros=0;
  184.   LISTVIEW->DoubleClicked=FALSE;
  185.  
  186.   DISPLAYOBJECT->XResize=TRUE;
  187.   DISPLAYOBJECT->YResize=TRUE;
  188.  
  189.   data->project->trp_IDCMPFlags|=LISTVIEWIDCMP|ARROWIDCMP|SCROLLERIDCMP;
  190.  
  191.   LISTVIEW->ScrollWidth=max(CHECKBOX_HEIGHT,data->project->trp_TotalPropFontHeight)+5;
  192.  
  193.   if((LISTVIEW->Flags)&TRLV_FWFONT)
  194.     {
  195.       LISTVIEW->FontHeight=data->project->trp_FixedWidthFont->tf_YSize;
  196.       DISPLAYOBJECT->MinHeight=
  197.     LISTVIEW->FontHeight*LISTVIEW->MinHeight+4;
  198.       DISPLAYOBJECT->MinWidth=
  199.     LISTVIEW->ScrollWidth+(data->project->trp_FixedWidthFont->tf_XSize*(LISTVIEW->MinWidth+1))+1;
  200.     }
  201.   else
  202.     {
  203.       LISTVIEW->FontHeight=data->project->trp_TotalPropFontHeight;
  204.       DISPLAYOBJECT->MinHeight=
  205.     LISTVIEW->FontHeight*LISTVIEW->MinHeight+4;
  206.       DISPLAYOBJECT->MinWidth=
  207.     LISTVIEW->ScrollWidth+(data->project->trp_PropFont->tf_XSize*(LISTVIEW->MinWidth+1))+1;
  208.     }
  209.  
  210.   return (ULONG)object;
  211. }
  212.  
  213.  
  214. TR_METHOD(Listview,INSTALL,InstallData)
  215. {
  216.   UWORD fillbottom;
  217.  
  218.   TRDP_DisplayObject_INSTALL(object,messageid,data,metaclass->trc_SuperClass);
  219.   fillbottom=DISPLAYOBJECT->Top-1+TR_GetBetterListviewHeight(object,DISPLAYOBJECT->Height);
  220.   TR_InternalAreaFill(OBJECT->Project,NULL,DISPLAYOBJECT->Left,DISPLAYOBJECT->Top,
  221.               DISPLAYOBJECT->Left+DISPLAYOBJECT->Width-1,fillbottom,TRBF_NONE);
  222.   if((LISTVIEW->Flags)&TRLV_FWFONT)
  223.     OBJECT->Project->trp_NewGadget->ng_TextAttr=OBJECT->Project->trp_FixedWidthAttr;
  224.   DISPLAYOBJECT->PrivData=
  225.     (ULONG)TR_CreateGadgetTags(OBJECT->Project,
  226.                    OBJECT,
  227.                    LISTVIEW_KIND,
  228.                    DISPLAYOBJECT->Left,
  229.                    DISPLAYOBJECT->Top,
  230.                    DISPLAYOBJECT->Width,
  231.                    DISPLAYOBJECT->Height,
  232.                    GA_Disabled,      TR_DO_DISABLED,
  233.                    GTLV_Labels,      LISTVIEW->Entries,
  234.                    GTLV_Top,         LISTVIEW->Top,
  235.                    GTLV_ReadOnly,    LISTVIEW->ReadOnly,
  236.                    (LISTVIEW->ShowSelected)?GTLV_ShowSelected:TAG_IGNORE,NULL,
  237.                    GTLV_Selected,    LISTVIEW->Value,
  238.                    GTLV_ScrollWidth, LISTVIEW->ScrollWidth,
  239.                    TAG_END);
  240.   if((LISTVIEW->Flags)&TRLV_FWFONT)
  241.     OBJECT->Project->trp_NewGadget->ng_TextAttr=OBJECT->Project->trp_PropAttr;
  242.   if(DISPLAYOBJECT->PrivData) return 1L; else return NULL;
  243. }
  244.  
  245.  
  246. TR_METHOD(Listview,SETATTRIBUTE,SetAttributeData)
  247. {
  248.   switch(data->attribute)
  249.     {
  250.     case TRAT_Value:
  251.       if(LISTVIEW->Value!=data->value)
  252.     {
  253.       LISTVIEW->Value=data->value;
  254.       //--? if(LISTVIEW->ShowSelected) TR_RethinkListview(object);
  255.       if(DISPLAYOBJECT->Installed) GT_SetGadgetAttrs((struct Gadget *)DISPLAYOBJECT->PrivData,
  256.                              OBJECT->Project->trp_Window, NULL,
  257.                              GTLV_Selected,LISTVIEW->Value,TAG_END);
  258.     }
  259.       return 1;
  260.  
  261.     case TRLV_Top:
  262.       if(LISTVIEW->Top!=data->value)
  263.     {
  264.       LISTVIEW->Top=data->value;
  265.       if(LISTVIEW->ShowSelected) TR_RethinkListview(object);
  266.       if(DISPLAYOBJECT->Installed) GT_SetGadgetAttrs((struct Gadget *)DISPLAYOBJECT->PrivData,
  267.                              OBJECT->Project->trp_Window, NULL,
  268.                              GTLV_Top,LISTVIEW->Top,TAG_END);
  269.     }
  270.       return 1;
  271.  
  272.     case TRAT_MinWidth:
  273.       LISTVIEW->MinWidth=data->value;
  274.       return 1;
  275.  
  276.     case TRAT_MinHeight:
  277.       LISTVIEW->MinHeight=data->value;
  278.       return 1;
  279.  
  280.     case TRAT_Flags:
  281.       LISTVIEW->Flags=data->value;
  282.       if(LISTVIEW->Flags&TRLV_SHOWSELECTED)
  283.     { LISTVIEW->ShowSelected=TRUE; LISTVIEW->ReadOnly=FALSE; }
  284.       else if(LISTVIEW->Flags&TRLV_SELECT)
  285.     { LISTVIEW->ShowSelected=FALSE; LISTVIEW->ReadOnly=FALSE; }
  286.       else /* TRLV_READONLY */
  287.     { LISTVIEW->ShowSelected=FALSE; LISTVIEW->ReadOnly=TRUE; }
  288.       return 1;
  289.  
  290.     case 0:
  291.       LISTVIEW->Entries=(struct List *)(data->value);
  292.       if((LISTVIEW->Entries) && (LISTVIEW->Entries!=(struct List *)(~0)))
  293.     {
  294.       LISTVIEW->TotLines=TR_CountListEntries(LISTVIEW->Entries);
  295.       LISTVIEW->Value=
  296.         min(LISTVIEW->Value,LISTVIEW->TotLines-1);
  297.     }
  298.       if(DISPLAYOBJECT->Installed) GT_SetGadgetAttrs((struct Gadget *)DISPLAYOBJECT->PrivData,
  299.                              OBJECT->Project->trp_Window,NULL,
  300.                              GTLV_Labels,LISTVIEW->Entries,
  301.                              GTLV_Selected,LISTVIEW->Value,TAG_END);
  302.       return 1;
  303.  
  304.     default:
  305.       return TRDP_DisplayObject_SETATTRIBUTE(object,messageid,data,metaclass->trc_SuperClass);
  306.     }
  307. }
  308.  
  309.  
  310. TR_SIMPLEMETHOD(Listview,GETATTRIBUTE)
  311. {
  312.   switch((ULONG)data)
  313.   {
  314.     case TRAT_Value:
  315.       return LISTVIEW->Value;
  316.     case TRLV_Top:
  317.       TR_ReadListviewPos(LISTVIEW);
  318.       return LISTVIEW->Top;
  319.     case TRLV_VisibleLines:
  320.       return LISTVIEW->DispLines;
  321.     default:
  322.       return TRDP_DisplayObject_GETATTRIBUTE(object,messageid,data,metaclass->trc_SuperClass);
  323.   }
  324. }
  325.  
  326.  
  327. TR_SIMPLEMETHOD(Listview,DISABLED_ENABLED)
  328. {
  329.   GT_SetGadgetAttrs((struct Gadget *)DISPLAYOBJECT->PrivData,
  330.             OBJECT->Project->trp_Window,NULL,
  331.             GA_Disabled,TR_DO_DISABLED,TAG_END);
  332.   TR_ReadListviewPos(LISTVIEW);
  333.   return 1L;
  334. }
  335.  
  336.  
  337. TR_SIMPLEMETHOD(Listview,PREGTREMOVE)
  338. {
  339.   TR_ReadListviewPos(LISTVIEW);
  340.   return 1L;
  341. }
  342.  
  343.  
  344. TR_METHOD(Listview,KEYDOWN_REPEATEDKEYDOWN,EventData)
  345. {
  346.   BOOL sendmsg=FALSE, newval=FALSE, newtop=FALSE;
  347.   struct TR_Message *m;
  348.  
  349.   if(!(LISTVIEW->TotLines)) return 1; /* Empty listview */
  350.  
  351.   TR_ReadListviewPos(LISTVIEW);
  352.  
  353.   if(LISTVIEW->ShowSelected)
  354.     {
  355.       if(data->imsg->Code)
  356.         {
  357.           if(LISTVIEW->Value>0)
  358.         {
  359.           LISTVIEW->Value--;
  360.           sendmsg=TRUE;
  361.           newval=TRUE;
  362.         }
  363.         }
  364.       else
  365.         {
  366.           if(LISTVIEW->Value<LISTVIEW->TotLines-1)
  367.         {
  368.           LISTVIEW->Value++;
  369.           sendmsg=TRUE;
  370.           newval=TRUE;
  371.         }
  372.         }
  373.       TR_RethinkListview(object);
  374.     }
  375.   else /* Not ShowSelected */
  376.     {
  377.       if(data->imsg->Code)
  378.         {
  379.           if(LISTVIEW->Top>0)
  380.         {
  381.           LISTVIEW->Top--;
  382.           newtop=TRUE;
  383.         }
  384.         }
  385.       else
  386.         {
  387.           if(LISTVIEW->Top+LISTVIEW->DispLines<LISTVIEW->TotLines)
  388.         {
  389.           LISTVIEW->Top++;
  390.           newtop=TRUE;
  391.         }
  392.         }
  393.       if(newtop) GT_SetGadgetAttrs((struct Gadget *)DISPLAYOBJECT->PrivData,
  394.                    OBJECT->Project->trp_Window,NULL,GTLV_Top,LISTVIEW->Top,TAG_END);
  395.     }
  396.  
  397.   if(sendmsg) if(m=TR_CreateMsg(Self.DO.O.Project->trp_App))
  398.     {
  399.       m->trm_ID=DISPLAYOBJECT->ID;
  400.       m->trm_Class=TRMS_NEWVALUE;
  401.       m->trm_Data=LISTVIEW->Value;
  402.     }
  403.   if(newval)
  404.     {
  405.       GT_SetGadgetAttrs((struct Gadget *)DISPLAYOBJECT->PrivData,OBJECT->Project->trp_Window,NULL,
  406.             GTLV_Selected,LISTVIEW->Value,TAG_END);
  407.       TR_SetAttribute(OBJECT->Project,DISPLAYOBJECT->ID,TRAT_Value,LISTVIEW->Value);
  408.     }
  409.   return 1L;
  410. }
  411.  
  412.  
  413. TR_METHOD(Listview,EVENT,EventData)
  414. {
  415.   BOOL sendmsg=FALSE;
  416.   struct IntuiMessage *imsg;
  417.   UWORD ckeys=1,nkeys=1;
  418.   ULONG oldval, oldtop;
  419.   struct TR_Message *m;
  420.  
  421.   imsg=data->imsg;
  422.   if((LISTVIEW->Flags)&TRLV_NOCURSORKEYS) ckeys=0;
  423.   if((LISTVIEW->Flags)&TRLV_NONUMPADKEYS) nkeys=0;
  424.  
  425.   switch(imsg->Class)
  426.     {
  427.     case IDCMP_GADGETUP:
  428.       if(imsg->IAddress==(APTR)(DISPLAYOBJECT->PrivData))
  429.     {
  430.       LISTVIEW->Value=imsg->Code;
  431.       if(m=TR_CreateMsg(Self.DO.O.Project->trp_App))
  432.         {
  433.           m->trm_ID=DISPLAYOBJECT->ID;
  434.           m->trm_Class=TRMS_NEWVALUE;
  435.           m->trm_Data=LISTVIEW->Value;
  436.           m->trm_Qualifier=0;
  437.           if(LISTVIEW->DoubleClicked==TRUE) LISTVIEW->DoubleClicked=FALSE;
  438.           else if(LISTVIEW->LastEntry==LISTVIEW->Value)
  439.         {
  440.           if(DoubleClick(LISTVIEW->LastSeconds,LISTVIEW->LastMicros,imsg->Seconds,imsg->Micros))
  441.             {
  442.               m->trm_Qualifier=IEQUALIFIER_REPEAT;
  443.               LISTVIEW->DoubleClicked=TRUE;
  444.             }
  445.         }
  446.             }
  447.       LISTVIEW->LastEntry=LISTVIEW->Value;
  448.       LISTVIEW->LastSeconds=imsg->Seconds;
  449.       LISTVIEW->LastMicros=imsg->Micros;
  450.       TR_SetAttribute(OBJECT->Project,DISPLAYOBJECT->ID,TRAT_Value,LISTVIEW->Value);
  451.       return 1L;
  452.     }
  453.  
  454.     case IDCMP_RAWKEY:
  455.       if(!(LISTVIEW->TotLines)) break; /* Empty listview */
  456.  
  457.       LISTVIEW->Top=
  458.     TR_ListViewPos((struct Gadget *)DISPLAYOBJECT->PrivData,OBJECT->Project->trp_Window);
  459.  
  460.       oldval=LISTVIEW->Value;
  461.       oldtop=LISTVIEW->Top;
  462.  
  463.       /*------------------------------------ line up -----------------------------*/
  464.       if( ckeys*((imsg->Code==76L)&&
  465.          (!(imsg->Qualifier&
  466.             (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT|
  467.              IEQUALIFIER_LALT|IEQUALIFIER_RALT|IEQUALIFIER_CONTROL))))
  468.       || nkeys*((imsg->Code==62L)&&(imsg->Qualifier&(IEQUALIFIER_NUMERICPAD))) )
  469.     {
  470.       if(LISTVIEW->ShowSelected)
  471.         {
  472.           if(oldval>0)
  473.         {
  474.           LISTVIEW->Value--;
  475.           sendmsg=TRUE;
  476.           TR_RethinkListview(object);
  477.         }
  478.         }
  479.       else if(oldtop>0) LISTVIEW->Top--;
  480.     }
  481.       /*-------------------------------- page up -------------------------------------*/
  482.       else if( ckeys*((imsg->Code==76L)&&(imsg->Qualifier&(IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)))
  483.            || nkeys*((imsg->Code==63L)&&(imsg->Qualifier&(IEQUALIFIER_NUMERICPAD))) )
  484.     {
  485.       if(LISTVIEW->ShowSelected)
  486.         {
  487.           if(oldval+2>LISTVIEW->DispLines)
  488.         {
  489.           LISTVIEW->Value-=(LISTVIEW->DispLines-1);
  490.           sendmsg=TRUE;
  491.           TR_RethinkListview(object);
  492.         }
  493.           else
  494.         {
  495.           LISTVIEW->Value=0;
  496.           sendmsg=TRUE;
  497.           TR_RethinkListview(object);
  498.         }
  499.         }
  500.       else
  501.         {
  502.           if(oldtop>LISTVIEW->DispLines-1) LISTVIEW->Top-=LISTVIEW->DispLines-1;
  503.           else if(oldtop>0) LISTVIEW->Top=0;
  504.         }
  505.     }
  506.       /*---------------------------------------- top ----------------------------------*/
  507.       else if( ckeys*((imsg->Code==76L)&&(imsg->Qualifier&IEQUALIFIER_CONTROL))
  508.            || nkeys*((imsg->Code==61L)&&(imsg->Qualifier&(IEQUALIFIER_NUMERICPAD))) )
  509.     {
  510.       if(LISTVIEW->ShowSelected)
  511.         {
  512.           if(oldval!=0)
  513.         {
  514.           LISTVIEW->Value=0;
  515.           sendmsg=TRUE;
  516.           TR_RethinkListview(object);
  517.         }
  518.         }
  519.       else if(oldtop>0) LISTVIEW->Top=0;
  520.     }
  521.       /*---------------------------------- line down -------------------------------------*/
  522.       else if( ckeys*((imsg->Code==77L)&&
  523.               (!(imsg->Qualifier&
  524.              (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT|IEQUALIFIER_LALT
  525.               |IEQUALIFIER_RALT|IEQUALIFIER_CONTROL))))
  526.            || nkeys*((imsg->Code==30L)&&(imsg->Qualifier&(IEQUALIFIER_NUMERICPAD))) )
  527.     {
  528.       if(LISTVIEW->ShowSelected)
  529.         {
  530.           if(oldval<LISTVIEW->TotLines-1)
  531.         {
  532.           LISTVIEW->Value++;
  533.           sendmsg=TRUE;
  534.           TR_RethinkListview(object);
  535.         }
  536.         }
  537.       else if(oldtop+LISTVIEW->DispLines<LISTVIEW->TotLines) LISTVIEW->Top++;
  538.     }
  539.       /*------------------------------------- page down -------------------------------*/
  540.       else if( ckeys*((imsg->Code==77L)&&(imsg->Qualifier&(IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)))
  541.            || nkeys*((imsg->Code==31L)&&(imsg->Qualifier&(IEQUALIFIER_NUMERICPAD))) )
  542.     {
  543.       if(LISTVIEW->ShowSelected)
  544.         {
  545.           if(oldval+LISTVIEW->DispLines-1<(LISTVIEW->TotLines))
  546.         {
  547.           LISTVIEW->Value+=(LISTVIEW->DispLines-1);
  548.           sendmsg=TRUE;
  549.           TR_RethinkListview(object);
  550.         }
  551.           else
  552.         {
  553.           LISTVIEW->Value=LISTVIEW->TotLines-1;
  554.           sendmsg=TRUE;
  555.           TR_RethinkListview(object);
  556.         }
  557.         }
  558.       else
  559.         {
  560.           if(oldtop+2*LISTVIEW->DispLines-1<LISTVIEW->TotLines)
  561.         LISTVIEW->Top+=LISTVIEW->DispLines-1;
  562.           else if(oldtop+LISTVIEW->DispLines<LISTVIEW->TotLines)
  563.         LISTVIEW->Top=LISTVIEW->TotLines-LISTVIEW->DispLines;
  564.         }
  565.     }
  566.       /*--------------------------------------- bottom ----------------------------------*/
  567.       else if( ckeys*((imsg->Code==77L)&&(imsg->Qualifier&IEQUALIFIER_CONTROL))
  568.            || nkeys*((imsg->Code==29L)&&(imsg->Qualifier&(IEQUALIFIER_NUMERICPAD))) )
  569.     {
  570.       if(LISTVIEW->ShowSelected)
  571.         {
  572.           if(oldval!=LISTVIEW->TotLines-1)
  573.         {
  574.           LISTVIEW->Value=LISTVIEW->TotLines-1;
  575.           sendmsg=TRUE;
  576.           TR_RethinkListview(object);
  577.         }
  578.         }
  579.       else if(oldtop+LISTVIEW->DispLines<LISTVIEW->TotLines)
  580.         LISTVIEW->Top=LISTVIEW->TotLines-LISTVIEW->DispLines;
  581.     }
  582.  
  583.       if(sendmsg) if(m=TR_CreateMsg(Self.DO.O.Project->trp_App))
  584.     {
  585.       m->trm_ID=DISPLAYOBJECT->ID;
  586.       m->trm_Class=TRMS_NEWVALUE;
  587.       m->trm_Data=LISTVIEW->Value;
  588.     }
  589.       if(!(LISTVIEW->ShowSelected)) if(LISTVIEW->Top!=oldtop)
  590.     {
  591.       GT_SetGadgetAttrs((struct Gadget *)DISPLAYOBJECT->PrivData,
  592.                 OBJECT->Project->trp_Window,NULL,GTLV_Top,LISTVIEW->Top,TAG_END);
  593.       TR_SetAttribute(OBJECT->Project,DISPLAYOBJECT->ID,TRLV_Top,LISTVIEW->Top);
  594.     }
  595.       if(LISTVIEW->Value!=oldval)
  596.     {
  597.       GT_SetGadgetAttrs((struct Gadget *)DISPLAYOBJECT->PrivData,
  598.                 OBJECT->Project->trp_Window,NULL,
  599.                 GTLV_Selected,LISTVIEW->Value,TAG_END);
  600.       TR_SetAttribute(OBJECT->Project,DISPLAYOBJECT->ID,TRAT_Value,LISTVIEW->Value);
  601.     }
  602.       return NULL;
  603.     }
  604.   return NULL;
  605. }
  606.  
  607.  
  608. TR_SIMPLEMETHOD(Listview,GETBETTERHEIGHT)
  609. {
  610.   if((LISTVIEW->Flags)&TRLV_NOGAP)
  611.     (*((ULONG *)(data)))=TR_GetBetterListviewHeight(object,(*((ULONG *)(data))));
  612.   return NULL;
  613. }
  614.