/* demo_german.c Dies ist ein Beispiel-Blanker für Madhouse, mit deutschen Kommentaren. Hinweisen zum kompilieren des Programms: - Vielleicht mag Dein Compiler nicht die -Includes. Dann kannst Du diese Includes evtl. weglassen, oder "pragma" muß ge- ändert werden. - Dieses Programm kann mit dem MaxonC++ Version 3 problemlos übersetzt werden. Für andere Compiler kann eine Anpassung nötig werden. */ #include #include #include #include #include #include #include #include #include #include #include #define ABNC 0x40 #define ABC 0x80 /* Prototypen: */ void write_stopblank(); void read_prefs(); void write_error( char *str ); /* Variablen */ char text[40]; short color, scroll; time_t start; short duration_sec=0; struct Library *IntuitionBase = NULL; struct Library *GfxBase = NULL; struct Screen *scr = NULL; struct Window *win = NULL; struct Message *msg = NULL; USHORT DemoPalette[] = { 0x0000, 0x0FFF }; struct TextAttr topaz8 = { "topaz.font", 8, 0, 0 }; /*************************************************************************** *** open_all() *** Öffnet alle benötigten Dinge. ***************************************************************************/ BOOL open_all() { IntuitionBase = OpenLibrary("intuition.library",37); if( !IntuitionBase ) return FALSE; GfxBase = OpenLibrary("graphics.library",37); if( !GfxBase ) return FALSE; /* Einen einfachen LowRes-Screen öffnen. */ scr = OpenScreenTags(NULL, SA_Depth, 1, SA_Width, 320, SA_Height, 256, SA_Font, &topaz8, TAG_DONE); if(!scr) return FALSE; /* Der Mauszeiger verschwindet, wenn man ihm die Farben des Hintergrunds gibt: */ SetRGB4( &scr->ViewPort,17,0,0,0); SetRGB4( &scr->ViewPort,18,0,0,0); SetRGB4( &scr->ViewPort,19,0,0,0); win = OpenWindowTags(NULL, WA_AutoAdjust, TRUE, WA_NoCareRefresh, TRUE, WA_CustomScreen, scr, WA_Flags, WFLG_RMBTRAP, WA_Borderless, TRUE, WA_Activate, TRUE, WA_IDCMP, IDCMP_MOUSEBUTTONS+IDCMP_RAWKEY, TAG_DONE ); if( !win ) return FALSE; LoadRGB4( &scr->ViewPort, DemoPalette, 2 ); return TRUE; } /*************************************************************************** *** close_all() *** Schließt alles, was wir geöffnet hatten. ***************************************************************************/ void close_all() { /* Diese Anweisung legt den Screen nach hinten. Dies verhindert einen nervigen Effekt, wenn der Screen auf einem 68000-Amiga geschlossen wird. */ if( scr ) ScreenToBack( scr ); /* Wenn etwas schlief lief, müssen wir das Madhouse mitteilen. Aber weil man write_error() nur einmal aufrufen darf, benötigen wir diese nette if-Konstruktion: */ if( !IntuitionBase ) write_error( "No intuition.lib V37!" ); else { if( !GfxBase ) write_error( "No graphics.lib V37!" ); else { if( !scr ) write_error( "Out of memory: Couldn't open screen."); else { if( !win ) write_error( "Out of memory: Couldn't open window."); } } } /* Jetzt schließen wir alles, was wir öffnen konnten. */ if( win ) CloseWindow( win ); if( scr ) CloseScreen( scr ); if( GfxBase ) CloseLibrary( GfxBase ); if( IntuitionBase ) CloseLibrary( IntuitionBase ); } /*************************************************************************** *** main() *** Hier steht nun endlich der richtige Blanker: ***************************************************************************/ void main() { BOOL quit = FALSE; BOOL user_quit = FALSE; short ypos = 20; short direction = 1; short oldy; /* Zuerst lesen wir die Blanker-Einstellungen (aus dem BlankerPrefs- Fenster) sowie den Duration-Wert, der angibt, wielange der Blanker blanken darf. */ read_prefs(); /* Jetzt wird die Stopp-Uhr gestartet (zum Überprüfen des Eigen-Abbruchs) */ start = time(NULL); /* Screen und Fenster werden geöffnet. */ if(open_all()) { /* Je nach Einstellung bekommt der Text eine andere Farbe: */ switch( color ) { case 0: SetRGB4( &scr->ViewPort, 1, 15,0,0 ); break; case 1: SetRGB4( &scr->ViewPort, 1, 15,15,0 ); break; case 2: SetRGB4( &scr->ViewPort, 1, 0,0,15 ); } /* Text-Parameter: der Text wird geschrieben. */ SetAPen( win->RPort, 1 ); Move( win->RPort, 5, ypos ); Text( win->RPort, text, ( strlen(text) > 38 ? 38 : strlen(text)) ); /* Hauptschleife. */ while( !quit ) { /* Wenn Scroll gewählt wurde, muß der Text bewegt werden: */ if( scroll ) { oldy = ypos; ypos += direction; if( (ypos > 220) || (ypos < 20) ) direction *= -1; ClipBlit(win->RPort, 5, oldy-10, win->RPort, 5, ypos-10, 310, 20, ABNC | ABC ); /* Minterme ABNC | ABC -> Rechteck ohne Veränderungen kopieren. */ } /* Mausknöpfe oder ein Tastendruck? */ if( msg = GetMsg(win->UserPort) ) { quit = TRUE; user_quit = TRUE; ReplyMsg( msg ); } /* Wenn 'Change Blanker' im Hauptfenster aktiviert wurde (duration_sec ist ungleich null) UND wir schon etwas länger blanken als erlaubt (difftime(time(NULL),start) > time_counter) dann müssen wir schlußmachen. */ if( duration_sec && difftime(time(NULL),start) > duration_sec ) quit = TRUE; WaitTOF(); } } /* Alles Angeforderte schließen (und vielleicht einen Fehler schreiben): */ close_all(); /* Wenn unser Blanker durch den Anwender beendet wurde, müssen wir das Mad- house mitteilen (sonst würde es [bei aktivertem Change Blanker] den nächsten Blanker starten. */ if( user_quit ) write_stopblank(); /* Und fertig! */ } /*************************************************************************** *** *** *** Funktionen zur Verständigung mit Madhouse *** *** *** ***************************************************************************/ /* Einige globale Variablen: */ char bu[1500]; /* Der Speicherbereich bu[] enthält die gesamte prefs- Datei. */ short bu_seek = 0; /* bu_seek ist der Offset von bu[]. Er gibt an, wo sich die "Lesemarke" in bu befindet, ab der der nächste Parameter gelsen wird. */ /* Erstmal einige nützliche Funktionen: */ /*************************************************************************** *** read_next_digit() *** Liest die nächste Nummer aus der prefs-Datei. *** (Der nächste Parameter muß eine Nummer sein.) ***************************************************************************/ long read_next_digit() { short number_cnt = 0; char number[50]; while( bu[bu_seek] != (char) 0x0D ) { number[number_cnt] = bu[bu_seek]; bu_seek++; number_cnt++; } number[number_cnt] = (char) 0x00; /* Das (0x0D)(0x0A) muß übersprungen werden. * (Madhouse schreibt diese Sequenzen zwischen die Zeilen.) */ bu_seek+=2; return strtol( number, 0, 10 ); } /*************************************************************************** *** read_next_string() *** Liest die nächste Zeichenkette aus der prefs-Datei. *** (Der nächste Parameter muß eine Zeichenkette sein.) **************************************************************************/ void read_next_string( char *string, short maxlen ) { short text_cnt = 0; /* Ein Madhouse-Text beginnt aus technischen Gründen (Aha) mit "$". Weil wir das "$" nicht benötigen, überspringen wir einfach das nächste Zeichen. */ bu_seek++; while( (bu[bu_seek] != (char) 0x0D) && (text_cnt < maxlen) ) { string[text_cnt] = bu[bu_seek]; bu_seek++; text_cnt++; } string[text_cnt] = (char) 0x00; /* Jetzt haben wir den Text in string[]. */ /* * Die (0x0D)(0x0A)-Sequenz überspringen. */ bu_seek+=2; } /*************************************************************************** *** read_prefs() *** Liest die Einstellungen. ***************************************************************************/ void read_prefs() { short text_cnt = 0; short number_cnt = 0; BPTR f = NULL; f = Open( "RAM:Madhouse_Storage/prefs", MODE_OLDFILE ); if (f) { Read( f, bu, sizeof( bu ) ); /* Nun hat bu[] zum Beispiel so einen Inhalt: "$Hello, this is a text(0x0D)(0x0A)2(0x0D)(0x0A)0(0x0D)(0x0A) 5(0x0D)(0x0A)RAM:Madhouse_Storage(0x0D)(0x0A)". Die beiden Zeichen (0x0D) und (0x0A) sind zwischen jeder Zeile. Hello,... ist unser erste Parameter. 2 ist der Zweite (die Farbe des Textes), 0 der Dritte (Scrollen ja/nein), 5 ist der Duration-Wert in Minuten und RAM:... ist der Pfad unseres Verzeichnisses, falls wir eine Datei nachladen möchten. Alle Madhouse-Strings beginnen mit "$". Der erste Parameter wird in text[] verfrachtet, der Zweite kommt in color, der Dritte in duration_sec und den Pfad brauchen wir gar nicht. */ /* * Erster Parameter (Text) */ read_next_string( text, 40 ); /* * Zweiter Parameter (Color) */ color = read_next_digit(); /* * Dritter Parameter (Scroll) */ scroll = read_next_digit(); /* * Duration-Parameter. */ duration_sec = read_next_digit() * 60; /*Minuten -> Sekunden*/ Close( f ); } else { /* Der Blanker wurde nicht von Madhouse gestarten: Abbruch! */ exit(0); } } /*************************************************************************** *** write_stopblank() *** Muß benutzt werden, wenn der Blanker durch den Anwender abgebrochen *** wurde, und nicht durch den Duration-Wert. ***************************************************************************/ void write_stopblank() { /* Wir müssen nur eine neue, leere Datei anlegen, schon weiß Madhouse bescheit. */ BPTR f; f = Open( "RAM:Madhouse_Storage/stopblank", MODE_NEWFILE ); if( f ) Close( f ); } /*************************************************************************** *** write_error() *** Macht Madhouse klar, daß ein Fehler auftrat (und wie der Fehler *** heißt) - darf nur EINMAL aufgerufen werden! ***************************************************************************/ void write_error( char *str ) { BPTR f; char eol_marker = 0x0D; f = Open( "RAM:Madhouse_Storage/errors", MODE_READWRITE ); if( f ) { Seek( f, 0, OFFSET_END ); Write( f, str, strlen(str) ); Write( f, &eol_marker, 1 ); Close( f ); } }