home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #3 / amigamamagazinepolishissue1998.iso / bazy / db3.4 / select.c < prev    next >
C/C++ Source or Header  |  1997-03-16  |  17KB  |  699 lines

  1. #include <exec/types.h>
  2. #include <exec/memory.h>
  3. #include <exec/nodes.h>
  4. #include <exec/lists.h>
  5. #include <intuition/intuition.h>
  6. #include <intuition/classes.h>
  7. #include <intuition/classusr.h>
  8. #include <intuition/imageclass.h>
  9. #include <intuition/gadgetclass.h>
  10. #include <libraries/gadtools.h>
  11. #include <libraries/commodities.h> /* This has a nice qualifier #define */
  12. #include <graphics/displayinfo.h>
  13. #include <graphics/gfxbase.h>
  14.  
  15. #include <proto/exec.h>
  16. #include <proto/intuition.h>
  17. #include <proto/gadtools.h>
  18. #include <proto/graphics.h>
  19. #include <proto/utility.h>
  20. #include <proto/dos.h>    /* Delay() for debugging */
  21.  
  22. #include <string.h>
  23. #include <stdlib.h>    /* malloc & free */
  24. #include <stdio.h>    /* debugging */
  25.  
  26. #include "Select_P.h"
  27. #include "dbGUI.h"    /* We use db's font instead of the screen font */
  28.  
  29. #define MARGIN 4
  30. #define TOGGLE_LED *(UBYTE *)0xbfe001 ^= 2
  31.  
  32. /* We use db's font engine instead.
  33. static struct TextAttr       *Font, Attr;
  34. static UWORD                  FontX, FontY;
  35. */
  36.  
  37.  
  38. /*
  39. void FlashLed(void)
  40. {
  41.     int i;
  42.     for (i=0; i<20; i++) {
  43.         TOGGLE_LED;
  44.         Delay(10);
  45.     }
  46. }
  47. */
  48.  
  49. /**********************************************************************/
  50. /*                         Support functions                          */
  51. /**********************************************************************/
  52.  
  53.  
  54. static UWORD ComputeX( UWORD value )
  55. {
  56.     return(( UWORD )((( FontX * value ) + 4 ) / 8 ));
  57. }
  58.  
  59. static UWORD ComputeY( UWORD value )
  60. {
  61.     return(( UWORD )((( FontY * value ) + 6 ) / 13 ));
  62. }
  63. /*
  64. static void ComputeFont( UWORD width, UWORD height )
  65. {
  66.     static UWORD                  OffX, OffY;
  67.     Font = &Attr;
  68.     Font->ta_Name = (STRPTR)Scr->RastPort.Font->tf_Message.mn_Node.ln_Name;
  69.     Font->ta_YSize = FontY = Scr->RastPort.Font->tf_YSize;
  70.     FontX = Scr->RastPort.Font->tf_XSize;
  71.  
  72.     OffX = Scr->WBorLeft;
  73.     OffY = Scr->RastPort.TxHeight + Scr->WBorTop + 1;
  74.  
  75.     if ( width && height ) {
  76.         if (( ComputeX( width ) + OffX + Scr->WBorRight ) > Scr->Width )
  77.             goto UseTopaz;
  78.         if (( ComputeY( height ) + OffY + Scr->WBorBottom ) > Scr->Height )
  79.             goto UseTopaz;
  80.     }
  81.     return;
  82.  
  83. UseTopaz:
  84.     Font->ta_Name = (STRPTR)"topaz.font";
  85.     FontX = FontY = Font->ta_YSize = 8;
  86. }
  87. */
  88. static void MyCreateAllGadgets(Select *s)
  89. {
  90.     struct Gadget    *g;
  91.     static struct NewGadget ng = { 4, 4, 213, 229,
  92.                                     NULL, NULL, GD_SELLview, 0,
  93.                                     NULL, (APTR)SELLviewClicked };
  94.  
  95.     g = CreateContext( &s->SelGList );
  96.  
  97.     ng.ng_VisualInfo = VisualInfo;
  98.     ng.ng_TextAttr   = Font;
  99.     ng.ng_LeftEdge   = s->SelWnd->BorderLeft + MARGIN;
  100.     ng.ng_TopEdge    = s->SelWnd->BorderTop + MARGIN;
  101.     ng.ng_Width      = s->SelWnd->Width - s->SelWnd->BorderLeft - s->SelWnd->BorderRight - 2*MARGIN;
  102.     ng.ng_Height     = s->SelWnd->Height - s->SelWnd->BorderTop - s->SelWnd->BorderBottom - 2*MARGIN;
  103.  
  104.     s->ListView = g = CreateGadget(LISTVIEW_KIND, g, &ng, 
  105.         GTLV_Labels, &s->SelList,
  106.         GTLV_ShowSelected, NULL,
  107.         GTLV_Selected, s->SelIndex,
  108.         GTLV_MakeVisible, s->SelIndex,
  109.         TAG_DONE);
  110.  
  111.     AddGList(s->SelWnd, s->SelGList, -1, -1, NULL);
  112.     RefreshWindowFrame(s->SelWnd);
  113.     RefreshGList(s->SelGList, s->SelWnd, NULL, -1);
  114.     GT_RefreshWindow( s->SelWnd, NULL ); /* Must also be called */
  115. }
  116.  
  117.  
  118. static void UpdateListView(Select *s)
  119. {
  120.     if (GadToolsBase->lib_Version < 39) {
  121.         GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL,
  122.         GTLV_Selected, s->SelIndex,
  123.         GTLV_Top, s->SelIndex,
  124.         TAG_END);
  125.     }
  126.     else {
  127.         GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL,
  128.         GTLV_Selected, s->SelIndex,
  129.         GTLV_MakeVisible, s->SelIndex,
  130.         TAG_END);
  131.     }
  132. }
  133.  
  134. static struct Node *FindIndex(struct List *list, int idx)
  135. {
  136.     /* Returns the node with index idx in the list, (first node is 0) */
  137.     struct Node *cn;    /* Current Node */
  138.     for (cn = list->lh_Head; idx; cn = cn->ln_Succ, idx--);
  139.     return cn;
  140. }
  141.  
  142. static int IndexInList(struct List *list, char *str)
  143. {
  144.     /* returs -1 if str doesn't match somewhere in list */
  145.     int len = strlen(str);
  146.     struct Node *node;
  147.     int i;
  148.     for (node = list->lh_Head, i=0;
  149.         node->ln_Succ && Strnicmp(str, node->ln_Name, len);
  150.          node = node->ln_Succ, i++);
  151.     if (node->ln_Succ) return i;
  152.     return -1;
  153. }
  154.  
  155. static int NextMatch(struct Node *cnode, char *str)
  156. {
  157.     /* returs -1 if str doesn't match somewhere in list */
  158.     int len = strlen(str);
  159.     struct Node *node;
  160.     int i;
  161.     if (!cnode->ln_Succ) return -1;
  162.     for (node = cnode->ln_Succ, i=1;
  163.         node->ln_Succ && Strnicmp(str, node->ln_Name, len);
  164.          node = node->ln_Succ, i++);
  165.     if (node->ln_Succ) return i;
  166.     return -1;
  167. }
  168.  
  169. static int PrevMatch(struct Node *cnode, char *str)
  170. {
  171.     /* returs -1 if str doesn't match somewhere in list */
  172.     int len = strlen(str);
  173.     struct Node *node;
  174.     int i;
  175.     if (!cnode->ln_Pred) return -1;
  176.     for (node = cnode->ln_Pred, i=1;
  177.         node->ln_Pred && Strnicmp(str, node->ln_Name, len);
  178.          node = node->ln_Pred, i++);
  179.     if (node->ln_Pred) return i;
  180.     return -1;
  181. }
  182.  
  183.  
  184. /**********************************************************************/
  185. /*                           Event handlers                           */
  186. /**********************************************************************/
  187.  
  188.  
  189. static int SelNewSize(Select *s)
  190. {
  191.     /* routine for "IDCMP_NEWSIZE". */
  192.  
  193.     RemoveGList(s->SelWnd, s->SelGList, -1);
  194.     FreeGadgets(s->SelGList);
  195.  
  196.     EraseRect(s->SelWnd->RPort, s->SelWnd->BorderLeft, s->SelWnd->BorderTop,
  197.      s->SelWnd->Width - s->SelWnd->BorderRight, s->SelWnd->Height - s->SelWnd->BorderBottom);
  198.  
  199.     MyCreateAllGadgets(s);
  200.  
  201.     return SEL_PRIVATE;
  202. }
  203.  
  204. static int SELOkClicked(Select *s)
  205. {
  206.     /* routine when gadget "_Ok" is clicked. */
  207.     /* CloseSelect(s); */
  208.     return SEL_OK;
  209. }
  210.  
  211. static int SELLviewClicked(Select *s)
  212. {
  213.     /* routine when listview gadget is clicked. */
  214.  
  215.     /* Handle doubleclicks.. */
  216.     if (DoubleClick(s->StartSecs, s->StartMicros, s->SelMsg.Seconds, s->SelMsg.Micros)
  217.          && s->SelMsg.Code == s->SelIndex) {
  218.         s->StartSecs = s->StartMicros = 0;    /* Prevent "triple clicks" */
  219.         s->SelIndex = s->SelMsg.Code;
  220.         return SELOkClicked(s);
  221.     }
  222.     else {
  223.         s->StartSecs = s->SelMsg.Seconds;
  224.         s->StartMicros = s->SelMsg.Micros;
  225.         s->SelIndex = s->SelMsg.Code;
  226.     }
  227.     return SEL_SELECT;
  228. }
  229.  
  230. static int SelCloseWindow(Select *s)
  231. {
  232.     /* routine for "IDCMP_CLOSEWINDOW". */
  233.     CloseSelect(s);
  234.     return SEL_CANCEL;
  235. }
  236.  
  237. static int SELCancelClicked(Select *s)
  238. {
  239.     /* routine when gadget "_Cancel" is clicked. */
  240.     return SelCloseWindow(s);
  241. }
  242.  
  243.  
  244. static int SelVanillaKey(Select *s)
  245. {
  246.     /* routine for "IDCMP_VANILLAKEY". */
  247.     int len;
  248.     int index;
  249.     struct List *list = (struct List *) &s->SelList;
  250.  
  251.     switch (s->SelMsg.Code) {
  252.         case '\r' :
  253.             return SELOkClicked(s);
  254.             break;
  255.         case VANILLA_ESC :
  256.             return SELCancelClicked(s);
  257.             break;
  258.  
  259.         case VANILLA_DEL :
  260.             s->SelCompleteBuf[1] = '\0';
  261.         case '\b' :
  262.             if (len = strlen(s->SelCompleteBuf)) {
  263.                 s->SelCompleteBuf[len-1] = '\0';
  264.                 if ((index = IndexInList(list, s->SelCompleteBuf)) >= 0) {
  265.                     s->SelIndex = index;
  266.                     UpdateListView(s);
  267.                 }
  268.             }
  269.             SetWindowTitles(s->SelWnd, s->SelWdt ,(UBYTE *)-1);
  270.             break;
  271.         case '\t' :
  272.             if ((index = NextMatch(FindIndex(list, s->SelIndex), s->SelCompleteBuf)) >= 0) {
  273.                     s->SelIndex += index;
  274.                     UpdateListView(s);
  275.                 } else DisplayBeep(Scr);
  276.             break;
  277.  
  278.         default :
  279.             if ((len = strlen(s->SelCompleteBuf)) < COMPLETEBUFSIZ-1 ) {
  280.                 s->SelCompleteBuf[len] = s->SelMsg.Code;
  281.                 s->SelCompleteBuf[len+1] = '\0';
  282.                 if ((index = IndexInList(list, s->SelCompleteBuf)) >= 0) {
  283.                     s->SelIndex = index;
  284.                     UpdateListView(s);
  285.                     SetWindowTitles(s->SelWnd, s->SelWdt ,(UBYTE *)-1);
  286.                 }
  287.                 else {
  288.                     s->SelCompleteBuf[len] = '\0';
  289.                     DisplayBeep(Scr);
  290.                 }
  291.             }
  292.             break;
  293.     }
  294.     return SEL_SELECT;
  295. }
  296.  
  297. static int SelRawKey(Select *s)
  298. {
  299.     /* routine for "IDCMP_RAWKEY". */
  300.  
  301.     int index;
  302.     struct List *list = (struct List *)&s->SelList;
  303.  
  304.     int rows = (s->ListView->Height-4)/FontY;     /* Rows visible in listview. Ugly but works */
  305.  
  306.     switch (s->SelMsg.Code) {
  307.         case RAW_UP :
  308.             if (s->SelIndex == 0) return SEL_PRIVATE;
  309.             if (s->SelMsg.Qualifier & IXSYM_ALTMASK)
  310.                 s->SelIndex = 0;
  311.             else if (s->SelMsg.Qualifier & IXSYM_SHIFTMASK) {
  312.                 s->SelIndex -= rows-1;
  313.                 if (s->SelIndex < 0) s->SelIndex = 0;
  314.             }
  315.             else s->SelIndex--;
  316.  
  317.             break;
  318.         case RAW_DOWN :
  319.             if (s->SelIndex >= s->SelTotal-1) return SEL_PRIVATE;
  320.             if (s->SelMsg.Qualifier & IXSYM_ALTMASK)
  321.                  s->SelIndex = s->SelTotal - 1;
  322.             else if (s->SelMsg.Qualifier & IXSYM_SHIFTMASK) {
  323.                 s->SelIndex += rows-1;
  324.                 if (s->SelIndex > s->SelTotal-1) s->SelIndex = s->SelTotal - 1;
  325.             }
  326.             else s->SelIndex++;
  327.             break;
  328.         case RAW_TAB :
  329.             if ((index = PrevMatch(FindIndex(list, s->SelIndex), s->SelCompleteBuf)) >= 0) {
  330.                     s->SelIndex -= index;
  331.                     UpdateListView(s);
  332.                 } else DisplayBeep(Scr);
  333.             break;
  334.         case RAW_HELP :
  335.             return SEL_HELP;
  336.             break;
  337.         default :
  338.             return SEL_PRIVATE;
  339.     }
  340.  
  341.     UpdateListView(s);
  342.     return SEL_SELECT;
  343. }
  344.  
  345.  
  346. /**********************************************************************/
  347. /*                        Interface functions                         */
  348. /**********************************************************************/
  349.  
  350. BOOL FixSelectSize(Select *s, int n)
  351. {
  352.     /* Makes the Select object allocate memory for n elements in one chunk for */
  353.     /* all fields. It is illegal to add more fields than allocated after this */
  354.     /* Use RemoveAllFields() to free up everything. */
  355.  
  356.     if (!(s->NodeArray = malloc(n * sizeof(struct Node)))) return FALSE;
  357.     s->FirstFree = 0;
  358.     return TRUE;
  359. }
  360.  
  361. char *SelectedString(Select *s)
  362. {
  363. /* Returns the selected string */
  364.  
  365.     return FindIndex((struct List *)&s->SelList, s->SelIndex)->ln_Name;
  366. }
  367.  
  368. void UpdateString(Select *s, int index, char *newstring)
  369. {
  370. /* Changes a string. */
  371.  
  372.     if (s->SelWnd)
  373.         GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, ~0, TAG_END); // Detach
  374.  
  375.     FindIndex((struct List *)&s->SelList, index)->ln_Name = newstring;
  376.  
  377.     if (s->SelWnd)
  378.          GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, &s->SelList, TAG_END);
  379. }
  380.  
  381.  
  382. /* // I comment this to save space
  383. char *AddStringFirst(Select *s, char *str)
  384. {
  385.     struct Node *newnode;
  386.  
  387.     if (s->NodeArray)    newnode = s->NodeArray[s->FirstFree++];
  388.     else if (!(newnode = (struct Node *)malloc(sizeof(struct Node)))) return str;
  389.     newnode->ln_Name = str;
  390.  
  391.     if (s->SelWnd)
  392.         GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, ~0, TAG_END); // Detach
  393.  
  394.     AddHead((struct List *)&s->SelList, newnode);
  395.     s->SelTotal++;
  396.  
  397.     if (s->SelWnd)
  398.          GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, &s->SelList, TAG_END);
  399.  
  400.     return str;
  401. }
  402. */
  403. char *AddStringLast(Select *s, char *str)
  404. {
  405.     struct Node *newnode;
  406.  
  407.     if (s->NodeArray)    newnode = &s->NodeArray[s->FirstFree++];
  408.     else if (!(newnode = (struct Node *)malloc(sizeof(struct Node)))) return str;
  409.     newnode->ln_Name = str;
  410.  
  411.     if (s->SelWnd)
  412.         GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, ~0, TAG_END); // Detach
  413.  
  414.     AddTail((struct List *)&s->SelList, newnode);
  415.     s->SelTotal++;
  416.  
  417.     if (s->SelWnd)
  418.          GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, &s->SelList, TAG_END);
  419.  
  420.     return str;
  421. }
  422.  
  423. /* // I comment this to save space
  424. char *AddString(Select *s, char *str, int index)
  425. {
  426.     struct Node *newnode;
  427.  
  428.     if (s->NodeArray)    newnode = &s->NodeArray[s->FirstFree++];
  429.     else if (!(newnode = (struct Node *)malloc(sizeof(struct Node)))) return str;
  430.     newnode->ln_Name = str;
  431.  
  432.     if (s->SelWnd)
  433.         GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, ~0, TAG_END); // Detach
  434.  
  435.     if (index == 0) AddHead((struct List *)&s->SelList, newnode);
  436.     else Insert((struct List *)&s->SelList, newnode,
  437.                      FindIndex((struct List *)&s->SelList, index-1));
  438.     s->SelTotal++;
  439.  
  440.     if (s->SelWnd)
  441.          GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, &s->SelList, TAG_END);
  442.  
  443.     return str;
  444. }
  445.  
  446. char *RemoveFirstString(Select *s)
  447. {
  448.     struct Node *old;
  449.     char *oldstr;
  450.  
  451.     if (!s->SelTotal) return NULL;
  452.  
  453.     if (s->SelWnd)
  454.         GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, ~0, TAG_END); // Detach
  455.  
  456.     old = RemHead((struct List *)&s->SelList);
  457.     s->SelTotal--;
  458.     if (s->SelIndex == s->SelTotal) s->SelIndex--;
  459.  
  460.     if (s->SelWnd)
  461.          GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, &s->SelList, TAG_END);
  462.  
  463.     oldstr = old->ln_Name;
  464.     if (!s->NodeArray) free(old);
  465.     return oldstr;
  466. }
  467.  
  468. char *RemoveLastString(Select *s)
  469. {
  470.     struct Node *old;
  471.     char *oldstr;
  472.  
  473.     if (!s->SelTotal) return NULL;
  474.  
  475.     if (s->SelWnd)
  476.         GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, ~0, TAG_END); // Detach
  477.  
  478.     old = RemTail((struct List *)&s->SelList);
  479.  
  480.     s->SelTotal--;
  481.     if (s->SelIndex == s->SelTotal) s->SelIndex--;
  482.  
  483.     if (s->SelWnd)
  484.          GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, &s->SelList, TAG_END);
  485.  
  486.     oldstr = old->ln_Name;
  487.     if (!s->NodeArray) free(old);
  488.     return oldstr;
  489. }
  490.  
  491. char *RemoveString(Select *s, int index)
  492. {
  493.     struct Node *old;
  494.     char *oldstr;
  495.  
  496.     if (s->SelWnd)
  497.         GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, ~0, TAG_END); // Detach
  498.  
  499.     old = FindIndex((struct List *)&s->SelList, index);
  500.     Remove(old);
  501.     s->SelTotal--;
  502.     if (s->SelIndex == s->SelTotal) s->SelIndex--;
  503.  
  504.     if (s->SelWnd)
  505.          GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, &s->SelList, TAG_END);
  506.  
  507.     if (old) {
  508.         oldstr = old->ln_Name;
  509.         if (!s->NodeArray) free(old);
  510.         return oldstr;
  511.     }
  512.     return NULL;
  513. }
  514.  
  515. */
  516.  
  517. void RemoveAllStrings(Select *s)
  518. {
  519.     struct Node *old;
  520.  
  521.     if (s->SelWnd)
  522.         GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, ~0, TAG_END); // Detach
  523.  
  524.     if (s->NodeArray) {
  525.         free(s->NodeArray);
  526.         s->NodeArray = NULL;
  527.         NewList((struct List *)&s->SelList);
  528.     }
  529.     else while (old = RemTail((struct List *)&s->SelList)) free(old);
  530.  
  531.     if (s->SelWnd)
  532.          GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, &s->SelList, TAG_END);
  533.     s->SelTotal = 0;
  534. }
  535.  
  536. void DisableSelect(Select *s, BOOL flag) {
  537.         if (s->SelWnd) {
  538.             GT_SetGadgetAttrs(s->ListView,s->SelWnd,NULL,
  539.              GA_Disabled, flag, TAG_DONE);
  540.         }
  541. }
  542.  
  543. void CurrentIndex(Select *s, int index)
  544. {
  545.     if (s) {
  546.         s->SelIndex = index;
  547.         if (s->SelWnd) UpdateListView(s);
  548.     }
  549. }
  550.  
  551. int HandleSelectIDCMP(Select *s)
  552. {
  553.     struct IntuiMessage    *m;
  554.     int            (*func)(Select*);
  555.     BOOL            running = SEL_PRIVATE;
  556.  
  557.     while( s->SelWnd && (m = GT_GetIMsg( s->SelWnd->UserPort ))) {
  558.  
  559.         CopyMem(( char * )m, ( char * )&s->SelMsg, (long)sizeof( struct IntuiMessage ));
  560.  
  561.         GT_ReplyIMsg( m );
  562.  
  563.         switch ( s->SelMsg.Class ) {
  564.  
  565.             case    IDCMP_REFRESHWINDOW:
  566.                 GT_BeginRefresh( s->SelWnd );
  567.                 GT_EndRefresh( s->SelWnd, TRUE );
  568.                 break;
  569.  
  570.             case    IDCMP_CLOSEWINDOW:
  571.                 running = SelCloseWindow(s);
  572.                 break;
  573.  
  574.             case    IDCMP_NEWSIZE:
  575.                 running = SelNewSize(s);
  576.                 break;
  577.  
  578.             case    IDCMP_VANILLAKEY:
  579.                 running = SelVanillaKey(s);
  580.                 break;
  581.  
  582.             case    IDCMP_RAWKEY:
  583.                 running = SelRawKey(s);
  584.                 break;
  585.  
  586.             case    IDCMP_GADGETUP:
  587.             case    IDCMP_GADGETDOWN:
  588.                 func = (int(*)(Select*))(( struct Gadget * )s->SelMsg.IAddress )->UserData;
  589.                 running = func(s);
  590.                 break;
  591.         }
  592.     }
  593.     return( running );
  594. }
  595.  
  596. int OpenSelect(Select *s, struct Window *parentwin, char *wintitle, char *screentitle)
  597. {
  598.     char *bufp, *namep;
  599.  
  600.     if (s->SelWnd) return 5L; /* Already opened */
  601.  
  602.     if (s->SelWidth == ~0) {    /* Window has never been opened before */
  603.         s->SelWidth = 220;
  604. //        ComputeFont( s->SelWidth, s->SelHeight );
  605.         s->SelWidth = ComputeX( s->SelWidth );
  606.         s->SelHeight = ComputeY( s->SelHeight );
  607.     
  608.         if (parentwin) {
  609.             s->SelLeft =  parentwin->LeftEdge + parentwin->Width;
  610.             s->SelTop = parentwin->TopEdge + (parentwin->Height - s->SelHeight)/2;
  611.         }
  612.         if (s->SelLeft + s->SelWidth > Scr->Width)
  613.             s->SelLeft = parentwin->LeftEdge - s->SelWidth;
  614.     }
  615.  
  616.     /* Strip underscore _ for cosmethic reasons */
  617.     for (bufp = s->SelWdt, namep = wintitle; *namep; namep++)
  618.         if (*namep != '_') *bufp++ = *namep;
  619.     
  620.     *bufp = ':';
  621.     s->SelCompleteBuf = bufp+1;
  622.  
  623.     s->SelCompleteBuf[0] = '\0';
  624.  
  625.     s->SelZoom[0] = s->SelLeft;
  626.     s->SelZoom[1] = 0;
  627.     s->SelZoom[2] = s->SelWidth;
  628.     s->SelZoom[3] = Scr->Height;
  629.     
  630.     if ( ! ( s->SelWnd = OpenWindowTags( NULL,
  631.                 WA_Left,    s->SelLeft,
  632.                 WA_Top,        s->SelTop,
  633.                 WA_Width,    s->SelWidth,
  634.                 WA_Height,    s->SelHeight,
  635.                 WA_IDCMP,    LISTVIEWIDCMP|BUTTONIDCMP|IDCMP_NEWSIZE|IDCMP_CLOSEWINDOW|IDCMP_RAWKEY|IDCMP_VANILLAKEY|IDCMP_REFRESHWINDOW,
  636.                 WA_Flags,    WFLG_SIZEGADGET|WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|WFLG_SIZEBBOTTOM|WFLG_SIMPLE_REFRESH|WFLG_ACTIVATE|WFLG_RMBTRAP,
  637.                 WA_Title,    s->SelWdt,
  638.                 WA_ScreenTitle,    screentitle,
  639.                 WA_PubScreen,    Scr,
  640.                 WA_MinWidth,    120,
  641.                 WA_MinHeight,    100,
  642.                 WA_MaxWidth,    -1,
  643.                 WA_MaxHeight,    -1,
  644.                 WA_Zoom, s->SelZoom,
  645.                 TAG_DONE )))
  646.     return( 4L );
  647.  
  648.     MyCreateAllGadgets(s);
  649.     return( 0L );
  650. }
  651.  
  652. void CloseSelect(Select *s)
  653. {
  654.     if ( s->SelWnd        ) {
  655.         s->SelLeft = s->SelWnd->LeftEdge;
  656.         s->SelTop = s->SelWnd->TopEdge;
  657.         s->SelWidth = s->SelWnd->Width;
  658.         s->SelHeight = s->SelWnd->Height;
  659.  
  660.         CloseWindow( s->SelWnd );
  661.         s->SelWnd = NULL;
  662.     }
  663.  
  664.     if ( s->SelGList      ) {
  665.         FreeGadgets( s->SelGList );
  666.         s->SelGList = NULL;
  667.     }
  668. }
  669.  
  670. Select *NewSelect(void)
  671. {
  672. /* Data för ListView gadget */
  673.     Select *s = (Select*) malloc(sizeof(Select));
  674.     if (!s) return NULL;
  675.  
  676.     s->SelWnd = NULL;
  677.     s->SelGList = NULL;
  678.     s->ListView = NULL;
  679.     s->SelWidth = ~0; /* (220) Window has never been opened before */
  680.     s->SelHeight = 280;
  681.     s->SelLeft =  (Scr->Width - 220) >> 1;
  682.     s->SelTop = (Scr->Height - s->SelHeight) >> 1;
  683.     s->SelIndex = 0;
  684.     s->SelTotal = 0;
  685.     s->StartSecs = 0, s->StartMicros = 0;
  686.     s->NodeArray = NULL;
  687.  
  688.     NewList((struct List *)&s->SelList);
  689.  
  690.     return s;
  691. }
  692.  
  693. void DeleteSelect(Select *s)
  694. {
  695.     CloseSelect(s);
  696.     RemoveAllStrings(s);
  697.     free(s);
  698. }
  699.