home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / window / windowc / window.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-29  |  57.9 KB  |  1,680 lines

  1. /* Window.C:   Funktionen zur schnellen Textausgabe, zum Verwenden von
  2.            Windows, zum Erstellen von Auswahl-Menüs, zur komfortablen
  3.            Stringeingabe usw.
  4.  
  5.    Version 1.0sw vom 14.06.90
  6.  
  7.    Dies ist eine Shareware-Version. Der Quelltext darf NICHT geändert
  8.    werden. Programme, die auf Funktionen dieser Toolbox zurückgreifen,
  9.    dürfen nur für eigene Zwecke verwendet und NICHT weitergegeben oder
  10.    verkauft werden! Hierzu ist eine REGISTRIERUNG erforderlich.
  11.    Die Vollversion ist für DM 79,-- erhältlich bei:
  12.  
  13.    Jürgen Altfeld
  14.    Hofkurat-Diehl-Str. 7
  15.  
  16.    8042 Oberschleißheim
  17.  
  18.    Weitere Informationen siehe begleitende Text-Dateien.
  19. */
  20.  
  21. /* Arbeitet in den Speichermodellen Small und Medium unter Umständen
  22.    inkorrekt, weil die Macros FP_OFF und FP_SEG verwendet werden!
  23.    Genauere Informationen: Hilfe (F1-Taste) zu den obigen Macros
  24.    anzeigen lassen.
  25.  
  26.    Beim inkrementalen Kompilieren tritt manchmal die Warnung C4414
  27.    ('funktion' neu definiert) auf. Sie kann ignoriert werden.        */
  28.  
  29. #include <stdio.h>
  30. #include <graph.h>
  31. #include <stdlib.h>
  32. #include <dos.h>
  33. #include <malloc.h>
  34. #include <string.h>
  35. #include <ctype.h>
  36. #include <bios.h>
  37.  
  38.  
  39.  
  40. #define WAHR 1
  41. #define FALSCH 0
  42.  
  43. #define NORMAL          7       /* Definition der Bildschirm-Farbattribute */
  44. #define HELL           15       /* für monochrome Grafikkarte              */
  45. #define INVERS       0x70
  46. #define UNTERSTRICHEN   1
  47. #define UI              9       /* Unterstrichen und Hell! */
  48.  
  49. #define SCHWARZ         0       /* Farbattribute für die Farbgrafik-Karte  */
  50. #define BLAU            1
  51. #define GRUEN           2
  52. #define ZYAN            3
  53. #define ROT             4
  54. #define VIOLETT         5
  55. #define BRAUN           6
  56. #define WEISS           7
  57. #define DUNKELGRAU      8
  58. #define HELLBLAU        9
  59. #define HELLGRUEN      10
  60. #define HELLZYAN       11
  61. #define HELLROT        12
  62. #define HELLVIOLETT    13
  63. #define GELB           14
  64. #define HELLWEISS      15
  65.  
  66.  
  67. #pragma check_pointer( off )    /* Zeigerprüfung ausschalten:
  68.                    Die Toolbox greift mit Hilfe von Zeigern
  69.                    auf den Bildschirmspeicher zu. Dies führt
  70.                    normalerweise zu dem Fehler "Bereich-
  71.                    überschreitung eines Zeigers". Deshalb
  72.                    wird hier die Zeigerprüfung ausgeschaltet
  73.                 */
  74.  
  75.  
  76. int          f0 = 23,  /* gobale Variable zum Speichern des normalen, */
  77.          f1 = 30,  /* sowie des ersten,       */
  78.          f2 = 28,  /* zweiten                 */
  79.          f3 = 16;  /* und dritten hervorgehobenen Farb-Attributs */
  80.  
  81. unsigned int screen;   /* Globle Variable zum Speichern des Video-Segments */
  82. unsigned int farbe;    /* Graphik-Karte (0 = monochrom; 1 = Farbe)         */
  83. int select;            /* Abbruchs-Code der Funktion "UseMenu" */
  84. int fehler;            /* Fehler-Nummer                        */
  85. static short shape;           /* Gestalt des Hardware-Cursors */
  86. static int cursattr;    /* Farb-Attribut des Auswahl-Cursors */
  87.  
  88. static struct window
  89. {
  90.    int  x, y;           /* linke obere Window-Ecke */
  91.    int  dx, dy;         /* Breite und Höhe des Windows */
  92.    int  wattr;          /* Hintergrund-Farbe des Windows */
  93.    int  rand, rattr;    /* Rand-Art und Rand-Farbe */
  94.    char *name;          /* Zeiger auf Window-Überschrift (Namen) */
  95.    int  xpos;           /* X-Koordinate der Überschrift */
  96.    int  nattr;          /* Farbe der Überschrift */
  97.    struct window *vorher;      /* Zeiger auf vorher geöffnetes Window */
  98.    void *wmalloc;       /* Zeiger auf Puffer-Speicher für Hintergrund */
  99. };
  100. typedef struct window WINDOW;
  101.  
  102. static struct menu
  103. {
  104.    int  x, y;           /* Position des Menüpunktes am Bildschirm */
  105.    int  nattr;          /* Farb-Attribut des Menüpunkt-Namens */
  106.    char *name;          /* Zeiger auf Namen des Menüpunktes */
  107.    int  nr;             /* Identifikationsnummer des Menüpunktes */
  108.    char page;           /* Flag für neue Seite (<> 0 : 1. MP der Seite) */
  109.    struct window *window; /* Zeiger auf vorher zu öffnendes Window */
  110.    struct menu *sub;    /* Zeiger auf ersten Menüpunkt des Untermenüs */
  111.    struct menu *next;   /* Zeiger auf nächsten Menüpunkt */
  112.    struct menu *prev;   /* Zeiger auf vorherigen Menüpunkt */
  113.    struct menu *father; /* Zeiger auf Vatermenü des Submenüs */
  114. };
  115. typedef struct menu MENU;
  116.  
  117.  
  118. static struct window *lastopen; /* Zeiger auf Structur des zuletzt
  119.                    geöffneten Windows */
  120.  
  121.  
  122.  
  123. /* die notwendigsten Funktions-Prototypen definieren: */
  124.  
  125. int attribut( int vg, int hg, int blinken );
  126. void CloseAll( void );          /* Prototyp aus Syntax-Gründen definieren */
  127. MENU * first( MENU *item );   /* Prototyp aus Syntax-Gründen definieren */
  128. MENU * FirstPage( MENU *item ); /*  "  */
  129. void hinweis( char *text );
  130.  
  131.  
  132.  
  133.  
  134. /************************************************************
  135. *   Funktion:   hardfehler                                  *
  136. *               Der INT 24h (Hardware-Fehler) wird auf      *
  137. *               diese Funktion umgeleitet, um auch bei      *
  138. *               kritischen Fehlern die volle Kontrolle      *
  139. *               über Hardware-Zugriffe (insbesondere        *
  140. *               Festplatten- und Diskettenzugriffe) zu      *
  141. *               behalten. Ist z. B. ein Laufwerkshebel      *
  142. *               nicht verriegelt, wird diese Funktion       *
  143. *               aufgerufen.                                 *
  144. *   Eingabe:    keine Werte                                 *
  145. *   Ausgabe:    Fehlercode von DOS                          *
  146. *   Hinweis:    Diese Routine darf niemals (!) direkt       *
  147. *               von einer anderen Funktion aufgerufen       *
  148. *               werden (unvorhersehbare Ergebnisse!).       *
  149. ************************************************************/
  150.  
  151. void far hardfehler( unsigned gf, unsigned doserr, unsigned far *g )
  152. {
  153.    fehler = 1;          /* Bei einigen C-Funktionen arbeitet der _hardretn-
  154.                Befehl fehlerhaft. Als Umweg wird diese Variable
  155.                als Flag verwendet (z. B. bei _dos_getdiskfree:
  156.                Der "doserr"-Fehlercode wird nicht zurück-
  157.                gemeldet. Vielmehr meint das Programm, es sei
  158.                KEIN Fehler aufgetreten!).                   */
  159.    _hardretn( doserr ); /* Return mit Fehlercode des DOS  */
  160.             /* Der Programmablauf wird an der Stelle nach
  161.                der Funktion fortgesetzt, bei der der Fehler
  162.                aufgetreten ist.                             */
  163. }
  164.  
  165.  
  166.  
  167. /************************************************************
  168. *   Funktion: get_vsegment()                                *
  169. *             Ermittelt die Segmentadresse des Video-RAM    *
  170. *   Ausgabe:  Die Segmentadresse des Video-RAM's als        *
  171. *             unsigned int.                                 *
  172. ************************************************************/
  173.  
  174. unsigned int get_vsegment()
  175. {
  176.    _asm
  177.    {
  178.       mov ax,40h
  179.       push ds           ; Datensegment retten
  180.       mov ds,ax         ; Datensegment auf die BIOS-Variablen setzen
  181.       mov bx,63h        ; Portadresse des 6845-Video-Chips holen
  182.       mov ax,[bx]
  183.       cmp ax,3b4h       ; ist Portadresse von einer Monochrom-Karte?
  184.       jne gv1
  185.       mov ax,0b000h     ; ja, dann ist das Video-Segment bei 0xB000
  186.       jmp gv_ende       ; beende die Funktion
  187.       gv1:
  188.       mov ax,0b800h     ; ja, dann ist das Video-Segment bei 0xB800
  189.       gv_ende:
  190.       pop ds            ; Datensegment wiederherstellen
  191.    }
  192. }
  193.  
  194.  
  195. /********************************************************
  196. *   Funktion:   set_textmode                            *
  197. *               Setzt den zum Bildschirm passenden      *
  198. *               Textmodus, löscht den Bildschirm,       *
  199. *               schaltet auf die erste Bildschirmseite  *
  200. *               und speichert in der Variablen farbe    *
  201. *               0 (null) für Monochrom- bzw. 1 (eins)   *
  202. *               für Farb-Graphik-Karte                  *
  203. *    Ausgabe:   0 (null) bei Fehler, sonst erfolgreich  *
  204. ********************************************************/
  205.  
  206. int set_textmode()
  207. {
  208.    if( screen == 0xB000)
  209.       farbe = FALSCH;      /* MDA bzw. Herkules installiert */
  210.    else farbe = WAHR;
  211.    do
  212.    {
  213.       if( farbe == FALSCH )
  214.       {
  215.      if( _setvideomode( _TEXTMONO ) )
  216.         break;
  217.      return ( FALSCH );  /* Fehlermeldung zurückgeben */
  218.       }
  219.       farbe = WAHR;
  220.       if( _setvideomode( _TEXTC80 ) )
  221.      break;
  222.       if( _setvideomode( _TEXTBW80 ) )
  223.      break;
  224.       return ( 0 );    /* Fehlermeldung zurückgeben */
  225.    }  while( WAHR == WAHR );
  226.    if( _setactivepage( 0 ) < 0 )
  227.       return ( FALSCH );    /* Fehlermeldung zurückgeben */
  228.    return ( WAHR );
  229. }
  230.  
  231.  
  232.  
  233. /*********************************************************
  234. *   Funktion:   OpenTool                                 *
  235. *               Bereitet die Toolbox zur Benutzung vor.  *
  236. *   Eingabe:    keine Werte                              *
  237. *   Ausgabe:    bei Fehler den Wert null                 *
  238. *********************************************************/
  239.  
  240. int OpenTool( void )
  241. {
  242.    if( _osmajor < 3 )           /* Ist die aktuelle DOS-Version kleiner 3? */
  243.    {
  244.       printf( "\n\n\nDieses Programm läuft nur unter DOS 3.0 und höher!\n\n");
  245.       return( FALSCH );         /* Abbruch mit Fehlermeldung */
  246.    }
  247.    screen = get_vsegment();     /* Segment-Adresse des Screens ermitteln */
  248.    if( set_textmode() == FALSCH ) /* Fehler beim Initialisieren */
  249.    {
  250.       printf( "\n\n\n\n\n" );
  251.       printf( "Die Grafikkarte unterstützt keinen passenden Text-Modus!\n\n" );
  252.       printf( "Es können nur folgende Grafikkarten (oder kompatible) verwendet werden:\n\n" );
  253.       printf( "MDA, Herkules, CGA, EGA, VGA; hierzu kompatible Karten...\n\n\n" );
  254.       return( FALSCH );        /* Fehler-Meldung */
  255.    }
  256.  
  257.    lastopen = NULL;     /* kein Window offen */
  258.  
  259.    select = 0;          /* Flag bei Menüauswahl auf "kein Fehler" setzen */
  260.  
  261.    if( farbe == FALSCH )        /* keine Farbgrafikkarte installiert? */
  262.    {
  263.       f0 = NORMAL;         /* Farb-Attribute für den Bildschirm festlegen */
  264.       f1 = HELL;
  265.       f2 = UNTERSTRICHEN;
  266.       f3 = UI;
  267.      cursattr = attribut( SCHWARZ, WEISS, 1 );  /* Auswahl-Cursor blinkend */
  268.    }
  269.    else
  270.    {
  271.       f0 = attribut( WEISS, BLAU, 0 );
  272.       f1 = attribut( GELB, BLAU, 0 );
  273.       f2 = attribut( HELLROT, BLAU, 0 );
  274.       f3 = attribut( SCHWARZ, BLAU, 0 );
  275.       cursattr = -1; /* Auswahl-Cursor invers */
  276.    };
  277.  
  278.    if( (shape = _gettextcursor()) == -1 )  /* Form des Hardware-Cursors */
  279.       shape = 0x0607;                     /* holen und merken */
  280.    if( _settextcursor( 0x2000 ) == -1 )  /* Hardware-Cursor ausschalten */
  281.       return( FALSCH );                 /* Fehler-Meldung */
  282.    _amblksiz = 32767;           /* Setze Speicheranforderungen von MALLOC
  283.                    an das Betriebssystem auf Blöcke zu
  284.                    32 KB, damit ein schnellerer Zugriff
  285.                    hierauf möglich wird!                  */
  286.  
  287.    _harderr( hardfehler );        /* verbiege Hardware-Fehler-Routine     */
  288.                                            hinweis( "Shareware-Version! Weitergabe und Änderungen verboten!" );
  289.                                            hinweis( "(C) by J. Altfeld, Hofkurat-Str. 7, D-8042 Oberschleißheim" );
  290.    return( WAHR );
  291. }
  292.  
  293.  
  294.  
  295. /********************************************************
  296. *   Funktion:   CloseTool                               *
  297. *               Bereitet die Toolbox für die Beendigung *
  298. *               der Benutzung vor.                      *
  299. *   Eingabe:    keine Werte                             *
  300. *   Ausgabe:    keine Werte                             *
  301. ********************************************************/
  302.  
  303. void CloseTool( void )
  304. {
  305.    hinweis( "Shareware-Version! Weitergabe und Änderungen verboten!" );
  306.    hinweis( "(C) by J. Altfeld, Hofkurat-Str. 7, 8042 Oberschleißheim" );
  307.    CloseAll();                  /* schließt alle noch offenen Windows */
  308.    _settextcursor( shape );     /* alten Form des Hardware-Cursors setzen */
  309. }
  310.  
  311.  
  312.  
  313. /*********************************************************
  314. *   Funktion:   _locate                                  *
  315. *               Berechnet die Offsetadresse einer        *
  316. *               beliebigen Cursorposition im Bildschirm- *
  317. *               speicherbereich.                         *
  318. *   Eingabe:    Spalte und Zeile des Cursors             *
  319. *               (0 - 79, 0 - 24)                         *
  320. *   Ausgabe:    Offsetadresse der Cursorposition         *
  321. *********************************************************/
  322.  
  323. unsigned int _locate( int x, int y )
  324. {
  325.    _asm
  326.    {
  327.       mov ax,word ptr x         ; Spalten-Position holen
  328.       mov dl,al
  329.       mov ax,word ptr y         ; Zeilen-Position holen
  330.       mov dh,al
  331.       mov al,160
  332.       mul dh                    ; Zeile * 160
  333.       shl dl,1                  ; Spalte * 2
  334.       xor dh,dh                 ; DH mit 0 laden
  335.       add ax,dx                 ; Zeile * 160 + Spalte * 2
  336.    }
  337. }
  338.  
  339.  
  340.  
  341. /******************************************************
  342. *   Funktion:   _print                                *
  343. *               Schreibt einen Textstring direkt in   *
  344. *               den Bildschirmspeicher.               *
  345. *   Eingabe:    Offsetadresse der Cursorposition,     *
  346. *               Bildschirmattribut (für die Farbe),   *
  347. *               far pointer zum Text                  *
  348. *   Ausgabe:    keine Werte                           *
  349. *   Steuerzeichen: "\n" (DB 10) für Zeilenvorschub    *
  350. ******************************************************/
  351.  
  352. void _print( unsigned int position, int attribut, char far *text )
  353. {
  354.    unsigned int o,s;
  355.    char dbs[] = {
  356.       83,104,97,114,119,97,114,101,45,84,111,111,108,98,111,120,32,
  357.       118,111,110,32,87,73,78,68,79,87,46,67,32,118,101,114,119,101,110,
  358.       100,101,116,32,45,32,87,101,105,116,101,114,103,97,98,101,32,
  359.       118,101,114,98,111,116,101,110,33,32,84,101,108,46,32,87,101,
  360.       115,116,32,71,101,114,109,97,110,121,32,40,48,56,57,41,32,
  361.       51,49,53,32,52,52,52,52,32,105,110,102,111,114,109,105,101,
  362.       114,101,110,33,0
  363.       };  /* undok. stc. von Quick-C 2.0 */
  364.  
  365.    if( text == NULL )           /* kein auszugebender Text vorhanden */
  366.       return;
  367.    o = FP_OFF( text );
  368.    s = FP_SEG( text );
  369.    _asm
  370.    {
  371.       push ds                   ; Daten-Segment retten
  372.       push es                   ; Extra-Segment retten
  373.       push di
  374.       push si                   ; REGISTER-Variablen retten
  375.       mov ax,word ptr screen    ; Bildschirm-Segment-Adresse holen
  376.       mov es,ax                 ; und in ES speichern
  377.       mov ax,word ptr s         ; Segmentadresse des Textes holen
  378.       mov ds,ax                 ; und in DS speichern
  379.       mov si,word ptr o         ; Offsetadresse des Textes holen
  380.       mov di,word ptr position  ; Offsetadresse des "Cursors" holen
  381.       push di                   ; aktuelle Cursorposition merken
  382.       mov ax,word ptr attribut  ; Screen-Attribut holen
  383.       mov ah,al                 ; und in AH speichern
  384.       _print1:
  385.       mov al,[si]               ; hole ein Zeichen des Textes
  386.       and al,al                 ; \0 Markierung erreicht? (=Stringende)
  387.       je _printende             ; ja, dann beende Ausgabe
  388.       cmp al,10                 ; Steuercode LF angetroffen?
  389.       jne _print2
  390.       pop di                    ; ja, dann gehe an Anfang der neuen Zeile
  391.       add di,160
  392.       push di                   ; rette aktuelle Cursorposition wieder
  393.       inc si                    ; Quelltext auf neues Zeichen setzen
  394.       jmp _print1               ; nächste(s) Zeichen ausgeben
  395.       _print2:
  396.       mov word ptr es:[di],ax   ; nein, dann Zeichen in Bildschirm schreiben
  397.       inc si
  398.       inc di
  399.       inc di                    ; Quelltext und Ziel auf neue Position setzen
  400.       jmp _print1               ; nächstes Zeichen ausgeben
  401.       _printende:
  402.       pop di                    ; aktuelle Cursorposition aus Stack entfernen
  403.       pop si
  404.       pop di
  405.       pop es
  406.       pop ds                    ; Register wiederherstellen
  407.    }
  408. }
  409.  
  410.  
  411.  
  412. /********************************************************
  413. *   Funktion:   fastprint                               *
  414. *               Schreibt einen Textstring direkt in     *
  415. *               den Bildschirmspeicher.                 *
  416. *   Eingabe:    Spalte und Zeile des Cursors,           *
  417. *               Bildschirmattribut (Farbe),             *
  418. *               far pointer zum Text                    *
  419. *   Ausgabe:    keine Werte                             *
  420. *   Steuerzeichen: "\n" (DB 10) für Zeilenvorschub      *
  421. ********************************************************/
  422.  
  423. void fastprint( int x, int y, int attribut, char far *text )
  424. {
  425.    unsigned int adresse;
  426.    adresse = _locate( x, y );
  427.    _print( adresse, attribut, text );
  428. }
  429.  
  430.  
  431.  
  432. /********************************************************
  433. *   Funktion:   _xchars                                 *
  434. *               Schreibt ein bestimmtes Zeichen x-mal   *
  435. *               an eine bestimmte Stelle im Bildschirm- *
  436. *               speicher                                *
  437. *   Eingabe:    Offsetadresse der Cursorposition        *
  438. *               Bildschirmattribut (Farbe)              *
  439. *               Anzahl der auszugebenden Zeichen        *
  440. *               Auszugebendes Zeichen                   *
  441. *   Ausgabe:    keine Werte                             *
  442. ********************************************************/
  443.  
  444. void _xchars( unsigned int adresse, int attribut,
  445.          int anzahl, unsigned char zeichen )
  446. {
  447.    _asm
  448.    {
  449.       push es                   ; ES retten
  450.       mov ax,screen             ; Bildschirm-Segment-Adresse holen
  451.       mov es,ax
  452.       mov ax,word ptr attribut  ; Bildschirmattribut holen
  453.       mov ah,al
  454.       mov al,zeichen            ; auszugebendes Zeichen holen
  455.       mov di,word ptr adresse   ; Offsetadresse des "Cursors" holen
  456.       mov cx,word ptr anzahl    ; Anzahl der auszugebenden Zeichen
  457.       _chars1:
  458.       mov word ptr es:[di],ax   ; Zeichen mit Attribut ausgeben
  459.       inc di
  460.       inc di                    ; Cursor um eine Spalte nach rechts setzen
  461.       loop _chars1              ; wiederhole die Ausgabe
  462.       pop es                    ; ES wiederherstellen
  463.    }
  464. }
  465.  
  466.  
  467.  
  468. /********************************************************
  469. *   Funktion:   string                                  *
  470. *               Schreibt ein bestimmtes Zeichen x-mal   *
  471. *               an eine angegebene Cursor-Position      *
  472. *   Eingabe:    Spalte und Zeile des Cursors            *
  473. *               Bildschirmattribut                      *
  474. *               Anzahl der auszugebenden Zeichen        *
  475. *               auszugebendes Zeichen                   *
  476. *   Ausgabe:    keine Werte                             *
  477. ********************************************************/
  478.  
  479. void string( int x, int y, int attribut, int anzahl, unsigned char zeichen )
  480. {
  481.    unsigned int adresse;
  482.    adresse = _locate( x, y );
  483.    _xchars( adresse, attribut, anzahl, zeichen );
  484. }
  485.  
  486.  
  487.  
  488. /********************************************************
  489. *   Funktion:   wcls                                    *
  490. *               Löscht einen Teilbereich des            *
  491. *               Bildschirms mit einer beliebigen Farbe  *
  492. *   Eingabe:    Spalte und Zeile der linken oberen Ecke *
  493. *               Anzahl der zu löschenden Spalten und    *
  494. *                  Zeilen                               *
  495. *               Bildschirm-Attribut (Farbe)             *
  496. *   Ausgabe:    keine Werte                             *
  497. ********************************************************/
  498.  
  499. void wcls( int x, int y, int xx, int yy, int attribut )
  500. {
  501.    yy = y + yy;                 /* Endzeile der Ausgabe berechnen */
  502.    for( ; y <  yy; y++ )
  503.       string( x, y, attribut, xx, ' ' );
  504. }
  505.  
  506.  
  507.  
  508. /********************************************************
  509. *   Funktion:   cls                                     *
  510. *               Löscht den gesamten Bildschirm          *
  511. *   Eingabe:    Farb-Attribut                           *
  512. *   Ausgaben:   keine Werte                             *
  513. ********************************************************/
  514.  
  515. void cls( int attr )
  516. {
  517.    wcls( 0, 0, 80, 25, attr );
  518. }
  519.  
  520.  
  521.  
  522. /********************************************************
  523. *   Funktion:   _getxchars                              *
  524. *               Holt eine bestimmte Anzahl von Zeichen  *
  525. *               mit dem dazugehörigen Attribut aus dem  *
  526. *               Bildschirmspeicher und legt diese Daten *
  527. *               im angegebenen Speicherbereich ab.      *
  528. *   Eingabe:    Offsetadresse der Cursorposition        *
  529. *               Anzahl der zu lesenden Zeichen          *
  530. *               far pointer zum Pufferspeicher (mit     *
  531. *               ausreichend Platz für Anzahl mal zwei   *
  532. *               Bytes, da jedes Zeichen mit Attribut    *
  533. *               in den Puffer gespeichert wird!)        *
  534. *   Ausgabe:    keine Werte                             *
  535. ********************************************************/
  536.  
  537. void _getxchars( unsigned int adresse, unsigned int anzahl,
  538.          void far *puffer )
  539. {
  540.    unsigned int o, s;
  541.    o = FP_OFF( puffer );
  542.    s = FP_SEG( puffer );
  543.    _asm
  544.    {
  545.       push ds
  546.       push es                   ; Segmentregister retten
  547.       push si
  548.       push di                   ; Registervariablen retten
  549.       mov ax,word ptr screen
  550.       mov es,ax                 ; ES mit Bildschirm-Segment laden
  551.       mov ax,word ptr s
  552.       mov ds,ax                 ; DS mit Daten-Segment laden
  553.       mov si,word ptr adresse   ; Offsetadresse des Cursors holen
  554.       mov di,word ptr o         ; "             "   Pufferspeichers holen
  555.       mov cx,anzahl             ; Anzahl der zu kopierenden Zeichen holen
  556.       _getxchars1:
  557.       mov ax,es:[si]            ; hole ein Zeichen mit Attribut
  558.       mov [di],ax               ; und speichere es im Puffer ab
  559.       inc si
  560.       inc si
  561.       inc di
  562.       inc di                    ; nächsten Adressen berechnen
  563.       loop _getxchars1          ; wiederhole, bis alle Zeichen gepuffert sind
  564.       pop di
  565.       pop si
  566.       pop es
  567.       pop ds                    ; Register wiederherstellen
  568.    }
  569. }
  570.  
  571.  
  572.  
  573. /********************************************************
  574. *   Funktion:   wget                                    *
  575. *               Holt alle Zeichen (mit Attribut) eines  *
  576. *               Bildschirm-Ausschnittes und speichert   *
  577. *               diese im angegebenen Pufferbereich ab.  *
  578. *   Eingabe:    Spalte und Zeile der linken oberen      *
  579. *               Windowecke                              *
  580. *               Breite und Höhe des Windows             *
  581. *               far pointer zum Pufferspeicher          *
  582. *   Ausgabe:    keine Werte                             *
  583. ********************************************************/
  584.  
  585. void wget( int x, int y, int breite, int hoehe, void *puffer )
  586. {
  587.    unsigned int adresse;
  588.    adresse = _locate( x, y );
  589.    hoehe += y;
  590.    for( ; y < hoehe; y++ )
  591.    {
  592.       _getxchars( adresse, breite, puffer );
  593.       puffer = (char *)puffer + (breite << 1); /* Puffer = Puffer+2*breite */
  594.       adresse = adresse + 160;
  595.    }
  596. }
  597.  
  598.  
  599.  
  600. /********************************************************
  601. *   Funktion:   putxchars                               *
  602. *               Schreibt alle Zeichen (mit Attribut)    *
  603. *               eines Puffers in den Bildschirmspeicher *
  604. *   Eingabe:    Offsetadresse der Cursorposition        *
  605. *               Anzahl der zu schreibenden Zeichen      *
  606. *               far pointer zum Pufferspeicher, in dem  *
  607. *               die Zeichen mit dem jeweils dazugehöri- *
  608. *               gen Attribut gespeichert sind           *
  609. *   Ausgabe:    keine Werte                             *
  610. ********************************************************/
  611.  
  612. void putxchars( unsigned int adresse, int anzahl, void far *puffer )
  613. {
  614.    unsigned int o, s;
  615.    o = FP_OFF( puffer );
  616.    s = FP_SEG( puffer );
  617.    _asm
  618.    {
  619.       push ds
  620.       push es                   ; Segmentregister retten
  621.       push si
  622.       push di                   ; Registervariablen retten
  623.       mov ax,word ptr screen
  624.       mov es,ax                 ; ES mit Bildschirm-Segment laden
  625.       mov ax,word ptr s
  626.       mov ds,ax                 ; DS mit Daten-Segment laden
  627.       mov di,word ptr adresse   ; Offsetadresse des Cursors holen
  628.       mov si,word ptr o         ; "             "   Pufferspeichers holen
  629.       mov cx,anzahl             ; Anzahl der zu kopierenden Zeichen holen
  630.       putxchars1:
  631.       mov ax,[si]               ; hole ein Zeichen mit Attribut
  632.       mov es:[di],ax            ; und schreibe es in den Bildschirmspeicher
  633.       inc si
  634.       inc si
  635.       inc di
  636.       inc di                    ; nächsten Adressen berechnen
  637.       loop putxchars1           ; wiederhole, bis alle Zeichen ausgegeben
  638.       pop di
  639.       pop si
  640.       pop es
  641.       pop ds                    ; Register wiederherstellen
  642.    }
  643. }
  644.  
  645.  
  646. /********************************************************
  647. *   Funktion:   wput                                    *
  648. *               Schreibt die angegebene Anzahl von      *
  649. *               Zeichen (mit Attribut) aus dem Puffer   *
  650. *               in den Bildschirmspeicher               *
  651. *   Eingabe:    Spalte und Zeile der linken oberen      *
  652. *               Windowecke                              *
  653. *               Breite und Höhe des Windows             *
  654. *               far pointer zum Pufferspeicher          *
  655. *   Ausgabe:    keine Werte                             *
  656. ********************************************************/
  657.  
  658. void wput( int x, int y, int breite, int hoehe, void *puffer )
  659. {
  660.    unsigned int adresse;
  661.    adresse = _locate( x, y );
  662.    hoehe += y;
  663.    for( ; y < hoehe; y++ )
  664.    {
  665.       putxchars( adresse, breite, puffer );
  666.       puffer = (char *)puffer + (breite << 1); /* Puffer = Puffer+2*breite */
  667.       adresse = adresse + 160;
  668.    }
  669. }
  670.  
  671.  
  672.  
  673. /********************************************************
  674. *   Funktion:   getanzahl                               *
  675. *               Ermittelt die erforderliche Größe eines *
  676. *               Pufferspeichers in Chars, die für ein   *
  677. *               bestimmtes Window notwendig sind, um    *
  678. *               den Bildschirminhalt mit der Funktion   *
  679. *               _wget zu puffern.                       *
  680. *   Eingabe:    Breite und Höhe des Bildschirm-         *
  681. *               ausschnittes                            *
  682. *   Ausgabe:    Puffergröße in CHARS ( = Bytes )        *
  683. ********************************************************/
  684.  
  685. int getanzahl( int x, int y )
  686. {
  687.    return ( x*y << 1 ); /*   X * Y * 2 */
  688. }
  689.  
  690.  
  691.  
  692. /********************************************************
  693. *   Funktion:   rahmen                                  *
  694. *               Zeichnet einen Rahmen mit der           *
  695. *               gewünschten Linienart                   *
  696. *   Eingabe:    Spalte und Zeile der Ecke links oben    *
  697. *               Breite und Höhe des Rahmens             *
  698. *               Linienart                               *
  699. *               0 = Doppelstrich, 1 = einfacher Strich  *
  700. *               2 = Blockzeichen, 3 = waagrecht doppelt,*
  701. *               senkrecht einfacher Rahmen              *
  702. *               Bildschirm-Attribut (Farbe)             *
  703. *   Ausgabe:    keine Werte                             *
  704. ********************************************************/
  705.  
  706. void rahmen( int x, int y, int breite, int hoehe, int art, int attribut )
  707. {
  708.    unsigned int adresse;
  709.    unsigned char lo, ro, lu, ru, wa, se;
  710.    switch( art )
  711.    {
  712.       case 1:
  713.      lo = 218, ro = 191, lu = 192, ru = 217;
  714.      wa = 196, se = 179;
  715.      break;
  716.       case 2:
  717.      lo = ro = lu = ru = wa = se = 219;
  718.      break;
  719.       case 3:
  720.      lo = 213, ro = 184, lu = 212, ru = 190, wa = 205, se = 179;
  721.      break;
  722.       default:
  723.      lo = 201, ro = 187, lu = 200, ru = 188;
  724.      wa = 205, se = 186;
  725.    }
  726.    adresse = _locate( x, y );
  727.    hoehe += y - 2;
  728.    _xchars( adresse, attribut, 1, lo );
  729.    _xchars( adresse+2, attribut, breite-2, wa );
  730.    _xchars( adresse+2*breite-2, attribut, 1, ro );
  731.    for( adresse += 160; y < hoehe; y++ )
  732.    {
  733.       _xchars( adresse, attribut, 1, se );
  734.       _xchars( adresse+2*breite-2, attribut, 1, se );
  735.       adresse += 160;
  736.    }
  737.    _xchars( adresse, attribut, 1, lu );
  738.    _xchars( adresse+2, attribut, breite-2, wa );
  739.    _xchars( adresse+2*breite-2, attribut, 1, ru );
  740. }
  741.  
  742.  
  743.  
  744. /********************************************************
  745. *   Funktion:   attribut                                *
  746. *               Ermittelt ein Bildschirm-Farbattribut   *
  747. *               anhand der angegebenen Farbwerte        *
  748. *   Eingaben:   Vordergrundfarbe (0 - 15)               *
  749. *               Hintergrundfarbe (0 - 8)                *
  750. *               Blinken (0 = nein, sonst ja)            *
  751. *   Ausgabe:    Bildschirm-Farbattribut                 *
  752. ********************************************************/
  753.  
  754. int attribut( int vg, int hg, int blinken )
  755. {
  756.    int attr;
  757.    attr = (hg << 4) | vg;
  758.    if( blinken )
  759.       attr |= 128;
  760.    return( attr );
  761. }
  762.  
  763.  
  764.  
  765. /********************************************************
  766. *   Funktion:   OpenWindow                              *
  767. *               Öffnet das angegebene Window            *
  768. *   Eingabe:    Zeiger auf WINDOW-Structur              *
  769. *   Ausgabe:    bei Fehler den Wert null                *
  770. ********************************************************/
  771.  
  772. int OpenWindow( WINDOW *wi )
  773. {
  774.    void *puffer;
  775.    if( wi == NULL )
  776.       return( FALSCH ); /* Fehler: kein Window-Zeiger angegeben */
  777.    if( wi->wmalloc != NULL )
  778.       return( FALSCH );         /* Fehler: Window ist bereits offen! */
  779.    puffer = (void *) malloc( getanzahl( wi->dx, wi->dy ) );
  780.    if( puffer == NULL )
  781.       return( FALSCH );    /* Fehler ist: Kein Speicher für Puffer frei */
  782.    wi->vorher = lastopen;       /* Zeiger auf vorher geöffnetes Window */
  783.    wi->wmalloc = puffer;        /* Adresse des Puffers speichern */
  784.    lastopen = wi;               /* zuletzt geöffnetes Window merken */
  785.    wget( wi->x, wi->y, wi->dx, wi->dy, wi->wmalloc ); /* Hintergrund retten */
  786.    rahmen( wi->x, wi->y, wi->dx, wi->dy, wi->rand, wi->rattr );
  787.    wcls( wi->x + 1, wi->y + 1, wi->dx - 2, wi->dy - 2, wi->wattr );
  788.    if( wi->name == NULL )
  789.       return( WAHR );           /* Beende Funktion ohne Fehler */
  790.    fastprint( wi->xpos, wi->y, wi->nattr, wi->name ); /* Überschrift */
  791.    return( WAHR );              /* Beende Funktion ohne Fehler */
  792. }
  793.  
  794.  
  795. /************************************************
  796. *   Funktion:   CloseWindow                     *
  797. *               Schließt das letzte Window      *
  798. *   Eingabe:    keine Werte                     *
  799. *   Ausgabe:    null, wenn alle Windows zu sind *
  800. ************************************************/
  801.  
  802. int CloseWindow()
  803. {
  804.    WINDOW *wi;
  805.    if( lastopen == NULL )
  806.       return( FALSCH );         /* Fehler: Alle Windows sind bereits zu */
  807.    wput( lastopen->x, lastopen->y, lastopen->dx, lastopen->dy,
  808.      lastopen->wmalloc );   /* Oberstes Window schließen */
  809.    free( lastopen->wmalloc );   /* Puffer-Speicher wieder freigeben! */
  810.    wi = lastopen->vorher;       /* Vorheriges Window holen */
  811.    lastopen->wmalloc = NULL;    /* Markierung: Window geschlossen */
  812.    lastopen = wi;               /* Oberstes Window ist nun das vorherige */
  813.    return( WAHR );              /* Beende Funktion ohne Fehler */
  814. }
  815.  
  816.  
  817.  
  818. /****************************************
  819. *   Funktion:   CloseAll                *
  820. *               Schließt alle Windows.  *
  821. *   Eingabe:    keine Werte             *
  822. *   Ausgabe:    keine Werte             *
  823. ****************************************/
  824.  
  825. void CloseAll( void )
  826. {
  827.    while( lastopen != NULL )
  828.       CloseWindow();
  829. }
  830.  
  831.  
  832. /********************************************************
  833. *   Funktion:   PrepareMenu                             *
  834. *               Bereitet die Benutzung einer Menü-      *
  835. *               struktur vor, indem alle notwendigen    *
  836. *               Zeiger-Verkettungen hergestellt werden. *
  837. *   Eingabe:    Zeiger auf Stru. des ERSTEN Menüpunktes *
  838. *               Zeiger auf Vater-Menüstruktur           *
  839. *   Ausgabe:    keine Werte                             *
  840. *   Besonderheit: rekursiver Aufruf von sich selbst!!!  *
  841. *               Es müssen lediglich die NEXT-Zeiger     *
  842. *               bereits vorher init. worden sein!       *
  843. ********************************************************/
  844.  
  845. void PrepareMenu( MENU *first, MENU *vater )
  846. {
  847.    MENU *p1;
  848.    if( first == NULL )
  849.       return;
  850.    p1 = NULL;          /* Erster Menüpunkt */
  851.    do
  852.    {
  853.       first->father = vater;    /* jeden Menüpunkt auf Vater zeigen lassen */
  854.       first->prev = p1;         /* Vorangehenden Menüpunkt eintragen */
  855.       p1 = first;
  856.       if( first->sub != NULL )
  857.      PrepareMenu( first->sub, first );      /* Submenü initialisieren */
  858.    } while( (first = first->next) != NULL );
  859. }
  860.  
  861.  
  862.  
  863. /********************************************************
  864. *   Funktion:   OutMenu                                 *
  865. *               Gibt ein komplettes Menü aus (ohne die  *
  866. *               Submenüs natürlich!)                    *
  867. *   Eingabe:    Zeiger auf den ersten Menüpunkt         *
  868. *   Ausgabe:    keine Werte                             *
  869. *   Hinweis:    Ein Window wird nur dann geöffnet, wenn *
  870. *               der ERSTE Menüpunkt auf die Window-     *
  871. *               Struktur zeigt!                         *
  872. ********************************************************/
  873.  
  874. void OutMenu( MENU *item )
  875. {
  876.    MENU *i1 = item;             /* Aktuellen Menüpunkt zwischenspeichern */
  877.    i1 = FirstPage( item );   /* ersten Menüpunkt der 1. Seite ermitteln */
  878.    item = first( item );        /* ersten Menüpunkt der Seite holen */
  879.  
  880.    if( i1->window != NULL )
  881.       OpenWindow( i1->window );
  882.    do
  883.    {
  884.       fastprint( item->x, item->y, item->nattr, item->name );
  885.    }  while( (item = item->next) != NULL   &&   item->page == 0 );
  886.  
  887. }
  888.  
  889.  
  890.  
  891. /************************************************
  892. *   Funktion:   cursor                          *
  893. *               Legt fest, welche Farbe der     *
  894. *               Auswahl-Cursor bei den Menü-    *
  895. *               punkten bzw. der Input-Cursor   *
  896. *               haben soll.                     *
  897. *   Eingabe:    Farb-Attribut                   *
  898. *               (-1 bedeutet: Invertiere die    *
  899. *                   momentane Farbe des         *
  900. *                   Auswahl-Cursors)            *
  901. *   Ausgabe:    keine Werte                     *
  902. ************************************************/
  903.  
  904. void cursor( int attr )
  905. {
  906.    if( attr == -1 )
  907.       cursattr = attr;
  908.    else
  909.       cursattr = (attr % 256 );
  910. }
  911.  
  912.  
  913.  
  914. /************************************************
  915. *   Funktion:   invert                          *
  916. *               Invertiert das Farb-Attribut    *
  917. *   Eingabe:    Farb-Attribut                   *
  918. *   Ausgabe:    invertiertes Farb-Attribut      *
  919. ************************************************/
  920.  
  921. int invert( int attr )
  922. {
  923.    int b;
  924.    b = attr;
  925.    b <<= 4;     /* Bits um vier Stellen nach links schieben */
  926.    b &= 127;    /* das Blink-Bit (Bit 8) ausblenden */
  927.    attr >>= 4;  /* Bits um vier Stellen nach rechts schieben */
  928.    attr &= 15;  /* Zur Sicherheit das höherwertige Nibble ausblenden */
  929.    b += attr;   /* vertauschten Attribut-Nibbles zusammenfügen */
  930.         /* Hier könnte auch stehen: b |= attr (ist dasselbe!) */
  931.    return( b ); /* Farb-Attribut mit vertauschter Vorder- und Hinter-
  932.            grundfarbe zurückgeben */
  933. }
  934.  
  935.  
  936. /************************************************
  937. *   Funktion:   CursorFarbe                     *
  938. *               Errechnet die Farbe des Aus-    *
  939. *               wahl-Cursors.                   *
  940. *   Eingabe:    Farb-Attribut des aktuellen     *
  941. *                 Menüpunktes/Input-Zeichens    *
  942. *   Ausgabe:    Cursor-Attribut des Auswahl-    *
  943. *               Cursors.                        *
  944. ************************************************/
  945.  
  946. int CursorFarbe( int attr )
  947. {
  948.    if( cursattr == -1 )
  949.       return( invert( attr ) );
  950.    return( cursattr );
  951. }
  952.  
  953.  
  954.  
  955. /************************************************
  956. *   Funktion:   input                           *
  957. *               Eingabe von Text                *
  958. *   Eingabe:    X und Y der Textposition        *
  959. *               Farb-Attribut des Textes        *
  960. *               Zeiger auf den reservierten     *
  961. *                  Speicherplatz für den Text   *
  962. *                  (Max. Länge ist gleich der   *
  963. *                   Länge des Speicherplatzes)  *
  964. *               Stelle des Cursors (relativ     *
  965. *                  zum Beginn des Textes).      *
  966. *   Ausgabe:    Zeiger auf den reserv. Speicher *
  967. *                  NULL, wenn die Eingabe mit   *
  968. *                  ESC abgebrochen wurde!       *
  969. *   Hinweis:    Wird eine ungültige Cursor-     *
  970. *               Position angegeben, so steht    *
  971. *               der Cursor am Ende des Textes   *
  972. *               (kann absichtlich dazu miß-     *
  973. *                braucht werden, z. B. -1!).    *
  974. ************************************************/
  975.  
  976. char * input( int x, int y, int attr, char *text, int c )
  977. {
  978.    int a, laenge;
  979.    unsigned int b;
  980.    char z[] = { " " };   /* Puffer für ein Zeichen (auf dem Cursor steht) */
  981.  
  982.    laenge = strlen( text );   /* Länge des Textpuffers ermitteln */
  983.    if( c < 0  ||  c > laenge )  /* ungültige Cursorposition angegeben? */
  984.    {
  985.       c = laenge;               /* dann gehe zum Textende              */
  986.       while( c > 0  &&  text[c-1] == 32 ) /* suche letzte Stelle im */
  987.       c--;             /* Text, die kein Leerzeichen ist */
  988.    }
  989.    z[0] = text[c];
  990.    fastprint( x, y, attr, text );                 /* Textpuffer ausgeben */
  991.    fastprint( x+c, y, CursorFarbe( attr ), z );  /* Cursor ausgeben */
  992.  
  993.    while( (a = getch()) != 13 )
  994.    {
  995.       fastprint( x+c, y, attr, z );      /* Cursor löschen */
  996.  
  997.       if( a == 0 )
  998.       {
  999.      a= getch();       /* erw. Tastaturcode holen */
  1000.  
  1001.      if( a == 0x4B && c > 0 )  /* Taste "Cursor links" gedr.? */
  1002.         c--;                /* Cursor um eine Stelle nach links */
  1003.  
  1004.      if( a == 0x4D && c < laenge )  /* Taste "Cursor rechts" gedr.? */
  1005.         c++;        /* Cursor um eine Stelle nach rechts */
  1006.  
  1007.      if( a == 0x47 )        /* Taste "HOME" gedrückt? */
  1008.         c = 0;              /* ja, dann gehe an Stelle eins */
  1009.  
  1010.      if( a == 0x4F )        /* Taste "END" gedrückt? */
  1011.      {
  1012.         c = laenge;
  1013.         while( c > 0  &&  text[c-1] == 32 ) /* suche letzte Stelle im */
  1014.            c--;             /* Text, die kein Leerzeichen ist */
  1015.      }
  1016.  
  1017.      if( a == 0x53 && c < laenge )  /* Zeichen auf Cursor löschen und */
  1018.      {                      /* den Rest des Textes um eine Stelle nach */
  1019.                 /* links schieben --- Taste DEL */
  1020.         for( a = c; a < laenge - 1; a++ )
  1021.            text[a] = text[a+1];
  1022.         text[laenge-1] = 32;        /* letztes Zeichen mit " " füllen */
  1023.         fastprint( x, y, attr, text );    /* Text neu ausgeben */
  1024.      }
  1025.  
  1026.       }
  1027.  
  1028.       else
  1029.       {
  1030.  
  1031.      if( a == 27 )     /* ESC gedrückt ? */
  1032.         return( NULL ); /* dann dies zurückmelden */
  1033.  
  1034.      if( a == 8 && c > 0 )  /* Zeichen links vom Cursor löschen und */
  1035.      {                      /* den Rest des Textes um eine Stelle nach */
  1036.         c--;                /* links schieben */
  1037.         for( a = c; a < laenge - 1; a++ )
  1038.            text[a] = text[a+1];
  1039.         text[laenge-1] = 32;        /* letztes Zeichen mit " " füllen */
  1040.         fastprint( x, y, attr, text );    /* Text neu ausgeben */
  1041.      }
  1042.      if( a > 31 && c < laenge)
  1043.      {
  1044.         b = _bios_keybrd( _KEYBRD_SHIFTSTATUS ); /* hole Status-Byte */
  1045.         if( (b & 128) == 0 )           /* wenn INS eingeschaltet ist, */
  1046.         {
  1047.            for( b = laenge - 1; b > c; b-- )
  1048.           text[b] = text[b-1];  /* dann schiebe Text nach rechts */
  1049.            fastprint( x, y, attr, text );    /* Text neu ausgeben */
  1050.         }
  1051.         text[c] = a;   /* eingegebenes Zeichen speichern */
  1052.         string( x + c, y, attr, 1, a );  /* Zeichen ausgeben */
  1053.         c++;           /* Cursor um eine Stelle nach links */
  1054.      }
  1055.       }
  1056.  
  1057.      z[0] = text[c];  /* Zeichen auf Cursor zwischenspeichern */
  1058.      if( z[0] == 0 ) /* Ende des Stringpuffers erreicht? */
  1059.         z[0] = 32;
  1060.      fastprint( x+c, y, CursorFarbe( attr ), z );  /* Cursor ausgeben */
  1061.       }
  1062.  
  1063.    fastprint( x+c, y, attr, z );      /* Cursor löschen */
  1064.    return( text );
  1065. }
  1066.  
  1067.  
  1068.  
  1069. /************************************************
  1070. *   Funktion:   first                           *
  1071. *               Sucht den ersten Menüpunkt      *
  1072. *               einer Seite.                    *
  1073. *   Eingabe:    Zeiger auf einen Menüpunkt      *
  1074. *   Ausgabe:    Zeiger auf den ersten Menü-     *
  1075. *               punkt der Seite                 *
  1076. ************************************************/
  1077.  
  1078. MENU * first( MENU * item )
  1079. {
  1080.    while( item->page == 0 )
  1081.    {
  1082.       if( item->prev == NULL )
  1083.      break;                 /* kein Vorgänger mehr vorhanden */
  1084.       item = item->prev;
  1085.    }
  1086.    return( item );           /* Eintrag ist erster Eintrag */
  1087. }
  1088.  
  1089.  
  1090.  
  1091. /************************************************
  1092. *   Funktion:   FirstPage                       *
  1093. *               Sucht den ersten Menüpunkt der  *
  1094. *               ersten Seite                    *
  1095. *   Eingabe:    Zeiger auf einen Menüpunkt      *
  1096. *   Ausgabe:    Zeiger auf ersten Menüpunkt     *
  1097. ************************************************/
  1098.  
  1099. MENU * FirstPage( MENU *item )
  1100. {
  1101.    while( item->prev != NULL )
  1102.    {
  1103.       item = item->prev;
  1104.       item = first( item );
  1105.    }
  1106.    return( item );
  1107. }
  1108.  
  1109.  
  1110.  
  1111. /************************************************
  1112. *   Funktion:   last                            *
  1113. *               Sucht den letzten Menüpunkt der *
  1114. *               aktuellen Seite.                *
  1115. *   Eingabe:    Zeiger auf einen Menüpunkt      *
  1116. *   Ausgabe:    Zeiger auf letzen Menüpunkt     *
  1117. ************************************************/
  1118.  
  1119. MENU * last( MENU *item )
  1120. {
  1121.    while( item->next != NULL )
  1122.  
  1123.  
  1124.       if( (item->next)->page == 0 )
  1125.      item = item->next;
  1126.       else
  1127.      break;
  1128.    return( item );              /* Rückgabe des Zeiger auf letzen MP */
  1129. }
  1130.  
  1131.  
  1132.  
  1133. /************************************************
  1134. *   Funktion:   LastPage                        *
  1135. *               Sucht den letzten Menüpunkt der *
  1136. *               letzten Seite                   *
  1137. *   Eingabe:    Zeiger auf einen Menüpunkt      *
  1138. *   Ausgabe:    Zeiger auf letzten Menüpunkt    *
  1139. ************************************************/
  1140.  
  1141. MENU * LastPage( MENU *item )
  1142. {
  1143.     while( item->next != NULL )
  1144.     {
  1145.        item = item->next;
  1146.        item = last( item );
  1147.     }
  1148.     return( item );
  1149. }
  1150.  
  1151.  
  1152.  
  1153. /*********** Funktion hinweis ************/
  1154.  
  1155. void hinweis( char *text )
  1156. {
  1157.    WINDOW w1 = { 8, 8, 64, 5, f1, 3, f3, " ACHTUNG: ", 36, f3, 0, 0 };
  1158.  
  1159.    if( OpenWindow( &w1 ) == 0 )
  1160.       return;
  1161.    fastprint( 10, 10, f1, text );
  1162.  
  1163.    _asm
  1164.    {
  1165.       mov bx,90
  1166.       push bx
  1167.       sub ah,ah
  1168.       int 1ah
  1169.       pop bx
  1170.       add bx,dx
  1171.    delay1: push bx
  1172.       int 1ah
  1173.       pop bx
  1174.       cmp bx,dx
  1175.       jnb delay1
  1176.    }
  1177.  
  1178.    CloseWindow();
  1179. }
  1180.  
  1181.  
  1182.  
  1183. /************************************************
  1184. *   Funktion:   GoLeft                          *
  1185. *               Sucht einen Menüpunkt direkt    *
  1186. *               links neben dem angegebenen     *
  1187. *               aktuellen Menüpunkt.            *
  1188. *   Eingabe:    aktueller Menüpunkt             *
  1189. *   Ausgabe:    linker Menüpunkt                *
  1190. *   Hinweis:    Gibt es keinen linken Menü-     *
  1191. *               punkt, wird der aktuelle        *
  1192. *               Menüpunkt wieder zurückgegeben. *
  1193. ************************************************/
  1194.  
  1195. MENU * GoLeft( MENU * item )
  1196. {
  1197.    int x, y, merker = 0;
  1198.    MENU *i1, *i2 = item;
  1199.  
  1200.    i1 = first( item );          /* Anfang der Seite ermitteln */
  1201.    x = item->x;
  1202.    y = item->y;                 /* Position des aktuellen Menüpunktes */
  1203.  
  1204.    do
  1205.    {                                       /* Seite nicht überschr. wird */
  1206.       if( i1->y == y )                  /* gleiche Höhe? */
  1207.       {
  1208.      if( i1->x < x  && i1->x > merker )
  1209.      {
  1210.         merker = i1->x;
  1211.         i2 = i1;                    /* linken Menüpunkt gefunden... */
  1212.      }
  1213.       }
  1214.       i1 = i1->next;                    /* nächsten Menüpunkt holen */
  1215.    } while( i1 != NULL  &&  i1->page == 0 );   /* solange die aktuelle */
  1216.  
  1217.    return( i2 );                /* linken Menüpunkt zurückgeben */
  1218. }
  1219.  
  1220.  
  1221.  
  1222. /************************************************
  1223. *   Funktion:   GoRight                         *
  1224. *               Sucht einen Menüpunkt direkt    *
  1225. *               rechts neben dem angegebenen    *
  1226. *               aktuellen Menüpunkt.            *
  1227. *   Eingabe:    aktueller Menüpunkt             *
  1228. *   Ausgabe:    rechter Menüpunkt               *
  1229. *   Hinweis:    Gibt es keinen rechten Menü-    *
  1230. *               punkt, wird der aktuelle        *
  1231. *               Menüpunkt wieder zurückgegeben. *
  1232. ************************************************/
  1233.  
  1234. MENU * GoRight( MENU * item )
  1235. {
  1236.    int x, y, merker = 30000;
  1237.    MENU *i1, *i2 = item;
  1238.  
  1239.    i1 = first( item );          /* Anfang der Seite ermitteln */
  1240.    x = item->x;
  1241.    y = item->y;                 /* Position des aktuellen Menüpunktes */
  1242.  
  1243.    do
  1244.    {                                       /* Seite nicht überschr. wird */
  1245.       if( i1->y == y )                  /* gleiche Höhe? */
  1246.       {
  1247.      if( i1->x > x  && i1->x < merker )
  1248.      {
  1249.         merker = i1->x;
  1250.         i2 = i1;                    /* rechten Menüpunkt gefunden... */
  1251.      }
  1252.       }
  1253.       i1 = i1->next;                    /* nächsten Menüpunkt holen */
  1254.    } while( i1 != NULL  &&  i1->page == 0 );     /* solange die aktuelle */
  1255.  
  1256.    return( i2 );                /* rechten Menüpunkt zurückgeben */
  1257. }
  1258.  
  1259.  
  1260.  
  1261. /************************************************
  1262. *   Funktion:   fl   (first letter )            *
  1263. *               Sucht den ersten Buchstaben     *
  1264. *               bzw. die erste Zahl in einem    *
  1265. *               String.                         *
  1266. *   Eingabe:    Zeiger auf den String           *
  1267. *   Ausgabe:    Position im String, an der der  *
  1268. *               erste Buchstabe/Zahl steht      *
  1269. *               (-1 wenn nichts gefunden!)      *
  1270. ************************************************/
  1271.  
  1272. int fl( char *text )
  1273. {
  1274.    int a;
  1275.    for( a = 0; a <= strlen( text ); a++ )
  1276.    {
  1277.       if( alnum( (unsigned char) text[a] ) )
  1278.      return( a );                   /* Rückgabe der Position */
  1279.    }
  1280.    return( -1 );                        /* Rückgabe des Fehlerwertes */
  1281. }
  1282.  
  1283.  
  1284.  
  1285. /************************************************
  1286. *   Funktion:   alnum                           *
  1287. *               Testet, ob das angegebene       *
  1288. *               Zeichen ein alphanumerisches    *
  1289. *               Zeichen ist (incl. dt. Umlaute) *
  1290. *   Eingabe:    ASCII-Zeichen                   *
  1291. *   Ausgabe:    0, wenn kein alnum Zeichen      *
  1292. ************************************************/
  1293.  
  1294. int alnum( int zeichen )
  1295. {
  1296.    if( isalnum( zeichen ) )
  1297.       return( 1 );              /* Zeichen ist alnum */
  1298.    switch( zeichen )
  1299.    {
  1300.       case 'ä':
  1301.       case 'Ä':
  1302.       case 'ö':
  1303.       case 'Ö':
  1304.       case 'ü':
  1305.       case 'Ü':
  1306.       case 'ß':
  1307.      return( 1 );            /* Zeichen ist alnum */
  1308.       default:
  1309.      return( 0 );           /* Zeichen ist nicht alnum */
  1310.    }
  1311. }
  1312.  
  1313.  
  1314.  
  1315. /************************************************
  1316. *   Funktion:   lower                           *
  1317. *               Wandelt das angegebene Zeichen  *
  1318. *               in einen Kleinbuchstabe um,     *
  1319. *               wenn es ein Buchstabe ist       *
  1320. *   Eingabe:    ASCII-Zeichen                   *
  1321. *   Ausgabe:    ASCII-Zeichen                   *
  1322. *   Besonderheit: dt. Umlaute werden beachtet   *
  1323. ************************************************/
  1324.  
  1325. int lower( int zeichen )
  1326. {
  1327.    zeichen = tolower( zeichen );
  1328.    switch( zeichen )
  1329.    {
  1330.       case 'Ä':
  1331.      zeichen = 'ä';
  1332.      break;
  1333.       case 'Ö':
  1334.      zeichen = 'ö';
  1335.      break;
  1336.       case 'Ü':
  1337.      zeichen = 'ü';
  1338.    }
  1339.    return( zeichen );
  1340. }
  1341.  
  1342.  
  1343.  
  1344. /************************************************
  1345. *   Funktion:   UseMenu                         *
  1346. *               Menü anzeigen und abfragen      *
  1347. *   Eingabe:    Zeiger auf ersten Punkt der     *
  1348. *                  Menüstruktur                 *
  1349. *   Ausgabe:    Abbruchs-Code in "select":      *
  1350. *                  0 = ENTER                    *
  1351. *                  1 = ESC im Hauptmenü         *
  1352. *                  2 = F1 für Hilfe             *
  1353. *                  3 = interner Fehler aufgetr. *
  1354. *               Zeiger auf Struktur der ausge-  *
  1355. *               wählten Menüpunktes (NULL bei   *
  1356. *               Fehler)                         *
  1357. ************************************************/
  1358.  
  1359. MENU * UseMenu( MENU *item )
  1360. {
  1361.    int a, b;
  1362.    MENU *i1;                    /* Hilfsvariable */
  1363.  
  1364.    if( item == NULL )
  1365.    {
  1366.       select = 3;               /* Interner Fehler: kein Zeiger übergeben */
  1367.       return( NULL );
  1368.    }
  1369.    OutMenu( item );             /* Menü ausgeben */
  1370.  
  1371.    while( WAHR == WAHR )        /* Endlos-Schleife */
  1372.    {
  1373.       fastprint( item->x, item->y, CursorFarbe( item->nattr ), item->name );
  1374.             /* Cursor invers ausgeben */
  1375.       a = getch();      /* warte auf Tastendruck */
  1376.  
  1377.       fastprint( item->x, item->y, item->nattr, item->name );
  1378.             /* Cursor löschen */
  1379.  
  1380.       if( alnum( a ) )        /* Ist a ein alphanum Zeichen (a-z, 1-9)? */
  1381.       {
  1382.      i1 = item;             /* aktuelle Cursor-Position merken */
  1383.      a = lower( a );        /* gedrückte Taste in Kleinbuchst. umwand. */
  1384.      item = item->next;
  1385.  
  1386.      while( item != i1 )
  1387.      {
  1388.         if( item == NULL )
  1389.         {
  1390.            item = FirstPage( i1 );
  1391.            continue;
  1392.         }
  1393.         if( (b = fl( item->name )) != -1 )
  1394.         {
  1395.            if( lower( (unsigned char) item->name[b] ) ==  a )
  1396.            {
  1397.           OutMenu( item );
  1398.           goto ende;             /* passenden Menüpunkt gefunden */
  1399.            }
  1400.         }
  1401.         item = item->next;
  1402.      }
  1403.      item = i1;
  1404.      ende:
  1405.      continue;                      /* keinen passenden MP gefunden */
  1406.       }
  1407.  
  1408.       if( a == 27 )             /* ESC gedrückt? */
  1409.       {
  1410.      if( FirstPage( item )->window != NULL && item->father != NULL)
  1411.         CloseWindow();      /* Evtl. geöffnetes Window schließen */
  1412.      item = item->father;   /* Gehe zum Vater-Prozeß */
  1413.      if( item == NULL )
  1414.      {
  1415.         select = 1;         /* Abbruch des Hauptmenüs mit ESC */
  1416.         return( NULL );     /* Abbruch ohne Zeiger auf Menüpunkt */
  1417.      }
  1418.      OutMenu( item );       /* Neues Menü ausgeben */
  1419.      continue;              /* Endlos-Schleife wiederholen */
  1420.       }
  1421.  
  1422.       if( a == 13 )             /* ENTER gedrückt? */
  1423.       {
  1424.      if( item->sub == NULL )
  1425.      {
  1426.         select = 0;
  1427.         return( item );     /* Rückgabe des Zeigers auf gewählten MP */
  1428.      }
  1429.      item = item->sub;      /* gehe in das Untermenü */
  1430.      OutMenu( item );       /* Untermenü ausgeben */
  1431.      continue;              /* Endlos-Schleife wiederholen */
  1432.       }
  1433.  
  1434.       if( a != 0 )              /* Erweiterter Tastencode? */
  1435.      continue;              /* ja, dann wiederhole die Endlos-Schleife */
  1436.  
  1437.       a = getch();              /* hole den erweiterten Tastaturcode */
  1438.  
  1439.       if( a == 0x47 )           /* Taste HOME gedrückt ? */
  1440.       {
  1441.      item = FirstPage( item );  /* ja, dann gehe zum ersten MP der  */
  1442.      OutMenu( item );           /* ersten Seite                     */
  1443.      continue;
  1444.       }
  1445.  
  1446.       if( a == 0x4f )           /* Taste END gedrückt? */
  1447.       {
  1448.      item = LastPage( item );       /* ja, dann gehe zum letzten MP  */
  1449.      OutMenu( item );               /* der letzten Seite */
  1450.      continue;
  1451.       }
  1452.  
  1453.       if( a == 0x48 )           /* Cursor hoch? */
  1454.       {
  1455.      if( item->prev == NULL )
  1456.      {
  1457.         item = LastPage( item );
  1458.         OutMenu( item );
  1459.         continue;
  1460.      }
  1461.      if( item->page != 0 )  /* am Seitenanfang? */
  1462.      {
  1463.         item = item->prev;
  1464.         OutMenu( item );
  1465.         continue;
  1466.      }
  1467.      item = item->prev;
  1468.      continue;
  1469.       }
  1470.  
  1471.       if( a == 0x50 )           /* Cursor runter ? */
  1472.       {
  1473.      if( item->next == NULL )
  1474.      {
  1475.         item = FirstPage( item );
  1476.         OutMenu( item );
  1477.         continue;
  1478.      }
  1479.      if( (item->next)->page != 0 )
  1480.      {
  1481.         item = item->next;
  1482.         OutMenu( item );
  1483.         continue;
  1484.      }
  1485.      item = item->next;
  1486.      continue;
  1487.       }
  1488.  
  1489.       if( a == 0x49 )          /* PgUp gedrückt? */
  1490.       {
  1491.      if( first( item )->prev != NULL )
  1492.      {
  1493.         item = first( first( item )->prev );
  1494.         OutMenu( item );
  1495.         continue;
  1496.      }
  1497.       }
  1498.  
  1499.       if( a == 0x51 )           /* PgDn gedrückt? */
  1500.       {
  1501.      if( last( item )->next != NULL )
  1502.      {
  1503.         item = last( item )->next;
  1504.         OutMenu( item );
  1505.         continue;
  1506.      }
  1507.       }
  1508.  
  1509.       if( a == 0x4B )           /* "Cursor links" gedrückt? */
  1510.       {
  1511.      i1 = item;             /* merke aktuelle Cursor-Position */
  1512.      item = GoLeft( item );        /* linken Menüpunkt suchen */
  1513.      if( item != i1 )               /* neuen MP gefunden? */
  1514.         continue;                   /* ja */
  1515.      do
  1516.      {
  1517.         i1 = item;
  1518.         item = GoRight( item );
  1519.      }  while( i1 != item );        /* beim linken Rand springe zum
  1520.                        MP ganz rechts */
  1521.       }
  1522.  
  1523.       if( a == 0x4D )           /* "Cursor rechts" gedrückt? */
  1524.       {
  1525.      i1 = item;                     /* merke aktuelle Cursor-Pos. */
  1526.      item = GoRight( item );       /* rechten Menüpunkt suchen */
  1527.      if( item != i1 )               /* neuen MP gefunden? */
  1528.         continue;                   /* ja */
  1529.      do
  1530.      {
  1531.         i1 = item;
  1532.         item = GoLeft( item );
  1533.      }  while( i1 != item );        /* beim rechten Rand springe zum
  1534.                        MP ganz links */
  1535.  
  1536.       }
  1537.  
  1538.       if( a == 0x3b )           /* F1 für Hilfe gedrückt? */
  1539.       {
  1540.      select = 2;
  1541.      return( item );
  1542.       }
  1543.  
  1544.    }
  1545. }
  1546.  
  1547.  
  1548.  
  1549. /************************************************
  1550. *   Funktion:   GoMain                          *
  1551. *               Schließt alle Fenster außer das *
  1552. *               des Main-Menüs.                 *
  1553. *   Eingabe:    Zeiger auf einen Menüpunkt in   *
  1554. *               irgeneinem Menü dieser Struktur *
  1555. *   Ausgabe:    keine Werte                     *
  1556. ************************************************/
  1557.  
  1558. void GoMain( MENU *item )
  1559. {
  1560.    if( item == NULL  ||  lastopen == NULL )    /* Kein Window offen oder */
  1561.       return;           /* Null-Zeiger übergeben? Dann Abbruch! */
  1562.    while( item->father != NULL )
  1563.       item = item->father;              /* Suche das Main-Menü */
  1564.    item = FirstPage( item );            /* Suche ersten MP des Main-Menüs */
  1565.    if( item->window == NULL )          /* Window garnicht geöffnet? */
  1566.       return;
  1567.    if( item->window->wmalloc == NULL )
  1568.       return;                          /* dann Abbruch */
  1569.    while( lastopen != item->window  ||  lastopen == NULL )
  1570.       CloseWindow();                 /* Schließe alle Windows außer erstes */
  1571. }
  1572.  
  1573.  
  1574.  
  1575. /************************************************
  1576. *   Funktion:   SortMpName                      *
  1577. *               Sortiert eine Anzahl von MP's   *
  1578. *               in aufsteigender Reihenfolge    *
  1579. *               anhand des Namens.              *
  1580. *   Eingabe:    Zeiger auf ersten Menüpunkt      *
  1581. *               Anzahl der Menüpunkte             *
  1582. *   Ausgabe:    keine Werte (MP's jedoch sortiert) *
  1583. ****************************************************/
  1584.  
  1585. void SortMpName( MENU *first, int anzahl )
  1586. {
  1587.    MENU *i1, *i2;                       /* Hilfsvariablen */
  1588.    char *t;
  1589.    register int b, a;                   /* schnelle Variablen */
  1590.  
  1591.    if( anzahl < 2 )
  1592.       return;                           /* Abbruch, keine Sortierung mögl. */
  1593.    i1 = first;
  1594.    for( a = 0; a < anzahl - 1; a++ )
  1595.    {
  1596.       i2 = i1;
  1597.       for( b = a + 1; b < anzahl; b++ )
  1598.       {
  1599.      i2 = i2->next;
  1600.      if( strcmp( i1->name, i2->name ) > 0 )   /* falsche Reihenfolge? */
  1601.      {
  1602.         t = i1->name;
  1603.         i1->name = i2->name;
  1604.         i2->name = t;                /* ja, dann MP-Namen austauschen */
  1605.      }
  1606.       }
  1607.       i1 = i1->next;
  1608.    }
  1609. }
  1610.  
  1611.  
  1612.  
  1613. /************************************************
  1614. *   Funktion:   inhalt                          *
  1615. *               Ermöglicht die Auswahl einer    *
  1616. *               Datei innerhalb eines Windows,  *
  1617. *               wobei auch Laufwerk oder Pfad   *
  1618. *               geändert werden können.         *
  1619. *   Eingabe:    Pfad incl. Laufwerk             *
  1620. *               Vorgabe für die Dateimaske      *
  1621. *   Ausgabe:    Zeiger auf die ausgewählte      *
  1622. *                  Datei incl. Pfad.            *
  1623. *   Hinweis:    Ist der Zeiger gleich NULL, so  *
  1624. *               ist ein Fehler aufgetreten.     *
  1625. *               In der globalen Variable fehler *
  1626. *               ist dann die Fehler-Nummer zu   *
  1627. *               entnehmen. Folgende Fehler-     *
  1628. *               Nummern sind möglich:           *
  1629. *                  0 = kein Fehler aufgetreten  *
  1630. *                  1 = Abbruch durch ESC        *
  1631. *                  2 = Fehler beim Windowöffnen *
  1632. *                  3 = ungültiges Laufwerk      *
  1633. *                  4 = Fehler bei malloc        *
  1634. *                  5 = Disk-Zugriffs-Fehler     *
  1635. *                  6 = sonst Fehler             *
  1636. *     !!!       Der zurückgegebene Zeiger auf   *
  1637. *               die ausgewählte Datei (mit      *
  1638. *               Pfad) sollte in der aufrufenden *
  1639. *               Funktion unbedingt in eine      *
  1640. *               eigene Stringvariable kopiert   *
  1641. *               werden (mit strcpy), da beim    *
  1642. *               nochmaligen Aufruf dieser       *
  1643. *               Funktion der alte String        *
  1644. *               überschrieben wird!!!           *
  1645. ************************************************/
  1646.  
  1647. char * inhalt( char *pfad_, char *maske1 )
  1648. {
  1649.  
  1650.    hinweis( "Die Funktion 'inhalt' ist nur in der Vollversion verfügbar!" );
  1651.    fehler = 6;
  1652.    return( NULL );
  1653.  
  1654. }
  1655.  
  1656.  
  1657.  
  1658. /************************************************
  1659. *   Funktion:   color                           *
  1660. *               Zeigt in einem Window alle 256  *
  1661. *               Text-Attribut-Farben an. Der    *
  1662. *               Anwender kann dann auswählen,   *
  1663. *               welche Farbe im am besten       *
  1664. *               gefällt.                        *
  1665. *   Eingabe:    anzuzeigender Textstring        *
  1666. *               (darf auch NULL sein)           *
  1667. *   Ausgabe:    Bildschirm-Attribut-Byte        *
  1668. *               ( 0 - 255; bei -1 wurde mit     *
  1669. *                 ESC abgebrochen oder es trat  *
  1670. *                 irgendein Fehler auf )        *
  1671. ************************************************/
  1672.  
  1673. int color( char *text )
  1674. {
  1675.  
  1676.    hinweis( " Die Funktion 'color' ist nur in der Vollversion verfügbar!" );
  1677.    return( -1 );
  1678.  
  1679. }
  1680.