home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / ehp14cs.zip / se.c < prev    next >
Text File  |  1994-07-14  |  49KB  |  1,196 lines

  1. /****************************************************************/
  2. /*                                                              */
  3. /*      MODUL:  se.c                                            */
  4. /*                                                              */
  5. /*      FUNKTIONEN:                                             */
  6. /*              - ask_replace (fragen, ob ersetzen)             */
  7. /*              - upcase (Buchstabe in Grossbuchstabe wandeln)  */
  8. /*              - instr (String in Text?)                       */
  9. /*              - find (Begriff im Text suchen)                 */
  10. /*              - str_to_num (String in Zahl wandeln)           */
  11. /*              - o_to_vals (Optionen in Werte wandeln)         */
  12. /*              - do_repfr (Latztes Suchen/Ersetzen wiederh.)   */
  13. /*              - do_find (Suche ausfuehren)                    */
  14. /*              - trag_e_ein (Ersetzungsbegriff eintragen)      */
  15. /*              - flash_word (Wort zum Blinken bringen)         */
  16. /*              - unflash_word (Wort "entblinken")              */
  17. /*              - do_replace (Ersetzen ausfuehren)              */
  18. /*              - find_next_par (nächste Klammer in Cursorum    */
  19. /*                gebung finden)                                */
  20. /*              - search_match_par (passende Klammer finden)    */
  21. /*                                                              */
  22. /****************************************************************/
  23.  
  24. #include "defs.h"
  25. #include <ctype.h>
  26. #include "regex.h"
  27.  
  28. extern char *fastzeichen(int), *fastzeile(zeil_typ*);
  29. extern char space, regexflag;
  30. extern WINDOW *status;
  31. extern int ersetzaddr;
  32.  
  33. void do_find(), do_replace();
  34.  
  35. /* *** globale Daten und Initialisierung *** */
  36. static char sbegriff[256],    /* Suchbegriff                                 */
  37.         ebegriff[256],    /* Ersetzungsbegriff                           */
  38.         optionen[256];    /* String fuer Optioneneingabe                 */
  39. int         repeatflag=FALSE, /* Ist aktueller Vorgang eine Wiederholung ?   */
  40.         last_func=F_NONE; /* Art des letzten Vorgangs (Suchen, Ersetzen) */
  41.  
  42. unsigned char upcase();
  43.  
  44. /*****************************************************************************
  45. *
  46. *  Funktion       Fragen, ob ersetzt werden soll (ask_replace)
  47. *  --------
  48. *
  49. *  Ergebnis     :
  50. *                   Typ          : int char
  51. *                   Wertebereich : J/N/A
  52. *                   Bedeutung    : Eingelesenes Zeichen (upcase)
  53. *
  54. *  Beschreibung : Es wird ein Prompt im Statusfenster ausgegeben, das
  55. *                 der User durch Eingabe eines Zeichens beantworten kann.
  56. *                 Es sind nur die Zeichen j,J,y,Y,n,N,a,A zugelassen. Der
  57. *                 Rueckgabewert ist das Zeichen, jedoch auf jeden Fall
  58. *                 als Grossbuchstabe. (y,Y werden nach j,J konvertiert)
  59. *
  60. *****************************************************************************/
  61.  
  62. int ask_replace()
  63. {
  64.   /* *** interne Daten *** */
  65.   int antw; /* zum Einlesen eines Zeichens */
  66.  
  67.   print_stat(PROMPT_REPLYN);
  68.   do
  69.     antw = newwgetch(status); /* Zeichen vom Tastatur / Macro lesen */
  70.   while (!strchr ("jnJNyYAa",antw));
  71.   clear_stat();
  72.   if (strchr ("yY", antw)) /* Beantwortung mit Y(es) zulassen */
  73.     antw = 'J';
  74.   return(upcase(antw));
  75. }
  76.  
  77. /*****************************************************************************
  78. *
  79. *  Funktion       Buchstabe in Grossbuchstabe wandeln (upcase)
  80. *  --------
  81. *
  82. *  Parameter    : c         :
  83. *                   Typ          : unsigned char
  84. *                   Wertebereich : (char) 0 - (char) 255
  85. *                   Bedeutung    : Umzuwandelndes Zeichen
  86. *
  87. *  Ergebnis     :
  88. *                   Typ          : unsigned char
  89. *                   Wertebereich : (char) 0 - (char) 255
  90. *                   Bedeutung    : umgewandeltes Zeichen
  91. *
  92. *  Beschreibung : Falls das Zeichen ein Buchstabe ist, wird es in einen
  93. *                 Grossbuchstaben umgewandelt.
  94. *
  95. *****************************************************************************/
  96.  
  97. unsigned char upcase (c)        /* eee klappt nicht bei Umlauten und anderen
  98.                    fremdsprachigen Zeichen, z.B. é und É */
  99. register unsigned char c;
  100. {
  101.   return (isalpha(c)?toupper(c):c);
  102. }
  103.  
  104. /*****************************************************************************
  105. *
  106. *  Funktion       Text in String ? (instr)
  107. *  --------
  108. *
  109. *  Parameter    : begriff   :
  110. *                   Typ          : char*
  111. *                   Wertebereich : Pointer auf ASCII-Zeichenkette
  112. *                   Bedeutung    : String, nach dem gesucht wird
  113. *
  114. *                 zeile     :
  115. *                   Typ          : char*
  116. *                   Wertebereich : Pointer auf ASCII-Zeichenkette
  117. *                   Bedeutung    : Start des Strings, in dem gesucht wird.
  118. *                                  Beachte: Suche beginnt an durch screencol
  119. *                                  bestimmter Position
  120. *
  121. *                 ignore    :
  122. *                   Typ          : int
  123. *                   Wertebereich : TRUE, FALSE
  124. *                   Bedeutung    : TRUE : Gross-/Kleinschreibung ignorieren
  125. *
  126. *                 word      :
  127. *                   Typ          : int
  128. *                   Wertebereich : TRUE, FALSE
  129. *                   Bedeutung    : TRUE : Nur ganze Woerter finden
  130. *
  131. *                 richtung  :
  132. *                   Typ          : int
  133. *                   Wertebereich : TRUE, FALSE
  134. *                   Bedeutung    : TRUE : Vorwaerts suchen
  135. *                                  FALSE: Rueckwaerts suchen
  136. *
  137. *                 pat_buf   :
  138. *                   Typ          : struct re_pattern_buffer *
  139. *                   Wertebereich : Pointer auf regex-Puffer
  140. *                   Bedeutung    : Übersetztes Suchpattern oder NULL,
  141.                                   falls regex nicht verwendet werden soll.
  142. *
  143. *  Ergebnis     :
  144. *                   Typ          : int
  145. *                   Wertebereich : 0-MAXLENGTH
  146. *                   Bedeutung    : Länge des gematchten Textes
  147. *                                  0 bedeutet: nicht gefunden
  148. *
  149. *  Beschreibung : Die uebergebene Zeile wird auf den uebergebenen Suchstring
  150. *                 begriff untersucht. Dabei wird, falls das ignore-Flag TRUE
  151. *                 ist, die Gross-/Kleinschreibung ignoriert. In diesem Fall
  152. *                 muß der Suchbegriff komplett in Großbuchstaben vorliegen.
  153. *                 Im Fall des
  154. *                 Pattern-Matchings mit regex wird bei ignore-Flag=TRUE
  155. *                 vorausgesetzt, daß im übersetzten pat_buf die translate-
  156. *                 table auf eine entsprechende Umsetzung von Klein- auf
  157. *                 Großbuchstaben eingetragen ist.
  158. *                 Ist das Word-Flag gesetzt, so werden nur Suchbegriffe gefun-
  159. *                 den, die rechts und links entweder Zeilenanfang bzw. Zeilen-
  160. *                 ende oder einen Worttrenner haben.
  161. *                 zeile muß auf einen String ohne Unterstreichungen zeigen.
  162. *                 akt_winp->screencol wird angepaßt und steht bei einem
  163. *                 Treffer auf dessen Anfang. Wird kein Vorkommen gefunden,
  164. *                 so ist screencol undefiniert, jedoch innerhalb der Zeile.
  165. *
  166. *****************************************************************************/
  167.  
  168. int instr(begriff,zeile,ignore,word,richtung,pat_buf)
  169. register char *begriff;
  170. char *zeile;
  171. int  ignore,word,richtung;
  172. struct re_pattern_buffer *pat_buf;
  173. {
  174.   /* *** interne Daten und Initialisierung *** */
  175.   register int  beg_sc,               /* Zwischenspeicher Cursorspalte  */
  176.         len,                  /* Laenge des Suchbegriffs        */
  177.         index=0,              /* Index in aktuellen Suchbegriff */
  178.         match_len,            /* Länge des Matches (Return-Wert)*/
  179.         match_pos,            /* Position des gefundenen Strings*/
  180.         fr_ret;               /* Rueckgabewert von fastright    */
  181.   struct re_registers regs;           /* Register für Matching mit regu-*/
  182.                       /* lären Ausdrücken               */
  183.   register char *beg_start,           /* Position des Suchbegriffs in   */
  184.                       /* der Zeile (nur bei word)       */
  185.         *in_zeile;            /* Zeiger in String zeile         */
  186.  
  187.   if (!word)    /* Es muss kein abgeschlossenes Wort gefunden werden */
  188.   {
  189.     if (pat_buf)               /* Matching mit regulären Ausdrücken ? */
  190.     {
  191.       match_pos = re_search (pat_buf, zeile, strlen (zeile),
  192.                  akt_winp->screencol, 
  193.                  richtung ? strlen (zeile)-akt_winp->screencol
  194.                       : -akt_winp->screencol-1,
  195.                  ®s);
  196.       if (match_pos != -1)
  197.       {
  198.     match_len = re_match (pat_buf, zeile, strlen (zeile),
  199.                   match_pos, ®s); /* Musterlänge bestimmen */
  200.     akt_winp->screencol = match_pos; /* Position des Matches */
  201.       }
  202.       else
  203.     match_len = 0;
  204.       return match_len;
  205.     }
  206.     else /* Kein Pattern, normaler Text, dann zeichenweise vergleichen */
  207.     {
  208.       in_zeile = & (zeile [akt_winp->screencol]); /* Startposition bestimmen */
  209.       len = strlen (begriff);
  210.       do
  211.       {
  212.     if (ignore? /* Wird Gross-/Kleinschreibung ignoriert, dann upcase */
  213.     (upcase(*in_zeile) != begriff[index++]):(*in_zeile != begriff[index++]))
  214.     {
  215.       if ((in_zeile -= index-richtung) < zeile) /* Nicht gefunden, ein Zeichen  */
  216.       {                                     /* weiter rechts/links mit der  */
  217.         index = 0;                          /* Suche starten. Zeile zuende, */
  218.         break;                              /* dann do-while abbrechen      */
  219.       }
  220.       index = 0;      /* Im Suchbegriff wieder vorne beginnen */
  221.       if (!richtung)  /* Falls rueckwaerts gesucht wird, nicht mehr nach */
  222.         continue;     /* rechts, da Position 0 getestet werden muss.     */
  223.     }
  224.  
  225.  
  226.     if(!*++in_zeile) /* ein Zeichen nach rechts gehen, wenn am Zeilenende,*/
  227.       break;         /* dann Schleife abbrechen. */
  228.       } while (index < len); /* Solange suchen, bis Suchbegriff gefunden wurde */
  229.       if (index == len)     /* Wenn Suchbegriff gefunden wurde: */
  230.       {                               /* Zum Anfang des Suchbegriffs gehen */
  231.     /* Falls Suchbegriff am Zeilenende, */
  232.     akt_winp->screencol = (in_zeile-zeile)-len;
  233.     return len;                   /* klappte fastright nicht, also 1 */
  234.       }                               /* weniger nach links */
  235.       else                  /* Wurde Suchbegriff nicht gefunden, NULL zurueck */
  236.     return (0);
  237.     }
  238.   }
  239.   else          /* Es soll ein abgeschlossenes Wort gefunden werden */
  240.   {
  241.     while (1)
  242.     {
  243.       /* Durch rekursiven Aufruf Begriff zunaechst normal in der Zeile */
  244.       /* suchen. Wird er nicht gefunden, return(NULL), sonst testen,   */
  245.       /* ob Wortgrenzen vorhanden                                      */
  246.       if (match_len = instr(begriff,zeile,ignore,FALSE,richtung,pat_buf))
  247.       {
  248.     beg_sc = akt_winp->screencol;
  249.     if (!beg_sc || wortende(zeile [beg_sc-1])) /* Wortende oder */
  250.                            /* Zeilenende links ? */
  251.       if (!zeile [beg_sc+match_len] || wortende(zeile [beg_sc+match_len]))
  252.       /* Wenn hinter Suchbegriff Zeilen- oder Wortende */
  253.         return (match_len);   /* dann gefunden ! */
  254.     /* Es lag kein Wortende vor, Suche ein Z. weiter rechts/links */
  255.     if(richtung)
  256.     {
  257.       if (!zeile [++akt_winp->screencol]) /* Zeilenende ? */
  258.         return 0;
  259.     }
  260.     else
  261.       if (!akt_winp->screencol--)         /* Zeilenanfang ? */
  262.       {
  263.         akt_winp->screencol++;  /* Screencol wieder auf Zeilenanfang */
  264.         return 0;
  265.       }
  266.       }
  267.       else
  268.     return (0); /* Begriff in aktueller Zeile nicht gefunden  */
  269.     } /* Falls kein Wortende gefunden, nach erneutem Vorkommen suchen */
  270.   }
  271. }
  272.  
  273. /*****************************************************************************
  274. *
  275. *  Funktion       Begriff im Text suchen (find)
  276. *  --------
  277. *
  278. *  Parameter    : begriff   :
  279. *                   Typ          : char*
  280. *                   Wertebereich : Pointer auf ASCII-Zeichenkette
  281. *                   Bedeutung    : Suchbegriff
  282. *
  283. *                 richtung  :
  284. *                   Typ          : int
  285. *                   Wertebereich : TRUE, FALSE
  286. *                   Bedeutung    : TRUE : vorwaerts , FALSE : rueckwaerts
  287. *
  288. *                 ignore    :
  289. *                   Typ          : int
  290. *                   Wertebereich : TRUE, FALSE
  291. *                   Bedeutung    : Gross-/Kleinschreibung ignorieren
  292. *
  293. *                 word      :
  294. *                   Typ          : int
  295. *                   Wertebereich : TRUE, FALSE
  296. *                   Bedeutung    : Nur ganze Woerter finden
  297. *
  298. *                 start_line:
  299. *                   Typ          : int
  300. *                   Wertebereich : 0-MAX_ANZ_LINES
  301. *                   Bedeutung    : Nummer der Zeile, in der die Suche
  302. *                                  gestartet wurde.
  303. *
  304. *                 start_col :
  305. *                   Typ          : int
  306. *                   Wertebereich : 0-MAXLENGTH
  307. *                   Bedeutung    : Nummer der Spalte, in der die Suche
  308. *                                  gestartet wurde.
  309. *
  310. *                 count     :
  311. *                   Typ          : int*
  312. *                   Wertebereich : Pointer auf Integer
  313. *                   Bedeutung    : Wenn die Zeile, in der die Suche begann,
  314. *                                  schon durchsucht wurde, ist *count 0,
  315. *                                  sonst 1.
  316. *
  317. *                 akt_regex :
  318. *                   Typ          : int
  319. *                   Wertebereich : TRUE, FALSE
  320. *                   Bedeutung    : Gibt an, ob mit regex oder ohne gesucht
  321. *                                  werden soll.
  322. *
  323. *  Ergebnis     :
  324. *                   Typ          : int
  325. *                   Wertebereich : -1-MAXINT
  326. *                   Bedeutung    : Länge des gefundenen Matches
  327. *                                  0 bedeutet: Nicht gefunden
  328. *                                 -1 bedeutet: Fehler bei Patternübersetzung
  329. *
  330. *  Beschreibung : Es wird ab der aktuellen Position im Text nach dem ueber-
  331. *                 gebenen Begriff gesucht. Dabei werden die Parameter richtung,
  332. *                 ignore und word beruecksichtigt. Kommt man in der Zeile hinter
  333. *                 der aktuellen an und count ist 0, so wird die Suche beendet.
  334. *                 Findet man den Suchbegriff in der Zeile, in der die Suche
  335. *                 gestartet wurde, hinter der Startspalte, so wird 0
  336. *                 zurueckgegeben.
  337. *                 Die Suche innerhalb einer Zeile wird durch die Funktion instr
  338. *                 durchgefuehrt.
  339. *                 Beim ersten Aufruf von find() werden die statischen Kompo-
  340. *                 nenten, die im Zusammenhang mit dem Pattern-Matching mit
  341. *                 regex stehen, initialisiert.
  342. *
  343. ******************************************************************************/
  344.  
  345. int find(begriff,richtung,ignore,word,start_line,start_col,count,
  346.      akt_regex)
  347. register char *begriff;
  348. int  richtung,ignore,word,start_line,start_col,*count,akt_regex;
  349. {
  350.   /* *** interne Daten und Initialisierung *** */
  351. #define INIT_REGEX_BUF_SIZE 100               /* Initiale Puffergröße    */
  352.   char *zeile,                                /* Zeiger auf Puffer, in   */
  353.                           /* dem Inhalt der aktuellen*/
  354.                           /* Zeile ohne Unterstrei-  */
  355.                           /* chung steht.            */
  356.        *begr_p,                               /* Pointer in Suchbegriff  */
  357.        *comp_err=(char*) NULL;                /* Flag, ob beim Übersetzen*/
  358.                           /* des Patterns ein Fehler */
  359.                           /* auftrat                 */
  360.   register int  blen = strlen(begriff),       /* Laenge des Suchbegriffs */
  361.         old_sc = akt_winp->screencol, /* Alte Cursorspalte       */
  362.         old_line=akt_winp->textline,  /* Alte Cursorzeile        */
  363.         nsl=start_line+2*richtung-1;  /* erste Zeile, die nicht  */
  364.                           /* zweimal durchsucht wer- */
  365.                           /* den darf.               */
  366.   int           fl,      /* Laenge der aktuellen Zeile im screencol-Mass */
  367.         match_len, /* Länge des aktuellen Matches in der Zeile   */
  368.         i;       /* Zähler zur Initialisierung der transl.-Table */
  369.   static char   *old_begriff = NULL;   /* letzter Suchbegriff        */
  370.   static struct re_pattern_buffer buf; /* Puffer für Handling regex  */
  371.   static char   upper_translate [256], /* Translate table upper case */
  372.         fastmap_table   [256]; /* Fastmap für schnelle Suche */
  373.  
  374.   if (ignore)              /* Groß/Klein ignorieren? Dann alles groß */
  375.     for (begr_p = begriff; *begr_p; begr_p++)
  376.       *begr_p = upcase (*begr_p);
  377.   if (akt_regex)
  378.   {
  379.     if (!old_begriff)  /* Initialisierung der static-Komponenten nötig! */
  380.     {
  381.       old_begriff = strcpy (reserve_mem (strlen (begriff)+1), begriff);
  382.       buf.buffer = reserve_mem (INIT_REGEX_BUF_SIZE);
  383.       buf.allocated = INIT_REGEX_BUF_SIZE;
  384.       buf.fastmap   = fastmap_table;   /* Übersetzungstabelle für Übersetzung */
  385.       for (i=0; i<256; i++)            /* von Klein- auf Großbuchstaben       */
  386.     upper_translate [i] = upcase(i);  /* initialisieren                   */
  387.  
  388.       buf.translate = ignore ? upper_translate : (char*) 0;
  389.       comp_err = re_compile_pattern (begriff, strlen (begriff), &buf);
  390.     }
  391.     buf.translate = ignore ? upper_translate : (char*) 0;
  392.     if (strcmp (old_begriff, begriff)) /* Suchbegriff hat sich geändert */
  393.     { 
  394.       free (old_begriff);
  395.       old_begriff = strcpy (reserve_mem (strlen (begriff)+1), begriff);
  396.       comp_err = re_compile_pattern (begriff, strlen (begriff), &buf);
  397.     }
  398.     if (comp_err)
  399.     {
  400.       print_err(comp_err);
  401.       /* Neuübersetzung beim nächsten Aufruf erzwingen: */
  402.       strcpy (old_begriff, ""); /* find() wird nie mit leerem Begriff */
  403.       return -1;                /* aufgerufen! */
  404.     }
  405.   }
  406.   if (!start_line && !richtung)
  407.     nsl=akt_winp->maxline+1;
  408.   else
  409.     if (start_line == akt_winp->maxline && richtung)
  410.       nsl = -1;
  411.  
  412.   /* Falls Cursor auf oder hinter dem Zeilenende steht und rueckwaerts
  413.      gesucht werden soll, Cursor auf das Zeilende setzen, falls mit
  414.      regulären Ausdrücken gesucht werden soll, da man dann die Länge
  415.      des Matches nicht voraussagen kann. Andernfalls Cursor um die
  416.      Länge des Suchbegriffs vor das Zeilenende setzen, da das die erste
  417.      mögliche Trefferposition ist. Bei Vorwärtssuche und Cursor hinter
  418.      dem Zeilenende Cursor auf Anfang der nächsten Zeile setzen. Falls 
  419.      screencol negativ (kann durch rückwärts Skippen des Suchbegriffs 
  420.      auftreten), dann ans Ende der darüberliegenden Zeile. */
  421.   /* Unterstreichung beseitigen */
  422.   zeile = fastzeile (akt_winp->alinep);
  423.  
  424.   if(akt_winp->screencol >= (fl = strlen(zeile)) && !richtung)
  425.   {
  426.     akt_winp->screencol = fl - (akt_regex ? 1 : blen);
  427.     if (akt_winp->screencol < 0) /* in diesem Fall wird zwar kein Match */
  428.       akt_winp->screencol = 0;   /* gefunden, aber es gibt auch keinen Fehler */
  429.   }
  430.   else
  431.     if (richtung && akt_winp->screencol >= strlen (zeile))
  432.     {
  433.       if (!down())
  434.     gotox(0);
  435.       zeile = fastzeile (akt_winp->alinep);
  436.       akt_winp->screencol = 0;
  437.     }
  438.     else
  439.       if(akt_winp->screencol < 0)
  440.       {
  441.     if(!up())
  442.       gotox(akt_winp->maxline);
  443.     zeile = fastzeile (akt_winp->alinep);
  444.     akt_winp->screencol =  strlen (zeile) - (akt_regex ? 1 : blen);
  445.       }
  446.   do
  447.   {
  448.     /* leere Zeilen werden übersprungen */
  449.     if(strlen (zeile))
  450.     { /* Zeile mit der Funktion instr durchsuchen */
  451.       if (match_len=instr(begriff,zeile,ignore,word,richtung,
  452.       akt_regex ? &buf : (struct re_pattern_buffer *) NULL))
  453.     /* Wenn Teil der Zeile schonmal durchsucht, testen, ob gefundener Teil*/
  454.     /* im schon durchsuchten Teil liegt.                                  */
  455.     if(akt_winp->textline == start_line &&
  456.     (richtung ? akt_winp->screencol >= start_col
  457.           : akt_winp->screencol <= start_col) && !*count)
  458.       break; /* Wenn ja, ist Ergebnis ungueltig, abbrechen */
  459.     else
  460.       return (match_len);   /* Begriff gefunden */
  461.     }
  462.     /* Zur naechsten zu durchsuchenden Zeile gehen */
  463.     akt_winp->alinep = richtung?akt_winp->alinep->next:akt_winp->alinep->prev;
  464.     if((akt_winp->textline += 2*richtung-1) < 0)
  465.       akt_winp->textline = akt_winp->maxline + 1; /* alinep steht auf dummyp */
  466.     else
  467.       if(akt_winp->textline > akt_winp->maxline)
  468.     akt_winp->textline = -1;        /* alinep steht auf dummyp */
  469.  
  470.     /* Bei vorwaertssuchen ab erster Spalte beginnen, bei Rueckwaertssuchen */
  471.     /* blen Spalten vor Zeilenende, da Suchbegriff nicht spaeter anfangen   */
  472.     /* kann.                                                                */
  473.     zeile = fastzeile (akt_winp->alinep);
  474.     akt_winp->screencol = richtung?0:strlen(zeile)-(akt_regex?1:blen);
  475.   }while(akt_winp->textline != nsl || (*count)--); /* ganzen Text durchlaufen */
  476.   gotox (old_line);             /* falls nicht gefunden, an alte Position */
  477.   akt_winp->screencol = old_sc;
  478.   return (0);
  479. }
  480.  
  481. /*****************************************************************************
  482. *
  483. *  Funktion       In einem String enthaltene Zahl berechnen (str_to_num)
  484. *  --------
  485. *
  486. *  Parameter    : string    :
  487. *                   Typ          : char*
  488. *                   Wertebereich : Pointer auf ASCII-Zeichenkette
  489. *                   Bedeutung    : String, in dem die Zahl enthalten ist
  490. *
  491. *  Ergebnis     :
  492. *                   Typ          : int
  493. *                   Wertebereich : 0-MAXINT
  494. *                   Bedeutung    : Im String enthaltene Zahl als int
  495. *
  496. *  Beschreibung : Zuerst wird die erste im String vorkommende Ziffer gesucht.
  497. *                 Dann wird die Ziffer in einen Integer umgewandelt. Bei
  498. *                 jeder weiteren gefundenen Ziffer wird der bisherige Wert
  499. *                 mit 10 multipliziert und der Wert der gefundenen Ziffer
  500. *                 addiert. Sobald das Stringende oder keine Ziffer gefuden
  501. *                 wird, bricht die Funktion ab.
  502. *
  503. *****************************************************************************/
  504.  
  505. int str_to_num(string)
  506. register char *string;
  507. {
  508.   /* *** interne Daten *** */
  509.   register int hilf=0; /* vorlaeufiges Ergebnis */
  510.  
  511.   while (*string && (*string < '0' || *string > '9'))
  512.     string++;   /* erste Ziffer suchen */
  513.   if (!*string) /* Keine Ziffer gefunden, -1 zurueck */
  514.     return (-1);
  515.   while (isdigit(*string))
  516.     hilf = 10*hilf + *string++ - '0';
  517.   return (hilf);
  518. }
  519.  
  520. /*****************************************************************************
  521. *
  522. *  Funktion       Optionen in Werte wandeln (o_to_vals)
  523. *  --------
  524. *
  525. *  Parameter    : optionen  :
  526. *                   Typ          : char*
  527. *                   Wertebereich : Pointer auf ASCII-Zeichenkette
  528. *                   Bedeutung    : Auszuwertender String
  529. *
  530. *               : richtung  :
  531. *                   Typ          : int*
  532. *                   Wertebereich : Pointer auf Integer
  533. *                   Bedeutung    : TRUE:vorwaerts, FALSE:rueckwaerts
  534. *
  535. *               : anzahl    :
  536. *                   Typ          : int*
  537. *                   Wertebereich : Pointer auf integer
  538. *                   Bedeutung    : Anzahl der Wiederholungen
  539. *
  540. *               : ignore    :
  541. *                   Typ          : int*
  542. *                   Wertebereich : Pointer auf integer
  543. *                   Bedeutung    : Gross-/Kleinschreibung ignorieren
  544. *
  545. *               : word      :
  546. *                   Typ          : int*
  547. *                   Wertebereich : Pointer auf integer
  548. *                   Bedeutung    : Nur ganze Worte finden
  549. *
  550. *               : anf_ende  :
  551. *                   Typ          : int*
  552. *                   Wertebereich : Pointer auf Integer
  553. *                   Bedeutung    : Soll vom Anfang oder vom Ende gesucht/
  554. *                                  ersetzt werden ?
  555. *
  556. *  Beschreibung : Anhand des Optionenstrings werden die Parameter gesetzt.
  557. *                 anzahl wird ueber str_to_num ermittelt, alle anderen
  558. *                 ueber die Funktion strchr.
  559. *                 Im Sonderfall, daß vom Anfang oder vom Ende gesucht werden
  560. *                 soll, wird anf_ende auf TRUE gesetzt und der interne Cursor
  561. *                 (screencol/textline) wird auf die entsprechende Position
  562. *                 gesetzt.
  563. *
  564. *****************************************************************************/
  565.  
  566. void o_to_vals(optionen,richtung,anzahl,ignore,word,anf_ende,akt_regex)
  567. char *optionen;
  568. int  *richtung,*anzahl,*ignore,*word,*anf_ende,*akt_regex;
  569. {
  570.   /* Wenn der aktuelle Vorgang eine Wiederholung ist */
  571.   /* oder der User keine Anzahl angegeben hat, wird  */
  572.   /* die Anzahl auf 1 gesetzt.                       */
  573.   if (repeatflag || (*anzahl = str_to_num(optionen))==-1)
  574.     *anzahl = 1;
  575.  
  576.   *richtung = !strchr(optionen,'r') && !strchr(optionen,'R');
  577.   *ignore   =  strchr(optionen,'i') ||  strchr(optionen,'I');
  578.   *word     =  strchr(optionen,'w') ||  strchr(optionen,'W');
  579.   if (strchr(optionen,'x') ||  strchr(optionen,'X'))
  580.     *akt_regex = TRUE;
  581.   else
  582.     if (strchr(optionen,'n') ||  strchr(optionen,'N'))
  583.       *akt_regex = FALSE;
  584.   *anf_ende =  FALSE;         /* default: nicht von Anfang oder Ende */
  585.   if (strchr(optionen,'b') || strchr(optionen,'B'))
  586.   {
  587.     if(!repeatflag) /* bei repeat nicht mehr vom anfang an */
  588.     {
  589.       *anf_ende = TRUE;
  590.       gotox(0);                /* Zeile 0, Spalte 0 aufsuchen */
  591.       akt_winp->screencol = 0;
  592.     }
  593.     *richtung = 1; /* Bei Suchen vom anfang immer vorawerts */
  594.   }
  595.   else
  596.     if (strchr(optionen,'e') || strchr(optionen,'E'))
  597.     {
  598.       if(!repeatflag)
  599.       {
  600.     *anf_ende = TRUE;         /* letzte Zeile, letzte Spalte aufsuchen */
  601.     gotox(akt_winp->maxline);
  602.     akt_winp->screencol = fastll(akt_winp->alinep->text)-1;
  603.       }
  604.       *richtung = 0;      /* Wenn vom Ende aus gesucht werden soll, dann  */
  605.     }                     /* auf jeden Fall rueckwaerts.                  */
  606. }
  607.  
  608. /*****************************************************************************
  609. *
  610. *  Funktion       Letztes Suchen/Ersetzen wiederholen (do_repfr)
  611. *  --------
  612. *
  613. *  Beschreibung : Falls schon eine Suche bzw. Ersetzung stattgefunden hat,
  614. *                 wird diese mit den gleichen Optionen, jedoch anzahl=1
  615. *                 wiederholt.
  616. *
  617. *****************************************************************************/
  618.  
  619. void do_repfr()
  620. {
  621.   if (last_func != F_NONE)
  622.   {
  623.     repeatflag = TRUE;
  624.     if (last_func == F_FIND)
  625.       do_find();
  626.     else
  627.       do_replace();
  628.     repeatflag = FALSE;
  629.   }
  630. }
  631.  
  632. /*****************************************************************************
  633. *
  634. *  Funktion       Suchen ausfuehren (do_find)
  635. *  --------
  636. *
  637. *  Beschreibung : Falls die Funktion nicht durch do_repfr() aufgerunfen wurde,
  638. *                 werden Suchbegriff und Optionen eingelesen. Anschliessend
  639. *                 wird mit der Funktion o_to_vals der Optionenstring in die
  640. *                 Parameter zerteilt und anzahl mal find() aufgerufen.
  641. *
  642. *****************************************************************************/
  643.  
  644. void do_find()
  645. {
  646.   /* *** interne Daten und Initialisierung *** */
  647.   int          richtung,   /* Flag, ob vorawerts gesucht wird                */
  648.            anzahl,     /* Anzahl der Suchwiederholungen                  */
  649.            alt_anz,    /* Zwischenspeicher fuer Wiederholungszahl        */
  650.            ignore,     /* Flag, ob Gross-/Kleinschreibung ignoriert wird */
  651.            word,       /* Flag, ob nur ganze Woerter gefunden werden     */
  652.            anf_ende,   /* Flag, ob vom Anfang oder vom Ende gesucht wird */
  653.            akt_regex,  /* für diese Suche reg. Ausdr. verwenden ?        */
  654.            match_len,  /* zeigt die Länge des gefundenen Musters an      */
  655.            count=1;    /* Zeigt an, ob die Zeile hinter der Anfangszeile */
  656.                /* schon einmal durchsucht wurde.                 */
  657.   register int start_line, /* Zeile, in der die Suche begann                 */
  658.            start_col;  /* Spalte, in der die Suche begann                */
  659.   char         dummy[256]; /* String fuer zusammengeflickte Fehlermeldung    */
  660.  
  661.   if(akt_winp->maxline >= 0) /* Wenn Text leer, dann auch nicht suchen */
  662.   {
  663.     last_func = F_FIND;      /* Fuer do_repfr Funktionstyp merken */
  664.     akt_regex = regexflag;   /* zunächst globales Flag übernehmen */
  665.     if (!repeatflag)         /* Handelt es sich um eine Wiederholung, dann   */
  666.     {                        /* wird der Suchbegriff nicht erneut eingelesen */
  667.       print_stat(PROMPT_SEARCH);
  668.       read_stat(sbegriff,255,GS_ANY);
  669.       clear_stat();
  670.     }
  671.     if(strlen(sbegriff)) /* Bei leerem Suchbegriff nichts unternehmen */
  672.     {
  673.       if (!repeatflag) /* Optionen nur einlesen, wenn es keine Wiederholung ist */
  674.       {
  675.     print_stat(PROMPT_FOPTIONS);
  676.     read_stat(optionen,255,GS_ANY);
  677.     clear_stat();
  678.       }
  679.       akt_winp->lastline = akt_winp->textline; /* Aktuelle Position als letzte */
  680.       akt_winp->lastcol = akt_winp->screencol; /* Position merken              */
  681.  
  682.       /* Optionen auswerten */
  683.       o_to_vals(optionen,&richtung,&anzahl,&ignore,&word,&anf_ende,&akt_regex);
  684.  
  685.       start_line = akt_winp->textline;
  686.       if (!anf_ende) /* Wenn nicht vom Anfang oder vom Ende gesucht werden soll,*/
  687.     akt_winp->screencol += 2*richtung-1;      /* Dann von einer Pos. weiter */
  688.       start_col=akt_winp->screencol;              /* rechts/links suchen        */
  689.       check_buff();       /* Evtl. Puffer zurueck, da auch alinep->text wichtig */
  690.  
  691.       /* Wenn der Cursor beim Vorwaertssuchen am Zeilenende steht oder beim */
  692.       /* Rueckwaertssuchen am Zeilenanfang, dann wird die Nummer der Start- */
  693.       /* zeile und der Startspalte angepasst. */
  694.       if (richtung ? fastzeichen(start_col) == &space : akt_winp->screencol == -1)
  695.       {
  696.     if((start_line += 2*richtung-1) < 0)
  697.       start_line = akt_winp->maxline;
  698.     else
  699.       if(start_line > akt_winp->maxline)
  700.         start_line = 0;
  701.     start_col=richtung?0:MAXLENGTH;  /* Fall rueckwaerts suchen, dann */
  702.       }                                  /* Zeilenende als Suchbeginn markieren */
  703.       if ((alt_anz = anzahl) > 0)
  704.       {
  705.     print_stat(PROMPT_SEARCHING);
  706.     /* Suchbegriff suchen bis nicht mehr zu finden oder gewuenschte Anzahl */
  707.     while ((match_len = find(sbegriff,richtung,ignore,word,start_line,
  708.                 start_col, &count, akt_regex)) > 0
  709.            && --anzahl)
  710.       akt_winp->screencol += richtung ? match_len : -1; /* begriff skippen */
  711.       /* Beachte: Hierdurch kann screencol < 0 werden. Dieser Fall muß
  712.          dann in find() berücksichtigt werden. */
  713.     clear_stat();
  714.     adapt_screen(match_len>=0?match_len:0); /* anschliessend Bildschirm anpassen */
  715.     if (anzahl) /* Wurde nicht die geforderte Anzahl gefunden ? */
  716.     {
  717.       if (alt_anz == anzahl) /* Keinmal ? */
  718.       {
  719.         if (!anf_ende)
  720.           akt_winp->screencol--;
  721.         strcpy(dummy,PROMPT_NOTFOUND);
  722.       }
  723.       else
  724.       { /* match_len == -1 kann hier nicht auftreten, da der Fehler
  725.            des Suchmusterübersetzens sofort beim ersten Aufruf
  726.            auftritt. */
  727.         akt_winp->screencol -= richtung ? match_len : -1; /* Skippen rueckgaengig machen */
  728.         sprintf (dummy,PROMPT_FOUNDN,alt_anz-anzahl);
  729.       }
  730.       pe_or(dummy);
  731.     }
  732.       }
  733.     }
  734.     setz_cursor(W_AKT);
  735.   }
  736.   else
  737.     print_err(PROMPT_FEMPTY);
  738. }
  739.  
  740. /*****************************************************************************
  741. *
  742. *  Funktion       Ersetzungsbegriff eintragen (trag_e_ein)
  743. *  --------
  744. *
  745. *  Parameter    : ebegriff  :
  746. *                   Typ          : char *
  747. *                   Wertebereich : Pointer auf ASCII-Zeichenkette
  748. *                   Bedeutung    : Einzutragender Begriff
  749. *
  750. *                 elen      :
  751. *                   Typ          : int
  752. *                   Wertebereich : 0 - MAX_INT
  753. *                   Bedeutung    : Laenge des Ersetzungsbegriffs
  754. *
  755. *  Beschreibung : Der uebergebene Ersetzungsbegriff wird mit der Funktion
  756. *                 enter_char() ab der aktuellen Position in den Text ein-
  757. *                 getragen. Dabei wird der Insert-Mode abgeschaltet.
  758. *
  759. *****************************************************************************/
  760.  
  761. void trag_e_ein(ebegriff,elen)
  762. register char *ebegriff;
  763. register int elen;
  764. {
  765.   /* *** interne Daten und Initialisierung *** */
  766.   register int i;                        /* Schleifenzaehler */
  767.  
  768.   for (i=0;i<elen;i++)
  769.     enter_char(*ebegriff++, (char*) 0, PUT);
  770. }
  771.  
  772. /*****************************************************************************
  773. *
  774. *  Funktion       Wort zum Blinken bringen (flash_word)
  775. *  --------
  776. *
  777. *  Parameter    : laenge    :
  778. *                   Typ          : int
  779. *                   Wertebereich : 0-MAXLENGTH
  780. *                   Bedeutung    : Laenge des zum Bilnek zu bringenden Worts
  781. *
  782. *  Beschreibung : Ab der aktuellen Cursorposition werden laenge Zeichen zum
  783. *                 blinken gebracht, d.h. mit dem Ersetzungsattribut.
  784. *                 versehen.
  785. *
  786. *****************************************************************************/
  787.  
  788. void flash_word(laenge)
  789. register int laenge;
  790. {
  791.   while (laenge--)
  792.     waddch(akt_winp->winp,winch(akt_winp->winp) | 256*ersetzaddr);
  793. }
  794.  
  795. /*****************************************************************************
  796. *
  797. *  Funktion       Wort "entblinken" (unflash_word)
  798. *  --------
  799. *
  800. *  Parameter    : laenge    :
  801. *                   Typ          : int
  802. *                   Wertebereich : 0-MAXLENGTH
  803. *                   Bedeutung    : Laenge des zu "entblinkenden" Wortes
  804. *
  805. *  Beschreibung : Ab der aktuellen Cursorposition wird bei laenge Zeichen
  806. *                 das Attribut fuer Blinken (ersatzaddr) geloescht.
  807. *
  808. *****************************************************************************/
  809.  
  810. void unflash_word(laenge)
  811. register int laenge;
  812. {
  813.   while (laenge--)
  814.     waddch(akt_winp->winp,winch(akt_winp->winp) & ~(256*ersetzaddr));
  815. }
  816.  
  817. /*****************************************************************************
  818. *
  819. *  Funktion       Ersetzen ausfuehren (do_replace)
  820. *  --------
  821. *
  822. *  Beschreibung : Falls die Funktion nicht von do_repfr aufgerufen wurde,
  823. *                 kann der Benutzer Such-, Ersetzungsbegriff und Optionen
  824. *                 eingeben. Dann wird ab der aktuellen Position aus der Such-
  825. *                 begriff gesucht und je nach Option mit oder ohne Abfrage
  826. *                 ersetzt. Die Suche kann vorwaerts und rueckwaerts, nur
  827. *                 nach ganzen worten oder unter Ignorierung der Gross-/Klein-
  828. *                 schreibnug durchgefuehrt werden. Zur Suche wird die Funktion
  829. *                 find() benutzt, um den Begriff zu ersetzen die Funktion
  830. *                 trag_e_ein().
  831. *
  832. *****************************************************************************/
  833.  
  834. void do_replace()
  835. {
  836.   /* *** interne Daten und Initialisierung *** */
  837.   register int oldu = akt_winp->underflag, /* Zwischenspeicher */
  838.            elen,        /* Laenge des Ersetzungsbegriffs                  */
  839.            ulflag,      /* Flag, ob Ersetzungsbegriff nach aktuellem      */
  840.                 /* Modus oder nach dem ersten Zeichen des gefun-  */
  841.                 /* denen Suchbegriffs unterstrichen werden soll   */
  842.            allflag;     /* Flag, ob alle vorkommenden Suchstrings ersetzt */
  843.                 /* werden sollen.                                 */
  844.   int          richtung,    /* Flag, ob vorawerts gesucht wird                */
  845.            anzahl,      /* Anzahl der Ersetzungswiederholungen            */
  846.            ignore,      /* Flag, ob Gross-/Kleinschreibung ignoriert wird */
  847.            word,        /* Flag, ob nur ganze Woerter gefunden werden     */
  848.            match_len=0, /* Länge des gefundenen Begriffs, Initialisierung,*/
  849.                 /* da am Ende für adapt_screen benutzt.           */
  850.            alt_anz,     /* Zwischenspeicher fuer Wiederholungszahl        */
  851.            diff,
  852.            dl,          /* Dummy, da Anf/Ende-Information unnötig         */
  853.            globalflag,
  854.            ret,         /* Rueckgabewert von ask_replace                  */
  855.            start_line=akt_winp->textline, /* Suchstart Zeile              */
  856.            start_col=akt_winp->screencol, /* Suchstart Spalte             */
  857.            akt_regex,   /* Flag, ob mit regulären Ausdrücken gesucht wird */
  858.            count=1;     /* Zeigt an, ob die Zeile hinter der Anfangszeile */
  859.                 /* schon einmal durchsucht wurde.                 */
  860.   char         dummy[256];
  861.  
  862.   if(akt_winp->maxline >= 0) /* Wenn Text leer, nichts suchen */
  863.   {
  864.     last_func = F_REPLACE; /* Funktionstyp fuer evtl. Wiederholung merken */
  865.     akt_regex = regexflag; /* Globales Regex-Flag übernehmen */
  866.     check_buff(); /* Evtl. Puffer zurueckschreiben, da alinep->text gebraucht */
  867.     if (!repeatflag)       /* wird. */
  868.     {                      /* Bei Wiederholung keinen neuen Suchbegriff,  */
  869.       print_stat(PROMPT_SEARCH); /* keinen neuen Ersetzungsbegriff und */
  870.       read_stat(sbegriff,255,GS_ANY); /* keine neuen Optionen einlesen    */
  871.       clear_stat();
  872.       if(!sbegriff[0])    /* falls leer, raus */
  873.       {
  874.     setz_cursor(W_AKT);
  875.     return;
  876.       }
  877.       print_stat(PROMPT_REPLACE);
  878.       read_stat(ebegriff,255,GS_ANY);
  879.       clear_stat();
  880.       print_stat(PROMPT_ROPTIONS);
  881.       read_stat(optionen,255,GS_ANY);
  882.       clear_stat();
  883.     }
  884.     /* Laengendifferenz zwischen Such- und Ersetzungsbegriff berechnen */
  885.     elen = strlen(ebegriff);
  886.     akt_winp->lastline = akt_winp->textline; /* aktuelle Position als  */
  887.     akt_winp->lastcol = akt_winp->screencol; /* letzte Position merken */
  888.  
  889.     /* Optionenstring auswerten */
  890.     o_to_vals(optionen,&richtung,&anzahl,&ignore,&word,&dl,&akt_regex);
  891.     alt_anz = anzahl;
  892.     globalflag = strchr(optionen,'g') || strchr(optionen,'G');
  893.     allflag = strchr(optionen,'a') || strchr(optionen,'A'); /* alle? */
  894.     ulflag = strchr(optionen,'u') || strchr(optionen,'U'); /* unterstr. nach modus?*/
  895.  
  896.     /* Falls Cursor hinter Zeilenende oder vor Zeilenanfang steht, */
  897.     /* naechste Suchposition als Startposition eintragen.          */
  898.     if (richtung && fastzeichen(start_col) == &space)
  899.     {
  900.       if((start_line += 2*richtung-1) < 0) /* Bei Textanfang oder */
  901.     start_line = akt_winp->maxline;    /* Textende wraparound */
  902.       else
  903.     if(start_line > akt_winp->maxline)
  904.       start_line = 0;
  905.       start_col=richtung?0:MAXLENGTH-1; /* Fall rueckwaerts suchen, dann Zeilenende als Suchbeginn markieren */
  906.     }
  907.  
  908.     /* Suchbegriff entweder anzahl mal oder bei gesetztem allflag so oft */
  909.     /* es geht suchen und ersetzen.                                      */
  910.     print_stat(PROMPT_SEARCHING);
  911.     while ((allflag || anzahl--)
  912.       && (match_len = find(sbegriff,richtung,ignore,word,
  913.                    start_line,start_col,&count,
  914.                    akt_regex)))
  915.     {
  916.       diff = elen - match_len;   /* Verlängerung der Zeile */
  917.       if (!globalflag)  /* muss Abfrage vorgenommen werden ? */
  918.       {
  919.     clear_stat();
  920.     adapt_screen(match_len); /* Ja, dann Bildschirm anpassen */
  921.     flash_word(match_len);   /* Suchbegriff highlighten */
  922.     setz_cursor(W_AKT);      /* und refreshen */
  923.     if((ret = ask_replace()) != 'J') /* soll nicht ersetzt werden ? */
  924.     {
  925.       if(ret == 'A')    /* Abbruch? */
  926.       {
  927.         setz_cursor(W_AKT); /* Highlight aus, aber noch kein refresh */
  928.         unflash_word(match_len);
  929.         anzahl = -1;    /* Meldung am Ende unterdruecken */
  930.         break;
  931.       }
  932.       setz_cursor(W_AKT);             /* Highlight aus */
  933.       unflash_word(match_len);
  934.       akt_winp->screencol+=match_len; /* Suchbegriff skippen */
  935.       setz_cursor(W_AKT);
  936.       wrefresh(akt_winp->winp);       /* Fenster refreshen   */
  937.       print_stat(PROMPT_SEARCHING);
  938.       continue;
  939.     }
  940.     else
  941.     {
  942.       setz_cursor(W_AKT);             /* Highlight aus */
  943.       unflash_word(match_len);
  944.     }
  945.       }
  946.       if(fastll(akt_winp->alinep->text) + diff > MAXLENGTH)
  947.       {
  948.     clear_stat();
  949.     print_err(PROMPT_ERREPLACE); /* Zeile würde zu lang werden */
  950.     if (globalflag && (allflag || anzahl))
  951.       print_stat(PROMPT_SEARCHING);
  952.       }
  953.       else
  954.       {
  955.     /* falls erstes Zeichen des Wortes unterstrichen, wird gesamtes Wort
  956.        unterstrichen, wenn ulflag = FALSE, sonst wird je nach underline-
  957.        modus unterstrichen */
  958.     if(!ulflag)
  959.       if(ul_char())
  960.         akt_winp->underflag = TRUE;
  961.       else
  962.         akt_winp->underflag = FALSE;
  963.     mdelete(match_len);
  964.     insert(elen); /* Platz fuer neuen (weil evtl. underlined) */
  965.     trag_e_ein(ebegriff,elen); /* Ersetzungsbegriff eintragen */
  966.     check_buff(); /* Puffer zurueckschreiben, da alinep->text gebraucht */
  967.       }
  968.       if(!globalflag) /* Wenn Abgefragt wurde, dann Bildschirm */
  969.       {               /* korrigieren */
  970.     lineout(akt_winp->textline - akt_winp->ws_line);
  971.     wrefresh(akt_winp->winp); /* veraenderte Zeile restaurieren */
  972.     if (allflag || anzahl)    /* wird nochmal gesucht? Dann prompten */
  973.       print_stat(PROMPT_SEARCHING);
  974.       }
  975.     } /* of while */
  976.     clear_stat();
  977.  
  978.     /* Wenn nicht alle vorkommenden Suchbegriffe gefunden werden sollten */
  979.     /* und nicht abgebrochen wurde, testen ob alle gewuenschten Er-      */
  980.     /* setzungen durchgefuehrt werden konnten.                           */
  981.     if (!allflag && anzahl != -1)
  982.     {
  983.       if (alt_anz-1 == anzahl)
  984.     strcpy(dummy,PROMPT_NOTFOUND);
  985.       else
  986.     sprintf (dummy,PROMPT_FOUNDN,alt_anz-anzahl-1);
  987.       print_err(dummy);
  988.     }
  989.     if (globalflag) /* Wenn keine Abfrage stattfand, dann jetzt Bildschirm */
  990.       adapt_screen(match_len); /* anpassen */
  991.     show_win(W_AKT); 
  992.   }
  993.   else
  994.     print_err(PROMPT_REMPTY);
  995.   akt_winp->underflag = oldu; /* underflag restaurieren */
  996. }
  997.  
  998. /*****************************************************************************
  999. *
  1000. *  Funktion       Nächste Klammer in Cursorumgebung finden (find_next_par)
  1001. *  --------
  1002. *
  1003. *  Ergebnis     :
  1004. *                   Typ          : int
  1005. *                   Wertebereich : TRUE, FALSE
  1006. *                   Bedeutung    : TRUE <=> Klammer in Umgebung gefunden
  1007. *
  1008. *  Beschreibung : In der Umgebung des Cursors wird im aktuellen Fenstertext
  1009. *                 nach einer runden, eckigen oder geschweiften Klammer
  1010. *                 gesucht. Dabei wird "gleichzeitig" vorwärts und
  1011. *                 rückwärts gesucht, um die Klammer zu finden, die am
  1012. *                 nächsten in Cursornähe steht. Wird eine Klammer gefunden,
  1013. *                 so wird textline/screencol auf die gefundene Klammer
  1014. *                 gesetzt. Ansonsten bleiben beide unverändert.
  1015. *
  1016. *****************************************************************************/
  1017.  
  1018. int find_next_par ()
  1019. {
  1020.   /* *** lokale Daten *** */
  1021.   char forw  = TRUE,   /* Flag, ob noch vorwärts gesucht wird  */
  1022.        back  = TRUE,   /* Flag, ob noch rückwärts gesucht wird */
  1023.        found = FALSE,  /* Flag, ob Klammer gefunden wurde */
  1024.        *par_str = "(){}[]", /* matchbare Klammern */
  1025.        *zeile;         /* Zeiger auf Zeilenpuffer (ohne Untersteichung) */
  1026.   int  f_tl,           /* Zeilennummer Vorwärtssuche */
  1027.        b_tl,           /* Zeilennummer Rückwärtssuche */
  1028.        diff,           /* Abstand zum Cursor in erster Suchzeile */
  1029.        len,            /* Länge der ersten Suchzeile */
  1030.        sc;             /* Spalte in Suchzeile */
  1031.   zeil_typ *f_tp,      /* Zeile Vorwärtssuche */
  1032.        *b_tp;      /* Zeile Rückwärtssuche */
  1033.  
  1034.   if (akt_winp->maxline != -1) /* Wenn Text leer, dann nichts machen. */
  1035.   {
  1036.     sc = akt_winp->screencol;
  1037.     f_tl = b_tl = akt_winp->textline;
  1038.     f_tp = b_tp = akt_winp->alinep;
  1039.  
  1040.     while ((forw || back) && !found)
  1041.     {
  1042.       if (forw)
  1043.       {
  1044.     zeile = fastzeile (f_tp); /* Zeile von Unterstreichung befreien */
  1045.     if (sc) /* sc>0, tritt nur bei erster durchsuchter Zeile auf: */
  1046.     {
  1047.       diff = 0;
  1048.       len = strlen (zeile);
  1049.       if (sc >= len) /* Falls Cursor hinter Zeilenende, dann auf */
  1050.         sc = len-1;  /* Zeilenende setzen */
  1051.       while ((sc-diff >= 0 || sc+diff < len) && !found)
  1052.       {
  1053.         if (sc+diff < len)
  1054.           found = strchr (par_str, zeile [sc+diff]) ? TRUE : FALSE;
  1055.         if (found) sc = sc + diff + 1; /* es wird noch 1 abgezogen */
  1056.         if (!found && sc-diff >= 0)
  1057.         {
  1058.           found = strchr (par_str, zeile [sc-diff]) ? TRUE : FALSE;
  1059.           if (found) sc = sc - diff + 1; /* es wird noch 1 abgezogen */
  1060.         }
  1061.         diff++;
  1062.       }
  1063.     }
  1064.     else /* Nicht erste Zeile, dann nur in einer Richtung durchsuchen */
  1065.       while (zeile [sc] && !found)
  1066.         found = strchr (par_str, zeile [sc++]) ? TRUE : FALSE;
  1067.     if (!found)
  1068.     {
  1069.       f_tp = f_tp->next; /* in nächste Zeile gehen */
  1070.       if (f_tp == akt_winp->dummyp) /* Am Ende? Dann nicht weiter vw. */
  1071.         forw = FALSE;
  1072.       else
  1073.         f_tl++;  /* Zeilennummer mitzählen */
  1074.     }
  1075.     else /* Bei Fund textline, screencol und alinep auf Fundzeile setzen */
  1076.     {
  1077.       akt_winp->textline = f_tl;
  1078.       akt_winp->alinep   = f_tp;
  1079.       akt_winp->screencol= sc-1;
  1080.     }
  1081.       }
  1082.       if (!found && back)
  1083.       {
  1084.     b_tp = b_tp->prev;
  1085.     if (b_tp != akt_winp->dummyp)  /* Nicht am Anfang ? */
  1086.     {
  1087.       b_tl--;    /* Zeilennummer mitzählen */
  1088.       zeile = fastzeile (b_tp); /* Unterstreichung raus */
  1089.       sc = strlen (zeile)-1;
  1090.       while (sc >= 0 && !found)
  1091.         found = strchr (par_str, zeile [sc--]) ? TRUE : FALSE;
  1092.     }
  1093.     else
  1094.       back = FALSE;
  1095.     if (!found) /* Bei Fund Spalte in sc merken */
  1096.       sc = 0;   /* in erste Spalte für nächste Zeile Vorwärtssuche */
  1097.     else  /* Bei Fund textline, screencol und alinep auf Fundzeile setzen */
  1098.     {
  1099.       akt_winp->alinep   = b_tp;
  1100.       akt_winp->textline = b_tl;
  1101.       akt_winp->screencol= sc+1;
  1102.     }
  1103.       }
  1104.     }
  1105.   }
  1106.   return found;
  1107. }
  1108.  
  1109. /*****************************************************************************
  1110. *
  1111. *  Funktion       Passende Klammer finden (search_match_par)
  1112. *  --------
  1113. *
  1114. *  Ergebnis     :
  1115. *                   Typ          : int
  1116. *                   Wertebereich : TRUE, FALSE
  1117. *                   Bedeutung    : TRUE: Passende Klammer gefunden
  1118. *                                  FALSE: Keine passende Klammer gefunden
  1119. *
  1120. *  Beschreibung : Zu der Klammer an der Cursorposition (dies ist eine
  1121. *                 Vorbedingung für die Funktion) wird die korrespondierende
  1122. *                 gesucht. Die Suchrichtung ist durch die Richtung der
  1123. *                 Klammer vorgegeben.
  1124. *                 Wird keine passende Klammer gefunden, so wird FALSE
  1125. *                 zurückgegeben. Ansonsten TRUE, und der Cursor steht
  1126. *                 auf der Position der gefundenen Klammer. Es wird jedoch
  1127.                  keine Refresh oder eine Anpassung des Bildschirmaus-
  1128. *                 schnitts vorgenommen.
  1129. *
  1130. *****************************************************************************/
  1131.  
  1132. int search_match_par ()
  1133. {
  1134.   char found = FALSE,  /* Flag, ob passende Klammer gefunden */
  1135.        vorwaerts=TRUE, /* Flag, in welche Richtung gesucht werden soll */
  1136.        *zeile,         /* zu durchsuchende aktuelle Zeile */
  1137.        par_open,       /* Zeichen der öffnenden Klammer */
  1138.        par_close;      /* Zeichen der schließenden Klammer */
  1139.   int  par_count = 0,  /* Zähler für öffnende und schließende Klammern */
  1140.        sc = akt_winp->screencol,   /* Spalte der 1. Klammer */
  1141.        tl = akt_winp->textline;    /* Zeilennummer der 1. Klammer */
  1142.   zeil_typ *tp = akt_winp->alinep; /* Zeilenstruktur der 1. Klammer */
  1143.  
  1144.   /* Zuerst ermitteln, ob öffnende/schließende Klammer */
  1145.   switch (par_open = *fastzeichen(akt_winp->screencol))
  1146.   {
  1147.     case '}': par_close = par_open;
  1148.           par_open = '{';      
  1149.           vorwaerts = FALSE;   
  1150.           break;               
  1151.     case ')': par_close = par_open;
  1152.           par_open = '(';       
  1153.           vorwaerts = FALSE;    
  1154.           break;                
  1155.     case ']': par_close = par_open;
  1156.           par_open = '[';       
  1157.           vorwaerts = FALSE;    
  1158.           break;                
  1159.     case '{': par_close = '}'; break;
  1160.     case '(': par_close = ')'; break;
  1161.     case '[': par_close = ']'; break;
  1162.   }
  1163.  
  1164.   /* Die Klammer, auf der der Cursor steht, wird mitgezählt. Dadurch
  1165.      wird die Zahl sofort != 0. */
  1166.   while (!found && tp != akt_winp->dummyp)
  1167.   {
  1168.     zeile = fastzeile (tp);
  1169.     if (sc >= strlen (zeile)) /* Falls Cursor hinter Zeilenende, dann auf */
  1170.       sc = strlen (zeile)-1;  /* Zeilenende setzen */
  1171.     while (!found && (vorwaerts ? zeile [sc] : sc >= 0))
  1172.     {
  1173.       if (zeile [sc] == par_close) par_count--;
  1174.       if (zeile [sc] == par_open) par_count++;
  1175.       found = !par_count; /* Gefunden, wenn Zähler wieder auf 0 */
  1176.       if (!found)
  1177.     vorwaerts ? sc++ : sc--;
  1178.     }
  1179.     if (!found)  /* nicht in Zeile gefunden, dann nächste Zeile */
  1180.     {
  1181.       if (vorwaerts)
  1182.       { tp = tp->next; tl = tl++; sc = 0; }
  1183.       else
  1184.       { tp = tp->prev; tl = tl--; sc = MAXLENGTH; }
  1185.     }
  1186.   }
  1187.   if (found)
  1188.   {
  1189.     akt_winp->screencol = sc;
  1190.     akt_winp->textline = tl;
  1191.     akt_winp->alinep = tp;
  1192.   }
  1193.  
  1194.   return found;
  1195. }
  1196.