' ******************************************************************************
'
' Der Detektor (Version 1.0)
'
' Copyright (c) 1991 by Philip K”ster
'                       Am Waldbad 13
'                       2122 Bleckede 6
'                       Tel.: (05854) 404
'
' GFA-BASIC 3.0
'
' ******************************************************************************
'
' 1. Der Detektor l„uft sowohl als echtes Fenster-Accessory als auch als
'    GEM-Programm. Er sucht einen (wahlweise bedingten!) Ausdruck in mehreren
'    Dateien und gibt die Suchergebnisse auf dem Drucker oder in einer Datei
'    aus.
'
' 2. Der Detektor ist gleichzeitig ein umfangreiches Demonstrationsprogramm,
'    in dem die Themen Accessory-Programmierung, Verwaltung von Fenstern
'    (inklusive intelligentem Scrolling) und Dialogboxen sowie vor allem die
'    Realisierung von "Wials" (Dialogboxen in Fenstern!) ausfhrlich und
'    hoffentlich bersichtlich dokumentiert werden.
'
' ******************************************************************************
'
' ***** Nur fr Interpreterbetrieb! ********************************************
'
' Damit der ben”tigte Speicher ermittelt werden kann
'
' RESERVE 49152
'
' Damit der Interpreter die Zusatzdateien findet
'
' CHDRIVE "D"
' CHDIR "D:\GFABASIC\DEVELOP\DETEKTOR"
'
' Praktisch fr den Direktmodus
'
' OPENW 0
'
' ***** Compilerbefehle ********************************************************
'
$%0     !Fliežkommadivisionen
$*%     !4-Byte-Multiplikationen
$m49152 !48 KByte Speicherplatz
$RC&    !2-Byte-RC_INTERSECT-Parameter
$U-     !Kein STOP und EVERY/AFTER
$I-     !Kein Interrupt
$S&     !2-Byte-SELECT-CASE-Parameter
$S<     !SELECT-CASE kurz
$E#     !Fehlernummern angeben
$P>     !GFA-BASIC-Prozeduren
$F<     !Keine ENDFUNC-Prfung
$N-     !Keine šberlaufprfung
'
' ***** Verwendete GEM-Konstanten **********************************************
'
' Ereigniskonstanten
'
mu_keybd_&=2^0
mu_button_&=2^1
mu_m1_&=2^2
mu_mesag_&=2^4
'
wm_redraw_&=20
wm_topped_&=21
wm_closed_&=22
wm_fulled_&=23
wm_arrowed_&=24
wm_hslid_&=25
wm_vslid_&=26
wm_sized_&=27
wm_moved_&=28
'
ac_open_&=40
ac_close_&=41
'
' Fensterkonstanten
'
LET name_&=2^0
close_&=2^1
full_&=2^2
move_&=2^3
info_&=2^4
size_&=2^5
uparrow_&=2^6
dnarrow_&=2^7
vslide_&=2^8
lfarrow_&=2^9
rtarrow_&=2^10
hslide_&=2^11
'
wc_border_&=0
'
wf_name_&=2
wf_info_&=3
wf_workxywh_&=4
wf_currxywh_&=5
wf_hslide_&=8
wf_vslide_&=9
wf_top_&=10
wf_firstxywh_&=11
wf_nextxywh_&=12
wf_hslize_&=15
wf_vslize_&=16
'
end_update_&=0
beg_update_&=1
end_mctrl_&=2
beg_mctrl_&=3
'
' Dialogkonstanten
'
LET selectable_&=2^0
default_&=2^1
exit_&=2^2
editable_&=2^3
rbutton_&=2^4
LET touchexit_&=2^6
'
LET selected_&=2^0
disabled_&=2^3
'
max_depth_&=8
'
fmd_start_&=0
fmd_finish_&=3
'
' ***** Reservierte Konstanten *************************************************
'
' Bildschirmaufl”sung
'
x_max&=WORK_OUT(0)
y_max&=WORK_OUT(1)
w_max&=WORK_OUT(0)+1
h_max&=WORK_OUT(1)+1
'
' Fenstergrenzen und Gr”že des Cursors
'
SELECT (w_max&*h_max&) DIV 1000
CASE 64 !ST niedrig
  wind_y_min&=11
  wind_w_min&=84
  wind_h_min&=77
  '
  cursor_w&=8
  cursor_h&=8
  '
CASE 128 !ST mittel
  wind_y_min&=11
  wind_w_min&=168
  wind_h_min&=77
  '
  cursor_w&=8
  cursor_h&=8
  '
DEFAULT !Alle anderen
  wind_y_min&=19
  wind_w_min&=133
  wind_h_min&=133
  '
  cursor_w&=8
  cursor_h&=16
ENDSELECT
'
' ***** Reservierte globale Variablen ******************************************
'
' Fenstergr”žen
'
' GLOBAL wind_w_max&,wind_h_max&,wind_w_old&,wind_h_old&
'
' Objekte edieren
'
' Die Bezeichner c1$ bis c5$ sind nicht reserviert!
'
c1$="0123456789"
c2$=" "
c3$="ABCDEFGHIJKLMNOPQRSTUVWXYZŽ™š"
c4$="abcdefghijklmnopqrstuvwxyz„”ž"
'
FOR i&=128 TO 255
  c5$=c5$+CHR$(i&)
NEXT i&
'
DIM te_pmask$(9)
'
te_pmask$(0)=c1$                     !9
te_pmask$(1)=c2$+c3$                 !A
te_pmask$(2)=c2$+c3$+c4$             !a
te_pmask$(3)=c1$+c2$+c3$             !N
te_pmask$(4)=c1$+c2$+c3$+c4$         !n
te_pmask$(5)=c1$+c3$+c5$+"_"         !f
te_pmask$(6)=c1$+c3$+c5$+"*:?_"      !F
te_pmask$(7)=c1$+c3$+c5$+".:\_"      !p
te_pmask$(8)=c1$+c3$+c5$+"*.:\_"     !P
'
FOR i&=1 TO 255
  te_pmask$(9)=te_pmask$(9)+CHR$(i&) !X
NEXT i&
'
' GLOBAL cursor!,editable!
' GLOBAL cursor_x&,cursor_y&
' GLOBAL te_ptmplt$,te_ptext$,te_pundo$,te_pvalid$
'
' ***** Reservierte Subroutinen ************************************************
'
' Wial-Bibliothek
'
' PROCEDURE wial_open(&,%,%,%,VAR &,&,&,&,&,&,&)
' PROCEDURE wial_close(&,%,VAR &,&,&,&,&,&)
' PROCEDURE wial_do(&,%,VAR &)
' PROCEDURE wial_wind_do(&,%,VAR &,!)
' PROCEDURE wial_dial_do(&,%,&,&,&,&,&,VAR &,!)
' PROCEDURE wial_scroll(&,%,&,&)
' PROCEDURE wial_draw_work(&,%,&,&,&,&,&,&)
' PROCEDURE wial_set_sliders(&,%)
' PROCEDURE wial_calc_cursor(%,VAR &,&)
'
' ***** Konstanten *************************************************************
'
' Dialogboxen
'
dialogboxen&=2
'
dial_detektor&=0
dial_suche&=1
'
' Alertboxen
'
DIM alert$(8)
'
alert$(0)="[3][DETEKTOR.RSC nicht gelesen!][ Oh ]"
alert$(1)="[3][Kein Fenster mehr frei!][ Oh ]"
alert$(2)="[3][Pfad existiert nicht!][ Oh ]"
alert$(3)="[3][Kein Suchausdruck angegeben!][ Oh ]"
alert$(4)="[3][Negativer Suchausdruck ohne|Bezug!][ Oh ]"
alert$(5)="[3][Keine Dateimaske angegeben!][ Oh ]"
alert$(6)="[2][Drucker nicht bereit.|Weitere Vorgehensweise?][ Abbruch | Weiter ]"
alert$(7)="[2][Suche abgebrochen.|Weitere Vorgehensweise?][ Abbruch | Springen | Weiter ]"
alert$(8)="[3][Keine Dateien gefunden!][ Oh ]"
'
' ***** Globale Variablen ******************************************************
'
' Programmsteuerung
'
' GLOBAL acc!,ende!,inf!,rsc!
' GLOBAL appl_id&,ereignis&,i&,objekt&
' GLOBAL inf_datei$
'
' Sucheinstellungen
'
DIM masken$(3)
'
' GLOBAL beachten!,datei!,drucker!,parallel!,wort!
' GLOBAL dmp_datei$,masken$,nicht$,suche$
'
' Wial
'
' GLOBAL dialog_x&,dialog_y&,fenster_attr&,fenster_handle&
' GLOBAL fenster_x&,fenster_y&,fenster_w&,fenster_h&
' GLOBAL fenster_info$,fenster_name$
'
' ***** Subroutinen ************************************************************
'
' Hauptprogramm
'
' PROCEDURE lies_inf_datei
' PROCEDURE objektauswertung(&)
' PROCEDURE lies_dialogbox
' PROCEDURE suche
' PROCEDURE ende
'
' FUNCTION anzeige$($)
' FUNCTION fund!($)
'
' Hilfsroutinen
'
' PROCEDURE bell
'
' FUNCTION path$($)
' FUNCTION name$($)
' FUNCTION dir_exist!($)
'
' ***** Variablen initialisieren ***********************************************
'
' Dateinamen fr INF-Datei einmalig ermitteln
'
inf_datei$=CHR$(GEMDOS(25)+65)+":"+DIR$(0)+"\DETEKTOR.INF"
'
' Ein Wial mit allen Schikanen
'
fenster_attr&=name_&+info_&+close_&+full_&+move_&+size_&+uparrow_&+dnarrow_&+vslide_&+lfarrow_&+rtarrow_&+hslide_&
'
fenster_name$=" Der Detektor "
fenster_info$=" Copyright (c) 1991 by Philip K”ster - GFA-BASIC 3.0"
'
' Erste Positionierung des Wials soll automatisch erfolgen
'
fenster_x&=-1
fenster_y&=-1
fenster_w&=-1
fenster_h&=-1
'
dialog_x&=-1
dialog_y&=-1
'
' ***** RSC-Datei lesen ********************************************************
'
DEFMOUSE 2
'
' 3 Kbyte reservieren
'
RESERVE FRE(0)-3072
'
' Resource einlesen
'
rsc!=(RSRC_LOAD("DETEKTOR.RSC")<>0)
'
IF rsc!
  ' Dialogadressen ermitteln
  '
  DIM dial_adr%(dialogboxen&-1)
  '
  FOR i&=0 TO dialogboxen&-1
    ~RSRC_GADDR(0,i&,dial_adr%(i&))
  NEXT i&
  '
  detektor_adr%=dial_adr%(dial_detektor&)
  suche_adr%=dial_adr%(dial_suche&)
