News   Magazin   Börse   Links   ArcArchie   Homepages
 Magazin  RISC OS & C-Programmierung 8: Vorlagen Home 
Hardware   Software   Praxis   Sonstiges  
RISC OS & C-Programmierung 8: Vorlagen  Alexander Ausserstorfer 28. 8. 2016

Fenster Fenster kann man auch grafisch mit Hilfe eines Editors, wie zum Beispiel FormEd und WinEd gestalten. Die Daten werden dann als Vorlage (engl. template) in eine Datei abgespeichert. Diese Dateien haben den Dateityp template. Die abgespeicherten Daten kann man später wieder auslesen und so in ein eigenes Programm einbinden. Sie ersetzen den für ein Fenster notwendigen Datenblock, der in Teil 6 und 7 dieser Serie behandelt worden ist.

Um Fenster-Vorlagen zu nutzen, gibt es in OSLib insgesamt drei Funktionen:

   wimp_open_template()
   wimp_load_template()
   wimp_close_template()
						

Diese Funktionen werden üblicherweise in der aufgezählten Reihenfolge angewandt. Während wimp_open_template() nur einen einzigen Parameter benötigt, nämlich den Dateinamen samt Pfad, benötigt die Funktion wimp_load_template() recht viele Parameter, die der näheren Erklärung bedürfen.

Vorlage öffnen

Die Funktion

   extern void wimp_open_template (char const *file name);
						

öffnet eine Datei vom Dateityp template als Vorlage für Fenster. Bei char const *file name handelt es sich um einen Zeiger, der auf eine Zeichenkette zeigt, welche den kompletten Dateipfad samt Namen enthält. Alternativ wird vom aktuell gesetzten Verzeichnispfad aus gesucht.

Man kann die C-Funktion getenv() verwenden, um den Inhalt einer von RISC OS verwalteten Variablen abzurufen. getenv() ist in der Standard-Bibliothek (stdlib.h) von C enthalten und wird mittels #include <stdlib.h> eingebunden. Unter RISC OS kann man einen bestimmten oder den aktuellen Verzeichnispfad mit Hilfe der Anweisung *Set App$Dir <Obey$Dir> einer Variablen zuweisen, wobei App für einen beliebigen Namen steht. Programme machen das so in einer Datei namens !Boot in ihrem Anwendungsverzeichnis. Dieses Anwendungsverzeichnis ist mit einem voranstehenden Ausrufezeichen markiert und mittels Doppelklick per linker Maustaste bei gleichzeitigem Festhalten der Umschalt- oder Shift-Taste zu öffnen.

Diese von RISC OS verwalteten Variablen können mittels dem Befehl *Show in der Kommandozeile (Druck auf die Funktionstaste F12) abgerufen werden und sind der Grund dafür, warum sich unter RISC OS Programme nahezu beliebig im Dateipfad verschieben lassen und trotzdem immer gefunden werden.

Vorlage laden

Dateien vom Dateityp template können Daten für mehr als nur ein Fenster enthalten. Die Funktion

   extern int wimp_load_template (wimp_window *window, char *data,
                                  char const *end, byte *font_ref,
                                  char *name, int context,
                                  int *used, int *data_used);
						

lädt jedoch nur die Daten für ein einziges Fenster mit dem Namen name, welcher nicht mit dem Dateinamen der Vorlage zu verwechseln ist. Diese Funktion muss für jede in der Datei enthaltene Fenster-Vorlage mit dem Namen name erneut aufgerufen werden:

wimp_window *window Zeiger auf freien Arbeitsspeicher für Fenstervorlage, alternativ wimp_GET_SIZE, um die Größe des notwendigen Arbeitsspeichers zurückzuliefern. An diese Stelle wird die zu ladende Vorlage (der Datenblock) für das Fenster aus der Datei kopiert.
char *data Zeiger auf Arbeitsbereich für indirekte Symbole.
char const *end Zeiger auf das Ende des indirekten Arbeitsbereichs.
byte *font_ref wimp_NO_FONTS verwenden, falls kein besonderer Zeichensatz verwendet werden soll.
char *name Name des Fensters, nicht zu verwechseln mit dem Dateinamen der Vorlage. Mit Hilfe des Sterns (*) als Platzhalter kann auch gleichzeitig nach mehreren Namen gesucht werden. context liefert dann die Position des nächsten gefundenen Namens zurück, der mit *name übereinstimmt. Bei der Suche nach weiteren übereinstimmenden Namen ist beim nächsten Aufruf der in context zurückgelieferte Wert wiederzuverwenden. Falls kein passender Namen gefunden wird, wird context mit dem Wert 0 zurückgeliefert.
int context Startposition der Suche für das Fenster, 0 für ersten Aufruf.
int *used Zeiger auf die Anfangsadresse des reservierten Arbeitsspeichers zur Aufnahme der Größe des benötigten Arbeitsspeichers für das Fenster, falls wimp_GET_SIZE als erster Parameter für wimp_window *window verwendet wird. Sonst hier NULL verwenden. Damit wird keine Adresse übergeben, deren Inhalt überschrieben werden könnte.
int *data_used Zeiger auf die Anfangsadresse des reservierten Arbeitsspeichers zur Aufnahme der Größe des benötigten Arbeitsbereichs für indirekte Symbole, falls wimp_GET-SIZE als erster Parameter verwendet wird. Sonst auch hier NULL verwenden.

Die Werte, welche uns zurückgeliefert werden, sind abhängig davon, welche Werte wir beim Aufruf dieser Funktion übergeben.

Falls beim Aufruf dieser Funktion als erster Parameter wimp_GET_SIZE verwendet wird, darf man ebenfalls zwei Adressen mit übergeben, an deren Positionen beim Verlassen der Funktion zwei Werte geschrieben werden:

  • der Arbeitsspeicherbedarf des Fensters
  • der Arbeitsspeicherbedarf für indirekte Symbole für das Fenster

