home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #3 / amigamamagazinepolishissue1998.iso / bazy / cdindexb2 / txt / cdindex.mod
Text File  |  1996-03-08  |  38KB  |  1,168 lines

  1. MODULE CDIndex;
  2.  
  3. IMPORT
  4.     id:IntuitionD, il:IntuitionL,
  5.     gtd:GadToolsD, gtl:GadToolsL,
  6.     ed:ExecD, el:ExecL, es:ExecSupport,
  7.     dd:DosD, dl:DosL, ds:DosSupport,
  8.     gd:GraphicsD,
  9.     ie:InputEvent,
  10.     String;
  11.  
  12. (*
  13. FROM Terminal IMPORT
  14.    WriteString, WriteInt;
  15. FROM Arts IMPORT
  16.     BreakPoint;
  17. *)
  18.  
  19. FROM CommoditiesSupport IMPORT
  20.     ArgInt, ArgString;
  21.  
  22. FROM Conversions IMPORT
  23.     ValToStr;
  24.  
  25. FROM UtilityD IMPORT
  26.     tagEnd;
  27.  
  28. FROM SYSTEM IMPORT
  29.     ADR, ADDRESS, CAST, TAG;
  30.  
  31. CONST
  32.     (* Gadget IDs *)
  33.     CDIDNO          = 0;
  34.     INTERPRET       = 1;
  35.     TITLE           = 2;
  36.     TRACKLISTING    = 3;
  37.     SEARCHAREA      = 4;
  38.     STARTSEARCH     = 5;
  39.     SEARCHPATTERN   = 6;
  40.     PREVIOUS        = 7;
  41.     NEXT            = 8;
  42.     MESSAGE         = 9;
  43.  
  44.     ITEMSVISIBLE = 11;  (* Soviele Items können im Listview-Gadget angezeigt werden. *)
  45.  
  46. TYPE
  47.     StringPtr = POINTER TO ARRAY [0..16383] OF CHAR;
  48.     SearchArea = (SAanywhere, SAartist, SAtitle, SAtracklisting);
  49.     SearchInfo = RECORD
  50.         buffer: StringPtr;
  51.         titlestart: LONGINT;
  52.         trackstart: LONGINT;
  53.     END;
  54.     SearchInfoPtr = POINTER TO SearchInfo;
  55.     StringList = ARRAY [0..4] OF ADDRESS;
  56.     CDData = RECORD
  57.         artist: StringPtr;
  58.         title: StringPtr;
  59.         tracks: ed.List;
  60.     END;
  61.     CDDataPtr = POINTER TO CDData;
  62.  
  63. VAR
  64.     searchareaLabels := StringList{
  65.         ADR("Anywhere"),
  66.         ADR("Artist"),
  67.         ADR("Title"),
  68.         ADR("Track listing"),
  69.         NIL};
  70.     topazfont: gd.TextAttr;
  71.     DISKSPATH: StringPtr;
  72.  
  73.     (* Punktvergabe in der Suche *)
  74.     INARTIST : INTEGER;   (* 10 Punkte, wenn Suchbegriff im Interpreten *)
  75.     INTITLE  : INTEGER;   (* 10       ,                     Title       *)
  76.     FULLWORD : INTEGER;   (*  5       ,                  ganzes Wort    *)
  77.     MATCHONLY: INTEGER;   (*  1 Punkt ,                  im Wort        *)
  78.  
  79. VAR
  80.     BMSkipArray: ARRAY [0..255] OF INTEGER;
  81.     searchresults: ed.List;
  82.     currentsearchresult: ed.NodePtr;
  83.     currentCDNumber: INTEGER;
  84.     totalCDsFound: INTEGER;
  85.     totalHits: INTEGER;
  86.     maxPoints: INTEGER;
  87.     itemcount, maxitems: INTEGER;
  88. VAR
  89.     mainWindow : id.WindowPtr;
  90.     glist: id.GadgetPtr;
  91.     visualinfo: ADDRESS;
  92.     artistGadget: id.GadgetPtr;
  93.     titleGadget: id.GadgetPtr;
  94.     tracklistingGadget: id.GadgetPtr;
  95.     patternGadget: id.GadgetPtr;
  96.     searchareaGadget: id.GadgetPtr;
  97.     startsearchGadget: id.GadgetPtr;
  98.     previousGadget, nextGadget: id.GadgetPtr;
  99.     messageGadget: id.GadgetPtr;
  100.  
  101. VAR
  102.     proclevel: INTEGER;
  103. PROCEDURE EnterProc(msg: ARRAY OF CHAR);
  104. VAR
  105.     i: INTEGER;
  106. BEGIN
  107.     (*
  108.     FOR i := 1 TO proclevel DO
  109.         WriteString ("   ");
  110.     END;
  111.     WriteString ("--> ");
  112.     WriteString (msg);
  113.     *)
  114.     INC (proclevel);
  115. END EnterProc;
  116.  
  117. PROCEDURE LeaveProc(msg: ARRAY OF CHAR);
  118. VAR
  119.     i: INTEGER;
  120. BEGIN
  121.     DEC (proclevel);
  122.     (*
  123.     FOR i := 1 TO proclevel DO
  124.         WriteString ("   ");
  125.     END;
  126.     WriteString ("<-- ");
  127.     WriteString (msg);
  128.     *)
  129. END LeaveProc;
  130.  
  131. PROCEDURE DebugMsg(msg: ARRAY OF CHAR);
  132. VAR
  133.     i: INTEGER;
  134. BEGIN
  135.     (*
  136.     FOR i := 1 TO proclevel DO
  137.         WriteString ("   ");
  138.     END;
  139.     WriteString (msg);
  140.     *)
  141. END DebugMsg;
  142.  
  143. (* strdup() kopiert die übergebene Zeichenkette. Der hierfür
  144.  * reservierte Speicher muß von der aufrufenden Prozedur
  145.  * mit ExecL.FreeVec() wieder freigegeben werden.
  146.  *)
  147. PROCEDURE strdup (VAR source: ARRAY OF CHAR) : ADDRESS;
  148. VAR
  149.     target: StringPtr;
  150. BEGIN
  151.     EnterProc ("strdup()\n");
  152.     target := el.AllocVec(String.Length(source)+1, ed.MemReqSet{ed.memClear});
  153.     IF target # NIL THEN
  154.         String.Copy (target^, source);
  155.     END;
  156.     LeaveProc ("strdup.\n");
  157.     RETURN target;
  158. END strdup;
  159.  
  160. PROCEDURE IsWhitespace (c: CHAR): BOOLEAN;
  161. BEGIN
  162.     RETURN (c = " ") OR (c = "\t") OR (c = "\n");
  163. END IsWhitespace;
  164.  
  165. PROCEDURE IsAlpha (c: CHAR) : BOOLEAN;
  166. BEGIN
  167.     RETURN ((c >= "a") AND (c <= "z")) OR ((c >= "A") AND (c <= "Z"));
  168. END IsAlpha;
  169.  
  170. PROCEDURE Fullword (
  171.     word: StringPtr;
  172.     startpos: INTEGER;
  173.     length: INTEGER) : BOOLEAN;
  174. VAR
  175.     beginning, end: BOOLEAN;
  176. BEGIN
  177.     beginning := (startpos = 0) OR NOT(IsAlpha(word^[startpos-1]));
  178.     end := NOT(IsAlpha(word^[startpos+length]));
  179.     RETURN beginning AND end;
  180. END Fullword;
  181.  
  182. PROCEDURE IsLowerCase (VAR string: ARRAY OF CHAR): BOOLEAN;
  183. VAR
  184.     i: INTEGER;
  185.     lowercase: BOOLEAN;
  186. BEGIN
  187.     lowercase := TRUE;
  188.     i := 0;
  189.  
  190.     WHILE ((string[i] # 0C) AND lowercase) DO
  191.         lowercase := string[i] # CAP(string[i]);
  192.         INC (i);
  193.     END;
  194.  
  195.     RETURN lowercase;
  196. END IsLowerCase;
  197.  
  198. PROCEDURE FreeSearchResultsList (searchresults: ed.ListPtr);
  199. VAR
  200.     node, nextnode: ed.NodePtr;
  201. BEGIN
  202.     node := searchresults^.head;
  203.  
  204.     IF node # NIL THEN
  205.         WHILE (node^.succ # NIL) DO
  206.             IF node^.name # NIL THEN
  207.                 el.FreeVec(node^.name);
  208.             END;
  209.             nextnode := node^.succ;
  210.             el.FreeVec (node);
  211.             node := nextnode;
  212.         END;
  213.     END;
  214.  
  215.     WITH searchresults^ DO
  216.         head := NIL;
  217.         tail := NIL;
  218.         tailPred := NIL;
  219.     END;
  220. END FreeSearchResultsList;
  221.  
  222. PROCEDURE FreeList (list: ed.ListPtr);
  223. BEGIN
  224.     FreeSearchResultsList (list);
  225. END FreeList;
  226.  
  227. PROCEDURE GetNodeName (pos: INTEGER; list: ed.ListPtr) : StringPtr;
  228. VAR
  229.     node: ed.NodePtr;
  230. BEGIN
  231.     IF (list = NIL) OR (list^.head = NIL) THEN
  232.         RETURN NIL;
  233.     END;
  234.  
  235.     node := list^.head;
  236.  
  237.     WHILE (node^.succ # NIL) AND (pos > 0) DO
  238.         node := node^.succ;
  239.         DEC (pos);
  240.     END;
  241.  
  242.     RETURN node^.name;
  243. END GetNodeName;
  244.  
  245. PROCEDURE FreeCDData (cddata: CDDataPtr);
  246. BEGIN
  247.     WITH cddata^ DO
  248.         IF artist # NIL THEN
  249.             el.FreeVec (artist);
  250.             artist := NIL;
  251.         END;
  252.         IF title # NIL THEN
  253.             el.FreeVec (title);
  254.             title := NIL;
  255.         END;
  256.         FreeList (ADR(tracks));
  257.     END;
  258. END FreeCDData;
  259.  
  260. PROCEDURE WriteList (list: ed.ListPtr);
  261. VAR
  262.     node: ed.NodePtr;
  263. BEGIN
  264.     (*
  265.     node := list^.head;
  266.  
  267.     IF node # NIL THEN
  268.         WHILE (node^.succ # NIL) DO
  269.             WriteString (CAST(StringPtr, node^.name)^);
  270.             WriteString (" hits=");
  271.             WriteInt (node^.pri, 0);
  272.             WriteString ("\n");
  273.             node := node^.succ;
  274.         END;
  275.     ELSE
  276.         WriteString ("The list is empty.\n");
  277.     END;
  278.     *)
  279. END WriteList;
  280.  
  281. PROCEDURE CreateMainWindow;
  282. VAR
  283.     ng: gtd.NewGadget;
  284.     gadget: id.GadgetPtr;
  285.     newgadget: gtd.NewGadget;
  286.     screen: id.ScreenPtr;
  287.     bool: BOOLEAN;
  288.     taglist: ARRAY [0..39] OF LONGINT;
  289. BEGIN
  290.     (* Das Hauptfenster soll auf dem Default-PublicScreen geöffnet
  291.      * werden:
  292.      *)
  293.     WITH topazfont DO
  294.         name    := ADR("topaz.font");
  295.         ySize   := 8;
  296.         style   := gd.FontStyleSet{};
  297.         flags   := gd.FontFlagSet{};
  298.     END;
  299.  
  300.     screen := il.LockPubScreen(NIL);
  301.     IF screen # NIL THEN
  302.         visualinfo := gtl.GetVisualInfoA(screen, NIL);
  303.         IF visualinfo # NIL THEN
  304.             glist := NIL;
  305.             gadget := gtl.CreateContext(glist);
  306.  
  307.             (* Gadgets initialisieren: *)
  308.             WITH newgadget DO
  309.                 leftEdge        := 68;
  310.                 topEdge         := 2;
  311.                 width           := 280;
  312.                 height          := 12;
  313.                 gadgetText      := ADR("_Artist:");
  314.                 textAttr        := ADR(topazfont);
  315.                 flags           := gtd.NewGadgetFlagSet{gtd.placetextLeft, gtd.ngHighlabel};
  316.                 gadgetID        := INTERPRET;
  317.                 visualInfo      := visualinfo;
  318.                 userData        := NIL;
  319.             END;
  320.             gadget := gtl.CreateGadgetA(gtd.textKind, gadget^, newgadget, TAG(taglist,
  321.                 gtd.gtUnderscore,    "_",
  322.                 gtd.gttxBorder,     TRUE,
  323.                 gtd.gttxText,       ADR("© 1996 Fin Schuppenhauer"),
  324.                 tagEnd));
  325.             artistGadget := gadget;
  326.  
  327.             WITH newgadget DO
  328.                 INC (topEdge, height + 2);
  329.                 gadgetText          := ADR("_Title:");
  330.                 gadgetID            := TITLE;
  331.             END;
  332.             gadget := gtl.CreateGadgetA(gtd.textKind, gadget^, newgadget, TAG(taglist,
  333.                 gtd.gtUnderscore,    "_",
  334.                 gtd.gttxBorder,     TRUE,
  335.                 gtd.gttxText,       ADR('See "CDIndex.readme" for details.'),
  336.                 tagEnd));
  337.             titleGadget := gadget;
  338.  
  339.             WITH newgadget DO
  340.                 INC (topEdge, height + 2);
  341.                 leftEdge            := 4;
  342.                 width               := 344;
  343.                 height              := 96;
  344.                 gadgetText          := NIL;
  345.                 gadgetID            := TRACKLISTING;
  346.             END;
  347.             gadget := gtl.CreateGadgetA(gtd.listviewKind, gadget^, newgadget, TAG(taglist,
  348.                 gtd.gtUnderscore,    "_",
  349.                 gtd.gtlvShowSelected, NIL,
  350.                 tagEnd));
  351.             tracklistingGadget := gadget;
  352.  
  353.             WITH newgadget DO
  354.                 INC (topEdge, height - 2);
  355.                 leftEdge            := 76;
  356.                 width               := 272;
  357.                 height              := 12;
  358.                 gadgetText          := ADR("_Pattern:");
  359.                 flags               := gtd.NewGadgetFlagSet{gtd.placetextLeft, gtd.ngHighlabel};
  360.                 gadgetID            := SEARCHPATTERN;
  361.             END;
  362.             gadget := gtl.CreateGadgetA(gtd.stringKind, gadget^, newgadget, TAG(taglist,
  363.                 gtd.gtUnderscore,   "_",
  364.                 tagEnd));
  365.             patternGadget := gadget;
  366.  
  367.             WITH newgadget DO
  368.                 INC (topEdge, height + 2);
  369.                 leftEdge            := 4;
  370.                 width               := 136;
  371.                 height              := 14;
  372.                 gadgetID            := SEARCHAREA;
  373.             END;
  374.             gadget := gtl.CreateGadgetA(gtd.cycleKind, gadget^, newgadget, TAG(taglist,
  375.                 gtd.gtUnderscore,   "_",
  376.                 gtd.gtcyLabels,     ADR(searchareaLabels),
  377.                 tagEnd));
  378.             searchareaGadget := gadget;
  379.  
  380.             WITH newgadget DO
  381.                 INC (leftEdge, width + 4);
  382.                 gadgetText          := ADR("Start _Search");
  383.                 flags               := gtd.NewGadgetFlagSet{gtd.placetextIn};
  384.                 gadgetID            := STARTSEARCH;
  385.             END;
  386.             gadget := gtl.CreateGadgetA(gtd.buttonKind, gadget^, newgadget, TAG(taglist,
  387.                 gtd.gtUnderscore,   "_",
  388.                 tagEnd));
  389.             startsearchGadget := gadget;
  390.  
  391.             WITH newgadget DO
  392.                 INC (leftEdge, width + 2);
  393.                 width               := 32;
  394.                 gadgetText          := ADR("_<");
  395.                 gadgetID            := PREVIOUS;
  396.             END;
  397.             gadget := gtl.CreateGadgetA(gtd.buttonKind, gadget^, newgadget, TAG(taglist,
  398.                 gtd.gtUnderscore,   "_",
  399.                 id.gaDisabled,     TRUE,
  400.                 tagEnd));
  401.             previousGadget := gadget;
  402.  
  403.             WITH newgadget DO
  404.                 INC (leftEdge, width + 2);
  405.                 gadgetText          := ADR("_>");
  406.                 gadgetID            := NEXT;
  407.             END;
  408.             gadget := gtl.CreateGadgetA(gtd.buttonKind, gadget^, newgadget, TAG(taglist,
  409.                 gtd.gtUnderscore,   "_",
  410.                 id.gaDisabled,     TRUE,
  411.                 tagEnd));
  412.             nextGadget := gadget;
  413.  
  414.             WITH newgadget DO
  415.                 INC (topEdge, height+2);
  416.                 leftEdge            := 4;
  417.                 width               := 344;
  418.                 gadgetText          := NIL;
  419.                 gadgetID            := MESSAGE;
  420.             END;
  421.             gadget := gtl.CreateGadgetA(gtd.textKind, gadget^, newgadget, TAG(taglist,
  422.                 gtd.gttxText,       ADR("Please, enter search pattern."),
  423.                 gtd.gttxBorder,     TRUE,
  424.                 gtd.gttxJustification, id.ActivationFlagSet{id.stringRight},
  425.                 tagEnd));
  426.             messageGadget := gadget;
  427.  
  428.             mainWindow := il.OpenWindowTagList(NIL, TAG(taglist,
  429.                 id.waLeft,          ArgInt(ADR("WINX"), 0),
  430.                 id.waTop,           ArgInt(ADR("WINY"), 0),
  431.                 id.waWidth,         360,
  432.                 id.waInnerHeight,   newgadget.topEdge + newgadget.height + 2,
  433.                 id.waMaxWidth,      screen^.width,
  434.                 id.waMaxHeight,     screen^.height,
  435.                 id.waIDCMP,         id.IDCMPFlagSet{id.refreshWindow, id.closeWindow, id.vanillaKey, id.rawKey} +
  436.                                     gtd.textIDCMP +
  437.                                     gtd.buttonIDCMP +
  438.                                     gtd.listviewIDCMP +
  439.                                     gtd.cycleIDCMP,
  440.                 id.waGadgets,       glist,
  441.                 id.waTitle,         ADR("CDIndex (Beta Release #2)"),
  442.                 id.waCloseGadget,   TRUE,
  443.                 id.waDragBar,       TRUE,
  444.                 id.waDepthGadget,   TRUE,
  445.                 (* id.waSizeGadget,    TRUE, *)
  446.                 id.waSizeBBottom,   TRUE,
  447.                 id.waActivate,      TRUE,
  448.                 id.waGimmeZeroZero, TRUE,
  449.                 id.waPubScreen,     screen,
  450.                 tagEnd));
  451.             IF mainWindow # NIL THEN
  452.                 il.UnlockPubScreen (NIL, screen);
  453.                 gtl.GTRefreshWindow (mainWindow, NIL);
  454.                 bool := il.ActivateGadget(patternGadget, mainWindow, NIL);
  455.             END;
  456.         END;
  457.     END;
  458. END CreateMainWindow;
  459.  
  460. PROCEDURE SetMessage (msg: StringPtr);
  461. VAR
  462.     taglist: ARRAY [0..9] OF LONGINT;
  463. BEGIN
  464.     gtl.GTSetGadgetAttrsA (messageGadget, mainWindow, NIL, TAG(taglist,
  465.         gtd.gttxText, msg,
  466.         tagEnd));
  467. END SetMessage;
  468.  
  469. (* --------------------------------------------------------------- *)
  470.  
  471. PROCEDURE LoadNextFile (
  472.     filelock: dd.FileLockPtr;
  473.     fib: dd.FileInfoBlockPtr;
  474.     searchinfo: SearchInfoPtr) : BOOLEAN;
  475. VAR
  476.     filename: ARRAY [0..1023] OF CHAR;
  477.     filehandle: dd.FileHandlePtr;
  478.     li: LONGINT;
  479. BEGIN
  480.     EnterProc ("LoadNextFile()\n");
  481.     String.Copy (filename, DISKSPATH^);
  482.     String.Concat (filename, fib^.fileName);
  483.     DebugMsg ("loading file '");
  484.     (*
  485.     WriteString (filename);
  486.     WriteString ("'...\n");
  487.     *)
  488.     filehandle := ds.Open(ADR(filename), dd.oldFile);
  489.     IF filehandle # NIL THEN
  490.         DebugMsg ("   file opened\n");
  491.         searchinfo^.buffer := el.AllocVec(fib^.size + 1, ed.MemReqSet{ed.memClear});
  492.         IF searchinfo^.buffer # NIL THEN
  493.             DebugMsg ("memory allocated\n");
  494.             li := dl.Read (filehandle, searchinfo^.buffer, fib^.size);
  495.         END;
  496.         DebugMsg ("data read\n");
  497.         (* Startpositionen des Titels und der Tracks ermitteln: *)
  498.         searchinfo^.titlestart := String.FirstPos (searchinfo^.buffer^, 0, "\n") + 1;
  499.         searchinfo^.trackstart := String.FirstPos (searchinfo^.buffer^, searchinfo^.titlestart, "\n") + 1;
  500.         DebugMsg ("positions marked\n");
  501.  
  502.         ds.Close (filehandle);
  503.     END;
  504.  
  505.     LeaveProc ("LoadNextFile.\n");
  506.     RETURN dl.ExNext(filelock, fib);
  507. END LoadNextFile;
  508.  
  509. PROCEDURE LoadCDData (filename: StringPtr; cddata: CDDataPtr);
  510. VAR
  511.     filehandle: dd.FileHandlePtr;
  512.     pathname: ARRAY [0..511] OF CHAR;
  513.     line: ARRAY [0..511] OF CHAR;
  514.     node: ed.NodePtr;
  515.     eof: BOOLEAN;
  516. BEGIN
  517.     EnterProc ("LoadCDData\n");
  518.  
  519.     FreeCDData (cddata);
  520.     maxitems := 0;
  521.     itemcount := 0;
  522.     es.NewList (ADR(cddata^.tracks));
  523.  
  524.     IF filename # NIL THEN
  525.         String.Copy (pathname, DISKSPATH^);
  526.         String.Concat (pathname, filename^);
  527.  
  528.         filehandle := ds.Open(ADR(pathname), dd.oldFile);
  529.         IF filehandle # NIL THEN
  530.             DebugMsg ("file opened\n");
  531.  
  532.             (* Namen des Interpreten einlesen: *)
  533.             eof := (dl.FGets(filehandle, ADR(line), 512) = NIL);
  534.             IF NOT(eof) THEN
  535.                 cddata^.artist := strdup(line);
  536.                 cddata^.artist^[String.Length(cddata^.artist^)-1] := 0C;
  537.  
  538.                 (* Title einlesen: *)
  539.                 eof := (dl.FGets(filehandle, ADR(line), 512) = NIL);
  540.                 IF NOT(eof) THEN
  541.                     cddata^.title := strdup(line);
  542.                     cddata^.title^[String.Length(cddata^.title^)-1] := 0C;
  543.                 END;
  544.             END;
  545.  
  546.             (* Tracks einlesen und in Exec-Listenstruktur für das
  547.              * Listview-Gadget einlesen:
  548.              *)
  549.             WHILE ~eof DO
  550.                 node := el.AllocVec(SIZE(ed.Node), ed.MemReqSet{ed.memClear});
  551.                 IF node # NIL THEN
  552.                     DebugMsg ("Node mem allocated\n");
  553.                     eof := (dl.FGets(filehandle, ADR(line), 512) = NIL);
  554.                     IF NOT(eof) THEN
  555.                         line[String.Length(line)-1] := 0C;
  556.                         node^.name := strdup(line);
  557.                         el.AddTail (ADR(cddata^.tracks), node);
  558.                         INC (maxitems);
  559.                     END;
  560.                 ELSE
  561.                     eof := TRUE;
  562.                 END;
  563.             END;
  564.  
  565.             ds.Close (filehandle);
  566.         END;
  567.     END;
  568.     LeaveProc ("LoadCDData\n");
  569. END LoadCDData;
  570.  
  571. (* --------------------------------------------------------------- *)
  572.  
  573. (* Initialisierung des Sprung-Arrays für die übergebene Zeichenkette.
  574.  * Das Sprungarray (BMSkipArray) gibt an, um wieviele Zeichen die
  575.  * zu vergleichende Zeichenkette verschoben werden kann, wenn ein
  576.  * Zeichen nicht übereinstimmt.
  577.  *)
  578. PROCEDURE InitBMSearch (pattern: StringPtr; length: INTEGER);
  579. VAR
  580.     i: INTEGER;         (* Schleifenvariable *)
  581. BEGIN
  582.     EnterProc ("InitBMSearch()\n");
  583.  
  584.     FOR i := 0 TO 255 DO
  585.         BMSkipArray[i] := length;
  586.     END;
  587.  
  588.     DEC (length);
  589.     FOR i := 0 TO length DO
  590.         BMSkipArray[ORD(pattern^[i])] := length-i;
  591.     END;
  592.     LeaveProc ("InitBMSearch.\n");
  593. END InitBMSearch;
  594.  
  595. PROCEDURE InitBMUppercaseSearch (pattern: StringPtr; length: INTEGER);
  596. VAR
  597.     i: INTEGER;         (* Schleifenvariable *)
  598. BEGIN
  599.     EnterProc ("InitBMUppercaseSearch()\n");
  600.  
  601.     FOR i := 0 TO 255 DO
  602.         BMSkipArray[i] := length;
  603.     END;
  604.  
  605.     DEC (length);
  606.     FOR i := 0 TO length DO
  607.         BMSkipArray[ORD(CAP(pattern^[i]))] := length-i;
  608.     END;
  609.     LeaveProc ("InitUppercaseBMSearch.\n");
  610. END InitBMUppercaseSearch;
  611.  
  612. PROCEDURE BMUppercaseSearch (
  613.     pattern : StringPtr;
  614.     text    : StringPtr;
  615.     startpos: LONGINT;
  616.     endpos  : LONGINT;
  617.     patternlength: INTEGER) : LONGINT;
  618. VAR
  619.     i,j,t: INTEGER;
  620. BEGIN
  621.     EnterProc ("BMUppercaseSearch()\n");
  622.     DebugMsg ("searching '");
  623.     (*
  624.     WriteString (pattern^);
  625.     WriteString ("' from "); WriteInt (startpos,0);
  626.     WriteString (" to "); WriteInt (endpos, 0); WriteString("...\n");
  627.     *)
  628.     IF (startpos >= endpos) OR (text = NIL) THEN
  629.         LeaveProc ("BMUppercaseSearch\n");
  630.         RETURN endpos;
  631.     END;
  632.  
  633.     IF startpos = 0 THEN
  634.         i := patternlength-1;
  635.     ELSE
  636.         i := startpos;
  637.     END;
  638.  
  639.     FOR j := patternlength-1 TO 0 BY -1 DO
  640.         WHILE (CAP(text^[i]) # CAP(pattern^[j])) DO
  641.             t := BMSkipArray[ORD(CAP(text^[i]))];
  642.             IF patternlength-j > t THEN
  643.                 INC (i, patternlength-j);
  644.             ELSE
  645.                 INC (i, t);
  646.             END;
  647.             IF i >= endpos THEN
  648.                 LeaveProc ("BMUppercaseSearch\n");
  649.                 RETURN endpos;
  650.             END;
  651.             j := patternlength-1;
  652.         END;
  653.         DEC (i);
  654.     END;
  655.  
  656.     LeaveProc ("BMUppercaseSearch.\n");
  657.     RETURN i+1;
  658. END BMUppercaseSearch;
  659.  
  660. PROCEDURE BMSearch (
  661.     pattern : StringPtr;
  662.     text    : StringPtr;
  663.     startpos: LONGINT;
  664.     endpos  : LONGINT;
  665.     patternlength: INTEGER) : LONGINT;
  666. VAR
  667.     i,j,t: INTEGER;
  668. BEGIN
  669.     EnterProc ("BMSearch()\n");
  670.     DebugMsg ("searching '");
  671.     (*
  672.     WriteString (pattern^);
  673.     WriteString ("' from "); WriteInt (startpos,0);
  674.     WriteString (" to "); WriteInt (endpos, 0); WriteString("...\n");
  675.     *)
  676.     IF (startpos >= endpos) OR (text = NIL) THEN
  677.         LeaveProc ("BMSearch\n");
  678.         RETURN endpos;
  679.     END;
  680.  
  681.     IF startpos = 0 THEN
  682.         i := patternlength-1;
  683.     ELSE
  684.         i := startpos;
  685.     END;
  686.  
  687.     FOR j := patternlength-1 TO 0 BY -1 DO
  688.         WHILE (text^[i] # pattern^[j]) DO
  689.             t := BMSkipArray[ORD(text^[i])];
  690.             IF patternlength-j > t THEN
  691.                 INC (i, patternlength-j);
  692.             ELSE
  693.                 INC (i, t);
  694.             END;
  695.             IF i >= endpos THEN
  696.                 LeaveProc ("BMSearch\n");
  697.                 RETURN endpos;
  698.             END;
  699.             j := patternlength-1;
  700.         END;
  701.         DEC (i);
  702.     END;
  703.  
  704.     LeaveProc ("BMSearch.\n");
  705.     RETURN i+1;
  706. END BMSearch;
  707.  
  708. PROCEDURE Search (
  709.     pattern : StringPtr;
  710.     text    : StringPtr;
  711.     startpos: LONGINT;
  712.     endpos  : LONGINT;
  713.     searchinfo: SearchInfoPtr;
  714.     VAR points: INTEGER) : INTEGER;
  715. VAR
  716.     hits: INTEGER;              (* Sooft wurder das Muster gefunden  *)
  717.     patternlength: INTEGER;     (* Länge des Suchbegriffs in Zeichen *)
  718.     casesensitiveSearch: BOOLEAN;
  719. BEGIN
  720.     EnterProc ("Search()\n");
  721.     hits := 0;
  722.     points := 0;
  723.     patternlength := String.Length(pattern^);
  724.  
  725.     casesensitiveSearch := NOT(IsLowerCase(pattern^));
  726.     IF casesensitiveSearch THEN
  727.         InitBMSearch (pattern, patternlength);
  728.     ELSE
  729.         InitBMUppercaseSearch (pattern, patternlength);
  730.     END;
  731.  
  732.     WHILE startpos < endpos DO
  733.         IF casesensitiveSearch THEN
  734.             startpos := BMSearch (pattern, text, startpos, endpos,
  735.                                   patternlength);
  736.         ELSE
  737.             startpos := BMUppercaseSearch (pattern, text, startpos, endpos, patternlength);
  738.         END;
  739.         IF startpos < endpos THEN
  740.             INC (hits);
  741.             IF startpos < searchinfo^.titlestart THEN
  742.                 INC (points, INARTIST);
  743.             ELSIF (startpos >= searchinfo^.titlestart) AND (startpos < searchinfo^.trackstart) THEN
  744.                 INC (points, INTITLE);
  745.             END;
  746.             IF Fullword(text, startpos, patternlength) THEN
  747.                 INC (points, FULLWORD);
  748.             ELSE
  749.                 INC (points, MATCHONLY);
  750.             END;
  751.             INC (startpos, 2*patternlength-1);
  752.         END;
  753.     END;
  754.     LeaveProc ("Search.\n");
  755.     RETURN hits;
  756. END Search;
  757.  
  758. PROCEDURE ShowSearchResult (cd: ed.NodePtr; cddata: CDDataPtr);
  759. VAR
  760.     taglist: ARRAY [0..9] OF LONGCARD;
  761.     list: ed.ListPtr;
  762.     message: ARRAY [0..79] OF CHAR;
  763.     value: ARRAY [0..15] OF CHAR;
  764.     err: BOOLEAN;
  765. BEGIN
  766.     EnterProc ("ShowSearchResults()\n");
  767.     (* Gültigen Knoten (Node) übergeben?: *)
  768.     IF cd^.succ = NIL THEN
  769.         (* Nein! *)
  770.         gtl.GTSetGadgetAttrsA(tracklistingGadget, mainWindow, NIL, TAG(taglist,
  771.                               gtd.gtlvLabels, NIL,
  772.                               tagEnd));
  773.         gtl.GTSetGadgetAttrsA(artistGadget, mainWindow, NIL, TAG(taglist,
  774.                               gtd.gttxText, NIL,
  775.                               tagEnd));
  776.         gtl.GTSetGadgetAttrsA(titleGadget, mainWindow, NIL, TAG(taglist,
  777.                               gtd.gttxText, NIL,
  778.                               tagEnd));
  779.         SetMessage (ADR("Sorry, pattern not found."));
  780.     ELSE
  781.         LoadCDData (cd^.name, cddata);
  782.         list := ADR(cddata^.tracks);
  783.         gtl.GTSetGadgetAttrsA(tracklistingGadget, mainWindow, NIL, TAG(taglist,
  784.                               gtd.gtlvLabels, list,
  785.                               gtd.gtlvSelected, 0,
  786.                               gtd.gtlvMakeVisible, 0,
  787.                               tagEnd));
  788.         taglist[0] := LONGCARD(gtd.gttxText);
  789.         taglist[1] := LONGCARD(cddata^.artist);
  790.         taglist[2] := tagEnd;
  791.         gtl.GTSetGadgetAttrsA(artistGadget, mainWindow, NIL, ADR(taglist));
  792.         taglist[1] := LONGCARD(cddata^.title);
  793.         gtl.GTSetGadgetAttrsA(titleGadget, mainWindow, NIL, ADR(taglist));
  794.         message := "CD ";
  795.         ValToStr (currentCDNumber, TRUE, value, 10, -10, 0C, err);
  796.         String.Concat (message, value);
  797.         String.Concat (message, " of ");
  798.         ValToStr (totalCDsFound, TRUE, value, 10, -10, 0C, err);
  799.         String.Concat (message, value);
  800.         String.Concat (message, "   Score: ");
  801.         ValToStr ((100*cd^.pri) DIV maxPoints, TRUE, value, 10, -10, 0C, err);
  802.         String.Concat (message, value);
  803.         String.Concat (message, "% (");
  804.         ValToStr (cd^.pri, TRUE, value, 10, -10, 0C, err);
  805.         String.Concat (message, value);
  806.         String.Concat (message, " points)");
  807.         SetMessage (ADR(message));
  808.     END;
  809.     LeaveProc ("ShowSearchResults\n");
  810. END ShowSearchResult;
  811.  
  812. (* --------------------------------------------------------------- *)
  813.  
  814. PROCEDURE SetSearchPattern (
  815.     VAR searchpattern: ARRAY OF CHAR;
  816.     gadget: id.GadgetPtr);
  817. BEGIN
  818.     EnterProc ("SetSearchPatter()\n");
  819.     String.Copy (searchpattern, CAST(StringPtr, CAST(id.StringInfoPtr, gadget^.specialInfo)^.buffer)^);
  820.     LeaveProc ("SetSearchPattern.\n");
  821. END SetSearchPattern;
  822.  
  823. PROCEDURE StartSearch (
  824.     VAR searchpattern: ARRAY OF CHAR;
  825.     searcharea: SearchArea;
  826.     cddata: CDDataPtr);
  827. VAR
  828.     fib: dd.FileInfoBlockPtr;
  829.     filelock: dd.FileLockPtr;
  830.     filename: ARRAY [0..127] OF CHAR;
  831.     searchinfo: SearchInfo;
  832.     startpos, endpos: LONGINT;
  833.     success: BOOLEAN;
  834.     count: INTEGER;
  835.     points: INTEGER;
  836.     node: ed.NodePtr;
  837.     taglist: ARRAY [0..9] OF LONGCARD;
  838. BEGIN
  839.     EnterProc ("StartSearch()\n");
  840.  
  841.     IF String.Length(searchpattern) = 0 THEN
  842.         SetMessage (ADR("No pattern specified!"));
  843.         RETURN;
  844.     END;
  845.  
  846.     (* Previous-, Next- und Pattern-Gadget dekativieren: *)
  847.     taglist[0] := LONGCARD(id.gaDisabled);
  848.     taglist[1] := LONGCARD(TRUE);
  849.     taglist[2] := tagEnd;
  850.     gtl.GTSetGadgetAttrsA (patternGadget, mainWindow, NIL, ADR(taglist));
  851.     gtl.GTSetGadgetAttrsA (searchareaGadget, mainWindow, NIL, ADR(taglist));
  852.     gtl.GTSetGadgetAttrsA (startsearchGadget, mainWindow, NIL, ADR(taglist));
  853.     gtl.GTSetGadgetAttrsA (previousGadget, mainWindow, NIL, ADR(taglist));
  854.     gtl.GTSetGadgetAttrsA (nextGadget, mainWindow, NIL, ADR(taglist));
  855.  
  856.     SetMessage (ADR("Searching..."));
  857.     currentCDNumber := 1;
  858.     totalCDsFound := 0;
  859.     totalHits := 0;
  860.     maxPoints := 0;
  861.  
  862.     (* Ergebnisliste initialisieren: *)
  863.     FreeSearchResultsList (ADR(searchresults));
  864.     es.NewList (ADR(searchresults));
  865.  
  866.  
  867.     fib := dl.AllocDosObject(dd.dosFib, NIL);
  868.     IF fib = NIL THEN
  869.         taglist[1] := LONGCARD(FALSE);
  870.         gtl.GTSetGadgetAttrsA (patternGadget, mainWindow, NIL, ADR(taglist));
  871.         gtl.GTSetGadgetAttrsA (searchareaGadget, mainWindow, NIL, ADR(taglist));
  872.         gtl.GTSetGadgetAttrsA (startsearchGadget, mainWindow, NIL, ADR(taglist));
  873.         SetMessage (ADR("Error: Not enough memory!"));
  874.         RETURN;
  875.     END;
  876.  
  877.     filelock := dl.Lock(DISKSPATH, dd.accessRead);
  878.     IF filelock = NIL THEN
  879.         dl.FreeDosObject (dd.dosFib, fib);
  880.         taglist[1] := LONGCARD(FALSE);
  881.         gtl.GTSetGadgetAttrsA (patternGadget, mainWindow, NIL, ADR(taglist));
  882.         gtl.GTSetGadgetAttrsA (searchareaGadget, mainWindow, NIL, ADR(taglist));
  883.         gtl.GTSetGadgetAttrsA (startsearchGadget, mainWindow, NIL, ADR(taglist));
  884.         SetMessage (ADR("Can't open disks directory! Check Tooltypes."));
  885.         RETURN;
  886.     END;
  887.  
  888.     success := dl.Examine (filelock, fib);
  889.     WHILE success DO
  890.         searchinfo.buffer := NIL;
  891.         String.Copy (filename, fib^.fileName);
  892.         endpos   := fib^.size;
  893.         success := LoadNextFile (filelock, fib, ADR(searchinfo));
  894.         startpos := 0;
  895.         CASE searcharea OF
  896.           | SAartist:
  897.                 endpos := searchinfo.titlestart;
  898.           | SAtitle:
  899.                 startpos := searchinfo.titlestart;
  900.                 endpos   := searchinfo.trackstart;
  901.           | SAtracklisting:
  902.                 startpos := searchinfo.trackstart;
  903.         ELSE
  904.         END;
  905.         DebugMsg ("Suche nach '");
  906.         (*
  907.         WriteString (searchpattern);
  908.         WriteString ("' von "); WriteInt (startpos,0);
  909.         WriteString (" bis "); WriteInt (endpos, 0);
  910.         WriteString (".\n");
  911.         *)
  912.         count := Search(ADR(searchpattern), searchinfo.buffer, startpos, endpos, ADR(searchinfo), points);
  913.         IF count > 0 THEN
  914.             (* Suchergebnisse merken *)
  915.             (*
  916.             t.Format ("Suchmuster %d mal gefunden.\n", ADR(count));
  917.             *)
  918.             node := el.AllocVec(SIZE(ed.Node), ed.MemReqSet{ed.memClear});
  919.             IF node # NIL THEN
  920.                 node^.pri := points; (*count;*)
  921.                 node^.name := strdup(filename);
  922.                 el.Enqueue (ADR(searchresults), node);
  923.             END;
  924.             INC (totalCDsFound);
  925.             INC (totalHits, count);
  926.             IF points > maxPoints THEN
  927.                 maxPoints := points;
  928.             END;
  929.         ELSE
  930.             (*
  931.             WriteString ("Suchmuster NICHT gefunden.\n");
  932.             *)
  933.         END;
  934.  
  935.         IF searchinfo.buffer # NIL THEN
  936.             el.FreeVec (searchinfo.buffer);
  937.         END;
  938.     END;
  939.  
  940.     dl.UnLock (filelock);
  941.     dl.FreeDosObject (dd.dosFib, fib);
  942.  
  943.     (* Gadgets aktualisieren und erstes Ergebnis anzeigen: *)
  944.     currentsearchresult := searchresults.head;
  945.  
  946.     taglist[1] := LONGCARD(FALSE);
  947.     gtl.GTSetGadgetAttrsA (patternGadget, mainWindow, NIL, ADR(taglist));
  948.     gtl.GTSetGadgetAttrsA (searchareaGadget, mainWindow, NIL, ADR(taglist));
  949.     gtl.GTSetGadgetAttrsA (startsearchGadget, mainWindow, NIL, ADR(taglist));
  950.  
  951.     (* Gibt es kein oder nur ein Ergebnis?: *)
  952.     taglist[1] := LONGCARD((currentsearchresult^.succ = NIL) OR (currentsearchresult^.succ^.succ = NIL));
  953.     gtl.GTSetGadgetAttrsA (nextGadget, mainWindow, NIL, ADR(taglist));
  954.     ShowSearchResult (currentsearchresult, cddata);
  955.  
  956.     WriteList (ADR(searchresults));
  957.     LeaveProc ("StartSearch.\n");
  958. END StartSearch;
  959.  
  960. PROCEDURE ViewPrevious (cddata: CDDataPtr);
  961. VAR
  962.     taglist: ARRAY [0..9] OF LONGCARD;
  963. BEGIN
  964.     IF currentsearchresult^.pred^.pred # NIL THEN
  965.         currentsearchresult := currentsearchresult^.pred;
  966.         DEC (currentCDNumber);
  967.         taglist[0] := LONGCARD(id.gaDisabled);
  968.         taglist[1] := LONGCARD(FALSE);
  969.         taglist[2] := tagEnd;
  970.         gtl.GTSetGadgetAttrsA (nextGadget, mainWindow, NIL, ADR(taglist));
  971.         taglist[1] := LONGCARD(currentsearchresult^.pred^.pred = NIL);
  972.         gtl.GTSetGadgetAttrsA (previousGadget, mainWindow, NIL, ADR(taglist));
  973.         ShowSearchResult (currentsearchresult, cddata);
  974.     END;
  975. END ViewPrevious;
  976.  
  977. PROCEDURE ViewNext (cddata: CDDataPtr);
  978. VAR
  979.     taglist: ARRAY [0..9] OF LONGCARD;
  980. BEGIN
  981.     IF currentsearchresult^.succ^.succ # NIL THEN
  982.         currentsearchresult := currentsearchresult^.succ;
  983.         INC (currentCDNumber);
  984.         taglist[0] := LONGCARD(id.gaDisabled);
  985.         taglist[1] := LONGCARD(FALSE);
  986.         taglist[2] := tagEnd;
  987.         gtl.GTSetGadgetAttrsA (previousGadget, mainWindow, NIL, ADR(taglist));
  988.         taglist[1] := LONGCARD(currentsearchresult^.succ^.succ = NIL);
  989.         gtl.GTSetGadgetAttrsA (nextGadget, mainWindow, NIL, ADR(taglist));
  990.         ShowSearchResult (currentsearchresult, cddata);
  991.     END;
  992. END ViewNext;
  993.  
  994. (* --------------------------------------------------------------- *)
  995.  
  996. PROCEDURE ProcessMsg;
  997. VAR
  998.     done: BOOLEAN;
  999.     imsg: id.IntuiMessagePtr;
  1000.     class: id.IDCMPFlagSet;
  1001.     code: CARDINAL;
  1002.     qual: ie.QualifierSet;
  1003.     gadget: id.GadgetPtr;
  1004.     searchpattern: ARRAY [0..255] OF CHAR;
  1005.     searcharea: SearchArea;
  1006.     cddata: CDData;
  1007.     bool: BOOLEAN;
  1008.     taglist: ARRAY [0..9] OF LONGCARD;
  1009. BEGIN
  1010.     WITH cddata DO
  1011.         artist := NIL;
  1012.         title  := NIL;
  1013.         es.NewList (ADR(tracks));
  1014.     END;
  1015.     searcharea := SAanywhere;
  1016.     done := FALSE;
  1017.  
  1018.     WHILE NOT(done) DO
  1019.         el.WaitPort (mainWindow^.userPort);
  1020.  
  1021.         LOOP
  1022.             imsg := gtl.GTGetIMsg(mainWindow^.userPort);
  1023.             IF imsg = NIL THEN EXIT; END;
  1024.  
  1025.             class := imsg^.class;
  1026.             code := imsg^.code;
  1027.             gadget := CAST(id.GadgetPtr, imsg^.iAddress);
  1028.             qual := imsg^.qualifier;
  1029.  
  1030.             gtl.GTReplyIMsg (imsg);
  1031.  
  1032.             IF id.closeWindow IN class THEN
  1033.                 done := TRUE;
  1034.             ELSIF id.refreshWindow IN class THEN
  1035.                 gtl.GTBeginRefresh (mainWindow);
  1036.                 gtl.GTEndRefresh (mainWindow, TRUE);
  1037.             ELSIF id.gadgetUp IN class THEN
  1038.                 CASE gadget^.gadgetID OF
  1039.                     SEARCHPATTERN:
  1040.                         SetSearchPattern (searchpattern, gadget);
  1041.                         StartSearch (searchpattern, searcharea, ADR(cddata));
  1042.                   | SEARCHAREA:
  1043.                         searcharea := SearchArea(code);
  1044.                   | STARTSEARCH:
  1045.                         SetSearchPattern (searchpattern, patternGadget);
  1046.                         StartSearch (searchpattern, searcharea, ADR(cddata));
  1047.                   | PREVIOUS:
  1048.                         ViewPrevious (ADR(cddata));
  1049.                   | NEXT:
  1050.                         ViewNext (ADR(cddata));
  1051.                   | TRACKLISTING:
  1052.                         gtl.GTSetGadgetAttrsA(patternGadget, mainWindow, NIL, TAG(taglist,
  1053.                             gtd.gtstString, GetNodeName (code, ADR(cddata.tracks)),
  1054.                             tagEnd));
  1055.                 ELSE
  1056.                 END;
  1057.             ELSIF id.vanillaKey IN class THEN
  1058.                 CASE CAP(CHAR(code)) OF
  1059.                     "Q","X", 33C:
  1060.                         done := TRUE;
  1061.                   | "C":
  1062.                         IF CHAR(code) = CAP(CHAR(code)) THEN
  1063.                             searcharea := SearchArea((INTEGER(searcharea) - 1) MOD 4);
  1064.                         ELSE
  1065.                             searcharea := SearchArea((INTEGER(searcharea) + 1) MOD 4);
  1066.                         END;
  1067.                         gtl.GTSetGadgetAttrsA(searchareaGadget, mainWindow, NIL, TAG(taglist,
  1068.                             gtd.gtcyActive, searcharea,
  1069.                             tagEnd));
  1070.                   | "P":
  1071.                         bool := il.ActivateGadget(patternGadget, mainWindow, NIL);
  1072.                   | "S":
  1073.                         SetSearchPattern (searchpattern, patternGadget);
  1074.                         StartSearch (searchpattern, searcharea, ADR(cddata));
  1075.                   | "A":
  1076.                     gtl.GTSetGadgetAttrsA(patternGadget, mainWindow, NIL, TAG(taglist,
  1077.                         gtd.gtstString, cddata.artist,
  1078.                         tagEnd));
  1079.                   | "T":
  1080.                     gtl.GTSetGadgetAttrsA(patternGadget, mainWindow, NIL, TAG(taglist,
  1081.                         gtd.gtstString, cddata.title,
  1082.                         tagEnd));
  1083.                   | "<":
  1084.                         ViewPrevious (ADR(cddata));
  1085.                   | ">":
  1086.                         ViewNext (ADR(cddata));
  1087.                   | 15C:
  1088.                         gtl.GTSetGadgetAttrsA(patternGadget, mainWindow, NIL, TAG(taglist,
  1089.                             gtd.gtstString, GetNodeName (itemcount, ADR(cddata.tracks)),
  1090.                             tagEnd));
  1091.                 ELSE
  1092.                 END;
  1093.             ELSIF id.rawKey IN class THEN
  1094.                 CASE code OF
  1095.                     id.cursorUp:
  1096.                         IF (ie.rShift IN qual) OR (ie.lShift IN qual) THEN
  1097.                             itemcount := 0;
  1098.                         ELSIF (ie.rAlt IN qual) OR (ie.lAlt IN qual) THEN
  1099.                             IF (itemcount-ITEMSVISIBLE) > 0 THEN
  1100.                                 DEC (itemcount, ITEMSVISIBLE);
  1101.                             ELSE
  1102.                                 itemcount := 0;
  1103.                             END;
  1104.                         ELSE
  1105.                             IF itemcount > 0 THEN
  1106.                                 DEC (itemcount);
  1107.                             END;
  1108.                         END;
  1109.                         gtl.GTSetGadgetAttrsA (tracklistingGadget, mainWindow, NIL, TAG(taglist,
  1110.                             gtd.gtlvMakeVisible, itemcount,
  1111.                             gtd.gtlvSelected, itemcount,
  1112.                             tagEnd));
  1113.                   | id.cursorDown:
  1114.                         IF (ie.rShift IN qual) OR (ie.lShift IN qual) THEN
  1115.                             itemcount := maxitems;
  1116.                         ELSIF (ie.rAlt IN qual) OR (ie.lAlt IN qual) THEN
  1117.                             IF (itemcount+ITEMSVISIBLE) < maxitems THEN
  1118.                                 INC (itemcount, ITEMSVISIBLE-1);
  1119.                             ELSE
  1120.                                 itemcount := maxitems;
  1121.                             END;
  1122.                         ELSE
  1123.                             IF itemcount < maxitems THEN
  1124.                                 INC (itemcount);
  1125.                             END;
  1126.                         END;
  1127.                         gtl.GTSetGadgetAttrsA (tracklistingGadget, mainWindow, NIL, TAG(taglist,
  1128.                             gtd.gtlvMakeVisible, itemcount,
  1129.                             gtd.gtlvSelected, itemcount,
  1130.                             tagEnd));
  1131.                   | id.cursorLeft:
  1132.                         ViewPrevious (ADR(cddata));
  1133.                   | id.cursorRight:
  1134.                         ViewNext (ADR(cddata));
  1135.                 ELSE
  1136.                 END;
  1137.             END;
  1138.         END; (* LOOP *)
  1139.     END; (* WHILE *);
  1140.  
  1141.     FreeCDData (ADR(cddata));
  1142. END ProcessMsg;
  1143.  
  1144. PROCEDURE Shutdown;
  1145. BEGIN
  1146.     il.CloseWindow (mainWindow); mainWindow := NIL;
  1147.     gtl.FreeGadgets (glist);
  1148.     gtl.FreeVisualInfo (visualinfo);
  1149.     FreeSearchResultsList (ADR(searchresults));
  1150. END Shutdown;
  1151.  
  1152. BEGIN
  1153.     DISKSPATH := ArgString(ADR("DISKSPATH"), ADR("EH0:PublicDomain/Disk/CeeD/Disks/"));
  1154.     INTITLE   := ArgInt(ADR("TITLEPOINTS"), 10);
  1155.     INARTIST  := ArgInt(ADR("ARTISTPOINTS"), 10);
  1156.     FULLWORD  := ArgInt(ADR("FULLWORDPOINTS"), 5);
  1157.     MATCHONLY := ArgInt(ADR("MATCHONLYPOINTS"), 1);
  1158.  
  1159.     CreateMainWindow;
  1160.     ProcessMsg;
  1161.     Shutdown;
  1162.  
  1163. CLOSE
  1164.     IF mainWindow # NIL THEN
  1165.         il.CloseWindow (mainWindow);
  1166.     END;
  1167. END CDIndex.
  1168.