ENDIF
'
DEFMOUSE 0
'
' ***** Accessory oder Programm? ***********************************************
'
appl_id&=APPL_INIT()
acc!=(appl_id&<>0)
'
IF acc!
  ' *** Steuerung fr Accessory ************************************************
  '
  ' Accessory in Menleiste eintragen
  '
  ~MENU_REGISTER(appl_id&,"  Der Detektor ")
  '
  ' Endlosschleife
  '
  DO
    ' Auf ac_open warten
    '
    REPEAT
      ~EVNT_MESAG(0)
    UNTIL MENU(1)=ac_open_&
    '
    IF rsc!
      ' INF-Datei noch nicht gelesen?
      '
      IF NOT inf!
        lies_inf_datei
      ENDIF
      '
      ' Wial ”ffnen
      '
      wial_open(fenster_attr&,V:fenster_name$,V:fenster_info$,detektor_adr%,fenster_handle&,fenster_x&,fenster_y&,fenster_w&,fenster_h&,dialog_x&,dialog_y&)
      '
      IF fenster_handle&>0
        REPEAT
          ' Wial verwalten
          '
          wial_do(fenster_handle&,detektor_adr%,objekt&)
          '
          ' Objekt auswerten
          '
          objektauswertung(objekt&)
        UNTIL ende!
        '
        ' Kein Programmende
        '
        ende!=FALSE
      ELSE
        ' Kein Fenster mehr frei
        '
        bell
        ~FORM_ALERT(1,alert$(1))
      ENDIF
    ELSE
      ' RSC-Datei nicht gelesen
      '
      bell
      ~FORM_ALERT(1,alert$(0))
    ENDIF
  LOOP
ELSE
  ' *** Steuerung fr Programm *************************************************
  '
  IF rsc!
    ' INF-Datei lesen
    '
    lies_inf_datei
    '
    ' Wial ”ffnen
    '
    wial_open(fenster_attr&,V:fenster_name$,V:fenster_info$,detektor_adr%,fenster_handle&,fenster_x&,fenster_y&,fenster_w&,fenster_h&,dialog_x&,dialog_y&)
    '
    IF fenster_handle&>0
      REPEAT
        ' Wial verwalten
        '
        wial_do(fenster_handle&,detektor_adr%,objekt&)
        '
        ' Objekt auswerten
        '
        objektauswertung(objekt&)
      UNTIL ende!
    ELSE
      ' Kein Fenster mehr frei
      '
      bell
      ~FORM_ALERT(1,alert$(1))
    ENDIF
  ELSE
    ' RSC-Datei nicht gelesen
    '
    bell
    ~FORM_ALERT(1,alert$(0))
  ENDIF
  '
  ' Programm beenden
  '
  ende
ENDIF
'
' ***** Prozedur wial_open: Fenster ”ffnen, Dialogbox positionieren ************
'
PROCEDURE wial_open(wind_attr&,wind_name_adr%,wind_info_adr%,dial_adr%,VAR wind_handle&,wind_x&,wind_y&,wind_w&,wind_h&,dial_x&,dial_y&)
  LOCAL dial_w&,dial_h&,dummy&,work_x&,work_y&,work_w&,work_h&
  '
  ' Fensterausdehnung bestimmen
  '
  ~WIND_CALC(wc_border_&,wind_attr&,OB_X(dial_adr%,0),OB_Y(dial_adr%,0),OB_W(dial_adr%,0),OB_H(dial_adr%,0),dummy&,dummy&,wind_w_max&,wind_h_max&)
  '
  wind_w_max&=MIN(w_max&,wind_w_max&)
  wind_h_max&=MIN(h_max&-wind_y_min&,wind_h_max&)
  '
  IF wind_x&=-1 AND wind_y&=-1 AND wind_w&=-1 AND wind_h&=-1
    ' Fenster auf Maximalgr”že und zentrieren
    '
    wind_x&=(w_max& DIV 2)-(wind_w_max& DIV 2)
    wind_y&=((h_max&-wind_y_min&) DIV 2)-(wind_h_max& DIV 2)+wind_y_min&
    wind_w&=wind_w_max&
    wind_h&=wind_h_max&
    '
    ' Bildschirm nicht berschreiten
    '
    ~RC_INTERSECT(0,wind_y_min&,w_max&,h_max&-wind_y_min&,wind_x&,wind_y&,wind_w&,wind_h&)
  ELSE
    ' Minimale Koordinaten nicht unterschreiten
    '
    wind_x&=MAX(0,wind_x&)
    wind_y&=MAX(wind_y_min&,wind_y&)
    '
    ' Maximale Koordinaten nicht berschreiten
    '
    wind_x&=MIN(x_max&,wind_x&)
    wind_y&=MIN(y_max&,wind_y&)
    '
    ' Minimale Gr”že nicht unterschreiten
    '
    wind_w&=MAX(wind_w_min&,wind_w&)
    wind_h&=MAX(wind_h_min&,wind_h&)
    '
    ' Maximale Gr”že nicht berschreiten
    '
    wind_w&=MIN(wind_w_max&,wind_w&)
    wind_h&=MIN(wind_h_max&,wind_h&)
  ENDIF
  '
  ' Fenster anmelden
  '
  wind_handle&=WIND_CREATE(wind_attr&,0,0,0,0) !wind_x&,wind_y&,wind_w&,wind_h&)
  '
  ' Hat geklappt?
  '
  IF wind_handle&>0
    IF wind_name_adr%
      ' Namen setzen
      '
      ~WIND_SET(wind_handle&,wf_name_&,wind_name_adr% DIV 65536,wind_name_adr% MOD 65536,dummy&,dummy&)
    ENDIF
    '
    IF wind_info_adr%
      ' Info setzen
      '
      ~WIND_SET(wind_handle&,wf_info_&,wind_info_adr% DIV 65536,wind_info_adr% MOD 65536,dummy&,dummy&)
    ENDIF
    '
    ' Fenster ”ffnen
    '
    ~GRAF_GROWBOX(0,wind_y_min&,0,0,wind_x&,wind_y&,wind_w&,wind_h&)
    ~WIND_OPEN(wind_handle&,wind_x&,wind_y&,wind_w&,wind_h&)
    '
    ' Dialogbox positionieren
    '
    dial_w&=OB_W(dial_adr%,0)
    dial_h&=OB_H(dial_adr%,0)
    '
    ~WIND_GET(wind_handle&,wf_workxywh_&,work_x&,work_y&,work_w&,work_h&)
    '
    IF dial_x&=-1 AND dial_y&=-1
      ' Dialogbox an Ursprung des Arbeitsbereichs setzen
      '
      dial_x&=work_x&
      dial_y&=work_y&
    ELSE
      ' Ggf. Lage der Dialogbox korrigieren
      '
      dial_x&=MIN(work_x&,dial_x&)
      dial_x&=MAX(work_x&+work_w&-dial_w&,dial_x&)
      '
      dial_y&=MIN(work_y&,dial_y&)
      dial_y&=MAX(work_y&+work_h&-dial_h&,dial_y&)
    ENDIF
    '
    OB_X(dial_adr%,0)=dial_x&
    OB_Y(dial_adr%,0)=dial_y&
    '
    ' Schieber initialisieren
    '
    wial_set_sliders(wind_handle&,dial_adr%)
  ENDIF
RETURN
'
' ***** Prozedur wial_close: Fenster schliežen, Koordinaten zurckliefern ******
'
PROCEDURE wial_close(wind_handle&,dial_adr%,VAR wind_x&,wind_y&,wind_w&,wind_h&,dial_x&,dial_y&)
  ' Ausdehnung des Fensters ...
  '
  ~WIND_GET(wind_handle&,wf_currxywh_&,wind_x&,wind_y&,wind_w&,wind_h&)
  '
  ' ... und Lage der Dialogbox ermitteln
  '
  dial_x&=OB_X(dial_adr%,0)
  dial_y&=OB_Y(dial_adr%,0)
  '
  ' Fenster schliežen und abmelden
  '
  ~WIND_CLOSE(wind_handle&)
  ~GRAF_SHRINKBOX(0,wind_y_min&,0,0,wind_x&,wind_y&,wind_w&,wind_h&)
  '
  ~WIND_DELETE(wind_handle&)
RETURN
'
' ***** Prozedur wial_do: Ggf. Cursor initialisieren, Ereignisse abwarten ******
'
PROCEDURE wial_do(wind_handle&,dial_adr%,VAR object&)
  LOCAL exit!
  LOCAL clicks&,dummy&,event&,i&,key&,mouse_x&,mouse_y&
  '
  ' Edierbares Objekt suchen
  '
  editable!=FALSE
  '
  FOR i&=OB_HEAD(dial_adr%,0) TO OB_TAIL(dial_adr%,0)
    IF OB_FLAGS(dial_adr%,i&) AND editable_&
      editable!=TRUE
      '
      ' Cursor noch nicht initialisiert oder Cursor-Objekt nicht mehr editable?
      '
      IF (cursor_x&=0 AND cursor_y&=0) OR (OB_FLAGS(dial_adr%,cursor_y&) AND editable_&)=0
        cursor_x&=32767
        cursor_y&=i&
      ENDIF
      '
      ' ob_spec-Informationen beschaffen
      '
      te_ptext$=CHAR{{OB_SPEC(dial_adr%,cursor_y&)}}
      te_pundo$=te_ptext$
      te_ptmplt$=CHAR{{OB_SPEC(dial_adr%,cursor_y&)+4}}
      te_pvalid$=CHAR{{OB_SPEC(dial_adr%,cursor_y&)+8}}
      '
      ' Ggf. Cursorposition korrigieren
      '
      cursor_x&=MIN(LEN(te_ptext$),cursor_x&)
    ENDIF
    '
    EXIT IF editable!
  NEXT i&
  '
  ' Edierbare Objekte?
  '
  IF editable!
    ' Cursor einschalten und zeichnen
    '
    cursor!=TRUE
    wial_draw_work(wind_handle&,dial_adr%,dummy&,-1,-1,-1,-1,-1)
  ENDIF
  '
  REPEAT
    ' Ereignis abwarten
    '
    event&=EVNT_MULTI(mu_keybd_&+mu_button_&+mu_mesag_&,2,1,1,dummy&,dummy&,dummy&,dummy&,dummy&,dummy&,dummy&,dummy&,dummy&,dummy&,0,dummy&,mouse_x&,mouse_y&,dummy&,dummy&,key&,clicks&)
    '
    ' Nachrichtenereignis?
    '
    IF event& AND mu_mesag_&
      SELECT MENU(1)
      CASE ac_open_&
        ' Da das Fenster zu diesem Zeitpunkt ge”ffnet sein muž, gengt wf_top
        '
        ~WIND_SET(wind_handle&,wf_top_&,dummy&,dummy&,dummy&,dummy&)
        '
      CASE ac_close_&
        ' Diese Meldung sendet GEM zu jedem Programmstart bzw. -ende aus
        '
        wial_close(wind_handle&,dial_adr%,dummy&,dummy&,dummy&,dummy&,dummy&,dummy&)
        exit!=TRUE
        '
      DEFAULT !Fensterereignis
        ' Richtiges Fenster ist angesprochen?
        '
        IF MENU(4)=wind_handle&
          wial_wind_do(wind_handle&,dial_adr%,object&,exit!)
        ENDIF
      ENDSELECT
    ENDIF
    '
    ' Dialogereignis?
    '
    IF (event& AND mu_keybd_&) OR (event& AND mu_button_&)
      wial_dial_do(wind_handle&,dial_adr%,event&,mouse_x&,mouse_y&,key&,clicks&,object&,exit!)
    ENDIF
  UNTIL exit!
  '
  ' Edierbare Objekte?
  '
  IF editable!
    ' Cursor l”schen und ausschalten
    '
    wial_draw_work(wind_handle&,dial_adr%,dummy&,-1,-1,-1,-1,-1)
    cursor!=FALSE
  ENDIF
