home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 13 / AACD13.ISO / AACD / Utilities / ACDPlay / src / V1.5 / ACDPlay.c.BAK < prev    next >
Text File  |  1997-12-23  |  70KB  |  2,159 lines

  1. /*************************************************************************
  2.  
  3.         |¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
  4.         |            ACDPlay - Utility              |
  5.         |           -------------------             |
  6.         |                                           |
  7.         |               Version 1.51                |
  8.         |___________________________________________|
  9.  
  10.    Autoren  : Marc Altmann  [MC3]
  11.               Martin Kresse [mak]
  12.    Copyright: E-Mailware
  13.  
  14.    Was: ACDPlay ist ein fantastisches Utility zum Abspielen von
  15.         CDDA-Disks auf SCSI-CD-ROM-Laufwerken.
  16.  
  17.    Umgebung : Maxon C++ light 3.10.1 auf Amiga 12oo OS3.0 68o3o 2MB Chip 8MB Fast
  18.  
  19.    Status   : letzte öffentliche Version 1.48b
  20.               nächste geplante öffentliche Version 1.5
  21.  
  22.    Bugs     : - Manchmal werden die Parameter von ShowMsgA() in der Shell
  23.                 falsch angezeigt
  24.  
  25.  
  26.    Autor   Version   Datum          Veränderungen
  27.   ------- --------- --------       ------------------------------------------
  28.     MC3        0.1        22.06.96    Ersterstellung (Programmgerüst)
  29.  
  30.     mak        0.11    19.09.96    Sourcecode überarbeitet
  31.                                 - ShowMsg() dazu
  32.                     20.09.96    - OpenLibs() / CloseLibs() dazu
  33.                                 - GetMem() / FreeAllMem() dazu
  34.                                 - InitCDStruct() / FreeCDStruct() dazu
  35.  
  36.     mak        0.12    22.09.96    - OpenApplication() dazu
  37.                                 - SetDefaultApplication() vorläufig dazu
  38.                                 - OpenApplicationWindow() dazu
  39.                     24.09.96    - CloseApplication() dazu
  40.                                 - CloseAppWin() dazu
  41.                                 - TextWidth() dazu
  42.                     26.09.96    - GetMem / FreeAllMem entfernt
  43.                                 - CreateApplication() dazu
  44.                                 - ReadConfig() dazu
  45.  
  46.     MC3        0.13    28.09.96    - IDCMP-Verwaltung implementiert
  47.                                 - HandleEvents() dazu (nur rudimentär)
  48.                                 - erste Commodity-Eigenschaften (Entfernen)
  49.                                 - HandleCommodityEvents() dazu
  50.                     29.09.96    - Weitere Commodity-Eigenschaften (Verbergen, Sichtbar)
  51.                                 - Hotkey-fähig
  52.                                 - CX_PRIORITY-, CX_POPUP-, CX_POPKEY-Unterstützung
  53.  
  54.     MC3        0.14    30.09.96    - MakeMenus() dazu (Behelfsversion)
  55.                                 - HandleEvents() um MENUPICK-Events ausgebaut
  56.                     02.10.96    - MakeMenus() in geplanter Form
  57.                                 - FindWidest() dazu
  58.                     03.10.96    - About-Window fertiggestellt
  59.                                 - Init/OpenCDStruct() und FreeCDStruct() verändert
  60.                     04.10.96    - Laufwerksinformationsfenster fertiggestellt
  61.  
  62.     mak        0.15    07.10.96    - Konstante STDWINDOWFLG eingeführt
  63.                                 - ReadConfig() greift notfalls auf Defaultwerte aus
  64.                                 - SaveConfig() und FreeConfig() dazu
  65.                     08.10.96    - GetVec() dazu
  66.                                 - main() Struktur überarbeitet
  67.                                   (keine Enforcer-Hits mehr)
  68.                     10.10.96    - Read- und SaveConfig() fertiggestellt
  69.                                 - CreateApp.() benutzt jetzt cfg-Struktur
  70.                                 - CX-Bug in CreateApp.() entfernt
  71.                     11.10.96    - HandleEvents() unterstüzt jetzt "Multi-Selection"
  72.                                 - Parameter *Window aus ShowMsg genommen
  73.                                 - AllocVec´s() in GetVec´s() geändert
  74.  
  75.     mak        0.16.a    12.10.96    - WindowToFront() u. ActivateWindow()
  76.                                   sind jetzt in OpenAppWin() integriert
  77.  
  78.     mak        0.17.a    12.10.96    - Das EXECUTABLE-Flag wird jetzt bei
  79.                                   SaveConfig() gelöscht
  80.                                 - Bug in SaveConfig() (wenn app=NULL) entfernt
  81.                                 - Bug in HandleEvents() entfernt
  82.                                   (wenn Multi-Selection: 1.Verbergen 2.Über)
  83.  
  84.     MC3        0.17b    14.10.96    - CxFilter und CxSender zur Timer-Event-Synchronisation
  85.                                   erstellt (jede 1/10-Sekunde)
  86.                                 - CD- und Laufwerks-Fenster jetzt zusätzlich mit Textgadgets,
  87.                                   zur besseren Aktualisierung (beim LW-Fenster unnötig)
  88.                                 - Bug in der Hauptschleife behoben. Ein 'done = TRUE' in
  89.                                   HandleEvents() wurde mitunter in HandleCommodityEvents()
  90.                                   wieder rückgängig gemacht.
  91.                                 - FlushMessages() dazu - beantwortet alle Messages eines Ports
  92.  
  93.     MC3        0.18    16.10.96    - Gadgets im Hauptfenster fertiggestellt. Durch ein Flag-Word
  94.                                   in der Application-Struktur können die einzelnen Reihen mit
  95.                                   Bedienungselementen an- oder ausgeschaltet werden.
  96.  
  97.     mak        0.19    17.10.96    - einige nichtüberprüfte GetVecs() überarbeitet
  98.                                 - SCSI_DEVICE Check in OpenCDStruct() eingebaut
  99.                                 - einige überflüssige Befehle entfernt
  100.                     18.10.96    - ToolTypes werden jetzt auch gelesen
  101.                                 - OpenApplication holt den Screen nach vorne falls
  102.                                   die Application schon offen ist
  103.                                 - Screennotify-Unterstützung für Open/CloseWorkBench()
  104.                                 - Application.Flags kann frei benutzt werden
  105.  
  106.     MC3        0.20    19.10.96    - MakeInterior() und UpdateGadgets() erweitert (Fenstertitel)
  107.                                 - Menü des Hauptfensters erweitert. Kontrolle der GUI-Elemente
  108.                                   nun über Menü möglich
  109.                                 - Bug in CloseAppWin() behoben. Bei FreeVec() usw. wurden die
  110.                                   Zeiger nicht auf NULL gesetzt
  111.                                 - Wenn keine GUI-Elemente angegeben werden, wird das Fenster als
  112.                                   Titelzeile *ohne* Zoom-Gadget göffnet
  113.                     20.10.96    - Neues Tooltype: PUBSCREEN
  114.                                 - PubScreen-Fenster eingebaut (stürzt manchmal ab!)
  115.                                 - Allerlei Listenfunktionen erstellt
  116.                     21.10.96    - Abstürz-Bug entfernt (siehe 20.10)
  117.                                 - GetPubScreenList() und KillPubScreenList() an das
  118.                                   Application-Konzept angepaßt
  119.                     22.10.96    - Eine Reihe von Abspielfunktionen eingebaut, die sich hoffentlich
  120.                                   für AREXX eignen.
  121.  
  122.     ???        0.21    ???            ???
  123.  
  124.     mak        0.22    24.10.96    - InitList() durch NewList() aus amiga.lib ersetzt
  125.                                 - ClearMenuStrip steht jetzt vor CloseWindow() (keine Enforcerhits mehr)
  126.                                 - Statusflags in Source eingefügt
  127.                                 - das Pubscreen-Fenster wird jetzt richtig aufgefrischt (ohne GimmeZeroZero)
  128.                     26.10.96    - Programm lokalisiert
  129.                                 - testweise Drive-Info Fenster verändert
  130.  
  131.     MC3        0.23    26.10.96    - Gadgets werden beim Öffnen des Fensters geshadet
  132.                                 - Trackslider funktioniert (noch nicht ganz bugfrei)
  133.                                 - ACDPlay_cat.c ab jetzt überflüssig
  134.                     27.10.96    - Bugfix: Wenn die CD zuende war, spielte der Trackslider verrückt
  135.                                 - Bugfix: Trackslider-Level wird in MakeGadgets() gesetzt
  136.             0.24    06.11.96    - Alpha-CD-Titel-Verwaltung implementiert
  137.                                 - Aktualisierung der Zeitanzeige (pro Sekunde ein neues Gadget - krass!)
  138.                                 - KillPubScreenList() entfernt, dafür FreeList() eingeführt
  139.                     07.11.96    - Fenstertitel arbeitet jetzt mit wirklichen CD-Namen (UpdateWinTitle())
  140.                                 - Kein Flackern mehr beim Pausegadget-Refresh (außerdem: eigene Funktion)
  141.                                 - NewSize-Events werden jetzt durch ManageNewSize() gehandhabt
  142.                                 - Neues Fenster: Titelauswahl
  143.             0.25    09.11.96    - VANILLAKEY-Support für Direktwahlbuttons
  144.                     10.11.96    - Neues Fenster: Titeleingabe (funktioniert!)
  145.                                 - In den Info-Fenstern werden Intuitexte jetzt weiß gezeichnet
  146.                                 - Index-Anzeige zeigt jetzt '1' beim Spielen an... Fake!  ;-)
  147.  
  148.             0.26    11.11.96    - Neues Tooltype: HOTKEYCAUSES
  149.                                 - GetPubScreenName() holt sich einen bestimmten Screennamen
  150.                                 - kleine Bugfixes (von >>>mak<<< erwünscht :-)
  151.                                 - Im Titelauswahl- und Pubscreenfenster jetzt Doppelklick
  152.                                   notwendig, um ein Element auszuwählen
  153.  
  154.     mak        0.26b    11.11.96    - Bug in OpenCDStruct() entfernt (zehnstellige Unitnummer :-)
  155.  
  156.     MC3        0.27    13.11.96    - Zwei neue Tooltypes: USEWINDOWBAR und USESCREENBAR
  157.                                 - Zeitanzeige mit 4 verschiedenen Modi implementiert
  158.                                 - Alle Fenster benutzen denselben Menustrip
  159.                                 - Code-Ersparnisse in MakeMenus() und HandleEvents()
  160.                                 - Cursortasten können benutzt werden (ausprobieren!)
  161.  
  162.     mak        0.28    18.11.96    - AsmLib eingeführt, welche OpenLibs(), CloseLibs(), ShowMsg()
  163.                                   GetVec(), FlushMessages() und MyFormat() (jetzt FormatA()) durch Assemblerroutinen
  164.                                   (z.B. ShowMsgA()) ersetzt. Die Parameter bleiben wie gehabt.
  165.                                 - ARexxPort (in AsmLib) integriert
  166.  
  167.     MC3        0.29    19.11.96    - Trackwiederholung eingebaut (Problem beim letzten Track)
  168.                                 - Schreiben und Lesen von Titeldaten implementiert;
  169.                                   Pfad als Tooltype DISKPATH angeben oder "ACDPlay:Disks/"
  170.                                 - AllocDosObject()-Einsatz auch in ReadConfig()
  171.  
  172.                     21.11.96    - Bugfix: Wiederholung funktioniert jetzt (bis auf letzter Track)
  173.                                 - Bugfix: Die Cycle-Gadgets zeigen jetzt den richtigen Modus an,
  174.                                   wenn sie erneut erzeugt werden.
  175.                                 - Bugfix: Jede Sekunde wurden 2 * sizeof(Gadget) Bytes 'gefressen'
  176.                                 - Wiederholung Track und Alles funktionieren vollständig (nach
  177.                                   Deinem System)
  178.  
  179.     mak        0.30    23.11.96    - ARexx endlich fertig und integriert (Errorrückgabe muß ich mir noch überlegen)
  180.                                   ACDPlay kennt jetzt: PLAY STOP EJECT NEXTSONG PREVSONG SHOW HIDE und QUIT
  181.                                 - FindARexxPortA() am Anfang eingefügt
  182.  
  183.     MC3        0.31    29.11.96    - Programmierung implementiert (Arexx-günstig)
  184.                     30.11.96    - Bugfixes
  185.  
  186.     mak        0.32    30.11.96    - Volumewindow (z.Z. noch ohne Funktion) eingebaut
  187.                                 - Menupunkt Fixieren funktioniert jetzt
  188.                                 - Bugfix: Absturz im Editwindow wenn Programmwindow nicht offen war
  189.  
  190.     MC3        0.33    07.12.96    - Zufallsmodus eingebaut
  191.                                 - Fixieren fixiert jetzt auch Fenstergrößen
  192.                                 - Volume-Fenster und A-B-Repeat ausgeklammert
  193.                                 - CD-Info-Fenster entsprechend Device-Info-Fenster geändert
  194.  
  195.             0.34    08.12.96    - Neues Tooltype: MAGICWB
  196.                                 - MagicWB-Toggle-Menü funktioniert
  197.                                 - FakeRequestA() bei drei Fenstern eingesetzt (sieht gut aus!)
  198.  
  199.             1.0        14.12.96    - SEARCHSECONDS-Tooltype
  200.                                 - ein paar Bugs weg, Catalogs geändert
  201.  
  202.     mak        1.0b    15.12.96    - Bugfix in MakeInterior (EnforcerHits)
  203.                                 - Volumeüberreste auskommentiert
  204.  
  205.     MC3        1.01a    01.01.97    - 'Update'-Button im Pubscreen-Fenster
  206.                                 - Funktion AdjustNewSize() für zukünftige Sizing-Wins
  207.                                 - In MakeVisuals() (ehem. MakeGadgets()) aufgeräumt
  208.                     02.01.97    - Die beiden Info-Fenster sind jetzt größenveränderbar
  209.                     04.01.97    - Das About-Fenster scrollt jetzt - mußte dazu leider die
  210.                                   Parameter bei TextWidth() und FindWidest() ändern.
  211.                                 - Nicht-aktualisierte-Titel-Bug ist weg... :-)
  212.             1.01ß    05.01.97    - numeric-Keypad-Bug ist weg!  :-)
  213.                                 - Neue Menüs
  214.  
  215.             1.1        26.01.97    - Config-Teil total verändert
  216.                                 - wahnsinnig viel anderes verändert :-)    (2 Tooltypes)
  217.                                 - CLI-Parameter
  218.  
  219.             1.12    29.01.97    - AppIcon
  220.  
  221.     mak        1.3        02.02.97    - Play überspringt Datentracks am Anfang
  222.                                 - viele CDPlayLib-Funktionen durch eigene ersetzt
  223.                     03.02.97    - Bug in ChangeButtonText() und ReadArguments() entfernt
  224.                     08.02.97    - restliche CD-Routinen ersetzt
  225.                                 - einige Optimierungen im Source
  226.  
  227.     MC3        1.31    14.02.97    - ChangeButtonText() optimiert (ein ½ Hack!) + Asm
  228.                                 - Richtige Searchbuttons... (und Trackslider)
  229.                                   (Ich weiß leider nicht, wie Du das im SCSI-Test-Programm
  230.                                   implementiert hattest. Wenn es besser war, bitte ersetzen)
  231.                                 - den Betatestern gegeben
  232.  
  233.             1.32    16.02.97    - "PROGDIR:ARexx" wird im ARexx-Menü angezeigt
  234.                                 - "Execute ARexx..." geht. mit Asl-Requester (nur mit asl.lib)
  235.  
  236.             1.33    16.02.97    - Neues Fenster A-B-Repeat: Vorsicht mit dem Konfig-File! Wenn man
  237.                                   ein neues Konfig-File hat und ein altes ACDP lädt, stürzt es ab(!)
  238.                                 - Lokalisiert (catalogs version 2)
  239.  
  240.             1.34    17.02.97    - Programm- und
  241.                     19.02.97    - Titeleingabefenster sind jetzt größenveränderbar
  242.  
  243.     mak        1.35    01.03.97    - ExecuteARexx() funktioniert jetzt in Asm
  244.                                 - Bugs in CloseApplication(), ReadConfig(), GetDir() und CreateAppIcon() beseitigt
  245.                                 - ARexxfunktionen geben jetzt endlich definierte Rückgabewerte zurück
  246.                                 - cdplay.library vollständig eleminiert
  247.                                 - NULL-test in einige Funktionen eingebaut
  248.  
  249.     MC3        1.36    11.03.97    - A-B-Repeat funktioniert
  250.                                 - alte ChangeButtonText()-Funktion
  251.                                 - []-Bug entfernt (hoffentlich!)
  252.                                 - setzen der Statusflags (im Source) vergessen... :-(
  253.  
  254.     mak        1.37    12.03.97    - Eject funktioniert jetzt richtig
  255.                                 - Laufwerkssperre und Unit/LUN-Wechsel funktionieren jetzt
  256.                                 - ACDPlay spult jetzt nicht mehr selbstständig
  257.                                 - MathLib Check entfernt: nutzte nichts :-(
  258.                     13.03.97    - an einige Betatester gegeben
  259.  
  260.     MC3        1.4        14.03.97    - A-B-Repeat-Bug entfernt
  261.                                 - Volumefenster im Menü geshadet
  262.                                 - ans Amiga-Magazin geschickt
  263.  
  264.             1.41    23.03.97    - UpdateGadgets() in viele Funktionen aufgeteilt
  265.                                 - einige Aktionen lösen jetzt direkt Aktualisierungen aus
  266.                                   (Trackslider, etc.)
  267.                                 - BF: HOTKEYCAUSES-Tooltype war immer auf HIDE
  268.  
  269.     mak        1.42    27.03.97    - BF: Konfig wird jetzt auch in ENV: gespeichert
  270.                     28.03.97    - Volumefenster funktioniert jetzt
  271.                                 - Konfigversion 3 (da Fenster dazu: sonst Absturz)
  272.  
  273.     MC3        1.43    28.03.97    - A-B-Repeat-Sicherheitsleck behoben
  274.                                 - neues Tooltype: SEARCHMODE
  275.                                   (Ergebnis steht in app->cdstr->searchmode)
  276.                                 - Beim Titeleditieren werden Standardtitel gelöscht
  277.                                 - Pfusch am Volume-Fenster :-)
  278.  
  279.     mak        1.44    29.03.97    - Slider im Volumefenster funktionieren jetzt unabhängig
  280.                                 - cdx_SimpleStatus in cdx_Active zurückumbenannt
  281.                     02.04.97    - verschiedene Searchmodi
  282.                     03.04.97    - das Indexgadget ist jetzt kein Fake mehr
  283.  
  284.             1.45    05.04.97    - Sony-Searchmode dazu
  285.                                 - globale Variablen CDROM_DEVICE und CDROM_UNIT werden benutzt,
  286.                                   falls kein ToolType oder Parameter vorhanden
  287.                                 - bei DOS-Fehlern werden nun Fehlermeldungen statt Codes ausgegeben
  288.                                 - UpdateUnitLUN() arbeitet jetzt vernünftig, glaube ich...
  289.  
  290.     MC3        1.46    05.04.97    - Öfteres Aktualisieren beim Spulen
  291.                                 - ein paar Verbesserungen
  292.     mak                08.04.97    - TOC wird bei zu langer Updatezeit aktualisiert
  293.             1.47    20.04.97    - Volumerefreshing in MakeInterior() eingebaut
  294.                                 - Tracktest in ProgramAppendElement() eingebaut (für ARexx)
  295.             1.48    27.04.97    - MainWindow wird in ProcessStruktur eingetragen (für Requester)
  296.                                 - WindowTitel flackern jetzt nicht mehr bei Volume-Fade-Makros
  297.                                 - viele neue ARexx-Cmds dazu
  298.     mak        1.49    11.07.97    - 2 Enforcerhits entfernt
  299.                                 - ListEmpty() durch IsListEmpty()/exec.library ersetzt
  300.                     16.07.97    - MakeBusy() erstellt und in ARexxMenü eingebaut
  301.                                 - kleine Verbesserungen
  302.                     28.07.97    - Menü Laufwerk/Laufwerksperre wird jetzt abhängig von cdx_Flags & SPECIALF_LOCKED gesetzt
  303.                     30.07.97    - cd.device-Laustärkeeinstellung (MONO) implementiert (was bei mir nicht funktioniert!)
  304.  
  305.     MC3        1.5        18.10.97    - Über Shift und Alt jetzt auch die Tracks 11-30 direkt anwählbar
  306.                                 - ACDP kommt jetzt mit unvollständigen Titeldateien zurecht
  307.  
  308.             1.51    13.11.97    - Die A-B-Range wird jetzt durch absolute Adressen angegeben
  309.                                   -> Geschwindigkeitssteigerung bei TestABRepeat()
  310.                                 - Fenster zur Audioabspeicherung programmiert
  311.                     22.11.97    - neue Verwaltung für ASL-Requester (ähnlich AppWindows)
  312.                                 - GetFileName() ist jetzt allgemein verwendbar
  313.                     29.11.97    - ExamineDiskSpace() für Audiosaving entwickelt
  314.  
  315.  
  316. **************************************************************************/
  317.  
  318.  
  319. /*    Erklärung der Statusflags:    < > keine Änderung        *** Die Statusflags sind toll ***
  320.                                 <c> verändert
  321.                                 <n> neu
  322.                                 <x> entfernt */
  323.  
  324. /*----- Includes ---------------< >-*/
  325. #include "Constants.h"
  326.  
  327. #include <exec/types.h>
  328. #include <exec/memory.h>
  329. #include <exec/libraries.h>
  330. #include <intuition/intuition.h>
  331. #include <intuition/intuitionbase.h>
  332. #include <intuition/gadgetclass.h>
  333. #include <libraries/gadtools.h>
  334. #include <libraries/commodities.h>
  335. #include <libraries/asl.h>
  336. #include <graphics/rastport.h>
  337. #include <devices/scsidisk.h>
  338. #include <devices/cd.h>
  339. #include <libraries/screennotify.h>
  340. #include <pragma/screennotify_lib.h>
  341. #include "AsmLib/CD-ROM.h"
  342. #include "Locale.h"
  343. #include "Structures/Application.h"
  344. #include "Structures/DirNode.h"
  345. #include "Structures/MyPubScreenNode.h"
  346. #include "Structures/CDTitleNode.h"
  347.  
  348. #include <clib/alib_protos.h>
  349. #include <clib/dos_protos.h>
  350. #include <clib/exec_protos.h>
  351. #include <clib/asl_protos.h>
  352. #include <clib/gadtools_protos.h>
  353. #include <clib/graphics_protos.h>
  354. #include <clib/intuition_protos.h>
  355. #include <clib/commodities_protos.h>
  356. #include <clib/icon_protos.h>
  357. #include <clib/locale_protos.h>
  358. #include <clib/wb_protos.h>
  359. #include <wbstartup.h>
  360. #include <string.h>
  361. #include <stdlib.h>
  362. #include <stdio.h>
  363. #include <math.h>
  364. #include "ACDPlay_protos.h"
  365.  
  366. /*----- globale Variablen ------< >-*/
  367. #define UNIT 0
  368.  
  369. char *ls[ANZ_MSG];
  370. struct LocaleInfo li = {NULL, NULL};
  371.  
  372. struct Library *IntuitionBase     = NULL;
  373. struct Library *CxBase            = NULL;
  374. struct Library *GadToolsBase      = NULL;
  375. struct Library *GfxBase            = NULL;
  376. struct Library *IconBase        = NULL;
  377. struct Library *LocaleBase        = NULL;
  378. struct Library *RexxSysBase        = NULL;
  379. struct Library *ScreenNotifyBase= NULL;
  380. struct Library *WorkbenchBase    = NULL;
  381. struct Library *AslBase            = NULL;
  382.  
  383. static char    PROG_VERSION[]                = "\0$VER: ACDPlay 1.5 [000] (24.12.97)";
  384. char        *PROG_FULLNAME                = PROG_VERSION + 7;
  385. char         PROG_NAME[]                    = "ACDPlay";
  386.  
  387.  
  388.  
  389. /*------------------ main() -----------------------------------< >-*/
  390. int main(int argc, char *argv[])
  391. {
  392.     struct Application *app = NULL;
  393.     ULONG rc = RETURN_FAIL;                    /* Return-Wert auf 20 setzen */
  394.  
  395.     if (FindARexxPortA()) return(0);        /* ACDPlay läuft schon */
  396.  
  397.     if (!(OpenLibsA()))
  398.     {
  399.         CloseLibsA(); return(RETURN_FAIL);
  400.     }
  401.  
  402.     if (app = CreateApplication(argv[0]))
  403.     {
  404.         ULONG        signals;
  405.         ULONG        waitbitmask;
  406.         BOOL        done = FALSE;
  407.  
  408.         if (app->cx_popup)
  409.             OpenApplication(app);    /* nur öffnen, wenn CX_POPUP */
  410.         else
  411.             CreateAppIcon(app);
  412.  
  413.         /***********************************
  414.         ** Hier beginnt die Event-Abfrage **
  415.         ***********************************/
  416.         while (!done)
  417.         {
  418.             waitbitmask    = 0;
  419.  
  420.             /* Control-C Signalbit dazu setzen */
  421.             waitbitmask |= SIGBREAKF_CTRL_C;
  422.  
  423.             /* Signalbits des IDCMP dazu setzen */
  424.             if (app->idcmp)
  425.                 waitbitmask |= (1L << app->idcmp->mp_SigBit);
  426.  
  427.             /* ARexxportsignalbit dazu odern :-) */
  428.             waitbitmask |= (1L << app->arexx_mp->mp_SigBit);
  429.  
  430.             /* Das Appicon-Bit auch noch */
  431.             if (app->appicon_mp)
  432.                 waitbitmask |= (1L << app->appicon_mp->mp_SigBit);
  433.  
  434.             /* Signalbit des Broker-Messageports dazu setzen */
  435.             waitbitmask |= (1L << app->broker_mp->mp_SigBit);
  436.  
  437.             /* Signalbit des Screennotify-Ports dazu setzen */
  438.             if (app->scrnotify_mp)
  439.                 waitbitmask |= (1L << app->scrnotify_mp->mp_SigBit);
  440.  
  441.             signals = Wait(waitbitmask);
  442.  
  443.             if (app->idcmp)
  444.                 if ((signals & (1L << app->idcmp->mp_SigBit)) && !done)
  445.                     done = HandleEvents(app);
  446.  
  447.             if ((signals & (1L << app->arexx_mp->mp_SigBit)) && !done)
  448.                 done = HandleARexxMsgA(app->arexx_mp, app);
  449.  
  450.             if (app->appicon_mp)
  451.                 if ((signals & (1L << app->appicon_mp->mp_SigBit)) && !done)
  452.                     HandleAppIconEvents(app);
  453.  
  454.             if ((signals & (1L << app->broker_mp->mp_SigBit)) && !done)
  455.                 done = HandleCommodityEvents(app);
  456.  
  457.             if (app->scrnotify_mp)
  458.                 if (signals & (1L << app->scrnotify_mp->mp_SigBit))
  459.                     HandleScreenNotify(app);
  460.  
  461.             if (signals & SIGBREAKF_CTRL_C)
  462.                 done = TRUE;
  463.         }
  464.         rc = RETURN_OK;
  465.         DeleteApplication(app);
  466.     }
  467.  
  468.     CloseLibsA();
  469.     return rc;
  470. }
  471.  
  472. void CopyRange(struct Application *app)
  473. {
  474.     char    *buf;
  475.     UBYTE    command[12];
  476.     int        i;
  477.  
  478.     struct SCSICmd *cmd;
  479.  
  480.     OpenAppWin(app, WINDOW_SAVING);
  481.  
  482.     if (buf = (char *)GetVecA(100000, MEMF_PUBLIC | MEMF_CLEAR))
  483.     {
  484.         printf("1");
  485.  
  486.         command[0] = 0xA8;    /* Command Description Block ausfüllen */
  487.         command[1] = 0x00;
  488.         command[2] = (app->cdstr->a_adr >> 24);
  489.         command[3] = ((app->cdstr->a_adr >> 16) & 0xFF);
  490.         command[4] = ((app->cdstr->a_adr >> 8) & 0xFF);
  491.         command[5] = (app->cdstr->a_adr & 0xFF);
  492.         command[6] = 0x0;
  493.         command[7] = 0x0;
  494.         command[8] = 0x0;
  495.         command[9] = 0x01;
  496.         command[10] = 0x0;
  497.         command[11] = 0x0;
  498.  
  499.         cmd = app->cdstr->cdx->cdx_Cmd;
  500.  
  501.         printf("2");
  502.  
  503.         if (cmd)
  504.         {
  505.             cmd->scsi_Data            = (UWORD *)buf;
  506.             cmd->scsi_Length        = 100000;
  507.             cmd->scsi_Actual        = 0;
  508.             cmd->scsi_Command          = command;
  509.             cmd->scsi_CmdLength        = 12;
  510.             cmd->scsi_CmdActual        = 0;
  511.             cmd->scsi_Flags            = SCSIF_READ | SCSIF_AUTOSENSE;
  512.             cmd->scsi_Status        = 0;
  513.             cmd->scsi_SenseData        = app->cdstr->cdx->cdx_SCSISense;
  514.             cmd->scsi_SenseLength    = 252;
  515.             cmd->scsi_SenseActual    = 0;
  516.  
  517.             printf("3");
  518.  
  519.             if (app->cdstr->cdx->cdx_IORequest)
  520.             {
  521.                 app->cdstr->cdx->cdx_IORequest->io_Command = HD_SCSICMD;
  522.                 app->cdstr->cdx->cdx_IORequest->io_Length = sizeof(struct SCSICmd);
  523.                 app->cdstr->cdx->cdx_IORequest->io_Data = (APTR)app->cdstr->cdx->cdx_Cmd;
  524.                 printf("4");
  525.                 printf("  %d  ", DoIO((struct IORequest *)app->cdstr->cdx->cdx_IORequest));
  526.                 printf("5");
  527.  
  528.                 /* Ausgabe */
  529.                 printf("\nSCSI-Command:");
  530.                 for (i = 0; i < 10; i++)
  531.                     printf(" %02x", (int)command[i]);
  532.  
  533.                 printf("\nSense Key:");
  534.                 for (i = 2; i < 4; i++)
  535.                     printf(" %02x", (int)*(((char *)cmd->scsi_SenseData) + i));
  536.  
  537.                 printf("\nAdditional Sense Code & Qualifier:");
  538.                 for (i = 12; i < 14; i++)
  539.                     printf(" %02x", (int)*(((char *)cmd->scsi_SenseData) + i));
  540.  
  541.                 SaveFile("ram:test", buf, 100000);
  542.             }
  543.         }
  544.         FreeVec(buf);
  545.     }
  546.  
  547.     /*
  548.     DoCDDBID(app->cdstr);
  549.     printf("ID:");
  550.     printf(app->cdstr->buf_cddb_id);
  551.     */
  552. }
  553.  
  554. /*------------------ ReadConfig() -----------------------------< >-*/
  555. void ReadConfig(struct Application *app, char *filename)
  556. {
  557.     WORD *buffer = NULL;
  558.     WORD i;
  559.     LONG err;
  560.  
  561.     /* Voreinstellungen */
  562.     for (i = 0; i < ANZ_WINDOWS; i++)
  563.     {
  564.         app->appwin[i].minsize[LEFT]    = 0;
  565.         app->appwin[i].minsize[TOP]        = 0;
  566.         app->appwin[i].minsize[WIDTH]    = MINWIDTH_LISTVIEWWIN;
  567.         /* Sonst wird aus nichtinitialisierten Feldern gelesen */
  568.         if (app->screen)
  569.             app->appwin[i].minsize[HEIGHT]    = MINHEIGHT_LISTVIEWWIN;
  570.         else
  571.             app->appwin[i].minsize[HEIGHT]    = 100;
  572.  
  573.         app->appwin[i].maxsize[LEFT]    = 200;
  574.         app->appwin[i].maxsize[TOP]        = 100;
  575.         app->appwin[i].maxsize[WIDTH]    = 150;
  576.         app->appwin[i].maxsize[HEIGHT]    = 150;
  577.  
  578.         app->appwin[i].maxwidth            = ~0;
  579.         app->appwin[i].maxheight        = ~0;
  580.     }
  581.     app->flag_main = FLAG_MAIN_DIRECTCHOICE0 | FLAG_MAIN_DIRECTCHOICE1 | FLAG_MAIN_TITLE | FLAG_MAIN_TIME | FLAG_MAIN_MODE | FLAG_MAIN_PANEL | FLAG_MAIN_TRACKSLIDER;
  582.  
  583.     if (buffer = (WORD *)OpenFile(filename))
  584.     {
  585.         WORD *offset = buffer;
  586.  
  587.         if ((*(LONG *)offset) == MAGIC)
  588.         {
  589.             UWORD win_anz, win_size, j;
  590.  
  591.             offset       += 2;
  592.             win_anz        = *(offset++);
  593.             win_size    = *(offset++);
  594.  
  595.             for (i = 0; i < (ANZ_WINDOWS > win_anz ? ANZ_WINDOWS : win_anz); i++)
  596.             {
  597.                 for (j = 0; j < 4; j++)
  598.                     app->appwin[i].minsize[j] = *(offset++);
  599.                 for (j = 0; j < 4; j++)
  600.                     app->appwin[i].maxsize[j] = *(offset++);
  601.  
  602.                 app->appwin[i].winopen = *(offset++);
  603.  
  604.                 ((char *)offset) += win_size - SIZE_WINDOW;
  605.             }
  606.  
  607.             ((char *)offset) += (win_anz - ANZ_WINDOWS) * win_size;
  608.             app->flag_main = *(LONG *)offset;
  609.         }
  610.         else ShowMsgA(ls[MSG_ERROR_TITLE], ls[MSG_NO_CFGFILE], filename);
  611.  
  612.         FreeVec(buffer);
  613.     }
  614.     else if ((err=IoErr()) != ERROR_OBJECT_NOT_FOUND)    /* nervt sonst... */
  615.     {
  616.         char errmsg[FAULT_MAX];
  617.         Fault(err, NULL, errmsg, FAULT_MAX);
  618.         ShowMsgA(ls[MSG_ERROR_TITLE], ls[MSG_BAD_FILE], filename, errmsg);
  619.     }
  620.  
  621.     /* Das auf jeden Fall */
  622.     app->appwin[WINDOW_MAIN].winopen = TRUE;
  623.     app->appwin[WINDOW_SAVING].winopen = FALSE;
  624. }
  625. /*------------------ SaveConfig() -----------------------------< >-*/
  626. BOOL SaveConfig(Application *app, char *filename)
  627. {
  628.     BOOL success = FALSE;
  629.     WORD i, j;
  630.     WORD *buffer = NULL;
  631.  
  632.     /* Wenn die Application noch offen ist, werden die Windowkoordinaten */
  633.     /* ausgelesen. Sonst hat CloseApplication() das schon erledigt. */
  634.     if (app->screen)
  635.     {
  636.         for (i = ANZ_WINDOWS-1; i >= 0; i--)
  637.         {
  638.             if (app->appwin[i].winopen && app->appwin[i].window)
  639.             {
  640.                 app->appwin[i].maxsize[LEFT]    = app->appwin[i].window->LeftEdge;
  641.                 app->appwin[i].maxsize[TOP]        = app->appwin[i].window->TopEdge;
  642.             }
  643.         }
  644.     }
  645.  
  646.     /* Ein wenig Speicher allozieren und dort alles hineinschreiben */
  647.     if (buffer = GetVecA(SIZE_CONFIG, MEMF_PUBLIC | MEMF_CLEAR))
  648.     {
  649.         WORD *offset = buffer;
  650.  
  651.         *(LONG *)offset = MAGIC;
  652.         offset += 2;
  653.  
  654.         *(offset++) = ANZ_WINDOWS;
  655.         *(offset++) = SIZE_WINDOW;
  656.  
  657.         for (i = 0; i < ANZ_WINDOWS; i++)
  658.         {
  659.             for (j = 0; j < 4; j++)
  660.                 *(offset++) = app->appwin[i].minsize[j];
  661.             for (j = 0; j < 4; j++)
  662.                 *(offset++) = app->appwin[i].maxsize[j];
  663.  
  664.             *(offset++) = app->appwin[i].winopen;
  665.         }
  666.  
  667.         *(LONG *)offset = app->flag_main;
  668.  
  669.         if (SaveFile(filename, (char *)buffer, SIZE_CONFIG))
  670.             success = TRUE;
  671.  
  672.         /* Execute-Flag löschen */
  673.         SetProtection(filename, FIBF_EXECUTE);
  674.  
  675.         FreeVec(buffer);
  676.     }
  677.  
  678.     return (success);
  679. }
  680. /*------------------ ReadArguments() --------------------------< >-*/
  681. void ReadArguments(struct Application *app)
  682. {
  683.     struct RDArgs *rda;
  684.     struct DiskObject *dobj;
  685.     char **toolarray, *s;
  686.     char var[30];
  687.  
  688.     /* Erst werden die Voreinstellungen gesetzt */
  689.     LONG unit = 0, lun = 0, updatedelay = 5, priority = 0;
  690.     LONG vec[] = {    (LONG)    "1230scsi.device",
  691.                     (LONG)    &unit,
  692.                     (LONG)    &lun,
  693.                     (LONG)    "Workbench",
  694.                             FALSE,
  695.                             TRUE,
  696.                             FALSE,
  697.                             TRUE,
  698.                     (LONG)    NULL,
  699.                     (LONG)    &updatedelay,
  700.                     (LONG)    NULL,
  701.                     (LONG)    "PROGDIR:Disks/",
  702.                             TRUE,
  703.                     (LONG)    "alt shift F1",
  704.                     (LONG)    &priority};
  705.  
  706.     if (GetVar("CDROM_UNIT", var, 2, 0) != -1)
  707.         unit = atoi(var);
  708.  
  709.     if (GetVar("CDROM_DEVICE", var, 30, 0) != -1)
  710.         vec[0] = (LONG)var;
  711.  
  712.     /* Dann werden diese durch eventuelle Tooltypes überschrieben */
  713.     if (dobj = GetDiskObject(app->progname))
  714.     {
  715.         toolarray = dobj->do_ToolTypes;
  716.  
  717.         if (s = (char *)FindToolType((UBYTE **)toolarray, "DEVICE"))
  718.             vec[0] = (LONG)s;
  719.         if (s = (char *)FindToolType((UBYTE **)toolarray, "UNIT"))
  720.             unit = atoi(s);
  721.         if (s = (char *)FindToolType((UBYTE **)toolarray, "LUN"))
  722.             lun = atoi(s);
  723.         if (s = (char *)FindToolType((UBYTE **)toolarray, "PUBSCREEN"))
  724.             vec[3] = (LONG)s;
  725.         if (s = (char *)FindToolType((UBYTE **)toolarray, "MAGICWB"))
  726.             vec[4] = (MatchToolValue(s, "NO") || MatchToolValue(s, "no")) ? FALSE : TRUE;
  727.         if (s = (char *)FindToolType((UBYTE **)toolarray, "USEWINDOWBAR"))
  728.             vec[5] = (MatchToolValue(s, "NO") || MatchToolValue(s, "no")) ? FALSE : TRUE;
  729.         if (s = (char *)FindToolType((UBYTE **)toolarray, "USESCREENBAR"))
  730.             vec[6] = (MatchToolValue(s, "NO") || MatchToolValue(s, "no")) ? FALSE : TRUE;
  731.         if (s = (char *)FindToolType((UBYTE **)toolarray, "QUITONCLOSE"))
  732.             vec[7] = (MatchToolValue(s, "NO") || MatchToolValue(s, "no")) ? FALSE : TRUE;
  733.         if (s = (char *)FindToolType((UBYTE **)toolarray, "HOTKEYCAUSES"))
  734.             vec[8] = (LONG)s;
  735.         if (s = (char *)FindToolType((UBYTE **)toolarray, "UPDATEDELAY"))
  736.             updatedelay = atoi(s);
  737.         if (s = (char *)FindToolType((UBYTE **)toolarray, "SEARCHMODE"))
  738.             vec[10] = (LONG)s;
  739.         if (s = (char *)FindToolType((UBYTE **)toolarray, "DISKPATH"))
  740.             vec[11] = (LONG)s;
  741.         if (s = (char *)FindToolType((UBYTE **)toolarray, "CX_POPUP"))
  742.             vec[12] = (MatchToolValue(s, "NO") || MatchToolValue(s, "no")) ? FALSE : TRUE;
  743.         if (s = (char *)FindToolType((UBYTE **)toolarray, "CX_POPKEY"))
  744.             vec[13] = (LONG)s;
  745.         if (s = (char *)FindToolType((UBYTE **)toolarray, "CX_PRIORITY"))
  746.             priority = atoi(s);
  747.     }
  748.  
  749.     /* Shell-Argumente können jedoch auch diese überschreiben */
  750.     if (rda = AllocDosObject(DOS_RDARGS, NULL))
  751.     {
  752.         rda->RDA_ExtHelp =    "ACDPlay CLI parameters:\n"
  753.                             "DEVICE:        device driver where the cd drive is connected, default: 1230scsi.device\n"
  754.                             "UNIT:          unit that belongs to the drive, default: 0\n"
  755.                             "LUN:           start logical unit number, default: 0\n"
  756.                             "PUBSCREEN:     where to start ACDPlay, default: Workbench\n"
  757.                             "MAGICWB:       whether ACDPlay should use MagicWB graphics, default: no\n"
  758.                             "USEWINDOWBAR:  enables window bar as information display, default: yes\n"
  759.                             "USESCREENBAR:  enables screen bar as information display, default: no\n"
  760.                             "QUITONCLOSE:   whether ACDPlay should quit when main window was closed, default: yes\n"
  761.                             "HOTKEYCAUSES:  SCREENTOFRONT, HIDE or FRONTMOST, default: SCREENTOFRONT\n"
  762.                             "UPDATEDELAY:   delay between SCSI updates in 1/10 secs, default: 5\n"
  763.                             "SEARCHMODE:    STANDARD, TOSHIBA or SONY (advanced search modes), default: STANDARD\n"
  764.                             "DISKPATH:      path where ID and program files are stored, default: PROGDIR:Disks/\n"
  765.                             "CX_POPUP:      whether the GUI is displayed when started, default: yes\n"
  766.                             "CX_POPKEY:     key combination to popup GUI, default: lshift alt F1\n"
  767.                             "CX_PRIORITY:   priority as a commodity, default: 0\n\n"
  768.                             "Enter parameters";
  769.  
  770.         if (ReadArgs("DEV=DEVICE/K,UNIT/N,LUN/N,PUBSCREEN/K,MWB=MAGICWB/T,USEWINDOWBAR/T,USESCREENBAR/T,QUITONCLOSE/T,HOTKEYCAUSES/K,UPDATEDELAY/N,SEARCHMODE/K,DISKPATH/K,CX_POPUP/T,CX_POPKEY/K,CX_PRIORITY/N", vec, rda))
  771.         {
  772.             FreeArgs(rda);
  773.         }
  774.  
  775.         FreeDosObject(DOS_RDARGS, rda);
  776.     }
  777.  
  778.     /* Werte verbindlich eintragen */
  779.     strncpy(app->cdstr->device,        (char *)vec[0], 30);
  780.     app->cdstr->unit            =    FitInteger(*(LONG *)vec[1], 0, 7);
  781.     app->cdstr->lun                =    FitInteger(*(LONG *)vec[2], 0, 7);
  782.  
  783.     strncpy(app->pubscreenname,        (char *)vec[3], MAXPUBSCREENNAME);
  784.     app->flag_tool                =    InsertBoolean(app->flag_tool, FLAG_TOOL_MWB, vec[4]);
  785.     app->flag_tool                =    InsertBoolean(app->flag_tool, FLAG_TOOL_USEWINDOWBAR, vec[5]);
  786.     app->flag_tool                =    InsertBoolean(app->flag_tool, FLAG_TOOL_USESCREENBAR, vec[6]);
  787.     app->flag_tool                =    InsertBoolean(app->flag_tool, FLAG_TOOL_QUITONCLOSE, vec[7]);
  788.  
  789.     if (vec[8])
  790.     {
  791.         if (strcmp((char *)vec[8], "HIDE") == 0)
  792.             app->hotkeymode   = HOTKEYMODE_HIDE;
  793.         else if (strcmp((char *)vec[8], "FRONTMOST") == 0)
  794.             app->hotkeymode   = HOTKEYMODE_FRONTMOST;
  795.         else
  796.             app->hotkeymode   = HOTKEYMODE_SCREENTOFRONT;
  797.      }
  798.  
  799.     app->cdstr->updatedelay        =    FitInteger(*(LONG *)vec[9], 1, 50);
  800.  
  801.     if (vec[10])
  802.     {
  803.         if (strcmp((char *)vec[10], "TOSHIBA") == 0)
  804.             app->cdstr->searchmode   = SEARCHMODE_TOSHIBA;
  805.         else if (strcmp((char *)vec[10], "SONY") == 0)
  806.             app->cdstr->searchmode   = SEARCHMODE_SONY;
  807.         else
  808.             app->cdstr->searchmode   = SEARCHMODE_STANDARD;
  809.      }
  810.  
  811.     app->cdstr->searchseconds    =    10;
  812.  
  813.     strncpy(app->cdstr->diskpath,    (char *)vec[11], DISKPATHLENGTH - 1);   /* evt. muß noch ein '/' ran */
  814.     if ((app->cdstr->diskpath[strlen(app->cdstr->diskpath) -1] != ':') && (app->cdstr->diskpath[strlen(app->cdstr->diskpath) - 1] != '/'))
  815.         strcat(app->cdstr->diskpath, "/");
  816.  
  817.     app->cx_popup                =    vec[12];
  818.     strncpy(app->cx_popkey,            (char *)vec[13], 40);
  819.     app->cx_priority            =    FitInteger(*(LONG *)vec[14], -128, 127);
  820.  
  821.     if (dobj) FreeDiskObject(dobj);    /* Damit die Strings erhalten bleiben */
  822. }
  823.  
  824. /*------------------ SaveTitles() -----------------------------< >-*/
  825. BOOL SaveTitles(Application *app)
  826. {
  827.     BOOL success     = FALSE;
  828.  
  829.     if (!IsListEmpty(app->cdstr->cdtitles))
  830.     {
  831.         int i, bufferlen;
  832.         char *buffer;
  833.  
  834.         bufferlen = strlen(app->cdstr->artistname) + strlen(app->cdstr->cdname) + 2;
  835.         for (i = 0; i < app->cdstr->num_track; i++)
  836.             bufferlen += strlen((FindNode(app->cdstr->cdtitles, i))->ln_Name) + 1;
  837.  
  838.         if (buffer = GetVecA(bufferlen, MEMF_PUBLIC | MEMF_CLEAR))
  839.         {
  840.             char *actpos = buffer;
  841.             char *filename;
  842.  
  843.             /* Künstler speichern */
  844.             strcpy(actpos, app->cdstr->artistname);
  845.             actpos += strlen(app->cdstr->artistname);
  846.             *(actpos) = 0x0A;
  847.             actpos++;
  848.  
  849.             /* CD-Name speichern */
  850.             strcpy(actpos, app->cdstr->cdname);
  851.             actpos += strlen(app->cdstr->cdname);
  852.             *(actpos) = 0x0A;
  853.             actpos++;
  854.  
  855.             /* jeden Titel */
  856.             for (i = 0; i < app->cdstr->num_track; i++)
  857.             {
  858.                 strcpy(actpos, (FindNode(app->cdstr->cdtitles, i))->ln_Name);
  859.                 actpos += strlen((FindNode(app->cdstr->cdtitles, i))->ln_Name);
  860.                 *(actpos) = 0x0A;
  861.                 actpos++;
  862.             }
  863.  
  864.             if (filename = GetVecA(strlen(app->cdstr->diskpath) + 22, MEMF_PUBLIC | MEMF_CLEAR))
  865.             {
  866.                 strcpy(filename, app->cdstr->diskpath);
  867.                 strcat(filename, "ID");
  868.                 strcat(filename, app->cdstr->cdx->cdx_TOCData->CDID);
  869.  
  870.                 if (SaveFile(filename, buffer, bufferlen))
  871.                     success = TRUE;
  872.  
  873.                 FreeVec(filename);
  874.             }
  875.  
  876.             FreeVec(buffer);
  877.         }    }
  878.  
  879.     return (success);
  880. }
  881. /*------------------ ProgramStart() ---------------------------< >-*/
  882. void ProgramStart(Application *app)
  883. {
  884.     if (app->cdstr->progtitles)
  885.         if (!IsListEmpty(app->cdstr->progtitles))
  886.         {
  887.             switch(app->cdstr->playmode)
  888.             {
  889.                 case PLAYMODE_PRG:
  890.                     app->cdstr->actprognode = (struct ProgramTitleNode *)app->cdstr->progtitles->lh_Head;
  891.                     break;
  892.                 case PLAYMODE_RNDPRG:
  893.                     app->cdstr->actprognode = GetRandomProgram(app) /*(struct ProgramTitleNode *)FindNode(app->cdstr->progtitles, RandomNum(0, ListLength(app->cdstr->progtitles)))*/;
  894.                     break;
  895.             }
  896.             CDPlayA(app->cdstr->cdx, app->cdstr->actprognode->ptn_track, 1);
  897.         }
  898. }
  899. /*------------------ ProgramDelete() --------------------------< >-*/
  900. BOOL ProgramDelete(Application *app)
  901. {
  902.     BOOL success = FALSE;
  903.  
  904.     /* Da diese Funktion auch von Arexx aus aufgerufen wird, muß sie alles mögliche */
  905.     /* selber machen, z.B: */
  906.     /* Laufwerk ggf. stoppen, Liste aus LV entfernen, Liste löschen, eine neue erstellen, */
  907.     /* aus Prinzip Liste wieder ins LV bauen */
  908.  
  909.     if (((app->cdstr->playmode == PLAYMODE_PRG) || (app->cdstr->playmode == PLAYMODE_RNDPRG)) && ((app->cdstr->active == AUDIO_STAT_PLAYING) || (app->cdstr->active == AUDIO_STAT_PAUSED)))
  910.     {
  911.         CDStopA(app->cdstr->cdx);
  912.         app->cdstr->useraction = TRUE;
  913.     }
  914.  
  915.     if (app->appwin[WINDOW_PROGRAM].window)
  916.         GT_SetGadgetAttrs(app->appwin[WINDOW_PROGRAM].gadget[GADGET_PROGRAM_LVPRG], app->appwin[WINDOW_PROGRAM].window, NULL, GTLV_Labels, ~0, TAG_END);
  917.  
  918.     FreeList(app->cdstr->progtitles);
  919.  
  920.     if (app->cdstr->progtitles = GetVecA(sizeof(struct List), MEMF_PUBLIC | MEMF_CLEAR))
  921.     {
  922.         NewList(app->cdstr->progtitles);
  923.         GT_SetGadgetAttrs(app->appwin[WINDOW_PROGRAM].gadget[GADGET_PROGRAM_LVPRG], app->appwin[WINDOW_PROGRAM].window, NULL, GTLV_Labels, app->cdstr->progtitles, TAG_END);
  924.         success = TRUE;
  925.     }
  926.  
  927.     return (success);
  928. }
  929. /*------------------ ProgramAppendElement() -------------------< >-*/
  930. BOOL ProgramAppendElement(Application *app, UWORD track)
  931. {
  932.     BOOL success = FALSE;
  933.     struct ProgramTitleNode *newnode;
  934.  
  935.     if ((track > app->cdstr->cdx->cdx_TOCData->LastTrack) || (track < app->cdstr->cdx->cdx_TOCData->FirstAudioTrack))
  936.         return (success);
  937.  
  938.     if (newnode = GetVecA(sizeof(struct ProgramTitleNode), MEMF_PUBLIC | MEMF_CLEAR))
  939.     {
  940.         if (app->appwin[WINDOW_PROGRAM].window)
  941.             GT_SetGadgetAttrs(app->appwin[WINDOW_PROGRAM].gadget[GADGET_PROGRAM_LVPRG], app->appwin[WINDOW_PROGRAM].window, NULL, GTLV_Labels, ~0, TAG_END);
  942.  
  943.         newnode->ptn_track = track;
  944.         newnode->ptn_Node.ln_Name = FindNode(app->cdstr->cdtitles, track - 1)->ln_Name;
  945.         AddTail(app->cdstr->progtitles, (Node *) newnode);
  946.  
  947.         if (app->appwin[WINDOW_PROGRAM].window)
  948.             GT_SetGadgetAttrs(app->appwin[WINDOW_PROGRAM].gadget[GADGET_PROGRAM_LVPRG], app->appwin[WINDOW_PROGRAM].window, NULL, GTLV_Labels, app->cdstr->progtitles, TAG_END);
  949.  
  950.         success = TRUE;
  951.     }
  952.  
  953.     return (success);
  954. }
  955. /*------------------ ProgramDeleteElement() -------------------< >-*/
  956. BOOL ProgramDeleteElement(Application *app, ULONG pos)
  957. {
  958.     BOOL success = FALSE;
  959.     struct ProgramTitleNode *oldnode;
  960.  
  961.     if (pos < ListLengthA(app->cdstr->progtitles))
  962.     {
  963.         oldnode = (struct ProgramTitleNode *)FindNode(app->cdstr->progtitles, pos);
  964.  
  965.         if (app->appwin[WINDOW_PROGRAM].window)
  966.             GT_SetGadgetAttrs(app->appwin[WINDOW_PROGRAM].gadget[GADGET_PROGRAM_LVPRG], app->appwin[WINDOW_PROGRAM].window, NULL, GTLV_Labels, ~0, TAG_END);
  967.  
  968.         /* evt. Spielvorgang abbrechen */
  969.         if (((app->cdstr->playmode == PLAYMODE_PRG) || (app->cdstr->playmode == PLAYMODE_RNDPRG)) && ((app->cdstr->active == AUDIO_STAT_PLAYING) || (app->cdstr->active == AUDIO_STAT_PAUSED)) && (app->cdstr->actprognode == oldnode))
  970.         {
  971.             CDStopA(app->cdstr->cdx);
  972.             app->cdstr->useraction = TRUE;
  973.         }
  974.  
  975.         Remove((struct Node *)oldnode);
  976.         FreeVec(oldnode);
  977.  
  978.         if (app->appwin[WINDOW_PROGRAM].window)
  979.             GT_SetGadgetAttrs(app->appwin[WINDOW_PROGRAM].gadget[GADGET_PROGRAM_LVPRG], app->appwin[WINDOW_PROGRAM].window, NULL, GTLV_Labels, app->cdstr->progtitles, TAG_END);
  980.  
  981.         success = TRUE;
  982.     }
  983.  
  984.     return (success);
  985. }
  986. /*------------------ ProgramCopyAll() -------------------------< >-*/
  987. BOOL ProgramCopyAll(Application *app)
  988. {
  989.     BOOL success = FALSE;
  990.  
  991.     if (app->appwin[WINDOW_PROGRAM].window)
  992.         GT_SetGadgetAttrs(app->appwin[WINDOW_PROGRAM].gadget[GADGET_PROGRAM_LVPRG], app->appwin[WINDOW_PROGRAM].window, NULL, GTLV_Labels, ~0, TAG_END);
  993.  
  994.     FreeList(app->cdstr->progtitles);
  995.  
  996.     if (app->cdstr->progtitles = GetVecA(sizeof(struct List), MEMF_PUBLIC | MEMF_CLEAR))
  997.     {
  998.         int i;
  999.         struct ProgramTitleNode *tempnode;
  1000.  
  1001.         NewList(app->cdstr->progtitles);
  1002.         success = TRUE;
  1003.  
  1004.         for (i = 0; i < ListLengthA(app->cdstr->cdtitles); i++)
  1005.         {
  1006.             if (tempnode = GetVecA(sizeof(struct ProgramTitleNode), MEMF_PUBLIC | MEMF_CLEAR))
  1007.             {
  1008.                 tempnode->ptn_track = i + 1;
  1009.                 tempnode->ptn_Node.ln_Name = (FindNode(app->cdstr->cdtitles, i))->ln_Name;
  1010.                 AddTail(app->cdstr->progtitles, ((struct Node *)tempnode));
  1011.             }
  1012.             else
  1013.                 success = FALSE;
  1014.         }
  1015.  
  1016.         if ((app->cdstr->playmode == PLAYMODE_PRG) || (app->cdstr->playmode == PLAYMODE_RNDPRG))
  1017.         {
  1018.             switch (app->cdstr->active)
  1019.             {
  1020.                 case AUDIO_STAT_PLAYING:
  1021.                 case AUDIO_STAT_PAUSED:
  1022.                     ProgramStart(app);
  1023.                     app->cdstr->useraction = TRUE;
  1024.                     break;
  1025.             }
  1026.             if (app->cdstr->active == AUDIO_STAT_PAUSED)
  1027.                 CDPauseA(app->cdstr->cdx, TRUE);
  1028.         }
  1029.     }
  1030.  
  1031.     if (app->appwin[WINDOW_PROGRAM].window)
  1032.         GT_SetGadgetAttrs(app->appwin[WINDOW_PROGRAM].gadget[GADGET_PROGRAM_LVPRG], app->appwin[WINDOW_PROGRAM].window, NULL, GTLV_Labels, app->cdstr->progtitles, TAG_END);
  1033.  
  1034.     return (success);
  1035. }
  1036. /*------------------ ProgramSave() ----------------------------< >-*/
  1037. BOOL ProgramSave(Application *app)
  1038. {
  1039.     BOOL success = FALSE;
  1040.     char *filename;
  1041.  
  1042.     if (IsListEmpty(app->cdstr->progtitles))
  1043.     {
  1044.         if (filename = GetVecA(strlen(app->cdstr->diskpath) + 22, MEMF_PUBLIC | MEMF_CLEAR))
  1045.         {
  1046.             strcpy(filename, app->cdstr->diskpath);
  1047.             strcat(filename, "PR");
  1048.             strcat(filename, app->cdstr->cdx->cdx_TOCData->CDID);
  1049.  
  1050.             DeleteFile(filename);
  1051.             FreeVec(filename);
  1052.         }
  1053.         return (TRUE);
  1054.     }
  1055.     else
  1056.     {
  1057.         int bufferlen;
  1058.         char *buffer;
  1059.  
  1060.         bufferlen = ListLengthA(app->cdstr->progtitles);
  1061.  
  1062.         if (buffer = GetVecA(bufferlen, MEMF_PUBLIC | MEMF_CLEAR))
  1063.         {
  1064.             char *actpos = buffer;
  1065.             struct ProgramTitleNode *tempnode;
  1066.  
  1067.             for (tempnode = ((struct ProgramTitleNode *)app->cdstr->progtitles->lh_Head); tempnode->ptn_Node.ln_Succ; tempnode = (struct ProgramTitleNode *)tempnode->ptn_Node.ln_Succ)
  1068.             {
  1069.                 *(actpos) = tempnode->ptn_track;
  1070.                 actpos++;
  1071.             }
  1072.  
  1073.             if (filename = GetVecA(strlen(app->cdstr->diskpath) + 22, MEMF_PUBLIC | MEMF_CLEAR))
  1074.             {
  1075.                 strcpy(filename, app->cdstr->diskpath);
  1076.                 strcat(filename, "PR");
  1077.                 strcat(filename, app->cdstr->cdx->cdx_TOCData->CDID);
  1078.  
  1079.                 if (SaveFile(filename, buffer, bufferlen))
  1080.                     success = TRUE;
  1081.  
  1082.                 FreeVec(filename);
  1083.             }
  1084.  
  1085.             FreeVec(buffer);
  1086.         }
  1087.         return (success);
  1088.     }
  1089. }
  1090. /*------------------ ProgramLoad() ----------------------------< >-*/
  1091. BOOL ProgramLoad(Application *app)
  1092. {
  1093.     BOOL success = FALSE;
  1094.     char *wantedname;
  1095.  
  1096.     if (!app->cdstr->progtitles)
  1097.     {
  1098.         app->cdstr->progtitles = GetVecA(sizeof(struct List), MEMF_PUBLIC | MEMF_CLEAR);
  1099.         NewList(app->cdstr->progtitles);
  1100.     }
  1101.  
  1102.     if (wantedname = GetVecA(strlen(app->cdstr->diskpath) + 22, MEMF_PUBLIC | MEMF_CLEAR))
  1103.     {
  1104.         int filelength;
  1105.         char *filebuffer;
  1106.  
  1107.         strcpy(wantedname, app->cdstr->diskpath);
  1108.         strcat(wantedname, "PR");
  1109.         strcat(wantedname, app->cdstr->cdx->cdx_TOCData->CDID);
  1110.  
  1111.         if ((filelength = ExamineFileLength(wantedname)) && (filebuffer = OpenFile(wantedname)))
  1112.         {
  1113.             ProgramTitleNode *tempnode;
  1114.  
  1115.             if (app->appwin[WINDOW_PROGRAM].window)
  1116.                 GT_SetGadgetAttrs(app->appwin[WINDOW_PROGRAM].gadget[GADGET_PROGRAM_LVPRG], app->appwin[WINDOW_PROGRAM].window, NULL, GTLV_Labels, ~0, TAG_END);
  1117.  
  1118.             FreeList(app->cdstr->progtitles);
  1119.             app->cdstr->progtitles = NULL;
  1120.  
  1121.             if (app->cdstr->progtitles = GetVecA(sizeof(struct List), MEMF_PUBLIC | MEMF_CLEAR))
  1122.             {
  1123.                 register int i;
  1124.                 NewList(app->cdstr->progtitles);
  1125.  
  1126.                 success = TRUE;
  1127.  
  1128.                 /* Für jedes Byte eine Node erstellen und ausfüllen */
  1129.                 for (i = 0; i < filelength; i++)
  1130.                 {
  1131.                     if (tempnode = GetVecA(sizeof(struct ProgramTitleNode), MEMF_PUBLIC | MEMF_CLEAR))
  1132.                     {
  1133.                         tempnode->ptn_track = (UBYTE)filebuffer[i];
  1134.                         tempnode->ptn_Node.ln_Name = FindNode(app->cdstr->cdtitles, (UBYTE)filebuffer[i] - 1)->ln_Name;
  1135.                         AddTail(app->cdstr->progtitles, (Node *) tempnode);
  1136.                     }
  1137.                     else
  1138.                         success = FALSE;
  1139.                 }
  1140.             }
  1141.  
  1142.             if (app->appwin[WINDOW_PROGRAM].window)
  1143.                 GT_SetGadgetAttrs(app->appwin[WINDOW_PROGRAM].gadget[GADGET_PROGRAM_LVPRG], app->appwin[WINDOW_PROGRAM].window, NULL, GTLV_Labels, app->cdstr->progtitles, TAG_END);
  1144.  
  1145.             if ((app->cdstr->playmode == PLAYMODE_PRG) || (app->cdstr->playmode == PLAYMODE_RNDPRG))
  1146.             {
  1147.                 switch (app->cdstr->active)
  1148.                 {
  1149.                     case AUDIO_STAT_PLAYING:
  1150.                     case AUDIO_STAT_PAUSED:
  1151.                         ProgramStart(app);
  1152.                         app->cdstr->useraction = TRUE;
  1153.                         break;
  1154.                 }
  1155.                 if (app->cdstr->active == AUDIO_STAT_PAUSED)
  1156.                     CDPauseA(app->cdstr->cdx, TRUE);
  1157.             }
  1158.  
  1159.             FreeVec(filebuffer);
  1160.         }
  1161.         FreeVec(wantedname);
  1162.     }
  1163.  
  1164.     return (success);
  1165. }
  1166. /*------------------ ProgramNext() ----------------------------< >-*/
  1167. BOOL ProgramNext(Application *app)
  1168. {
  1169.     BOOL success = FALSE;
  1170.  
  1171.     if (app->cdstr->actprognode)
  1172.     {
  1173.         switch (app->cdstr->playmode)
  1174.         {
  1175.             case PLAYMODE_PRG:
  1176.                 if ((struct Node *)app->cdstr->actprognode == app->cdstr->progtitles->lh_TailPred)
  1177.                 {
  1178.                     if (app->cdstr->repeatmode == REPEATMODE_REPALL)
  1179.                     {
  1180.                         ProgramStart(app);
  1181.                         success = TRUE;
  1182.                     }
  1183.                 }
  1184.                 else
  1185.                 {
  1186.                     app->cdstr->actprognode = (struct ProgramTitleNode *)app->cdstr->actprognode->ptn_Node.ln_Succ;
  1187.                     CDPlayVerify(app->cdstr, app->cdstr->actprognode->ptn_track);
  1188.                     success = TRUE;
  1189.                 }
  1190.                 break;
  1191.  
  1192.             case PLAYMODE_RNDPRG:
  1193.                 {
  1194.                     struct ProgramTitleNode *tempnode = app->cdstr->actprognode;
  1195.                     app->cdstr->actprognode = GetRandomProgram(app);
  1196.  
  1197.                     if (app->cdstr->actprognode)
  1198.                     {
  1199.                         CDPlayVerify(app->cdstr, app->cdstr->actprognode->ptn_track);
  1200.                         success = TRUE;
  1201.                     }
  1202.                     else
  1203.                         app->cdstr->actprognode = tempnode;
  1204.                 }
  1205.                 break;
  1206.         }
  1207.     }
  1208.  
  1209.     return (success);
  1210. }
  1211. /*------------------ ProgramPrev() ----------------------------< >-*/
  1212. void ProgramPrev(Application *app)
  1213. {
  1214.     if (app->cdstr->actprognode)
  1215.     {
  1216.         switch (app->cdstr->playmode)
  1217.         {
  1218.             case PLAYMODE_PRG:
  1219.                 if ((struct Node *)app->cdstr->actprognode != app->cdstr->progtitles->lh_Head)
  1220.                 {
  1221.                     app->cdstr->actprognode = (struct ProgramTitleNode *)app->cdstr->actprognode->ptn_Node.ln_Pred;
  1222.                     CDPlayVerify(app->cdstr, app->cdstr->actprognode->ptn_track);
  1223.                 }
  1224.                 break;
  1225.             case PLAYMODE_RNDPRG:
  1226.                 {
  1227.                     struct ProgramTitleNode *tempnode = app->cdstr->actprognode;
  1228.                     app->cdstr->actprognode = GetRandomProgram(app);
  1229.  
  1230.                     if (app->cdstr->actprognode)
  1231.                         CDPlayVerify(app->cdstr, app->cdstr->actprognode->ptn_track);
  1232.                     else
  1233.                         app->cdstr->actprognode = tempnode;
  1234.                 }
  1235.                 break;
  1236.         }
  1237.     }
  1238. }
  1239. /*------------------ GetRandomProgram() -----------------------< >-*/
  1240. struct ProgramTitleNode *GetRandomProgram(Application *app)
  1241. {
  1242.     struct ProgramTitleNode **buffer;
  1243.     struct ProgramTitleNode *returnnode = NULL;
  1244.  
  1245.     if (buffer = GetVecA(ListLengthA(app->cdstr->progtitles) * sizeof(struct ProgramTitleNode *), MEMF_PUBLIC | MEMF_CLEAR))
  1246.     {
  1247.         struct Node *tempnode;
  1248.         int j = 0;
  1249.  
  1250.         for (tempnode = app->cdstr->progtitles->lh_Head; tempnode->ln_Succ; tempnode = tempnode->ln_Succ)
  1251.             if (!(((struct ProgramTitleNode *)tempnode)->ptn_randomplayed))
  1252.             {
  1253.                 buffer[j] = (struct ProgramTitleNode *)tempnode;
  1254.                 j++;
  1255.             }
  1256.  
  1257.         if (j > 0)
  1258.         {
  1259.             returnnode = buffer[RandomNum(0, j - 1)];
  1260.             /* Flag auf TRUE setzen */
  1261.             returnnode->ptn_randomplayed = TRUE;
  1262.         }
  1263.         else
  1264.         {
  1265.             if (app->cdstr->repeatmode == REPEATMODE_REPALL)
  1266.             {
  1267.                 InitRandomTracks(app->cdstr->progtitles);
  1268.                 returnnode = GetRandomProgram(app);
  1269.             }
  1270.         }
  1271.  
  1272.         FreeVec(buffer);
  1273.     }
  1274.  
  1275.     return (returnnode);
  1276. }
  1277.  
  1278. /*------------------ GetRandomTrack() -------------------------< >-*/
  1279. UBYTE GetRandomTrack(Application *app)
  1280. {
  1281.     UBYTE *buffer;
  1282.     int returnval = 0;
  1283.  
  1284.     if (buffer = GetVecA(app->cdstr->num_track, MEMF_PUBLIC | MEMF_CLEAR))
  1285.     {
  1286.         struct Node *tempnode;
  1287.         int j = 0, i = 1;
  1288.  
  1289.         /* Feld erstellen, aus dem dann zufällig ein Element ausgewählt wird */
  1290.         for (tempnode = app->cdstr->cdtitles->lh_Head; tempnode->ln_Succ; tempnode = tempnode->ln_Succ, i++)
  1291.             if (!(((struct CDTitleNode *)tempnode)->cdtn_randomplayed))
  1292.             {
  1293.                 buffer[j] = i;
  1294.                 j++;
  1295.             }
  1296.  
  1297.         if (j > 0)    /* Falls alles schon gespielt wurde, wird 0 zurückgegeben */
  1298.         {
  1299.             returnval = buffer[RandomNum(0, j - 1)];
  1300.             /* Flag setzen */
  1301.             ((struct CDTitleNode *)FindNode(app->cdstr->cdtitles, returnval - 1))->cdtn_randomplayed = TRUE;
  1302.         }
  1303.         else
  1304.         {
  1305.             if (app->cdstr->repeatmode == REPEATMODE_REPALL)
  1306.             {
  1307.                 InitRandomTracks(app->cdstr->cdtitles);
  1308.                 returnval = GetRandomTrack(app);
  1309.             }
  1310.         }
  1311.  
  1312.         FreeVec(buffer);
  1313.     }
  1314.  
  1315.     return (returnval);
  1316. }
  1317. /*------------------ InitRandomTracks() -----------------------< >-*/
  1318. void InitRandomTracks(struct List *tracklist)
  1319. {
  1320.     /* Dies hier cleared die Random-Flags in jeder einzelnen Node-Struktur */
  1321.     struct Node *tempnode;
  1322.  
  1323.     for (tempnode = tracklist->lh_Head; tempnode->ln_Succ; tempnode = tempnode->ln_Succ)
  1324.         ((struct ProgramTitleNode *)tempnode)->ptn_randomplayed = FALSE;
  1325. }
  1326. /*------------------ CDPlayVerify() ---------------------------< >-*/
  1327. void CDPlayVerify(struct CDStruct *cds, UBYTE track)
  1328. {
  1329.     if (track != cds->cur_track)
  1330.         CDPlayA(cds->cdx, track, 1);
  1331. }
  1332.  
  1333.  
  1334.  
  1335. /*------------------ OpenAppWin() -----------------------------< >-*/
  1336. BOOL OpenAppWin(Application *app, WORD win)
  1337. {
  1338.     BOOL success = FALSE;
  1339.  
  1340.     /* PopUp falls Window schon offen ist */
  1341.     if (app->appwin[win].window != NULL)
  1342.     {
  1343.         WindowToFront(app->appwin[win].window);
  1344.         ActivateWindow(app->appwin[win].window);
  1345.         return (TRUE);
  1346.     }
  1347.  
  1348.     if (MakeVisuals(app, win))
  1349.     {
  1350.         ULONG idcmpflags = IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW | IDCMP_MENUPICK;
  1351.         struct TagItem wintags[] = {    WA_Left,        app->appwin[win].maxsize[LEFT],
  1352.                                         WA_Top,            app->appwin[win].maxsize[TOP],
  1353.                                          WA_Width,        app->appwin[win].maxsize[WIDTH],
  1354.                                         WA_Height,        app->appwin[win].maxsize[HEIGHT],
  1355.                                         WA_Flags,        WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_ACTIVATE | WFLG_NEWLOOKMENUS,
  1356.                                         WA_Gadgets,        (ULONG)app->appwin[win].gadgetlist,
  1357.                                         WA_PubScreen,    (ULONG)app->screen,
  1358.                                         WA_Title,        NULL,
  1359.                                         TAG_IGNORE,        (ULONG)&app->appwin[win].minsize,
  1360.                                         WA_MinWidth,    app->appwin[win].minwidth,
  1361.                                         WA_MinHeight,    app->appwin[win].minheight,
  1362.                                         WA_MaxWidth,    app->appwin[win].maxwidth,
  1363.                                         WA_MaxHeight,    app->appwin[win].maxheight,
  1364.                                         (IntuitionBase->lib_Version >= 39)?WA_BusyPointer:TAG_IGNORE,    (app->Flags & APPF_BUSY)?TRUE:FALSE,
  1365.                                         TAG_END        };
  1366.  
  1367.         switch(win)
  1368.         {
  1369.             case WINDOW_MAIN:
  1370.                 idcmpflags |= BUTTONIDCMP | SLIDERIDCMP | IDCMP_VANILLAKEY | IDCMP_RAWKEY | IDCMP_CHANGEWINDOW | IDCMP_INTUITICKS | IDCMP_MOUSEBUTTONS;
  1371.                 /* gegebenenfalls ohne Zoomgadget öffnen */
  1372.                 wintags[8].ti_Tag = app->flag_main ? WA_Zoom : TAG_IGNORE;
  1373.                 break;
  1374.  
  1375.             case WINDOW_ABOUT:
  1376.                 idcmpflags |= BUTTONIDCMP | IDCMP_INTUITICKS;
  1377.                 wintags[7].ti_Data = (ULONG)ls[MSG_ABOUT_TITLE];
  1378.                 break;
  1379.  
  1380.             case WINDOW_CDINFO:
  1381.                 idcmpflags |= BUTTONIDCMP | IDCMP_NEWSIZE | IDCMP_CHANGEWINDOW;
  1382.                 wintags[4].ti_Data |= WFLG_SIZEGADGET | WFLG_SIZEBBOTTOM;
  1383.                 wintags[7].ti_Data    = (ULONG)ls[MSG_CDINFO_TITLE];
  1384.                 wintags[8].ti_Tag    = WA_Zoom;
  1385.                 break;
  1386.  
  1387.             case WINDOW_DRIVEINFO:
  1388.                 idcmpflags |= BUTTONIDCMP | IDCMP_NEWSIZE | IDCMP_CHANGEWINDOW;
  1389.                 wintags[4].ti_Data |= WFLG_SIZEGADGET | WFLG_SIZEBBOTTOM;
  1390.                 wintags[7].ti_Data    = (ULONG)ls[MSG_DRIVEINFO_TITLE];
  1391.                 wintags[8].ti_Tag    = WA_Zoom;
  1392.                 break;
  1393.  
  1394.             case WINDOW_PUBSCREEN:
  1395.                 idcmpflags |= LISTVIEWIDCMP | BUTTONIDCMP | IDCMP_NEWSIZE | IDCMP_CHANGEWINDOW;
  1396.                 wintags[4].ti_Data |= WFLG_SIZEGADGET | WFLG_SIZEBBOTTOM;
  1397.                 wintags[7].ti_Data    = (ULONG)ls[MSG_PUBSCREEN_TITLE];
  1398.                 wintags[8].ti_Tag    = WA_Zoom;
  1399.                 break;
  1400.  
  1401.             case WINDOW_TITLES:
  1402.                 idcmpflags |= LISTVIEWIDCMP | IDCMP_NEWSIZE | IDCMP_CHANGEWINDOW;
  1403.                 wintags[4].ti_Data |= WFLG_SIZEGADGET | WFLG_SIZEBBOTTOM;
  1404.                 wintags[8].ti_Tag    = WA_Zoom;
  1405.                 break;
  1406.  
  1407.             case WINDOW_EDIT:
  1408.                 idcmpflags |= BUTTONIDCMP | LISTVIEWIDCMP | IDCMP_NEWSIZE | IDCMP_CHANGEWINDOW;
  1409.                 wintags[4].ti_Data |= WFLG_SIZEGADGET | WFLG_SIZEBBOTTOM;
  1410.                 wintags[7].ti_Data    = (ULONG)ls[MSG_EDIT_TITLE];
  1411.                 wintags[8].ti_Data    = WA_Zoom;
  1412.                 break;
  1413.  
  1414.             case WINDOW_PROGRAM:
  1415.                 idcmpflags |= BUTTONIDCMP | LISTVIEWIDCMP | IDCMP_NEWSIZE | IDCMP_CHANGEWINDOW;
  1416.                 wintags[4].ti_Data |= WFLG_SIZEGADGET | WFLG_SIZEBBOTTOM;
  1417.                 wintags[7].ti_Data    = (ULONG)ls[MSG_PROGRAM_TITLE];
  1418.                 wintags[8].ti_Tag    = WA_Zoom;
  1419.                 break;
  1420.  
  1421.             case WINDOW_VOLUME:
  1422.                 idcmpflags |= SLIDERIDCMP | IDCMP_NEWSIZE | IDCMP_CHANGEWINDOW;
  1423.                 wintags[4].ti_Data |= WFLG_SIZEGADGET | WFLG_SIZEBBOTTOM;
  1424.                 wintags[7].ti_Data = (ULONG)ls[MSG_VOLUME_TITLE];
  1425.                 wintags[8].ti_Tag    = WA_Zoom;
  1426.                 break;
  1427.  
  1428.             case WINDOW_AB:
  1429.                 idcmpflags |= BUTTONIDCMP | STRINGIDCMP | IDCMP_NEWSIZE | IDCMP_CHANGEWINDOW;
  1430.                 wintags[4].ti_Data |= WFLG_SIZEGADGET | WFLG_SIZEBBOTTOM;
  1431.                 wintags[7].ti_Data    = (ULONG)ls[MSG_AB_TITLE];
  1432.                 wintags[8].ti_Tag    = WA_Zoom;
  1433.                 break;
  1434.         }
  1435.  
  1436.         if (app->appwin[win].window = OpenWindowTagList(NULL, wintags))
  1437.         {
  1438.             success = TRUE;
  1439.  
  1440.             switch(win)
  1441.             {
  1442.                 case WINDOW_MAIN:
  1443.                     ((struct Process *)FindTask(NULL))->pr_WindowPtr = app->appwin[win].window;
  1444.                     break;
  1445.                 case WINDOW_ABOUT:
  1446.                 case WINDOW_CDINFO:
  1447.                 case WINDOW_DRIVEINFO:
  1448.                     /* cool :-) */
  1449.                     FakeRequestA(app->appwin[win].window, app->visualinfo, FAKEREQUESTSPACE, FAKEREQUESTSPACE, app->appwin[win].maxsize[HEIGHT] - 3 - app->font->ta_YSize - 2 * FAKEREQUESTSPACE - INTERHEIGHT - BUTTONHEIGHT - (win == WINDOW_ABOUT ? 2 : 10));
  1450.                     RefreshGadgets(app->appwin[win].gadgetlist, app->appwin[win].window, NULL);
  1451.                     break;
  1452.                 case WINDOW_PUBSCREEN:
  1453.                     GetPubScreenList(app);
  1454.                     break;
  1455.             }
  1456.  
  1457.             GT_RefreshWindow(app->appwin[win].window, NULL);
  1458.  
  1459.             /* Den shared-IDCMP mit noch einem Fenster teilen */
  1460.             app->appwin[win].window->UserPort = app->idcmp;
  1461.             ModifyIDCMP(app->appwin[win].window, idcmpflags);
  1462.  
  1463.             if (app->appwin[win].img && (win != WINDOW_MAIN))
  1464.                 DrawImage(app->appwin[win].window->RPort, app->appwin[win].img, 0, 0);
  1465.             if (app->appwin[win].itext)
  1466.                 PrintIText(app->appwin[win].window->RPort, app->appwin[win].itext, 0, 0);
  1467.             if (app->appwin[win].bbox)
  1468.                 RefreshBevelBox(app->appwin[win].window->RPort, app->appwin[win].bbox, 0, 0);
  1469.  
  1470.             /*  Menü mit Fenster verbinden  */
  1471.             if (app->menustrip)
  1472.             {
  1473.                 if (!SetMenuStrip(app->appwin[win].window, app->menustrip))
  1474.                 {
  1475.                     CloseWindow(app->appwin[win].window);
  1476.                     return (FALSE);
  1477.                 }
  1478.             }
  1479.  
  1480.             app->appwin[win].winopen = TRUE;
  1481.  
  1482.             /* Gadget-Inhalte zeichnen */
  1483.             MakeInterior(app, win);
  1484.  
  1485.             /* Fenster mit Requester blockieren, falls die Application busy ist */
  1486.             if (app->Flags & APPF_BUSY)
  1487.             {
  1488.                 if (app->appwin[win].request = GetVecA(sizeof(struct Requester), MEMF_PUBLIC))
  1489.                 {
  1490.                     InitRequester(app->appwin[win].request);
  1491.                     if (!Request(app->appwin[win].request, app->appwin[win].window))
  1492.                     {
  1493.                         FreeVec(app->appwin[win].request);
  1494.                         app->appwin[win].request = NULL;
  1495.                     }
  1496.                 }
  1497.             }
  1498.         }
  1499.         else
  1500.             ShowMsgA(ls[MSG_ERROR_TITLE], ls[MSG_NO_WINDOW], app->pubscreenname);
  1501.     }
  1502.  
  1503.     return (success);
  1504. }
  1505. /*------------------ CloseAppWin() ----------------------------< >-*/
  1506. void CloseAppWin(Application *app, WORD win, BOOL realclose)
  1507. {
  1508.     if (!app->appwin[win].window)
  1509.         return;
  1510.  
  1511.     app->appwin[win].maxsize[LEFT]    = app->appwin[win].window->LeftEdge;
  1512.     app->appwin[win].maxsize[TOP]    = app->appwin[win].window->TopEdge;
  1513.  
  1514.     /* Menüs entfernen */
  1515.     if (app->menustrip)
  1516.         ClearMenuStrip(app->appwin[win].window);
  1517.  
  1518.     /* Requester entfernen */
  1519.     if (app->appwin[win].request)
  1520.     {
  1521.         EndRequest(app->appwin[win].request, app->appwin[win].window);
  1522.         FreeVec(app->appwin[win].request);
  1523.         app->appwin[win].request = NULL;
  1524.     }
  1525.  
  1526.     /* So, hier ist die CloseWindowSafely()-Funktion aus den RKMs integriert */
  1527.     Forbid();
  1528.     StripIntuiMessages(app->appwin[win].window);
  1529.     app->appwin[win].window->UserPort = NULL;
  1530.     ModifyIDCMP(app->appwin[win].window, 0L);
  1531.     Permit();
  1532.     /* originalen WindowPointer aus der Process-Struktur wieder eintragen */
  1533.     if (win == WINDOW_MAIN)
  1534.         ((struct Process *)FindTask(NULL))->pr_WindowPtr = app->orgprwin;
  1535.     CloseWindow(app->appwin[win].window);
  1536.     app->appwin[win].window = NULL;
  1537.  
  1538.     if (realclose)
  1539.         app->appwin[win].winopen = FALSE;
  1540.  
  1541.     /* Gadgetliste(n) entfernen */
  1542.     if (app->appwin[win].gadgetlist)
  1543.     {
  1544.         FreeGadgets(app->appwin[win].gadgetlist);
  1545.         app->appwin[win].gadgetlist = NULL;
  1546.     }
  1547.     FreeVec(app->appwin[win].gadget);
  1548.     app->appwin[win].gadget = NULL;
  1549.  
  1550.     /* Intuitexte entfernen */
  1551.     FreeVec(app->appwin[win].itext);
  1552.     app->appwin[win].itext = NULL;
  1553.  
  1554.     /* Images entfernen */
  1555.     FreeVec(app->appwin[win].img);
  1556.     app->appwin[win].img = NULL;
  1557.  
  1558.     /* BevelBoxen entfernen */
  1559.     FreeVec(app->appwin[win].bbox);
  1560.     app->appwin[win].bbox = NULL;
  1561.  
  1562.     /* Window-spezifisches */
  1563.     switch (win)
  1564.     {
  1565.         case WINDOW_ABOUT:
  1566.             DisposeScrollObject(app->scroller);
  1567.             break;
  1568.         case WINDOW_PUBSCREEN:
  1569.             FreeList(app->pubscreenlist);
  1570.             app->pubscreenlist = NULL;
  1571.             break;
  1572.         case WINDOW_EDIT:
  1573.             if (realclose)
  1574.                 app->edit_pos = -1;
  1575.             break;
  1576.     }
  1577. }
  1578. /*------------------ StripIntuiMessages() ---------------------< >-*/
  1579. void StripIntuiMessages(struct Window *win)
  1580. {
  1581.     /* Aus den RKMs, aber mit nur einem Parameter */
  1582.  
  1583.     struct IntuiMessage *msg;
  1584.     struct Node *succ;
  1585.  
  1586.     msg = (struct IntuiMessage *)win->UserPort->mp_MsgList.lh_Head;
  1587.  
  1588.     while (succ = msg->ExecMessage.mn_Node.ln_Succ)
  1589.     {
  1590.         if (msg->IDCMPWindow == win)
  1591.         {
  1592.             Remove((struct Node *)msg);
  1593.             ReplyMsg((struct Message *)msg);
  1594.         }
  1595.         msg = (struct IntuiMessage *)succ;
  1596.     }
  1597. }
  1598.  
  1599. /*------------------ DoTimeBuffer() ---------------------------< >-*/
  1600. VOID DoTimeBuffer(Application *app)
  1601. {
  1602.     /* Damit ist das Programm tatsächlich kürzer... */
  1603.     register struct CDxRequest *cdx = app->cdstr->cdx;
  1604.  
  1605.     switch (app->cdstr->timemode)
  1606.     {
  1607.         case TIMEMODE_TRACKCUR:
  1608.             FormatA(app->timeshowbuf, "%02ld:%02ld / %02ld:%02ld", (LONG)base2min(cdx->cdx_CurrentRelAddr), (LONG)base2sec(cdx->cdx_CurrentRelAddr), (LONG)base2min(cdx->cdx_TrackLength), (LONG)base2sec(cdx->cdx_TrackLength));
  1609.             break;
  1610.         case TIMEMODE_TRACKREM:
  1611.             FormatA(app->timeshowbuf, "%02ld:%02ld / %02ld:%02ld", (LONG)base2min(cdx->cdx_RelRemainBlocks), (LONG)base2sec(cdx->cdx_RelRemainBlocks), (LONG)base2min(cdx->cdx_TrackLength), (LONG)base2sec(cdx->cdx_TrackLength));
  1612.             break;
  1613.         case TIMEMODE_ALLCUR:
  1614.             FormatA(app->timeshowbuf, "%02ld:%02ld / %02ld:%02ld", (LONG)base2min(cdx->cdx_CurrentAbsAddr), (LONG)base2sec(cdx->cdx_CurrentAbsAddr), (LONG)base2min(cdx->cdx_TOCData->Entry[0].Address), (LONG)base2sec(cdx->cdx_TOCData->Entry[0].Address));
  1615.             break;
  1616.         case TIMEMODE_ALLREM:
  1617.             FormatA(app->timeshowbuf, "%02ld:%02ld / %02ld:%02ld", (LONG)base2min(cdx->cdx_AbsRemainBlocks), (LONG)base2sec(cdx->cdx_AbsRemainBlocks), (LONG)base2min(cdx->cdx_TOCData->Entry[0].Address), (LONG)base2sec(cdx->cdx_TOCData->Entry[0].Address));
  1618.             break;
  1619.     }
  1620. }
  1621. /*------------------ DoABBuffer() -----------------------------< >-*/
  1622. void DoABBuffer(Application *app)
  1623. {
  1624.     if (app->cdstr->a_track > 0)
  1625.         FormatA(app->cdstr->buf_ab_time_a, "%02ld:%02ld.%02ld", (LONG)base2min((app->cdstr->a_adr - app->cdstr->cdx->cdx_TOCData->Entry[app->cdstr->a_track].Address)), (LONG)base2sec((app->cdstr->a_adr - app->cdstr->cdx->cdx_TOCData->Entry[app->cdstr->a_track].Address)), (LONG)base2frm((app->cdstr->a_adr - app->cdstr->cdx->cdx_TOCData->Entry[app->cdstr->a_track].Address)));
  1626.     else
  1627.         strcpy(app->cdstr->buf_ab_time_a, "n/a");
  1628.  
  1629.     if (app->cdstr->b_track > 0)
  1630.         FormatA(app->cdstr->buf_ab_time_b, "%02ld:%02ld.%02ld", (LONG)base2min((app->cdstr->b_adr - app->cdstr->cdx->cdx_TOCData->Entry[app->cdstr->b_track].Address)), (LONG)base2sec((app->cdstr->b_adr - app->cdstr->cdx->cdx_TOCData->Entry[app->cdstr->b_track].Address)), (LONG)base2frm((app->cdstr->b_adr - app->cdstr->cdx->cdx_TOCData->Entry[app->cdstr->b_track].Address)));
  1631.     else
  1632.         strcpy(app->cdstr->buf_ab_time_b, "n/a");
  1633.  
  1634.     if (app->appwin[WINDOW_AB].window)
  1635.     {
  1636.         GT_SetGadgetAttrs(app->appwin[WINDOW_AB].gadget[GADGET_AB_A_TIME], app->appwin[WINDOW_AB].window, NULL, GTST_String, app->cdstr->buf_ab_time_a, TAG_END);
  1637.         GT_SetGadgetAttrs(app->appwin[WINDOW_AB].gadget[GADGET_AB_A_TRACK], app->appwin[WINDOW_AB].window, NULL, GTIN_Number, app->cdstr->a_track, TAG_END);
  1638.         GT_SetGadgetAttrs(app->appwin[WINDOW_AB].gadget[GADGET_AB_B_TIME], app->appwin[WINDOW_AB].window, NULL, GTST_String, app->cdstr->buf_ab_time_b, TAG_END);
  1639.         GT_SetGadgetAttrs(app->appwin[WINDOW_AB].gadget[GADGET_AB_B_TRACK], app->appwin[WINDOW_AB].window, NULL, GTIN_Number, app->cdstr->b_track, TAG_END);
  1640.     }
  1641. }
  1642. /*------------------ DoSizeBuffer() ---------------------------< >-*/
  1643. void DoSizeBuffer(Application *app)
  1644. {
  1645.     float    size;
  1646.     BOOL    pointflag;
  1647.     char    str[16];
  1648.     int        pos_s,
  1649.             pos_d,
  1650.             i,
  1651.             j;
  1652.  
  1653.     size = CalcAudioSize(app->cdstr->a_adr, app->cdstr->b_adr, 44100);
  1654.  
  1655.     inttostr((LONG)size, str, 10);
  1656.  
  1657.     pointflag = FALSE;
  1658.     for (pos_s = 0, pos_d = 0; pos_s < strlen(str) % 3; pos_s++, pos_d++)
  1659.     {
  1660.         pointflag = TRUE;
  1661.         app->cdstr->buf_copy_size[pos_d] = str[pos_s];
  1662.     }
  1663.  
  1664.     for (i = 0; i < strlen(str) / 3; i++)
  1665.     {
  1666.         /* Punkt setzen */
  1667.         if (i > 0 || pointflag)
  1668.         {
  1669.             app->cdstr->buf_copy_size[pos_d] = '.';
  1670.             pos_d++;
  1671.         }
  1672.         /* 3 Stellen kopieren */
  1673.         for (j = 0; j < 3; j++, pos_s++, pos_d++)
  1674.             app->cdstr->buf_copy_size[pos_d] = str[pos_s];
  1675.     }
  1676.  
  1677.     /* Nullstelle */
  1678.     app->cdstr->buf_copy_size[pos_d] = 0;
  1679.  
  1680.     if (strlen(app->cdstr->buf_copy_size) < 15)
  1681.     strcat(app->cdstr->buf_copy_size, " Byte");
  1682.  
  1683.     if (app->appwin[WINDOW_SAVEAUDIO].window)
  1684.         GT_SetGadgetAttrs(app->appwin[WINDOW_SAVEAUDIO].gadget[GADGET_SAVEAUDIO_SIZE], app->appwin[WINDOW_SAVEAUDIO].window, NULL, GTTX_Text, app->cdstr->buf_copy_size, TAG_END);
  1685. }
  1686. /*------------------ CalcAudioSize() --------------------------<n>-*/
  1687. float CalcAudioSize(LONG start, LONG end, LONG freq)
  1688. {
  1689.     /* Berechnet die Länge in Bytes bei gegebener Start- und Endadresse
  1690.        und Frequenz in Hz */
  1691.  
  1692.     float    size;
  1693.  
  1694.     size = end - start;
  1695.     /* Abs */
  1696.     if (size < 0)
  1697.         size *= -1;
  1698.  
  1699.     /* Umrechnen in Bytes */
  1700.     return (size / 75 * 4 * freq);
  1701. }
  1702. /*------------------ DoCDDBID() -------------------------------<n>-*/
  1703. void DoCDDBID(struct CDStruct *cdstr)
  1704. {
  1705.     int        i,
  1706.             n         = 0,
  1707.             t         = 0;
  1708.  
  1709.     char    buf[12],
  1710.             *z;
  1711.  
  1712.     struct CDTOCEntry *entry = cdstr->cdx->cdx_TOCData->Entry;
  1713.  
  1714.     for (i = 0; i < cdstr->num_track; i++)
  1715.     {
  1716.         FormatA(buf, "%lu", (int)(entry[i].Address / 75));
  1717.         for (z = buf; *z != 0; z++)    /* Quersumme */
  1718.             n += (*z - '0');
  1719.     }
  1720.  
  1721.     t = ((int)(entry[cdstr->num_track].Address / 75)) - ((int)(entry[0].Address / 75));
  1722.  
  1723.     FormatA(cdstr->buf_cddb_id, "%08x", (((n % 0xff) << 24) | (t << 8) | cdstr->num_track));
  1724. }
  1725.  
  1726.  
  1727.  
  1728.  
  1729.  
  1730. /*------------------ MakeBusy() -------------------------------< >-*/
  1731. void MakeBusy(struct Application *app, BOOL really)
  1732. {
  1733.     WORD win;
  1734.  
  1735.     if (really)
  1736.     {
  1737.         app->Flags |= APPF_BUSY;
  1738.  
  1739.         for (win = ANZ_WINDOWS-1; win >= 0; win--)
  1740.             if (app->appwin[win].window)
  1741.             {
  1742.                 if (IntuitionBase->lib_Version >= 39)
  1743.                     SetWindowPointer(app->appwin[win].window, WA_BusyPointer, TRUE, WA_PointerDelay, TRUE, TAG_END);
  1744.  
  1745.                 if (app->appwin[win].request == NULL)
  1746.                     if (app->appwin[win].request = GetVecA(sizeof(struct Requester), MEMF_PUBLIC))
  1747.                     {
  1748.                         InitRequester(app->appwin[win].request);
  1749.                         if (!Request(app->appwin[win].request, app->appwin[win].window))
  1750.                         {
  1751.                             FreeVec(app->appwin[win].request);
  1752.                             app->appwin[win].request = NULL;
  1753.                         }
  1754.                     }
  1755.             }
  1756.     }
  1757.     else
  1758.     {
  1759.         app->Flags &= ~APPF_BUSY;
  1760.  
  1761.         for (win = ANZ_WINDOWS-1; win >= 0; win--)
  1762.             if (app->appwin[win].window)
  1763.             {
  1764.                 if (IntuitionBase->lib_Version >= 39)
  1765.                     SetWindowPointer(app->appwin[win].window, WA_BusyPointer, FALSE, TAG_END);
  1766.  
  1767.                 if (app->appwin[win].request)
  1768.                 {
  1769.                     EndRequest(app->appwin[win].request, app->appwin[win].window);
  1770.                     FreeVec(app->appwin[win].request);
  1771.                     app->appwin[win].request = NULL;
  1772.                 }
  1773.             }
  1774.     }
  1775. }
  1776.  
  1777.  
  1778.  
  1779. /*------------------ IsDefaultTitle() -------------------------< >-*/
  1780. BOOL IsDefaultTitle(char *str, UBYTE track)
  1781. {
  1782.     char defaultstr[MAXTITLENAME + 1];
  1783.  
  1784.     /* Defaultstring erstellen */
  1785.     strncpy(defaultstr, ls[MSG_CDTITLE_TRACK], MAXTITLENAME - 5);
  1786.     strcat(defaultstr, " #");
  1787.     inttostr(track, defaultstr + strlen(defaultstr), 10);
  1788.  
  1789.     /* Jetzt vergleichen */
  1790.     if (strcmp(str, defaultstr) == 0)
  1791.         return (TRUE);
  1792.     else
  1793.         return (FALSE);
  1794. }
  1795.  
  1796. /*------------------ RefreshBevelBox() ------------------------< >-*/
  1797. void RefreshBevelBox(struct RastPort *rp, struct BevelBox *bbox, WORD xoffset, WORD yoffset)
  1798. {
  1799.     struct BevelBox *tempbox;
  1800.  
  1801.     for (tempbox = bbox; tempbox; tempbox = tempbox->bb_NextBevelBox)
  1802.         DrawBevelBox(rp, xoffset + tempbox->bb_LeftEdge, yoffset + tempbox->bb_TopEdge, tempbox->bb_Width, tempbox->bb_Height,
  1803.                                             GT_VisualInfo,    tempbox->bb_VisualInfo,
  1804.                                             GTBB_FrameType,    tempbox->bb_FrameType,
  1805.                                             GTBB_Recessed,    tempbox->bb_Recessed,
  1806.                                             TAG_DONE);
  1807. }
  1808.  
  1809.  
  1810.  
  1811. /*------------------ ManageNewSize() --------------------------< >-*/
  1812. void ManageNewSize(Application *app, WORD win)
  1813. {
  1814.     register struct AppWin *appwin = &app->appwin[win];
  1815.  
  1816.     appwin->maxsize[WIDTH]    = appwin->window->Width;
  1817.     appwin->maxsize[HEIGHT]    = appwin->window->Height;
  1818.  
  1819.     RemoveGList(appwin->window, appwin->gadgetlist, -1);
  1820.  
  1821.     /* Gadgetliste(n) entfernen */
  1822.     if (appwin->gadgetlist)
  1823.     {
  1824.         FreeGadgets(appwin->gadgetlist);
  1825.         appwin->gadgetlist = NULL;
  1826.     }
  1827.     FreeVec(appwin->gadget);
  1828.     appwin->gadget = NULL;
  1829.  
  1830.     /* Intuitexte entfernen */
  1831.     FreeVec(appwin->itext);
  1832.     appwin->itext = NULL;
  1833.  
  1834.     EraseRect(appwin->window->RPort,appwin->window->BorderLeft,
  1835.                                     appwin->window->BorderTop,
  1836.                                     appwin->window->Width - appwin->window->BorderRight - 1,
  1837.                                     appwin->window->Height - appwin->window->BorderBottom - 1);
  1838.     RefreshWindowFrame(appwin->window);
  1839.     MakeVisuals(app, win);
  1840.     AddGList(appwin->window, appwin->gadgetlist, ~0, -1, NULL);
  1841.  
  1842.     /* Nicht so toll, aber was soll es */
  1843.     switch (win)
  1844.     {
  1845.         case WINDOW_CDINFO:
  1846.         case WINDOW_DRIVEINFO:
  1847.             FakeRequestA(appwin->window, app->visualinfo, FAKEREQUESTSPACE, FAKEREQUESTSPACE, appwin->maxsize[HEIGHT] - 3 - app->font->ta_YSize - 2 * FAKEREQUESTSPACE - INTERHEIGHT - BUTTONHEIGHT - 10);
  1848.             break;
  1849.     }
  1850.  
  1851.     /* ggf. Intuitexte neu */
  1852.     if (appwin->itext)
  1853.         PrintIText(appwin->window->RPort, appwin->itext, 0, 0);
  1854.  
  1855.  
  1856.     MakeInterior(app, win);
  1857.     RefreshGList(appwin->gadgetlist, appwin->window, NULL, -1);
  1858. }
  1859. /*------------------ AdjustNewSize() --------------------------< >-*/
  1860. void AdjustNewSize(struct Application *app, WORD win, WORD newx, WORD newy)
  1861. {
  1862.     register struct AppWin *appwin = &app->appwin[win];
  1863.  
  1864.     /* Manchmal müssen die vorgegebenen Werte bei größenveränderbaren Gadgets */
  1865.     /* überschrieben werden, da die Mindestgröße vom verwendeten Font und     */
  1866.     /* natürlich vom verwendeten Text (Locale) abhängen kann */
  1867.     /* Diese Funktion überprüft also, ob eine derartige Änderung notwendig ist */
  1868.  
  1869.     if (newx > appwin->maxsize[WIDTH])
  1870.         appwin->maxsize[WIDTH] = newx;
  1871.     if (newx > appwin->minsize[WIDTH])
  1872.         appwin->minsize[WIDTH] = newx;
  1873.     if (newx > appwin->minwidth)
  1874.         appwin->minwidth = newx;
  1875.  
  1876.     if (appwin->maxsize[WIDTH] > appwin->maxwidth)
  1877.         appwin->maxsize[WIDTH] = appwin->maxwidth;
  1878.  
  1879.     if (newy > appwin->maxsize[HEIGHT])
  1880.         appwin->maxsize[HEIGHT] = newy;
  1881.     if (newy > appwin->minsize[HEIGHT])
  1882.         appwin->minsize[HEIGHT] = newy;
  1883.     if (newy > appwin->minheight)
  1884.         appwin->minheight = newy;
  1885.  
  1886.     if (appwin->maxsize[HEIGHT] > appwin->maxheight)
  1887.         appwin->maxsize[HEIGHT] = appwin->maxheight;
  1888. }
  1889.  
  1890. /*------------------ TextWidth() ------------------------------< >-*/
  1891. WORD TextWidth(char *text, struct TextAttr *font)
  1892. {
  1893.     struct IntuiText itext = {    1, 0,        /* FrontPen, BackPen */
  1894.                                 JAM1,        /* DrawMode */
  1895.                                 0, 0,        /* LeftEdge, TopEdge */
  1896.                                 font,        /* ITextFont */
  1897.                                 text,        /* IText */
  1898.                                 NULL };        /* NextText */
  1899.  
  1900.     return ((WORD)IntuiTextLength(&itext));
  1901. }
  1902. /*------------------ FindWidest() -----------------------------< >-*/
  1903. WORD FindWidest(char **textarr, struct TextAttr *font)
  1904. {
  1905.     int highest = 0, counter, temp;
  1906.  
  1907.     for (counter = 0; textarr[counter] != NULL; counter++)
  1908.     {
  1909.         temp = TextWidth(textarr[counter], font);
  1910.         if (temp > highest)
  1911.             highest = temp;
  1912.     }
  1913.  
  1914.     return highest;
  1915. }
  1916.  
  1917.  
  1918. /*------------------ NumToStr() -------------------------------< >-*/
  1919. char *NumToStr(LONG number)
  1920. {
  1921.     static char str[14];
  1922.     return (inttostr(number, str, 10));
  1923. }
  1924. /*------------------ RandomNum() ------------------------------< >-*/
  1925. LONG RandomNum(LONG startnum, LONG endnum)
  1926. {
  1927.     LONG result;
  1928.     struct DateStamp date;
  1929.  
  1930.     DateStamp(&date);
  1931.     srand((unsigned int)date.ds_Tick);
  1932.  
  1933.     /* Es wird eine Zahl zwischen startnum und endnum ermittelt */
  1934.     /* (einschließlich startnum bzw. endnum!) */
  1935.  
  1936.     result = LONG((((double)(endnum - startnum + 1) * ((double)rand() / double(RAND_MAX))) + startnum));
  1937.     if (result > endnum) result = endnum;
  1938.     return (result);
  1939. }
  1940. /*------------------ FitInteger() -----------------------------< >-*/
  1941. LONG FitInteger(LONG num, LONG lowborder, LONG highborder)
  1942. {
  1943.     if (num < lowborder)
  1944.         return (lowborder);
  1945.     else if (num > highborder)
  1946.         return (highborder);
  1947.     else
  1948.         return (num);
  1949. }
  1950. /*------------------ InsertBoolean() --------------------------< >-*/
  1951. LONG InsertBoolean(LONG dest, LONG flag, BOOL state)
  1952. {
  1953.     if (state)
  1954.         return (dest | flag);
  1955.     else
  1956.         return (dest & ~flag);
  1957. }
  1958.  
  1959.  
  1960. /*------------------ FreeList() -------------------------------< >-*/
  1961. void FreeList(List *list)
  1962. {
  1963.     if (list)
  1964.     {
  1965.         Node *temp_node, *next_temp_node;
  1966.  
  1967.         for (temp_node = list->lh_Head; temp_node->ln_Succ;)
  1968.         {
  1969.             next_temp_node = temp_node->ln_Succ;
  1970.             FreeVec(temp_node);
  1971.             temp_node = next_temp_node;
  1972.         }
  1973.  
  1974.         FreeVec(list);
  1975.     }
  1976. }
  1977. /*------------------ FindNode() -------------------------------< >-*/
  1978. Node *FindNode(List * list, ULONG number)
  1979. {
  1980.     Node * tempnode = list->lh_Head;
  1981.     ULONG i;
  1982.  
  1983.     for (i = 0; i < number; i++)
  1984.     {
  1985.         if (tempnode->ln_Succ)
  1986.             tempnode = tempnode->ln_Succ;
  1987.         else
  1988.         {
  1989.             tempnode = NULL;
  1990.             break;
  1991.         }
  1992.     }
  1993.     return (tempnode);
  1994. }
  1995.  
  1996.  
  1997.  
  1998. /*------------------ CreateScrollObject() ---------------------< >-*/
  1999. BOOL CreateScrollObject(struct Scroll *so)
  2000. {
  2001.     int widest, count;
  2002.     struct IntuiText *itexts;
  2003.     BOOL success = TRUE;
  2004.  
  2005.     for (count = 0; so->Text[count]; count++)
  2006.     {
  2007.     }
  2008.  
  2009.     so->p_height    = count * so->Font->ta_YSize + 2 * so->Height;
  2010.     so->p_pos        = 0;
  2011.  
  2012.     widest = FindWidest(so->Text, so->Font);
  2013.  
  2014.     if (itexts = GetVecA(sizeof(struct IntuiText) * count, MEMF_CLEAR))
  2015.     {
  2016.         /* Rastport etc. */
  2017.         if (so->RPort = GetVecA(sizeof(struct RastPort), MEMF_CLEAR))
  2018.         {
  2019.             InitRastPort(so->RPort);
  2020.  
  2021.             if (so->RPort->BitMap = GetVecA(sizeof(struct BitMap), MEMF_CLEAR))
  2022.             {
  2023.                 if (so->RPort->BitMap->Planes[0] = GetVecA((so->Width / 8) * so->p_height, MEMF_CLEAR | MEMF_CHIP))
  2024.                 {
  2025.                     int i;
  2026.  
  2027.                     InitBitMap(so->RPort->BitMap, 1, so->Width, so->p_height);
  2028.  
  2029.                     for (i = 0; i < count; i++)
  2030.                     {
  2031.                         itexts[i].FrontPen    = 1;
  2032.                         itexts[i].DrawMode    = JAM1;
  2033.                         itexts[i].LeftEdge    = (so->Width - TextWidth(so->Text[i], so->Font)) / 2;
  2034.                         itexts[i].TopEdge    = so->Height + i * so->Font->ta_YSize;
  2035.                         itexts[i].ITextFont = so->Font;
  2036.                         itexts[i].IText        = so->Text[i];
  2037.                         itexts[i].NextText    = NULL;
  2038.  
  2039.                         PrintIText(so->RPort, &itexts[i], 0, 0);
  2040.                         if (so->Flags[i])
  2041.                             PrintIText(so->RPort, &itexts[i], 1, 0);
  2042.                     }
  2043.  
  2044.                     /* Image vorbereiten */
  2045.                     so->Img.LeftEdge    = so->LeftEdge;
  2046.                     so->Img.TopEdge        = so->TopEdge;
  2047.                     so->Img.Width        = so->Width;
  2048.                     so->Img.Height        = so->Height;
  2049.                     so->Img.Depth        = 1;
  2050.                     so->Img.PlanePick    = 1;
  2051.                     so->Img.PlaneOnOff    = 0;
  2052.                     so->Img.NextImage    = NULL;
  2053.  
  2054.                     success = TRUE;
  2055.                 }
  2056.             }
  2057.         }
  2058.         FreeVec(itexts);
  2059.     }
  2060.  
  2061.     return (success);
  2062. }
  2063. /*------------------ UpdateScrollObject() ---------------------< >-*/
  2064. void UpdateScrollObject(struct Scroll *so, struct Window *win)
  2065. {
  2066.     so->Img.ImageData = (UWORD *)(so->RPort->BitMap->Planes[0] + so->p_pos * (so->Width / 8));
  2067.  
  2068.     so->p_pos++;
  2069.     if (so->p_pos > so->p_height - so->Height)
  2070.         so->p_pos = 0;
  2071.  
  2072.     DrawImage(win->RPort, &(so->Img), 0, 0);
  2073. }
  2074. /*------------------ DisposeScrollObject() --------------------< >-*/
  2075. void DisposeScrollObject(struct Scroll *so)
  2076. {
  2077.     if (so->RPort->BitMap->Planes[0])
  2078.     {
  2079.         FreeVec(so->RPort->BitMap->Planes[0]);
  2080.         so->RPort->BitMap->Planes[0] = NULL;
  2081.     }
  2082.     if (so->RPort->BitMap)
  2083.     {
  2084.         FreeVec(so->RPort->BitMap);
  2085.         so->RPort->BitMap = NULL;
  2086.     }
  2087.     if (so->RPort)
  2088.     {
  2089.         FreeVec(so->RPort);
  2090.         so->RPort = NULL;
  2091.     }
  2092. }
  2093.  
  2094.  
  2095.  
  2096. /*------------------ GetPubScreenName() -----------------------< >-*/
  2097. BOOL GetPubScreenName(struct Screen *wantedscreen, char *buffer)
  2098. {
  2099.     /* Diese Funktion schaut in der PubScreenList nach, ob die Adresse  */
  2100.     /* vorhanden ist, und kopiert den Screennamen in buffer (Buffer muß */
  2101.     /* also mindestens MAXPUBSCREENNAME + 1 lang sein */
  2102.  
  2103.     struct PubScreenNode *actnode = NULL;
  2104.     struct List *pubscreenlist = NULL;
  2105.     BOOL success = FALSE;
  2106.  
  2107.     if (pubscreenlist = LockPubScreenList())
  2108.     {
  2109.         for (actnode = (struct PubScreenNode *)pubscreenlist->lh_Head; actnode->psn_Node.ln_Succ; actnode = (struct PubScreenNode *)actnode->psn_Node.ln_Succ)
  2110.         {
  2111.             if (wantedscreen == actnode->psn_Screen)
  2112.             {
  2113.                 strncpy(buffer, actnode->psn_Node.ln_Name, MAXPUBSCREENNAME);
  2114.                 success = TRUE;
  2115.                 break;
  2116.             }
  2117.         }
  2118.         UnlockPubScreenList();
  2119.     }
  2120.  
  2121.     return (success);
  2122. }
  2123. /*------------------ GetPubScreenList() -----------------------< >-*/
  2124. BOOL GetPubScreenList(Application *app)
  2125. {
  2126.     struct List *systemlist;
  2127.     struct MyPubScreenNode *cur_node;
  2128.     struct Node *temp_node;
  2129.  
  2130.     if (app->appwin[WINDOW_PUBSCREEN].window)
  2131.         GT_SetGadgetAttrs(app->appwin[WINDOW_PUBSCREEN].gadget[GADGET_PUBSCREEN_LISTVIEW], app->appwin[WINDOW_PUBSCREEN].window, NULL, GTLV_Labels, ~0, TAG_END);
  2132.  
  2133.     FreeList(app->pubscreenlist);
  2134.  
  2135.     if (!(app->pubscreenlist = GetVecA(sizeof(struct List), MEMF_PUBLIC | MEMF_CLEAR)))
  2136.         return (FALSE);
  2137.  
  2138.     NewList(app->pubscreenlist);
  2139.  
  2140.     if (!(systemlist = LockPubScreenList()))
  2141.         return (FALSE);
  2142.  
  2143.     for (temp_node = systemlist->lh_Head; temp_node->ln_Succ; temp_node = temp_node->ln_Succ)
  2144.     {
  2145.         if (!(cur_node = GetVecA(sizeof(struct MyPubScreenNode), MEMF_PUBLIC | MEMF_CLEAR)))
  2146.             return (NULL);
  2147.         strncpy(cur_node->mpsn_pubscreenname, temp_node->ln_Name, MAXPUBSCREENNAME);
  2148.         cur_node->mpsn_Node.ln_Name = cur_node->mpsn_pubscreenname;
  2149.         AddTail(app->pubscreenlist, (Node *) cur_node);
  2150.     }
  2151.  
  2152.     UnlockPubScreenList();
  2153.  
  2154.     if (app->appwin[WINDOW_PUBSCREEN].window)
  2155.         GT_SetGadgetAttrs(app->appwin[WINDOW_PUBSCREEN].gadget[GADGET_PUBSCREEN_LISTVIEW], app->appwin[WINDOW_PUBSCREEN].window, NULL, GTLV_Labels, app->pubscreenlist, TAG_END);
  2156.  
  2157.     return (TRUE);
  2158. }
  2159.