Die Funktion selbst liefert C-typisch den Wert int context zurück:

   context = wimp_load_template (...);
						

context gibt den Index des nächsten Fensters zurück. Sind in einer Vorlagen-Datei zum Beispiel drei verschiedene Fenster definiert, liefert context beim ersten Aufruf der Funktion wimp_load_template() eine 1 zurück, beim zweiten Aufruf eine 2 und so weiter. Der Index beginnt also C-typisch bei 0.

Grundsätzlich wird diese Funktion normalerweise zweimal hintereinander verwendet: Im ersten Schritt fragt man die Größe des notwendigen Arbeitspeichers einer Fenster-Vorlage ab:

   wimp_window *window = NULL;
   int used, data_used;
   char *data;

   wimp_load_template(wimp_GET_SIZE, NULL, NULL, wimp_NO_FONTS,
                      name, 0, &used, &data_used)
						

Der Parameter name steht für den Namen des betreffenden Fensters in der Vorlage.

Anschließend reserviert man den notwendigen Arbeitsspeicher:

   window = malloc(used);
   data = malloc(data_used);
						

Jetzt kann man die Vorlage in den Speicher holen:

   wimp_load_template (window, data,
                       (char const *) data + data_used,
                       wimp_NO_FONTS, name, 0, NULL, NULL);
						

Vorlage schließen

Nach diesem Schritt kann die Vorlage wieder geschlossen werden.

   wimp_close_template();
						

Der Rest erfolgt genau wie in den Teilen 6 und 7 beschrieben.

Beispiel

Folgendes Programm-Listing greift auf eine Vorlage mit dem Dateinamen Template_Hello_World vom Dateityp Templates zurück und kopiert von dort ein Fenster mit dem Namen main in den zuvor eingerichteten Arbeitsspeicher, wobei es die Größe des notwendigen Arbeitsspeichers selbst aus der Fenster-Vorlage bestimmt. Man kann damit die Inhalte des Fensters beliebig verändern, ohne eine Programmänderung vornehmen zu müssen. Den Quellcode kann man herunterladen.

   #include "oslib/wimp.h"
   #include <stdbool.h>
   #include <stdlib.h>

   int main()
   {
    // richte Aufgabe ein (Anmeldung an RISC OS)
    wimp_version_no version_out;
    wimp_t task_handle;
    task_handle=wimp_initialise(310, "Wimp 8", NULL, &version_out);

    // Lade Vorlage
    wimp_open_template ("Template_Hello_World");

    // richte benötigte Variablen ein
    wimp_window *window;
    int used, data_used;
    char *data;
    char name[11]="main";
    int context;

    // hole Größe des benötigten Arbeitsspeichers für Fenster-
    // Vorlage
    context = wimp_load_template (wimp_GET_SIZE, NULL, NULL,
              wimp_NO_FONTS, name, 0, &used, &data_used);

    // reserviere benötigten Speicher
    window = malloc (used);
    data = malloc (data_used);

    // lade Vorlage in den Speicher
    context = wimp_load_template (window, data,
                (char const *) data + data_used, wimp_NO_FONTS,
                name,0, NULL, NULL);

    // Schließe Vorlage
    wimp_close_template ();

    // Erzeuge Fenster aus Arbeitsspeicher
    wimp_block block;
    block.open.w = wimp_create_window (window);
    block.open.visible.x0 = window->visible.x0;
    block.open.visible.y0 = window->visible.y0;
    block.open.visible.x0 = window->visible.x0;
    block.open.visible.y0 = window->visible.y0;
    block.open.visible.x1 = window->visible.x1;
    block.open.visible.y1 = window->visible.y1;
    block.open.xscroll = window->xscroll;
    block.open.yscroll = window->yscroll;
    block.open.next = window->next;

    // öffne Fenster
    wimp_open_window (&(block.open));

    // Variablen für wimp_poll_Schleife (Kernschleife)
    wimp_event_no event;
    wimp_poll_flags mask = 1;
    osbool quit_pending = FALSE;

    // Kernschleife des Programms
    while (!quit_pending)
       {
         event = wimp_poll(mask, &block, NULL);
         switch (event)
         {
          case wimp_OPEN_WINDOW_REQUEST:
                   wimp_open_window(&(block.open));
                   break;

          case wimp_CLOSE_WINDOW_REQUEST:
                   wimp_close_window(block.close.w);
                   quit_pending = true;
                   break;

           case wimp_USER_MESSAGE:
           case wimp_USER_MESSAGE_RECORDED:
              if (block.message.action == message_QUIT)
                {
                    quit_pending = true;
                    break;
                }
          }

       }
    wimp_close_down(task_handle);
    return 0;
   }
						

Zum Ausprobieren und Herumexperimentieren kopiert man sich am besten die Datei Template_Hello_World mit der Vorlage sowie das übersetzte (kompilierte) Programm in den aktuellen Verzeichnispfad. Dieser ist abrufbar mit dem Befehl *Cat in der Kommandozeile. [Anm. cms: In der Kommandozeile kann das aktuelle Verzeichnis zum Beispiel mit "*Dir $.Verzeichnis" gesetzt werden. Im Dateimanager (Filer) kann man auch in das gewünschte Verweichnis wechseln und dann über das Filermenü "Set directory" anklickt.]

Im neunten Teil dreht es sich um Symbole und Ereignisbehandlung.

Fehler, Unklarheiten, Ergänzung, ein Tipp? Einfach nur einen Kommentar schicken!

Name: *

EMail:

Text: *
Hardware   Software   Praxis   Sonstiges  
ArcSite   News   Magazin   Börse   Links   ArcArchie   Homepages