RETURN
'
' ***** Prozedur wial_wind_do: Fensterereignis auswerten ***********************
'
PROCEDURE wial_wind_do(wind_handle&,dial_adr%,VAR object&,exit!)
  LOCAL dial_x&,dial_y&,dial_w&,dial_h&,dial_x_new&,dial_y_new&,dummy&,rect_x&
  LOCAL rect_y&,rect_w&,rect_h&,wind_x&,wind_y&,wind_w&,wind_h&,work_x&,work_y&
  LOCAL work_w&,work_h&,x_scroll&,y_scroll&
  '
  ' Arbeits- und Gesamtbereich des Fensters ermitteln
  '
  ~WIND_GET(wind_handle&,wf_workxywh_&,work_x&,work_y&,work_w&,work_h&)
  ~WIND_GET(wind_handle&,wf_currxywh_&,wind_x&,wind_y&,wind_w&,wind_h&)
  '
  ' Ausdehnung der Dialogbox ermitteln
  '
  dial_x&=OB_X(dial_adr%,0)
  dial_y&=OB_Y(dial_adr%,0)
  dial_w&=OB_W(dial_adr%,0)
  dial_h&=OB_H(dial_adr%,0)
  '
  SELECT MENU(1)
  CASE wm_redraw_&
    ' Fensterausschnitt(e) zeichnen
    '
    ' Erstes Rechteck aus Liste
    '
    ~WIND_GET(wind_handle&,wf_firstxywh_&,rect_x&,rect_y&,rect_w&,rect_h&)
    '
    WHILE rect_w&>0 AND rect_h&>0
      ' Rechteck schneidet zu zeichnenden Bereich?
      '
      IF RC_INTERSECT(MENU(5),MENU(6),MENU(7),MENU(8),rect_x&,rect_y&,rect_w&,rect_h&)
        wial_draw_work(wind_handle&,dial_adr%,0,max_depth_&,rect_x&,rect_y&,rect_w&,rect_h&)
      ENDIF
      '
      ' N„chstes Rechteck aus Liste
      '
      ~WIND_GET(wind_handle&,wf_nextxywh_&,rect_x&,rect_y&,rect_w&,rect_h&)
    WEND
    '
  CASE wm_topped_&
    ' Fenster aktivieren
    '
    ~WIND_SET(wind_handle&,wf_top_&,dummy&,dummy&,dummy&,dummy&)
    '
  CASE wm_closed_&
    ' Kontrolle an Hauptprogramm zurckgeben
    '
    object&=-22
    exit!=TRUE
    '
  CASE wm_fulled_&
    ' Fenster vergr”žern oder verkleinern
    '
    IF wind_w&<wind_w_max& OR wind_h&<wind_h_max&
      ' Fenster auf Maximalgr”že
      '
      ~GRAF_GROWBOX(wind_x&,wind_y&,wind_w&,wind_h&,wind_x&,wind_y&,wind_w_max&,wind_h_max&)
      ~WIND_SET(wind_handle&,wf_currxywh_&,wind_x&,wind_y&,wind_w_max&,wind_h_max&)
      ~WIND_GET(wind_handle&,wf_workxywh_&,work_x&,work_y&,work_w&,work_h&)
      '
      ' Ggf. Dialogbox verschieben
      '
      OB_X(dial_adr%,0)=MAX(dial_x&,work_x&+work_w&-dial_w&)
      OB_Y(dial_adr%,0)=MAX(dial_y&,work_y&+work_h&-dial_h&)
    ELSE
      IF wind_w_old&=0 AND wind_h_old&=0
        ' Fenster auf Minimalgr”že
        '
        wind_w_old&=wind_w_min&
        wind_h_old&=wind_h_min&
      ENDIF
      '
      ' Fenster auf vorherige Gr”že
      '
      ~WIND_SET(wind_handle&,wf_currxywh_&,wind_x&,wind_y&,wind_w_old&,wind_h_old&)
      ~GRAF_SHRINKBOX(wind_x&,wind_y&,wind_w_old&,wind_h_old&,wind_x&,wind_y&,wind_w&,wind_h&)
    ENDIF
    '
    wial_set_sliders(wind_handle&,dial_adr%)
    '
  CASE wm_arrowed_&
    ' Ggf. Dialogbox verschieben
    '
    ' Scroll-Abst„nde festsetzen
    '
    x_scroll&=8
    '
    IF h_max&<400
      y_scroll&=8
    ELSE
      y_scroll&=16
    ENDIF
    '
    SELECT MENU(5)
    CASE 0 !Seite nach oben
      wial_scroll(wind_handle&,dial_adr%,0,MIN(work_y&-dial_y&,work_h&))
      '
    CASE 1 !Seite nach unten
      wial_scroll(wind_handle&,dial_adr%,0,-MIN((dial_y&+dial_h&)-(work_y&+work_h&),work_h&))
      '
    CASE 2 !Zeile nach oben
      IF dial_y&<work_y&
        wial_scroll(wind_handle&,dial_adr%,0,MIN(work_y&-dial_y&,y_scroll&))
      ENDIF
      '
    CASE 3 !Zeile nach unten
      IF dial_y&+dial_h&>work_y&+work_h&
        wial_scroll(wind_handle&,dial_adr%,0,-MIN((dial_y&+dial_h&)-(work_y&+work_h&),y_scroll&))
      ENDIF
      '
    CASE 4 !Seite nach links
      wial_scroll(wind_handle&,dial_adr%,MIN(work_x&-dial_x&,work_w&),0)
      '
    CASE 5 !Seite nach rechts
      wial_scroll(wind_handle&,dial_adr%,-MIN((dial_x&+dial_w&)-(work_x&+work_w&),work_w&),0)
      '
    CASE 6 !Spalte nach links
      IF dial_x&<work_x&
        wial_scroll(wind_handle&,dial_adr%,MIN(work_x&-dial_x&,x_scroll&),0)
      ENDIF
      '
    CASE 7 !Spalte nach rechts
      IF dial_x&+dial_w&>work_x&+work_w&
        wial_scroll(wind_handle&,dial_adr%,-MIN((dial_x&+dial_w&)-(work_x&+work_w&),x_scroll&),0)
      ENDIF
    ENDSELECT
    '
  CASE wm_hslid_&
    ' Horizontaler Schieber
    '
    dial_x_new&=ROUND(work_x&-(MENU(5)*(dial_w&-work_w&)/1000))
    '
    IF dial_x_new&<>dial_x&
      wial_scroll(wind_handle&,dial_adr%,dial_x_new&-dial_x&,0)
    ENDIF
    '
  CASE wm_vslid_&
    ' Vertikaler Schieber
    '
    dial_y_new&=ROUND(work_y&-(MENU(5)*(dial_h&-work_h&)/1000))
    '
    IF dial_y_new&<>dial_y&
      wial_scroll(wind_handle&,dial_adr%,0,dial_y_new&-dial_y&)
    ENDIF
    '
  CASE wm_sized_&
    ' Fenster auf neue Gr”že setzen, neuen Arbeitsbereich ermitteln
    '
    wind_w&=MIN(wind_w_max&,MENU(7))
    wind_w&=MAX(wind_w_min&,wind_w&)
    '
    wind_h&=MIN(wind_h_max&,MENU(8))
    wind_h&=MAX(wind_h_min&,wind_h&)
    '
    ~WIND_SET(wind_handle&,wf_currxywh_&,MENU(5),MENU(6),wind_w&,wind_h&)
    ~WIND_GET(wind_handle&,wf_workxywh_&,work_x&,work_y&,work_w&,work_h&)
    '
    ' Ggf. Dialogbox verschieben
    '
    OB_X(dial_adr%,0)=MAX(dial_x&,work_x&+work_w&-dial_w&)
    OB_Y(dial_adr%,0)=MAX(dial_y&,work_y&+work_h&-dial_h&)
    '
    IF wind_w&<wind_w_max& OR wind_h&<wind_h_max&
      ' Fenstergr”že merken
      '
      wind_w_old&=wind_w&
      wind_h_old&=wind_h&
    ENDIF
    '
    wial_set_sliders(wind_handle&,dial_adr%)
    '
  CASE wm_moved_&
    ' Fenster ...
    '
    ~WIND_SET(wind_handle&,wf_currxywh_&,MENU(5),MENU(6),MENU(7),MENU(8))
    '
    ' ... mitsamt Dialogbox verschieben
    '
    OB_X(dial_adr%,0)=dial_x&+MENU(5)-wind_x&
    OB_Y(dial_adr%,0)=dial_y&+MENU(6)-wind_y&
  ENDSELECT
RETURN
'
' ***** Prozedur wial_dial_do: Dialogereignis auswerten ************************
'
PROCEDURE wial_dial_do(wind_handle&,dial_adr%,event&,mouse_x&,mouse_y&,key&,clicks&,VAR object&,exit!)
  LOCAL jumped!,valid!
  LOCAL counter&,cursor_y_old&,distance&,dummy&,graf_x&,graf_y&,i&,ob_default&
  LOCAL ob_flags&,ob_mother&,ob_next&,ob_state&,ob_type&,ob_x&,ob_y&,ob_w&,ob_h&
  LOCAL valid&,work_x&,work_y&,work_w&,work_h&,x&,y&,w&,h&
  LOCAL ascii$,valid$
  '
  ' Arbeitsbereich des Fensters ermitteln
  '
  ~WIND_GET(wind_handle&,wf_workxywh_&,work_x&,work_y&,work_w&,work_h&)
  '
  ' Ereignisart feststellen
  '
  IF event& AND mu_keybd_&
    ' Tastaturereignis
    '
    IF BYTE(key&)=13 !Return, Enter
      ' Default-Objekt suchen
      '
      FOR i&=OB_HEAD(dial_adr%,0) TO OB_TAIL(dial_adr%,0)
        IF OB_FLAGS(dial_adr%,i&) AND default_&
          ob_default&=i&
        ENDIF
        '
        EXIT IF ob_default&
      NEXT i&
      '
      ' Default-Objekt existiert?
      '
      IF ob_default&
        ' Default-Objekt selektieren
        '
        OB_STATE(dial_adr%,ob_default&)=OB_STATE(dial_adr%,ob_default&) OR selected_&
        '
        ~OBJC_OFFSET(dial_adr%,ob_default&,x&,y&)
        w&=OB_W(dial_adr%,ob_default&)
        h&=OB_H(dial_adr%,ob_default&)
        '
        wial_draw_work(wind_handle&,dial_adr%,ob_default&,max_depth_&,x&,y&,w&,h&)
        '
        ' Objekt bergeben
        '
        object&=ob_default&
        '
        ' Immer exit
        '
        exit!=TRUE
      ENDIF
    ELSE
      ' Edierbare Objekte?
      '
      IF editable!
        ' Cursor l”schen und ausschalten
        '
        wial_draw_work(wind_handle&,dial_adr%,dummy&,-1,-1,-1,-1,-1)
        cursor!=FALSE
        '
        ' Cursor-Objekt merken
        '
        cursor_y_old&=cursor_y&
        '
        ' Tastencode auswerten
        '
        SELECT key&
        CASE 283 !Escape
          ' Zeile l”schen
          '
          te_ptext$=""
          cursor_x&=0
          '
        CASE 18488 !Shift + Cursor hoch
          ' Erstes edierbares Objekt suchen
          '
          cursor_y&=0
          '
          FOR i&=OB_HEAD(dial_adr%,0) TO OB_TAIL(dial_adr%,0)
            IF OB_FLAGS(dial_adr%,i&) AND editable_&
              cursor_y&=i&
            ENDIF
            '
            EXIT IF cursor_y&
          NEXT i&
          '
        CASE 20530 !Shift + Cursor runter
          ' Letztes edierbares Objekt suchen
          '
          cursor_y&=0
          '
          FOR i&=OB_TAIL(dial_adr%,0) DOWNTO OB_HEAD(dial_adr%,i&)
            IF OB_FLAGS(dial_adr%,i&) AND editable_&
              cursor_y&=i&
            ENDIF
            '
            EXIT IF cursor_y&
          NEXT i&
          '
        CASE 18432 !Cursor hoch
          ' Niedrigeres edierbares Objekt suchen
          '
          IF cursor_y&>OB_HEAD(dial_adr%,0)
            FOR i&=cursor_y&-1 DOWNTO OB_HEAD(dial_adr%,0)
              IF OB_FLAGS(dial_adr%,i&) AND editable_&
                cursor_y&=i&
              ENDIF
              '
              EXIT IF cursor_y&<>cursor_y_old&
            NEXT i&
          ENDIF
          '
        CASE 20480 !Cursor runter
          ' H”heres edierbares Objekt suchen
          '
          IF cursor_y&<OB_TAIL(dial_adr%,0)
            FOR i&=cursor_y&+1 TO OB_TAIL(dial_adr%,0)
              IF OB_FLAGS(dial_adr%,i&) AND editable_&
                cursor_y&=i&
              ENDIF
              '
              EXIT IF cursor_y&<>cursor_y_old&
            NEXT i&
          ENDIF
          '
        CASE 19252 !Shift + Cursor links
          ' Cursor an Zeilenanfang
          '
          cursor_x&=0
          '
        CASE 19766 !Shift + Cursor rechts
          ' Cursor an Zeilenende
          '
          cursor_x&=LEN(te_ptext$)
          '
        CASE 19200 !Cursor links
          ' Cursor nach links
          '
          cursor_x&=MAX(0,cursor_x&-1)
          '
        CASE 19712 !Cursor rechts
          ' Cursor nach rechts
          '
          cursor_x&=MIN(LEN(te_ptext$),cursor_x&+1)
          '
        CASE 3592 !Backspace
          ' Zeichen vor Cursor l”schen
          '
          IF cursor_x&
            te_ptext$=LEFT$(te_ptext$,cursor_x&-1)+MID$(te_ptext$,cursor_x&+1)
            DEC cursor_x&
          ENDIF
          '
        CASE 21375 !Delete
          ' Zeichen an Cursor l”schen
          '
          te_ptext$=LEFT$(te_ptext$,cursor_x&)+MID$(te_ptext$,cursor_x&+2)
          '
        CASE 24832 !Undo
          ' Alten String wiederherstellen
          '
          te_ptext$=te_pundo$
          cursor_x&=LEN(te_ptext$)
          '
        DEFAULT
          ' Zeicheneingabe
          '
          ascii$=CHR$(BYTE(key&))
          '
          ' te_pvalid-Zeichen ermitteln
          '
          valid$=MID$(te_pvalid$,MIN(LEN(te_pvalid$),cursor_x&+1),1)
          valid&=INSTR("9AaNnfFpPX",valid$)-1
          '
          ' Datei- oder Pfadname?
          '
          IF valid&>4 AND valid&<9
            ' Nur Grožbuchstaben
            '
            ascii$=UPPER$(ascii$)
          ENDIF
          '
          ' te_pvalid-Zeichen ist bekannt?
          '
          IF valid&>-1
            ' Eingegebenes Zeichen ist erlaubt?
            '
            IF INSTR(te_pmask$(valid&),ascii$)
              valid!=TRUE
            ENDIF
          ENDIF
          '
          IF valid!
            ' Zeichen ist gltig
            '
            ' Zeichen verarbeiten
            '
            IF cursor_x&<LEN(te_pvalid$)
              ' Cursor steht in Eingabefeld
              '
              ' Neuen String ermitteln und ggf. krzen
              '
              te_ptext$=LEFT$(te_ptext$,cursor_x&)+ascii$+MID$(te_ptext$,cursor_x&+1)
              te_ptext$=LEFT$(te_ptext$,LEN(te_pvalid$))
              '
              INC cursor_x&
            ELSE
              ' Cursor steht hinter Eingabefeld
              '
              ' Nur letztes Zeichen setzen
              '
              MID$(te_ptext$,LEN(te_ptext$),1)=ascii$
            ENDIF
          ELSE
            ' Zeichen ist nicht gltig
            '
            ' Ggf. hinter Zeichen aus te_ptmplt springen
            '
            FOR i&=1 TO LEN(te_ptmplt$)
              IF MID$(te_ptmplt$,i&,1)="_"
                ' Z„hler erh”hen
                '
                INC counter&
              ELSE IF MID$(te_ptmplt$,i&,1)=ascii$
                ' Zeichen steht hinter Cursor?
                '
                IF counter&>cursor_x&
                  ' Leerzeichen einfgen, Zeile ab Cursor l”schen
                  '
                  te_ptext$=LEFT$(te_ptext$,cursor_x&)+SPACE$(counter&-cursor_x&)
                  cursor_x&=counter&
                  '
                  jumped!=TRUE
                ENDIF
              ENDIF
              '
              ' Nur h”chstens einmal springen
              '
              EXIT IF jumped!
            NEXT i&
          ENDIF
        ENDSELECT
        '
        ' Neues Cursor-Objekt?
        '
        IF cursor_y&<>cursor_y_old&
          ' ob_spec-Informationen beschaffen
          '
          te_ptext$=CHAR{{OB_SPEC(dial_adr%,cursor_y&)}}
          te_pundo$=te_ptext$
          te_ptmplt$=CHAR{{OB_SPEC(dial_adr%,cursor_y&)+4}}
          te_pvalid$=CHAR{{OB_SPEC(dial_adr%,cursor_y&)+8}}
          '
          ' Ggf. Cursorposition korrigieren
          '
          cursor_x&=MIN(LEN(te_ptext$),cursor_x&)
        ENDIF
        '
        ' Cursorkoordinaten berechnen
        '
        wial_calc_cursor(dial_adr%,graf_x&,graf_y&)
        '
        ' Scrolling erforderlich?
        '
        IF graf_x&<work_x&
          ' Nach links
          '
          wial_scroll(wind_handle&,dial_adr%,work_x&-graf_x&,0)
        ENDIF
        '
        IF graf_x&+cursor_w&>work_x&+work_w&
          ' Nach rechts
          '
          wial_scroll(wind_handle&,dial_adr%,(work_x&+work_w&)-(graf_x&+cursor_w&),0)
        ENDIF
        '
        IF graf_y&<work_y&
          ' Nach oben
          '
          wial_scroll(wind_handle&,dial_adr%,0,work_y&-graf_y&)
        ENDIF
        '
        IF graf_y&+cursor_h&>work_y&+work_h&
          ' Nach unten
          '
          wial_scroll(wind_handle&,dial_adr%,0,(work_y&+work_h&)-(graf_y&+cursor_h&))
        ENDIF
        '
        ' te_ptext ge„ndert?
        '
        IF te_ptext$<>CHAR{{OB_SPEC(dial_adr%,cursor_y&)}}
          CHAR{{OB_SPEC(dial_adr%,cursor_y&)}}=te_ptext$
          '
          ' Zu zeichnenden Bereich ermitteln ...
          '
          ~OBJC_OFFSET(dial_adr%,cursor_y&,x&,y&)
          w&=OB_W(dial_adr%,cursor_y&)
          h&=OB_H(dial_adr%,cursor_y&)
          '
          ' ... und Objekt zeichnen
          '
          wial_draw_work(wind_handle&,dial_adr%,cursor_y&,max_depth_&,x&,y&,w&,h&)
        ENDIF
        '
        ' Cursor einschalten und zeichnen
        '
        cursor!=TRUE
        wial_draw_work(wind_handle&,dial_adr%,dummy&,-1,-1,-1,-1,-1)
      ENDIF
    ENDIF
  ELSE
    ' Buttonereignis
    '
    IF RC_INTERSECT(mouse_x&,mouse_y&,1,1,work_x&,work_y&,work_w&,work_h&)
      ' Objekt suchen
      '
      object&=OBJC_FIND(dial_adr%,0,max_depth_&,mouse_x&,mouse_y&)
      '
      ' Informationen ber angeklicktes Objekt beschaffen
      '
      ob_type&=OB_TYPE(dial_adr%,object&)
      ob_flags&=OB_FLAGS(dial_adr%,object&)
      ob_state&=OB_STATE(dial_adr%,object&)
      '
      ~OBJC_OFFSET(dial_adr%,object&,ob_x&,ob_y&)
      ob_w&=OB_W(dial_adr%,object&)
      ob_h&=OB_H(dial_adr%,object&)
      '
      ' Objekt ist selectable?
      '
      IF ob_flags& AND selectable_&
        ' Objekt ist nicht disabled?
        '
        IF (ob_state& AND disabled_&)=0
          IF (ob_flags& AND rbutton_&)=0
            ' Kein Radiobutton
            '
            ' Warten, bis Mausbutton losgelassen
            '
            REPEAT
              IF OB_STATE(dial_adr%,object&)=ob_state&
                ' Warten, bis Maus innerhalb des Objekts
                '
                event&=EVNT_MULTI(mu_button_&+mu_m1_&,0,1,0,0,ob_x&,ob_y&,ob_w&,ob_h&,dummy&,dummy&,dummy&,dummy&,dummy&,0,dummy&,dummy&,dummy&,dummy&,dummy&,dummy&,dummy&)
              ELSE
                ' Warten, bis Maus aužerhalb des Objekts
                '
                event&=EVNT_MULTI(mu_button_&+mu_m1_&,0,1,0,1,ob_x&,ob_y&,ob_w&,ob_h&,dummy&,dummy&,dummy&,dummy&,dummy&,0,dummy&,dummy&,dummy&,dummy&,dummy&,dummy&,dummy&)
              ENDIF
              '
              IF event& AND mu_m1_&
                ' selected-Bit tauschen
                '
                OB_STATE(dial_adr%,object&)=OB_STATE(dial_adr%,object&) XOR selected_&
                wial_draw_work(wind_handle&,dial_adr%,object&,max_depth_&,ob_x&,ob_y&,ob_w&,ob_h&)
              ENDIF
            UNTIL event& AND mu_button_&
          ELSE
            ' Radiobutton
            '
            ' Mutterobjekt ermitteln
            '
            ob_next&=object&
            '
            REPEAT
              ob_next&=OB_NEXT(dial_adr%,ob_next&)
            UNTIL ob_next&<object&
            '
            ob_mother&=ob_next&
            '
            ' Objekt ist nicht selected?
            '
            IF (ob_state& AND selected_&)=0
              ' Alle Radiobuttons deselektieren
              '
              FOR i&=OB_HEAD(dial_adr%,ob_mother&) TO OB_TAIL(dial_adr%,ob_mother&)
                IF OB_FLAGS(dial_adr%,i&) AND rbutton_&
                  IF OB_STATE(dial_adr%,i&) AND selected_&
                    OB_STATE(dial_adr%,i&)=OB_STATE(dial_adr%,i&) AND NOT selected_&
                    '
                    ~OBJC_OFFSET(dial_adr%,i&,x&,y&)
                    w&=OB_W(dial_adr%,i&)
                    h&=OB_H(dial_adr%,i&)
                    '
                    wial_draw_work(wind_handle&,dial_adr%,i&,max_depth_&,x&,y&,w&,h&)
                  ENDIF
                ENDIF
              NEXT i&
              '
              ' Angeklickten Radiobutton selektieren
              '
              OB_STATE(dial_adr%,object&)=ob_state& OR selected_&
              wial_draw_work(wind_handle&,dial_adr%,object&,max_depth_&,ob_x&,ob_y&,ob_w&,ob_h&)
              '
              ' Warten, bis Mausbutton losgelassen
              '
              ~EVNT_BUTTON(0,1,0)
            ENDIF
          ENDIF
        ENDIF
      ENDIF
      '
      ' Edierbares Objekt angeklickt?
      '
      IF ob_flags& AND editable_&
        ' Cursor l”schen
        '
        wial_draw_work(wind_handle&,dial_adr%,dummy&,-1,-1,-1,-1,-1)
        '
        ' Cursor-Objekt merken
        '
        cursor_y_old&=cursor_y&
        '
        ' Ggf. neues Cursorobjekt festlegen
        '
        cursor_y&=object&
        '
        ' Neues Cursor-Objekt?
        '
        IF cursor_y&<>cursor_y_old&
          ' ob_spec-Informationen beschaffen
          '
          te_ptext$=CHAR{{OB_SPEC(dial_adr%,cursor_y&)}}
          te_pundo$=te_ptext$
          te_ptmplt$=CHAR{{OB_SPEC(dial_adr%,cursor_y&)+4}}
          te_pvalid$=CHAR{{OB_SPEC(dial_adr%,cursor_y&)+8}}
        ENDIF
        '
        ' x-Position des Cursors bestimmen
        '
        distance&=(mouse_x&-ob_x&) DIV cursor_w&
        cursor_x&=0
        '
        FOR i&=0 TO distance&-1
          IF MID$(te_ptmplt$,i&+1,1)="_"
            INC cursor_x&
          ENDIF
        NEXT i&
        '
        ' Ggf. Cursor korrigieren
        '
        cursor_x&=MIN(LEN(te_ptext$),cursor_x&)
        '
        ' Cursor zeichnen
        '
        wial_draw_work(wind_handle&,dial_adr%,dummy&,-1,-1,-1,-1,-1)
      ENDIF
      '
      ' Objekt ist exit?
      '
      IF ob_flags& AND exit_&
        ' Nur exit, wenn Objekt selektiert
        '
        IF OB_STATE(dial_adr%,object&) AND selected_&
          exit!=TRUE
        ENDIF
      ENDIF
      '
      ' Objekt ist touchexit?
      '
      IF ob_flags& AND touchexit_&
        ' Doppelklick?
        '
        IF clicks&=2
          ' 15. Bit setzen
          '
          INT{V:object&}=BSET(object&,15)
        ENDIF
        '
        ' Immer exit
        '
        exit!=TRUE
      ENDIF
    ENDIF
  ENDIF
RETURN
'
' ***** Prozedur wial_scroll: Arbeitsbereich intelligent scrollen **************
'
PROCEDURE wial_scroll(wind_handle&,dial_adr%,move_x&,move_y&)
  LOCAL dest_x&,dest_y&,draw_x&,draw_y&,draw_w&,draw_h&,srce_x&,srce_y&,srce_w&
  LOCAL srce_h&,work_x&,work_y&,work_w&,work_h&
  '
  ' Dialogbox verschieben
  '
  OB_X(dial_adr%,0)=OB_X(dial_adr%,0)+move_x&
  OB_Y(dial_adr%,0)=OB_Y(dial_adr%,0)+move_y&
  '
  ' Arbeitsbereich des Fensters ermitteln
  '
  ~WIND_GET(wind_handle&,wf_workxywh_&,work_x&,work_y&,work_w&,work_h&)
  '
  ' Zielkoordinaten und potentielles Quellraster ermitteln
  '
  dest_x&=MAX(work_x&,work_x&+move_x&)
  dest_y&=MAX(work_y&,work_y&+move_y&)
  '
  srce_x&=MAX(work_x&,work_x&-move_x&)
  srce_y&=MAX(work_y&,work_y&-move_y&)
  srce_w&=MIN(w_max&-dest_x&,work_w&-ABS(move_x&))
  srce_h&=MIN(h_max&-dest_y&,work_h&-ABS(move_y&))
  '
  ' Zu zeichnenden Bereich initialisieren
  '
  draw_x&=-1
  draw_y&=-1
  draw_w&=-1
  draw_h&=-1
  '
  ' Quellraster schneidet Arbeitsbereich?
  '
  IF RC_INTERSECT(work_x&,work_y&,work_w&,work_h&,srce_x&,srce_y&,srce_w&,srce_h&)
    ' Quellraster schneidet Bildschirm?
    '
    IF RC_INTERSECT(0,0,w_max&,h_max&,srce_x&,srce_y&,srce_w&,srce_h&)
      ' Kopieren
      '
      RC_COPY XBIOS(2),srce_x&,srce_y&,srce_w&,srce_h& TO XBIOS(2),dest_x&,dest_y&
      '
      ' Zu zeichnenden Bereich neu berechnen
      '
      IF move_x&
        ' Horizontale Verschiebung
        '
        IF move_x&<0
          draw_x&=work_x&+srce_w&
        ELSE
          draw_x&=work_x&
        ENDIF
        '
        draw_y&=work_y&
        draw_w&=work_w&-srce_w&
        draw_h&=work_h&
      ELSE
        ' Vertikale Verschiebung
        '
        IF move_y&<0
          draw_y&=work_y&+srce_h&
        ELSE
          draw_y&=work_y&
        ENDIF
        '
        draw_x&=work_x&
        draw_w&=work_w&
        draw_h&=work_h&-srce_h&
      ENDIF
    ENDIF
  ENDIF
  '
  ' Ausschnitt der Dialogbox zeichnen
  '
  wial_draw_work(wind_handle&,dial_adr%,0,max_depth_&,draw_x&,draw_y&,draw_w&,draw_h&)
  '
  ' Schieber setzen
  '
  wial_set_sliders(wind_handle&,dial_adr%)
RETURN
'
' ***** Prozedur wial_draw_work: Dialogbox und ggf. Cursor zeichnen ************
'
PROCEDURE wial_draw_work(wind_handle&,dial_adr%,object&,depth&,draw_x&,draw_y&,draw_w&,draw_h&)
  LOCAL graf_x&,graf_y&,graf_w&,graf_h&,work_x&,work_y&,work_w&,work_h&
  '
  ~WIND_UPDATE(beg_update_&)
  '
  ' Arbeitsbereich des Fensters ...
  '
  ~WIND_GET(wind_handle&,wf_workxywh_&,work_x&,work_y&,work_w&,work_h&)
  '
  ' ... und zu zeichnenden Bereich ermitteln
  '
  IF draw_x&=-1 AND draw_y&=-1 AND draw_w&=-1 AND draw_h&=-1
    ' Gesamten Arbeitsbereich zeichnen
    '
    draw_x&=work_x&
    draw_y&=work_y&
    draw_w&=work_w&
    draw_h&=work_h&
  ELSE
    ' Arbeitsbereich nicht berschreiten
    '
    ~RC_INTERSECT(work_x&,work_y&,work_w&,work_h&,draw_x&,draw_y&,draw_w&,draw_h&)
  ENDIF
  '
  ' Zu zeichnender Bereich ist sichtbar?
  '
  IF RC_INTERSECT(0,0,w_max&,h_max&,draw_x&,draw_y&,draw_w&,draw_h&)
    ' Ausschnitt der Dialogbox zeichnen?
    '
    IF depth&>-1
      ~OBJC_DRAW(dial_adr%,object&,depth&,draw_x&,draw_y&,draw_w&,draw_h&)
    ENDIF
    '
    ' Edierbare Objekte?
    '
    IF editable!
      ' Cursor ist eingeschaltet?
      '
      IF cursor!
        ' Graffikkoordinaten des Cursors ermitteln
        '
        wial_calc_cursor(dial_adr%,graf_x&,graf_y&)
        '
        ' Cursor schneidet zu zeichnenden Bereich?
        '
        graf_w&=cursor_w&
        graf_h&=cursor_h&
        '
        IF RC_INTERSECT(draw_x&,draw_y&,draw_w&,draw_h&,graf_x&,graf_y&,graf_w&,graf_h&)
          ' Cursor zeichnen (Grafikeinstellungen werden ver„ndert!)
          '
          BOUNDARY 0
          DEFFILL 1,1
          GRAPHMODE 3
          '
          CLIP  OFFSET graf_x&,graf_y&
          PBOX 0,0,graf_w&-1,graf_h&-1
        ENDIF
      ENDIF
    ENDIF
  ENDIF
  '
  ~WIND_UPDATE(end_update_&)
RETURN
'
' ***** Prozedur wial_set_sliders: Schieber berechnen und setzen ***************
'
PROCEDURE wial_set_sliders(wind_handle&,dial_adr%)
  LOCAL dial_x&,dial_y&,dial_w&,dial_h&,dummy&,work_x&,work_y&,work_w&,work_h&
  '
  ' Arbeitsbereich des Fensters ...
  '
  ~WIND_GET(wind_handle&,wf_workxywh_&,work_x&,work_y&,work_w&,work_h&)
  '
  ' ... und Ausdehnung der Dialogbox ermitteln
  '
  dial_x&=OB_X(dial_adr%,0)
  dial_y&=OB_Y(dial_adr%,0)
  dial_w&=OB_W(dial_adr%,0)
  dial_h&=OB_H(dial_adr%,0)
  '
  ' Horizontalen ...
  '
  ~WIND_SET(wind_handle&,wf_hslide_&,ROUND((work_x&-dial_x&)/(dial_w&-work_w&+0.1)*1000),dummy&,dummy&,dummy&)
  ~WIND_SET(wind_handle&,wf_hslize_&,ROUND((work_w&/dial_w&)*1000),dummy&,dummy&,dummy&)
  '
  ' ... und vertikalen Schieber setzen
  '
  ~WIND_SET(wind_handle&,wf_vslide_&,ROUND((work_y&-dial_y&)/(dial_h&-work_h&+0.1)*1000),dummy&,dummy&,dummy&)
  ~WIND_SET(wind_handle&,wf_vslize_&,ROUND((work_h&/dial_h&)*1000),dummy&,dummy&,dummy&)
RETURN
'
' ***** Prozedur wial_calc_cursor: Cursorkoordinaten berechnen *****************
'
PROCEDURE wial_calc_cursor(dial_adr%,VAR graf_x&,graf_y&)
  LOCAL counter&,i&
  '
  ~OBJC_OFFSET(dial_adr%,cursor_y&,graf_x&,graf_y&)
  '
  ' Ggf. x-Koordinate erh”hen
  '
  FOR i&=1 TO LEN(te_ptmplt$)
    IF MID$(te_ptmplt$,i&,1)="_"
      INC counter&
    ENDIF
    '
    EXIT IF counter&=cursor_x&+1
  NEXT i&
  '
  ADD graf_x&,(i&-1)*cursor_w&
RETURN
'
' ***** Prozedur lies_inf_datei: INF-Datei lesen, Dialogbox initialisieren *****
'
PROCEDURE lies_inf_datei
  LOCAL i&
  '
  DEFMOUSE 2
  '
  ' INF-Datei existiert?
  '
  IF EXIST(inf_datei$)
    ' INF-Datei lesen
    '
    OPEN "I",#1,inf_datei$
    '
    LINE INPUT #1,suche$
    LINE INPUT #1,nicht$
    INPUT #1,wort!
    INPUT #1,beachten!
    '
    FOR i&=0 TO 3
      LINE INPUT #1,masken$(i&)
    NEXT i&
    '
    INPUT #1,drucker!
    INPUT #1,parallel!
    INPUT #1,datei!
    INPUT #1,dmp_datei$
    '
    CLOSE #1
  ELSE
    ' Standardeinstellungen vornehmen
    '
    drucker!=TRUE
    parallel!=TRUE
    '
    datei!=FALSE
    dmp_datei$=CHR$(GEMDOS(25)+65)+":\DETEKTOR.DMP"
  ENDIF
  '
  ' Dialogbox initialisieren
  '
  CHAR{{OB_SPEC(detektor_adr%,3)}}=suche$
  CHAR{{OB_SPEC(detektor_adr%,4)}}=nicht$
  '
  IF wort!
    OB_STATE(detektor_adr%,5)=selected_&
  ENDIF
  '
  IF beachten!
    OB_STATE(detektor_adr%,7)=selected_&
  ENDIF
  '
  FOR i&=0 TO 3
    CHAR{{OB_SPEC(detektor_adr%,11+i&)}}=masken$(i&)
  NEXT i&
  '
  IF drucker!
    OB_STATE(detektor_adr%,17)=selected_&
  ENDIF
  '
  IF parallel!
    CHAR{{OB_SPEC(detektor_adr%,18)}}="Drucker (parallel)"
  ELSE
    CHAR{{OB_SPEC(detektor_adr%,18)}}="Drucker (seriell) "
  ENDIF
  '
  IF datei!
    OB_STATE(detektor_adr%,19)=selected_&
  ENDIF
  '
  CHAR{{OB_SPEC(detektor_adr%,20)}}="Datei: "+@anzeige$(dmp_datei$)
  '
  inf!=TRUE
  '
  DEFMOUSE 0
RETURN
'
' ***** Prozedur objektauswertung: Objektbergabe von wial_do auswerten ********
'
PROCEDURE objektauswertung(objekt&)
  LOCAL unsinnig!
  LOCAL button&,i&
  LOCAL pfad$,name$
  '
  ' Applikation bernimmt Mauskontrolle
  '
  ~WIND_UPDATE(beg_mctrl_&)
  '
  ' Objektnummer auswerten
  '
  SELECT SGN(objekt&)*BYTE(ABS(objekt&))
  CASE -22 !Schliežfeld
    ' Wial schliežen
    '
    wial_close(fenster_handle&,detektor_adr%,fenster_x&,fenster_y&,fenster_w&,fenster_h&,dialog_x&,dialog_y&)
    ende!=TRUE
    '
  CASE 17 !Drucker-Button
    drucker!=NOT drucker!
    '
    IF drucker!
      ' Nur max. ein Ausgabeger„t
      '
      datei!=FALSE
    ELSE
      ' Button deselektieren
      '
      OB_STATE(detektor_adr%,17)=0
      wial_draw_work(fenster_handle&,detektor_adr%,17,0,-1,-1,-1,-1)
    ENDIF
    '
  CASE 18 !Drucker-Port
    parallel!=NOT parallel!
    '
    ' Objekt neu beschriften und zeichnen
    '
    IF parallel!
      CHAR{{OB_SPEC(detektor_adr%,18)}}="Drucker (parallel)"
    ELSE
      CHAR{{OB_SPEC(detektor_adr%,18)}}="Drucker (seriell) "
    ENDIF
    '
    wial_draw_work(fenster_handle&,detektor_adr%,18,0,-1,-1,-1,-1)
    '
  CASE 19 !Datei-Button
    datei!=NOT datei!
    '
    IF datei!
      ' Datei ausw„hlen
      '
      pfad$=@path$(dmp_datei$)+"*.*"
      LET name$=@name$(dmp_datei$)
      '
      ~FSEL_INPUT(pfad$,name$,button&)
      '
      ' OK angeklickt, Dateinamen angegeben und Pfad existiert?
      '
      pfad$=@path$(pfad$)
      '
      IF button&=1 AND LEN(name$)>0 AND @dir_exist(pfad$)
        ' Dateinamen „ndern
        '
        dmp_datei$=@path$(pfad$)+name$
        '
        CHAR{{OB_SPEC(detektor_adr%,20)}}="Datei: "+@anzeige$(dmp_datei$)
        wial_draw_work(fenster_handle&,detektor_adr%,20,0,-1,-1,-1,-1)
      ELSE
        IF NOT @dir_exist(pfad$)
          ' Pfad existiert nicht
          '
          bell
          ~FORM_ALERT(1,alert$(2))
        ENDIF
        '
        datei!=FALSE
      ENDIF
    ENDIF
    '
    ' Button bleibt selektiert?
    '
    IF datei!
      ' Nur max. ein Ausgabeger„t
      '
      drucker!=FALSE
    ELSE
      IF drucker!
        ' Drucker-Button wieder selektieren
        '
        OB_STATE(detektor_adr%,17)=selected_&
        wial_draw_work(fenster_handle&,detektor_adr%,17,0,-1,-1,-1,-1)
      ENDIF
      '
      ' Button deselektieren
      '
      OB_STATE(detektor_adr%,19)=0
      wial_draw_work(fenster_handle&,detektor_adr%,19,0,-1,-1,-1,-1)
    ENDIF
    '
  CASE 21 !Sichern-Button
    ' Dialogbox auslesen
    '
    lies_dialogbox
    '
    ' INF-Datei schreiben
    '
    DEFMOUSE 2
    '
    OPEN "O",#1,inf_datei$
    '
    PRINT #1,suche$
    PRINT #1,nicht$
    PRINT #1,wort!
    PRINT #1,beachten!
    '
    FOR i&=0 TO 3
      PRINT #1,masken$(i&)
    NEXT i&
    '
    PRINT #1,drucker!
    PRINT #1,parallel!
    PRINT #1,datei!
    PRINT #1,dmp_datei$
    '
    CLOSE #1
    '
    DEFMOUSE 0
    '
    ' Button deselektieren
    '
    OB_STATE(detektor_adr%,21)=0
    wial_draw_work(fenster_handle&,detektor_adr%,21,0,-1,-1,-1,-1)
    '
  CASE 22 !Start-Button
    ' Dialogbox auslesen
    '
    lies_dialogbox
    '
    ' Kein Suchausdruck angegeben?
    '
    IF suche$=""
      bell
      ~FORM_ALERT(1,alert$(3))
      '
      unsinnig!=TRUE
    ENDIF
    '
    ' Negativer Suchausdruck ohne Bezug?
    '
    IF LEN(nicht$)
      IF INSTR(nicht$,"[...]")=0
        bell
        ~FORM_ALERT(1,alert$(4))
        '
        unsinnig!=TRUE
      ENDIF
    ENDIF
    '
    ' Keine Dateimaske?
    '
    IF masken$=""
      bell
      ~FORM_ALERT(1,alert$(5))
      '
      unsinnig!=TRUE
    ENDIF
    '
    ' Keine unsinnigen Eingaben?
    '
    IF NOT unsinnig!
      ' Suche starten
      '
      suche
    ENDIF
    '
    ' Button deselektieren
    '
    OB_STATE(detektor_adr%,22)=0
    wial_draw_work(fenster_handle&,detektor_adr%,22,0,-1,-1,-1,-1)
  ENDSELECT
  '
  ' Applikation gibt Mauskontrolle wieder ab
  '
  ~WIND_UPDATE(end_mctrl_&)
RETURN
'
' ***** Prozedur lies_dialogbox: Dialogbox auslesen ****************************
'
PROCEDURE lies_dialogbox
  LOCAL i&
  '
  suche$=CHAR{{OB_SPEC(detektor_adr%,3)}}
  nicht$=CHAR{{OB_SPEC(detektor_adr%,4)}}
  '
  wort!=(OB_STATE(detektor_adr%,5)=selected_&)
  beachten!=(OB_STATE(detektor_adr%,7)=selected_&)
  '
  masken$=""
  '
  FOR i&=0 TO 3
    masken$(i&)=UPPER$(CHAR{{OB_SPEC(detektor_adr%,11+i&)}})
    masken$=masken$+masken$(i&)
  NEXT i&
RETURN
'
' ***** Prozedur suche: Suche durchfhren **************************************
'
PROCEDURE suche
  LOCAL abbruch!,dateiname!,springen!
  LOCAL alert&,balken&,dummy&,instr&,maus_x&,maus_y&,maus_k&,stellen&
  LOCAL suchergebnis&,x&,y&,w&,h&,zeichen&
  LOCAL bytes%,dateien%,fundstellen%,zaehler%,zeile%
  LOCAL ablage$,datei$,info$,maske$,puffer$,zeile$
  '
  ' Zuallererst Anzahl der zu untersuchenden Dateien ermitteln
  '
  DEFMOUSE 2
  '
  ablage$=masken$
  '
  WHILE LEN(ablage$)
    ' Maske aus String holen
    '
    instr&=INSTR(ablage$,",")
    '
    IF instr&
      maske$=LEFT$(ablage$,instr&-1)
      ablage$=MID$(ablage$,instr&+1)
    ELSE
      maske$=ablage$
      ablage$=""
    ENDIF
    '
    ' Dateien suchen
    '
    suchergebnis&=FSFIRST(maske$,&X100111) !Keine Diskettenlabels und Ordner
    '
    WHILE suchergebnis&=0
      ' Datei ist nicht die ge”ffnete Dump-Datei?
      '
      IF NOT (datei! AND @path$(maske$)+CHAR{FGETDTA()+30}=dmp_datei$)
        ' Z„hler erh”hen
        '
        INC dateien%
      ENDIF
      '
      suchergebnis&=FSNEXT()
    WEND
  WEND
  '
  DEFMOUSE 0
  '
  IF dateien%
    ' Ggf. Ausgabeger„t ”ffnen
    '
    IF drucker!
      ' Drucker ist nicht bereit?
      '
      IF parallel!
        ' Parallele Schnittstelle
        '
        WHILE (NOT OUT?(0)) AND (NOT abbruch!)
          bell
          IF FORM_ALERT(2,alert$(6))=1
            abbruch!=TRUE
          ENDIF
        WEND
        '
        IF NOT abbruch!
          OPEN "O",#2,"LST:"
        ENDIF
      ELSE
        ' Serielle Schnittselle
        '
        WHILE (NOT OUT?(1)) AND (NOT abbruch!)
          bell
          IF FORM_ALERT(2,alert$(6))=1
            abbruch!=TRUE
          ENDIF
        WEND
        '
        IF NOT abbruch!
          OPEN "O",#2,"AUX:"
        ENDIF
      ENDIF
    ENDIF
    '
    IF datei!
      OPEN "O",#2,dmp_datei$
    ENDIF
    '
    IF NOT abbruch!
      DEFMOUSE 2
      '
      ' Stellen fr numerische Ausgabe berechnen
      '
      stellen&=INT(LOG10(MAX(1,dateien%)))+1
      '
      ' Ausmaže der Dialogbox ermitteln
      '
      ~FORM_CENTER(suche_adr%,x&,y&,w&,h&)
      '
      ' Korrektur fr Umrahmung
      '
      DEC x&
      DEC y&
      ADD w&,2
      ADD h&,2
      '
      ' Dialogbox initialisieren ...
      '
      CHAR{OB_SPEC(suche_adr%,5)}=suche$ !Suchausdruck
      CHAR{{OB_SPEC(suche_adr%,8)}}=""   !Datei
      CHAR{{OB_SPEC(suche_adr%,11)}}=""  !Bytes
      CHAR{{OB_SPEC(suche_adr%,14)}}="0" !Fundstellen
      OB_STATE(suche_adr%,15)=0          !ESC
      '
      ' ... und zeichnen
      '
      ~FORM_DIAL(fmd_start_&,dummy&,dummy&,dummy&,dummy&,x&,y&,w&,h&)
      ~OBJC_DRAW(suche_adr%,0,2,0,0,w_max&,h_max&)
      '
      ' Suchen
      '
      ' Ggf. Suchinformationen ausgeben
      '
      IF drucker! OR datei!
        PRINT #2,DATE$;" - ";TIME$
        PRINT #2
        PRINT #2,"Der Detektor (Version 1.0)"
        PRINT #2,"Copyright (c) 1991 by Philip K”ster - GFA-BASIC 3.0"
        PRINT #2
        PRINT #2,STRING$(79,"*")
        PRINT #2
        PRINT #2,"     Suche: ";suche$
        PRINT #2,"Aber nicht: ";nicht$
        PRINT #2
        '
        info$="[ ] als Wort  [ ] Grož- und Kleinschreibung beachten"
        '
        IF wort!
          MID$(info$,2,1)="X"
        ENDIF
        '
        IF beachten!
          MID$(info$,16,1)="X"
        ENDIF
        '
        PRINT #2,info$
        PRINT #2
        PRINT #2,STRING$(79,"*")
      ENDIF
      '
      ablage$=masken$
      '
      WHILE LEN(ablage$)
        ' Maske aus String holen
        '
        instr&=INSTR(ablage$,",")
        '
        IF instr&
          maske$=LEFT$(ablage$,instr&-1)
          ablage$=MID$(ablage$,instr&+1)
        ELSE
          maske$=ablage$
          ablage$=""
        ENDIF
        '
        ' Dateien suchen
        '
        suchergebnis&=FSFIRST(maske$,&X100111) !Keine Diskettenlabels und Ordner
        '
        WHILE suchergebnis&=0
          ' Dateinamen und -l„nge ermitteln
          '
          datei$=@path$(maske$)+CHAR{FGETDTA()+30}
          bytes%={FGETDTA()+26}
          '
          ' Datei ist nicht die ge”ffnete Dump-Datei?
          '
          IF NOT (datei! AND datei$=dmp_datei$)
            ' Z„hler erh”hen
            '
            INC zaehler%
            '
            ' Dateinamen und -l„nge anzeigen
            '
            CHAR{{OB_SPEC(suche_adr%,8)}}=@anzeige$(datei$)+" ("+STR$(zaehler%,stellen&)+"/"+STR$(dateien%,stellen&)+")"
            ~OBJC_DRAW(suche_adr%,8,0,0,0,w_max&,h_max&)
            '
            CHAR{{OB_SPEC(suche_adr%,11)}}=STR$(bytes%,10)+" Bytes"
            ~OBJC_DRAW(suche_adr%,11,0,0,0,w_max&,h_max&)
            '
            ' Rahmen zeichnen, Balken initialisieren
            '
            ~OBJC_DRAW(suche_adr%,9,0,0,0,w_max&,h_max&)
            OB_W(suche_adr%,10)=0
            '
            ' Datei durchsuchen
            '
            OPEN "I",#1,datei$
            '
            dateiname!=FALSE
            zeile%=0
            '
            WHILE (NOT EOF(#1)) OR LEN(puffer$)
              ' Speicherplatz ist knapp?
              '
              IF FRE()<4096
                ' Speicher aur„umen
                '
                ~FRE(0)
              ENDIF
              '
              ' Anzahl der zu lesenden Zeichen ermitteln und an Puffer anh„ngen
              '
              zeichen&=MIN(LOF(#1)-LOC(#1),256-LEN(puffer$))
              puffer$=puffer$+INPUT$(zeichen&,#1)
              '
              ' Form Feed in Puffer enthalten?
              '
              instr&=INSTR(puffer$,CHR$(13)+CHR$(10))
              '
              SELECT instr&
              CASE 0 !Kein Form Feed
                ' Puffer in Zeile kopieren
                '
                zeile$=puffer$
                puffer$=""
                '
              CASE 1 !Form Feed am Anfang
                ' Zeile ist Leerstring
                '
                zeile$=""
                puffer$=MID$(puffer$,3)
                '
              DEFAULT !Form Feed irgendwo
                ' Trennen
                '
                zeile$=LEFT$(puffer$,instr&-1)
                puffer$=MID$(puffer$,instr&+2)
              ENDSELECT
              '
              ' Zeilennummer erh”hen
              '
              INC zeile%
              '
              ' Zeile ist Fundstelle?
              '
              IF @fund(zeile$)
                ' Z„hler erh”hen und anzeigen
                '
                INC fundstellen%
                '
                CHAR{{OB_SPEC(suche_adr%,14)}}=STR$(fundstellen%)
                ~OBJC_DRAW(suche_adr%,14,0,0,0,w_max&,h_max&)
                '
                ' Ggf. Informationen ausgeben
                '
                IF drucker! OR datei!
                  IF NOT dateiname!
                    ' Dateinamen ausgeben
                    '
                    PRINT #2
                    PRINT #2,datei$
                    PRINT #2,STRING$(LEN(datei$),"-")
                    PRINT #2
                    '
                    dateiname!=TRUE
                  ENDIF
                  '
                  ' Zeilennummer und Zeile ausgeben
                  '
                  PRINT #2,"Zeile "+STR$(zeile%,10)+":"
                  '
                  ' Zeilentext ist um zwei Zeichen eingerckt
                  '
                  WHILE LEN(zeile$)
                    IF LEN(zeile$)>77
                      PRINT #2,"  ";LEFT$(zeile$,77)
                      zeile$=MID$(zeile$,78)
                    ELSE
                      PRINT #2,"  ";zeile$
                      zeile$=""
                    ENDIF
                  WEND
                ENDIF
              ENDIF
              '
              ' Neue Balkenbreite ermitteln
              '
              balken&=INT(320*(LOC(#1)/LOF(#1)))
              '
              ' N„chstes Intervall erreicht?
              '
              IF (OB_W(suche_adr%,10) DIV 32)<>(balken& DIV 32)
                ' Balkenbreite setzen
                '
                OB_W(suche_adr%,10)=balken&
                '
                IF balken&=0
                  ' Rahmen zeichnen
                  '
                  ~OBJC_DRAW(suche_adr%,9,0,0,0,w_max&,h_max&)
                ELSE
                  ' Balken zeichnen
                  '
                  ~OBJC_DRAW(suche_adr%,10,0,0,0,w_max&,h_max&)
                ENDIF
              ENDIF
              '
              ' Esc gedrckt?
              '
              IF INKEY$=CHR$(27)
                abbruch!=TRUE
              ENDIF
              '
              ' Linke Maustaste gedrckt?
              '
              ~GRAF_MKSTATE(maus_x&,maus_y&,maus_k&,dummy&)
              '
              IF maus_k&=1
                ' ESC-Button angeklickt?
                '
                IF OBJC_FIND(suche_adr%,0,max_depth_&,maus_x&,maus_y&)=15
                  abbruch!=TRUE
                ENDIF
              ENDIF
              '
              ' Abbruch?
              '
              IF abbruch!
                ' Button selektieren
                '
                OB_STATE(suche_adr%,15)=selected_&
                ~OBJC_DRAW(suche_adr%,15,0,0,0,w_max&,h_max&)
                '
                ' Warten, bis Mausbutton losgelassen
                '
                ~EVNT_BUTTON(0,1,0)
                '
                ' Weitere Vorgehensweise?
                '
                bell
                alert&=FORM_ALERT(1,alert$(7))
                '
                ' Nicht Abbruch angeklickt?
                '
                IF alert&<>1
                  abbruch!=FALSE
                  '
                  ' Button deselektieren
                  '
                  OB_STATE(suche_adr%,15)=0
                  ~OBJC_DRAW(suche_adr%,15,0,0,0,w_max&,h_max&)
                  '
                  ' Springen?
                  '
                  IF alert&=2
                    springen!=TRUE
                  ENDIF
                ENDIF
              ENDIF
              '
              EXIT IF abbruch! OR springen!
            WEND
            '
            CLOSE #1
          ENDIF
          '
          ' Nur einmal springen
          '
          springen!=FALSE
          '
          ' N„chste Datei suchen
          '
          suchergebnis&=FSNEXT()
          '
          EXIT IF abbruch!
        WEND
        '
        EXIT IF abbruch!
      WEND
      '
      ' Ggf. Statistik ausgeben und Ausgabeger„t schliežen
      '
      IF drucker! OR datei!
        PRINT #2
        PRINT #2,STRING$(79,"*")
        PRINT #2
        PRINT #2,zaehler%;" von ";dateien%;" Dateien untersucht, ";fundstellen%;" Fundstelle(n)."
        '
        CLOSE #2
      ENDIF
      '
      DEFMOUSE 0
      '
      ' Suche ist beendet
      '
      CHAR{{OB_SPEC(suche_adr%,14)}}=STR$(fundstellen%)+", Suche beendet (Taste)"
      ~OBJC_DRAW(suche_adr%,14,0,0,0,w_max&,h_max&)
      '
      ' Auf Tastendruck warten
      '
      bell
      ~EVNT_KEYBD()
      '
      ' Dialogbox vom Bildschirm entfernen
      '
      ~FORM_DIAL(fmd_finish_&,dummy&,dummy&,dummy&,dummy&,x&,y&,w&,h&)
    ENDIF
  ELSE
    ' Keine Dateien gefunden
    '
    bell
    ~FORM_ALERT(1,alert$(8))
  ENDIF
RETURN
'
' ***** Prozedur ende: Speicher freigeben, Programm beenden ********************
'
PROCEDURE ende
  ' Resource aus Speicher entfernen
  '
  ~RSRC_FREE()
  RESERVE
  '
  ' Als dann ...
  '
  ~APPL_EXIT()
  END
RETURN
'
' ***** Funktion anzeige$: Dateinamen fr Anzeige formatieren ******************
'
FUNCTION anzeige$(datei$)
  LOCAL instr&
  LOCAL anzeige$
  '
  ' Name
  '
  anzeige$=@name$(datei$)
  '
  ' Punkt in String enthalten?
  '
  instr&=INSTR(anzeige$,".")
  '
  IF instr&
    ' Acht Zeichen vor Punkt
    '
    anzeige$=LEFT$(anzeige$,instr&-1)+SPACE$(8-LEN(LEFT$(anzeige$,instr&-1)))+MID$(anzeige$,instr&)
  ENDIF
  '
  ' Ggf. Leerzeichen anfgen
  '
  anzeige$=anzeige$+SPACE$(12-LEN(anzeige$))
  '
  ' Laufwerk vorweg
  '
  anzeige$=LEFT$(datei$)+":"+anzeige$
  '
  RETURN anzeige$
ENDFUNC
'
' ***** Funktion fund: Zeile ist Fundstelle? ***********************************
'
FUNCTION fund(zeile$)
  $F%
  '
  LOCAL fehler!
  LOCAL ascii&,i&,instr&
  LOCAL pos_ausdruck$,neg_ausdruck$,test$
  '
  ' Suche initialisieren
  '
  IF beachten!
    test$=zeile$
  ELSE
    test$=UPPER$(zeile$)
  ENDIF
  '
  ' Zeile durchsuchen
  '
  WHILE LEN(test$)
    fehler!=FALSE
    '
    ' Positiven Suchausdruck ermitteln
    '
    IF beachten!
      ' Grož- und Kleinschreibung beachten
      '
      pos_ausdruck$=suche$
      neg_ausdruck$=nicht$
    ELSE
      ' Nicht beachten
      '
      pos_ausdruck$=UPPER$(suche$)
      neg_ausdruck$=UPPER$(nicht$)
    ENDIF
    '
    instr&=INSTR(test$,pos_ausdruck$)
    '
    IF instr&
      ' Zeile enth„lt positiven Suchausdruck
      '
      ' Als Wort?
      '
      IF wort!
        ' Zeichen links von Suchausdruck ermitteln
        '
        IF instr&>1
          ascii&=ASC(MID$(test$,instr&-1,1))
        ELSE
          ascii&=0
        ENDIF
        '
        IF ascii&>32
          fehler!=TRUE
        ENDIF
        '
        IF NOT fehler!
          ' Zeichen rechts von Suchausdruck ermitteln
          '
          ascii&=ASC(MID$(test$,instr&+LEN(pos_ausdruck$),1))
          '
          IF ascii&>32
            fehler!=TRUE
          ENDIF
        ENDIF
      ENDIF
      '
      IF NOT fehler!
        ' Negativer Suchausdruck angegeben?
        '
        IF LEN(neg_ausdruck$)
          ' Als Wort?
          '
          IF wort!
            ' Ggf. positiven Suchausdruck erweitern
            '
            FOR i&=instr&+LEN(pos_ausdruck$) TO LEN(test$)
              ' Ggf. rechts erweitern
              '
              ascii&=ASC(MID$(test$,i&,1))
              '
              IF ascii&<33
                pos_ausdruck$=pos_ausdruck$+CHR$(ascii&)
              ENDIF
              '
              EXIT IF ascii&>32
            NEXT i&
            '
            FOR i&=instr&-1 DOWNTO 1
              ' Ggf. links erweitern
              '
              ascii&=ASC(MID$(test$,i&,1))
              '
              IF ascii&<33
                pos_ausdruck$=CHR$(ascii&)+pos_ausdruck$
              ENDIF
              '
              EXIT IF ascii&>32
            NEXT i&
          ENDIF
          '
          ' Bezug durch positiven Suchausdruck ersetzen
          '
          instr&=INSTR(neg_ausdruck$,"[...]")
          '
          neg_ausdruck$=LEFT$(neg_ausdruck$,instr&-1)+pos_ausdruck$+MID$(neg_ausdruck$,instr&+5)
          '
          ' Negativer Suchausdruck in Zeile enthalten?
          '
          IF INSTR(test$,neg_ausdruck$)
            fehler!=TRUE
          ENDIF
        ENDIF
      ENDIF
      '
      IF NOT fehler!
        ' Alle Suchbedingungen erfllt
        '
        RETURN TRUE
      ENDIF
      '
      ' Suche geht ggf. weiter
      '
      test$=MID$(test$,instr&+1)
    ELSE
      ' Zeile enth„lt positiven Suchausdruck nicht
      '
      ' Ende der Suche
      '
      test$=""
    ENDIF
  WEND
  '
  ' Nichts gefunden
  '
  RETURN FALSE
ENDFUNC
'
' ***** Prozedur bell: Klingelzeichen ausgeben *********************************
'
PROCEDURE bell
  PRINT CHR$(7);
RETURN
'
' ***** Funktion path$: Pfad aus Datei *****************************************
'
FUNCTION path$(file$)
  RETURN LEFT$(file$,RINSTR(file$,"\"))
ENDFUNC
'
' ***** Funktion name$: Name aus Datei *****************************************
'
FUNCTION name$(file$)
  RETURN MID$(file$,RINSTR(file$,"\")+1)
ENDFUNC
'
' ***** Funktion dir_exist: Prfen, ob Pfad existiert **************************
'
FUNCTION dir_exist(path$)
  $F%
  '
  IF LEN(path$)=3
    ' Laufwerk angeschlossen?
    '
    RETURN BTST(BIOS(10),ASC(UPPER$(path$))-65)
  ELSE
    ' Datei oder Ordner existiert?
    '
    RETURN (FSFIRST(path$+"*.*",-1)=0)
  ENDIF
ENDFUNC
'
' ******************************************************************************
