home *** CD-ROM | disk | FTP | other *** search
/ M.u.C.S. Disc 2000 / MUCS2000.iso / anwend / qed453 / src / find.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-08-29  |  29.6 KB  |  1,332 lines

  1. #include "global.h"
  2. #include "aktion.h"
  3. #include "ausgabe.h"
  4. #include "block.h"
  5. #include "clipbrd.h"
  6. #include "comm.h"
  7. #include "edit.h"
  8. #include "event.h"
  9. #include "file.h"
  10. #include "icon.h"
  11. #include "memory.h"
  12. #include "rsc.h"
  13. #include "set.h"
  14. #include "tasten.h"
  15. #include "text.h"
  16. #include "umbruch.h"
  17. #include "window.h"
  18. #include "find.h"
  19.  
  20. extern void    menu_help(int title, int item);
  21.  
  22. /* exportierte Variablen ***************************************************/
  23.  
  24. bool                    s_grkl, s_quant, s_wort, s_vorw, s_global, s_round,
  25.                         ff_rekursiv;
  26. int                    r_modus, rp_box_x, rp_box_y;
  27. char                    r_str[HIST_LEN+1], s_str[HIST_LEN+1],
  28.                         s_history[HIST_ANZ][HIST_LEN+1],
  29.                         r_history[HIST_ANZ][HIST_LEN+1],
  30.                         ff_mask[15+1];
  31.  
  32. UMLAUTENCODING     umlaut_from, umlaut_to;
  33.  
  34. /*****************************************************************************/
  35.  
  36. #define SETANZ         5
  37.  
  38. #define M_CURSOR        0        /* Werte für modus von start_suche */
  39. #define M_TSTART        1
  40. #define M_TENDE        2
  41.  
  42. static ZEILEP     start;
  43. static int        text_len, text_x,
  44.                     last_op = -1;
  45. static long        text_y;
  46. static SET        wort_set;
  47.  
  48. /* Variablen, die über set_suchmode gesetzt werden */
  49. /* !!! muessen bei match gesichet werden !!! */
  50. static bool        quantor, vorw, grkl, wort, modus, round, line_start;
  51. static int        muster_len;
  52. static char     muster_txt[HIST_LEN+1];
  53. static char     replace_txt[HIST_LEN+1];
  54. static SET        group[SETANZ];
  55. static int        setanz;
  56. static int        delta[256];
  57.  
  58. /* lokale Prototypen *****************************************************/
  59. static bool    build_popup (char h[HIST_ANZ][HIST_LEN+1], POPUP *pop);
  60. static int    hist_popup    (char h[HIST_ANZ][HIST_LEN+1], OBJECT *tree, int obj_pos, int obj_text);
  61.  
  62. /*=======================================================================*/
  63.  
  64. static void init_suche(TEXTP t_ptr, int modus)
  65. {
  66.     if (modus == M_CURSOR)
  67.     {
  68.         start = t_ptr->cursor_line;
  69.         text_y = t_ptr->ypos;
  70.         if (vorw)
  71.         {
  72.             text_x = t_ptr->xpos;
  73.             text_len = start->len-t_ptr->xpos;
  74.             if (text_len>0)
  75.             {
  76. /*
  77.     Mu₧ das sein? Dann findet ^G nämlich nichts, wenn der Cursor auf dem
  78.     gesuchten steht!?
  79.                 text_x++;
  80.                 text_len--;
  81. */
  82.             }
  83.             else if (!IS_LAST(start))
  84.             {
  85.                 NEXT(start);
  86.                 text_y++;
  87.                 text_x = 0;
  88.                 text_len = start->len;
  89.             }
  90.         }
  91.         else
  92.         {
  93.             text_x = 0;
  94.             text_len = t_ptr->xpos;
  95.             if (text_len>0)
  96.             {
  97. /*
  98.     Diese Zeile mü₧te eigentlich auch raus, damit das gefunden wird (rückwärts)
  99.     wo der Cursor 'draufsteht. Dann klappt aber der ^G nicht, da dann der
  100.     Cursor (Blockmarkierung!) wieder hinter dem gefundenen steht und so immer
  101.     wieder das gleiche findet!
  102. */
  103.                 text_len--;
  104.             }
  105.             else if (!IS_FIRST(start))
  106.             {
  107.                 VORG(start);
  108.                 text_y--;
  109.                 text_len = start->len;
  110.             }
  111.         }
  112.     }
  113.     else if (modus==M_TSTART)
  114.     {
  115.         start = FIRST(&t_ptr->text);
  116.         text_x = 0;
  117.         text_len = start->len;
  118.         text_y = 0;
  119.     }
  120.     else
  121.     {
  122.         start = LAST(&t_ptr->text);
  123.         text_x = 0;
  124.         text_len = start->len;
  125.         text_y = t_ptr->text.lines-1;
  126.     }
  127.     setcpy(wort_set,t_ptr->loc_opt->wort_set);
  128. }
  129.  
  130. static int suche1(ZEILEP col, int x, int str_len, int *such_len,
  131.                         char*(*call)(char*,int,char*,int*))
  132. /* vorw */
  133. {
  134.     char *ptr, *str, *str2;
  135.  
  136.     if (quantor)
  137.     {
  138.         if (x>0 && line_start)                                    /* Muster am Anfang finden */
  139.             return -1;
  140.         if (x+str_len<col->len && muster_len>=2 &&
  141.              muster_txt[muster_len-2]=='[' && muster_txt[muster_len-1]==0xFC)
  142.             return -1;
  143.     }
  144.     ptr = TEXT(col);
  145.     str = ptr+x;
  146.     str2 = (*call)(str, str_len, muster_txt, such_len);
  147.     if (str2==NULL) return -1;
  148.     if (wort)
  149.     {
  150.         while (!(str2==ptr || !setin(wort_set,str2[-1])) ||
  151.                  !(str2[*such_len]==EOS || !setin(wort_set,str2[*such_len])))
  152.         {
  153.             str2++;
  154.             str_len -= (int)(str2 - str);
  155.             str = str2;
  156.             str2 = (*call)(str, str_len, muster_txt, such_len);
  157.             if (str2==NULL) return -1;
  158.         }
  159.     }
  160.     return (int)(str2 - ptr);
  161. }
  162.  
  163. static int suche2(ZEILEP col, int x, int str_len, int *such_len,
  164.                         char*(*call)(char*,int,char*,int*))
  165. /* rauf */
  166. {
  167.     int    x2, merk;
  168.  
  169.     merk = 0;
  170.     while (TRUE)
  171.     {
  172.         x2 = suche1(col, x, str_len, such_len, call);
  173.         if (x2==-1) break;
  174.         x2++;                                 /* Weiter suchen */
  175.         str_len -= x2-x;                    /* Restlänge */
  176.         merk = x = x2;
  177.     }
  178.     return merk-1;
  179. }
  180.  
  181. static char *STRSTR(char *str_anf, int str_len, char *mstr_anf, int *found_len)
  182. /* Suche ohne Quantoren */
  183. {
  184.     char *mstr, *str;
  185.     int    i, mstr_len = muster_len;
  186.  
  187.     *found_len = mstr_len;
  188.     str_anf += mstr_len;
  189.     str_len -= mstr_len;
  190.     mstr_anf += mstr_len;
  191.     while (str_len>=0)
  192.     {
  193.         str = str_anf;
  194.         mstr = mstr_anf;
  195.         i = mstr_len;
  196.         while(TRUE)
  197.         {
  198.             if (*(--mstr)!=*(--str)) break;        /* Match fehlgeschlagen */
  199.             if ((--i)<=0) return(str);             /* gefunden */
  200.             if (*(--mstr)!=*(--str)) break;        /* Match fehlgeschlagen */
  201.             if ((--i)<=0) return(str);                /* gefunden */
  202.             if (*(--mstr)!=*(--str)) break;        /* Match fehlgeschlagen */
  203.             if ((--i)<=0) return(str);             /* gefunden */
  204.             if (*(--mstr)!=*(--str)) break;        /* Match fehlgeschlagen */
  205.             if ((--i)<=0) return(str);             /* gefunden */
  206.         }
  207.         i = delta[str_anf[-1]];
  208.         str_anf += i;                                        /* weiterrücken */
  209.         str_len -= i;
  210.     }
  211.     return(NULL);
  212. }
  213.  
  214. static char *STRSTR1(char *str_anf, int str_len, char *mstr_anf, int *found_len)
  215. /* Suche ohne Quantoren (Gross/Klein) */
  216. {
  217.     char *mstr, *str, s;
  218.     int    i, mstr_len = muster_len;
  219.  
  220.     *found_len = mstr_len;
  221.     str_anf += mstr_len;
  222.     str_len -= mstr_len;
  223.     mstr_anf += mstr_len;
  224.     while (str_len>=0)
  225.     {
  226.         str = str_anf;
  227.         mstr = mstr_anf;
  228.         i = mstr_len;
  229.         while (TRUE)
  230.         {
  231.             s = *(--str);
  232. /*
  233.             if (s>='a' && s<='z') s-=32;
  234.             else if (s=='ö') s = 'Ö';
  235.             else if (s=='ü') s = 'Ü';
  236.             else if (s=='ä') s = 'Ä';
  237. */
  238.             s = nkc_toupper(s);
  239.             if (*(--mstr)!=s) 
  240.                 break;                    /* Match fehlgeschlagen */
  241.             if ((--i)<=0) 
  242.                 return (str);            /* gefunden */
  243.         }
  244.         s = str_anf[-1];
  245. /*
  246.         if (s>='a' && s<='z') s-=32;
  247.         else if (s=='ö') s = 'Ö';
  248.         else if (s=='ü') s = 'Ü';
  249.         else if (s=='ä') s = 'Ä';
  250. */
  251.         s = nkc_toupper(s);
  252.         i = delta[s];
  253.         str_anf += i;                                        /* weiterrücken */
  254.         str_len -= i;
  255.     }
  256.     return(NULL);
  257. }
  258.  
  259. static char *STRSTR2(char *str_anf, int str_len, char *mstr_anf, int *found_len)
  260. /* Suche mit Quantoren (rekursiv) */
  261. {
  262.     char *str, *mstr, m, s;
  263.     int    len, anz;
  264.  
  265.     if (line_start)                                        /* Muster am Anfang finden */
  266.         anz = 1;
  267.     else
  268.         anz = str_len+1;                                    /* Anzahl der Tests */
  269.     while ((--anz)>=0)                                    /* auch len=0 kann Treffer sein */
  270.     {
  271.         mstr = mstr_anf;                                    /* Muster reset */
  272.         str = str_anf;                                     /* String reset */
  273.         len = str_len;
  274.         while (TRUE)
  275.         {
  276.             m = *mstr++;                                    /* neue Zeichen holen */
  277.             s = *str;
  278.             if (m==EOS)                                     /* Muster komplett gefunden */
  279.             {
  280.                 *found_len = (int)(str - str_anf);
  281.                 return str_anf;
  282.             }
  283.             if (len==0)
  284.                 s = EOS;
  285.  
  286.             if (m=='*')
  287.             {
  288.                 bool    save = line_start;
  289.  
  290.                 line_start = FALSE;
  291.                 str = STRSTR2(str, len, mstr, found_len);
  292.                 line_start = save;
  293.                 if (str==NULL)
  294.                     return NULL;
  295.                 *found_len += (int)(str - str_anf);
  296.                 return str_anf;
  297.             }
  298.             if (!grkl)
  299.             {
  300. /*
  301.                 if (s>='a' && s<='z') s-=32;
  302.                 else if (s=='ö') s = 'Ö';
  303.                 else if (s=='ü') s = 'Ü';
  304.                 else if (s=='ä') s = 'Ä';
  305. */
  306.                 s = nkc_toupper(s);
  307.             }
  308.             if (m=='[')
  309.             {
  310.                 m = *mstr++;                                /* nach '[' folgt ein Infozeichen */
  311.                 if (m==0xFF)                            /* echtes '[' */
  312.                 {
  313.                     if (s!='[') break;
  314.                 }
  315.                 else if (m==0xFE)                             /* Wortende (letztes in Muster) */
  316.                 {
  317.                     if (len==0 || !setin(wort_set,s))
  318.                     {
  319.                         *found_len = (int)(str - str_anf);
  320.                         return str_anf;
  321.                     }
  322.                     break;
  323.                 }
  324.                 else if (m==0xFC)                         /* Zeilenende */
  325.                 {
  326.                     if (len==0)
  327.                     {
  328.                         *found_len = (int)(str - str_anf);
  329.                         return str_anf;
  330.                     }
  331.                     break;
  332.                 }
  333.                 else                                            /* Wildcard */
  334.                 {
  335.                     if (!setin(group[m-1],s)) break;
  336.                 }
  337.             }
  338.             else                                                /* normale Zeichen und '?' */
  339.                 if (m!=s && m!='?') break;
  340.  
  341.             if (len==0) break;
  342.             str++; len--;                                    /* nächstes Zeichen */
  343.         }
  344.         str_anf++;                                            /* String ein Zeichen weiter */
  345.         str_len--;
  346.     }
  347.     return NULL;
  348. }
  349.  
  350. /* rein : start, text_x, text_len, text_y */
  351. /* raus : start, text_x, text_len, text_y */
  352. /* -1:Abbruch, 0:nichts gefunden 1:gefunden */
  353.  
  354. static int suchen2(int *such_len)
  355. {
  356.     char*    (*call)    (char*,int,char*,int*);
  357.     long    y;
  358.     ZEILEP lauf;
  359.     int    step, x;
  360.  
  361.     x = text_x;
  362.     y = text_y;
  363.     lauf = start;
  364.     if (muster_len==0) return 0;
  365.     step = 70;
  366.     if (quantor)
  367.         call = STRSTR2;
  368.     else if (grkl)
  369.         call = STRSTR;
  370.     else
  371.         call = STRSTR1;
  372.     if (vorw)
  373.     {
  374.         while (TRUE)
  375.         {
  376.             if ((text_x=suche1(lauf,x,text_len,such_len,call))>=0)
  377.             {
  378.                 text_y = y;
  379.                 start = lauf;
  380.                 return 1;
  381.             }
  382.             NEXT(lauf); y++; x = 0; text_len = lauf->len;
  383.             if (IS_TAIL(lauf)) return 0;
  384.             if ((--step)==0)
  385.             {
  386. /*
  387.                 if (check_for_abbruch() && note(1, 2, BREAK) == 1) 
  388.                     return -1;
  389. */
  390.                 step = 70;
  391.             }
  392.         }
  393.     }
  394.     else
  395.     {
  396.         while (TRUE)
  397.         {
  398.             if ((text_x=suche2(lauf,x,text_len,such_len,call))>=0)
  399.             {
  400.                 text_y = y;
  401.                 start = lauf;
  402.                 return 1;
  403.             }
  404.             VORG(lauf);
  405.             if (IS_HEAD(lauf)) return 0;
  406.             y--;
  407.             x = 0;
  408.             text_len = lauf->len;
  409.             if ((--step)==0)
  410.             {
  411. /*
  412.                 if (check_for_abbruch() && note(1, 2, BREAK) == 1) 
  413.                     return -1;
  414. */
  415.                 step = 70;
  416.             }
  417.         }
  418.     }
  419. }
  420.  
  421. /* rein : start, text_x, text_len, text_y */
  422. /* raus : start, text_x, text_len, text_y */
  423. /* -1:Abbruch, 0:nichts gefunden 1:gefunden */
  424.  
  425. static int suchen(TEXTP t_ptr, int *such_len)
  426. {
  427.     int    erg;
  428.  
  429.     erg = suchen2(such_len);
  430.     if (erg==0 && round)
  431.     {
  432.         int    m;
  433.  
  434.         Bconout(2, 7);
  435.         if (vorw)
  436.             m = M_TSTART;
  437.         else
  438.             m = M_TENDE;
  439.         init_suche(t_ptr,m);
  440.         erg = suchen2(such_len);
  441.     }
  442.     return erg;
  443. }
  444.  
  445. /* ====================================================================== */
  446.  
  447. static void set_suchmode(char *Muster, char *Replace, bool Grkl, bool Quantor, 
  448.                                  bool Vorw, bool Wort, bool Global, bool Round)
  449. {
  450.     char    *ptr, *d, help[HIST_LEN+1];
  451.     bool    invers;
  452.  
  453.     /* Spezial für '@' am Editfeld-Anfang! */
  454.     if (Muster[0] == '\\' && Muster[1] == '@' && Quantor)
  455.         strcpy((char *)muster_txt, Muster+1);        /* \ überspringen */
  456.     else
  457.         strcpy((char *)muster_txt, Muster);
  458.  
  459.     if (Replace[0] == '\\' && Replace[1] == '@' && Quantor)
  460.         strcpy(replace_txt, Replace+1);
  461.     else
  462.         strcpy(replace_txt, Replace);
  463.     
  464.     grkl = Grkl;
  465.     quantor = Quantor;
  466.     vorw = Vorw;
  467.     wort = Wort;
  468.     round = Round;
  469.     setanz = 0;
  470.     if (!grkl) 
  471.         str_toupper((char *)muster_txt);
  472.     if (quantor)
  473.     {
  474.         d = help;
  475.         ptr = muster_txt;
  476.         if (*ptr=='^')
  477.         {
  478.             line_start = TRUE;
  479.             ptr++;
  480.         }
  481.         else
  482.             line_start = FALSE;
  483.  
  484.         for (; *ptr; ptr++)
  485.         {
  486.             *d++ = *ptr;
  487.             if (*ptr=='$' && ptr[1]==EOS)
  488.             {
  489.                 d[-1] = '[';
  490.                 *d++ = 0xFC;
  491.             }
  492.             else if (*ptr=='[' && setanz<SETANZ)
  493.             {
  494.                 char *merk = ptr;
  495.  
  496.                 ptr++;
  497.                 invers = FALSE;
  498.                 if (*ptr=='^')
  499.                 {
  500.                     invers = TRUE;
  501.                     ptr++;
  502.                 }
  503.                 setclr(group[setanz]);
  504.                 while(*ptr && *ptr!=']')
  505.                 {
  506.                     if (ptr[0]=='-' && ptr[-1]!='[' && ptr[1]!=']')
  507.                     {
  508.                         char i;
  509.  
  510.                         ptr++;
  511.                         for (i=ptr[-2]; i<*ptr; i++)
  512.                             setincl(group[setanz],i);
  513.                     }
  514.                     else
  515.                         setincl(group[setanz],*ptr++);
  516.                 }
  517.                 if (*ptr)                            /* Keine ']' gefunden */
  518.                 {
  519.                     if (invers)
  520.                         setnot(group[setanz]);
  521.                     setanz++;
  522.                     *d++ = setanz;                 /* immer einen grö₧er (weil nie Null) */
  523.                 }
  524.                 else
  525.                 {
  526.                     *d++ = 0xFF;                    /* Echtes '[' */
  527.                     ptr = merk;                     /* Neu Scannen */
  528.                 }
  529.             }
  530.         }
  531.         if (wort && d>help)                        /* nur Worte und überhaupt ein Muster */
  532.         {
  533.             *d++ = '[';
  534.             *d++ = 0xFE;                            /* Wortende */
  535.         }
  536.         *d = EOS;
  537.         strcpy((char *)muster_txt, help);
  538.         muster_len = (int) strlen(muster_txt);
  539.     }
  540.     else
  541.     {
  542.         int i,j;
  543.  
  544.         muster_len = (int) strlen(muster_txt);
  545.         for (i=0; i<256; i++) 
  546.             delta[i] = muster_len;
  547.         j = muster_len-1;
  548.         for (i=0; i<j; i++) 
  549.             delta[muster_txt[i]] = j-i;
  550.     }
  551.     if (Global)
  552.     {
  553.         if (vorw)
  554.             modus = M_TSTART;
  555.         else
  556.             modus = M_TENDE;
  557.     }
  558.     else
  559.             modus = M_CURSOR;
  560. }
  561.  
  562. int start_find(TEXTP t_ptr, bool quiet)
  563. {
  564.     int    len, erg;
  565.  
  566.     last_op = 1;
  567.     graf_mouse(HOURGLASS, NULL);
  568.     init_suche(t_ptr, modus);            /* Suchzeiger an den Start bringen */
  569.     erg = suchen(t_ptr,&len);
  570.     graf_mouse(ARROW, NULL);
  571.     if (erg == 1 && !quiet)
  572.     {
  573.         blk_demark(t_ptr);
  574.         t_ptr->cursor_line = start;
  575.         t_ptr->xpos = text_x;
  576.         t_ptr->ypos = text_y;
  577.         make_chg(t_ptr->link,POS_CHANGE,0);
  578.         blk_mark(t_ptr,0);
  579.         t_ptr->xpos = text_x+len;
  580.         blk_mark(t_ptr,1);
  581.         restore_edit();
  582.     }
  583.     return erg;
  584. }
  585.  
  586. int start_replace(TEXTP t_ptr)
  587. {
  588.     char     *ptr;
  589.     int    delta, erg, loc_r_modus, d,
  590.             such_len, rpl_len;
  591.     long    anz;
  592.  
  593.     last_op = 2;
  594.     graf_mouse(HOURGLASS, NULL);
  595.     rpl_len    = (int) strlen(replace_txt);
  596.     anz = 0L;
  597.     init_suche(t_ptr, modus);
  598.  
  599.     /* Nur zentrieren, wenn kein andere Pos bekannt. */
  600.     if (rp_box_x == 0 && rp_box_y == 0)
  601.         form_center(repask, &d, &d, &d, &d);
  602.     else
  603.     {
  604.         repask[0].ob_x = rp_box_x;
  605.         repask[0].ob_y = rp_box_y;
  606.     }
  607.     loc_r_modus = r_modus;
  608.     
  609.     while((erg=suchen(t_ptr, &such_len))==1)
  610.     {
  611.         delta = rpl_len-such_len;
  612.         if (start->len + delta > MAX_LINE_LEN)
  613.         {
  614.             inote(1, 0, TOOLONG, MAX_LINE_LEN);
  615.             erg = -1;
  616.             break;
  617.         }
  618.         text_len = start->len-text_x;
  619.         t_ptr->cursor_line = start;
  620.         t_ptr->xpos = text_x;
  621.         t_ptr->ypos = text_y;
  622.         if (loc_r_modus != RP_ALL)             /* Optional oder einzeln */
  623.         {
  624.             blk_demark(t_ptr);
  625.             make_chg(t_ptr->link,POS_CHANGE,0);
  626.             restore_edit();
  627.             if (loc_r_modus == RP_OPT)
  628.             {
  629.                 int antw;
  630.  
  631.                 blk_mark(t_ptr,0);
  632.                 t_ptr->xpos = text_x+such_len;
  633.                 blk_mark(t_ptr,1);
  634.                 restore_edit();
  635.  
  636.                 antw = simple_mdial(repask, 0) & 0x7fff;
  637.  
  638.                 /* die Pos des Dialogs merken */
  639.                 rp_box_x = repask[0].ob_x;
  640.                 rp_box_y = repask[0].ob_y;
  641.  
  642.                 if (antw == RAALL)                    /* ab jetzt nicht mehr fragen */
  643.                     loc_r_modus = RP_ALL;
  644.                 else if (antw ==  RANEIN)            /* Nicht ersetzen */
  645.                 {
  646.                     if (vorw)
  647.                     {
  648.                         text_x++;
  649.                         text_len--;
  650.                     }
  651.                     else
  652.                     {
  653.                         text_len = text_x+such_len-1;
  654.                         text_x = 0;
  655.                     }
  656.                     continue;
  657.                 }
  658.                 else if (antw == RAENDE)            /* aufhören */
  659.                 {
  660.                     erg = -1;
  661.                     break;
  662.                 }
  663.                 blk_demark(t_ptr);
  664.             }
  665.         }
  666.         anz ++;
  667.         get_undo_col(t_ptr);
  668.         ptr = REALLOC(&start, text_x, delta);
  669.         memcpy(ptr, replace_txt, rpl_len);
  670.         t_ptr->cursor_line = start;
  671.         if (loc_r_modus != RP_ALL)
  672.         {
  673.             make_chg(t_ptr->link,LINE_CHANGE,t_ptr->ypos);
  674.             restore_edit();
  675.             if (loc_r_modus == RP_FIRST) 
  676.                 break;
  677.         }
  678.         if (vorw)
  679.         {
  680.             text_x += rpl_len;
  681.             text_len += delta;
  682.             text_len -= rpl_len;
  683.         }
  684.         else
  685.         {
  686.             text_len = text_x;
  687.             text_x = 0;
  688.         }
  689.     }
  690.     graf_mouse(ARROW, NULL);
  691.     if (anz > 0L)
  692.     {
  693.         t_ptr->moved++;
  694.         make_chg(t_ptr->link,POS_CHANGE,0);         /* wg. `*'    */
  695.         if (loc_r_modus == RP_ALL)
  696.         {
  697.             if (t_ptr->block)
  698.             {
  699.                 t_ptr->p1 = get_line(&t_ptr->text,t_ptr->z1);
  700.                 t_ptr->p2 = get_line(&t_ptr->text,t_ptr->z2);
  701.                 blk_demark(t_ptr);
  702.             }
  703.             make_chg(t_ptr->link,TOTAL_CHANGE,0);
  704.         }
  705.         if (loc_r_modus != RP_FIRST)
  706.         {
  707.             char    info[30];
  708.  
  709.             sprintf(info, rsc_string(REPLACESTR), anz);
  710.             set_info(t_ptr, info);
  711.         }
  712.         if (erg!=-1)
  713.             erg = 1;
  714.     }
  715.     else
  716.         if (erg != -1) 
  717.             erg = 0;
  718.     restore_edit();
  719.     return erg;
  720. }
  721.  
  722. int do_next(TEXTP t_ptr)
  723. {
  724.     int    erg;
  725.     bool    vorw;
  726.  
  727.     vorw = (shift_pressed()) ? (!s_vorw) : s_vorw;
  728.     set_suchmode(s_str, r_str, s_grkl, s_quant, vorw, s_wort, FALSE, s_round);
  729.     if (last_op == 1)
  730.         erg = start_find(t_ptr,FALSE);
  731.     else if (last_op == 2)
  732.         erg = start_replace(t_ptr);
  733.     else
  734.         erg = -1;
  735.     return erg;
  736. }
  737.  
  738. void find_selection(TEXTP t_ptr)
  739. {
  740.     if (t_ptr->block)
  741.     {
  742.         RING    r;
  743.         bool    vorw;
  744.         
  745.         block_copy(t_ptr, &r);
  746.         if (strlen(TEXT(FIRST(&r))) > 0)
  747.         {
  748.             strncpy(s_str, TEXT(FIRST(&r)), HIST_LEN);
  749.             kill_textring(&r);
  750.             s_str[HIST_LEN] = EOS;
  751.             vorw = (shift_pressed()) ? (!s_vorw) : s_vorw;
  752.             set_suchmode(s_str, r_str, s_grkl, s_quant, vorw, s_wort, FALSE, s_round);
  753.             if (start_find(t_ptr, FALSE) == 0)
  754.                 Bconout(2, 7);
  755.         }
  756.     }
  757. }
  758.  
  759.  
  760. bool filematch(char *str, char *m, int fs_typ)
  761. {
  762.     char     *where, muster[HIST_LEN+1];
  763.     int        i;
  764.     bool    gk = FALSE, old_flg[2];
  765.  
  766.     if ((str[0] == EOS) || (m[0] == EOS))
  767.         return FALSE;
  768.     
  769.     if ((m[0] == '*') && (m[1] == '.'))        /* Ist m eine Extension? */
  770.         gk = FALSE;                                    /* dann Gro₧ == klein! */
  771.     else
  772.     {
  773.         if (fs_typ == -1)
  774.             fs_typ = fs_case_sens((char *)str);
  775.         /* Echter GRkl-Unterscheidung nur bei Minix */
  776.         gk = (fs_typ == FULL_CASE);
  777.     }
  778.  
  779.     old_flg[0] = (modus != M_CURSOR);
  780.     old_flg[1] = round;
  781.  
  782.     sprintf(muster, "^%s$", m);
  783.     set_suchmode(muster, "", gk, TRUE, TRUE, FALSE, FALSE, FALSE);
  784.     where = STRSTR2((char*)str, (int) strlen(str), muster_txt, &i);
  785.  
  786.     /* 
  787.      * Für den Fall, das ein Projekt durchsucht wird, wird filematch() für
  788.      * die Zuordnung der lokalen Optionen für jede durchsuchte Datei einmal
  789.      * aufgerufen. Damit danach die eigentlichen Such-Parameter wieder stimmen,
  790.      * der folgende Befehl!
  791.     */
  792.     set_suchmode(s_str, r_str, s_grkl, s_quant, s_vorw, s_wort, old_flg[0], old_flg[1]);
  793.  
  794.     return (where==str);
  795. }
  796.  
  797. /* Such-Dialoge *************************************************************/
  798.  
  799. static void insert_history(char h[HIST_ANZ][HIST_LEN+1], char *str)
  800. {
  801.     int    i,j;
  802.     char    old_history[HIST_ANZ][HIST_LEN+1];
  803.  
  804.     /* alte History merken */
  805.     memcpy(old_history[0], h[0], HIST_ANZ*(HIST_LEN+1));
  806.     strcpy(h[0], str);
  807.     j = 1;
  808.     /* n-1 kopieren */
  809.     for (i = 0; i < (HIST_ANZ - 1); i++)
  810.     {
  811.         /* jeden Eintrag nur einmal */
  812.         if ((old_history[i][0] != EOS) && (strcmp(old_history[i], h[0])!=0))
  813.         {
  814.             strcpy(h[j], old_history[i]);
  815.             j++;
  816.         }
  817.     }
  818. }
  819.  
  820.  
  821. static bool build_popup(char h[HIST_ANZ][HIST_LEN+1], POPUP *pop)
  822. {
  823.     char    str[HIST_LEN + 1];
  824.     int    i;
  825.  
  826.     pop->tree = NULL;            /* init */
  827.  
  828.     if (h[0][0] == EOS)
  829.         return FALSE;
  830.     
  831.     strcpy(str, " ");
  832.     strcat(str, h[0]);
  833.     create_popup(pop, HIST_ANZ, HIST_LEN + 3, str);
  834.  
  835.     for (i = 1; i < HIST_ANZ; i++)
  836.     {
  837.         if (h[i][0] != EOS)
  838.         {
  839.             strcpy(str, " ");
  840.             strcat(str, h[i]);
  841.             append_popup(pop, str);
  842.         }
  843.     }
  844.     return (pop->tree != NULL);
  845. }
  846.  
  847.  
  848. static int circle_popup(char h[HIST_ANZ][HIST_LEN+1], void *dial, OBJECT* tree, int text_obj, int pos)
  849. {
  850.     if ((pos + 1 < HIST_ANZ) && (h[pos + 1][0] != EOS))
  851.         pos++;
  852.     else
  853.         pos = 0;
  854.     set_string(tree, text_obj, h[pos]);
  855.     redraw_mdobj(dial, text_obj);
  856.     return pos;
  857. }
  858.  
  859.  
  860. /*
  861.  * Suchen/Ersetzen in Texten
  862.  * Rückgabe:     0: Abbruch
  863.  *                    1: Suchen
  864.  *                    2: Ersetzen
  865. */
  866. int replace_dial(void)
  867. {
  868.     int    antw, d, r_cycle, s_cycle;
  869.     bool    im_kreis, s_p_v, r_p_v;            /* *_popup_valid */
  870.     bool    close = FALSE;
  871.     MDIAL    *dial;
  872.     POPUP    s_pop, r_pop;
  873.     char    s[HIST_LEN+1];
  874.             
  875.     /* Klemmbrett sichern, damit die Dialog das aktuelle haben */
  876.     save_clip();
  877.  
  878.     set_state(replace, RPGLOBAL, SELECTED, s_global);
  879.     set_state(replace, RPCURSOR, SELECTED, !s_global);
  880.     set_state(replace, RPROUND, SELECTED, s_round);
  881.  
  882.     set_string(replace, RPTEXT1, s_str);
  883.     set_string(replace, RPTEXT2, r_str);
  884.     set_state(replace, RPGRKL, SELECTED, s_grkl);
  885.     set_state(replace, RPWILD, SELECTED, s_quant);
  886.     set_state(replace, RPWORT, SELECTED, s_wort);
  887.     set_state(replace, RPVORW, SELECTED, s_vorw);
  888.     set_state(replace, RPRUCKW, SELECTED, !s_vorw);
  889.     set_state(replace, RPFIRST, SELECTED, r_modus==RP_FIRST);
  890.     set_state(replace, RPALL, SELECTED, r_modus==RP_ALL);
  891.     set_state(replace, RPOPTION, SELECTED, r_modus==RP_OPT);
  892.  
  893.     s_p_v = build_popup(s_history, &s_pop);
  894.     r_p_v = build_popup(r_history, &r_pop);
  895.  
  896.     /* Popups ggf. abschalten */
  897.     set_state(replace, RPSHIST, DISABLED, !s_p_v);
  898.     set_state(replace, RPEHIST, DISABLED, !r_p_v);
  899.  
  900.     s_cycle = 0;
  901.     r_cycle = 0;
  902.     dial = open_mdial(replace, RPTEXT1);
  903.     if (dial != NULL)
  904.     {
  905.         while (!close)
  906.         {
  907.             antw = do_mdial(dial) & 0x7fff;
  908.             switch (antw)
  909.             {
  910.                 case RPSSTR :
  911.                     if (s_p_v)
  912.                         s_cycle = circle_popup(s_history, dial, replace, RPTEXT1, s_cycle);
  913.                     break;
  914.                 case RPSHIST :
  915.                     if (s_p_v)
  916.                     {
  917.                         d = handle_popup(replace, RPSHIST, s_pop.tree, 0, POP_OPEN);
  918.                         if (d > 0)
  919.                         {
  920.                             s_cycle = d;
  921.                             get_string(s_pop.tree, s_cycle, s);
  922.                             set_string(replace, RPTEXT1, s+1);
  923.                             redraw_mdobj(dial, RPTEXT1);
  924.                         }
  925.                     }
  926.                     break;
  927.         
  928.                 case RPESTR :
  929.                     if (r_p_v)
  930.                         r_cycle = circle_popup(r_history, dial, replace, RPTEXT2, r_cycle);
  931.                     break;
  932.                 case RPEHIST :
  933.                     if (r_p_v)
  934.                     {
  935.                         d = handle_popup(replace, RPEHIST, r_pop.tree, 0, POP_OPEN);
  936.                         if (d > 0)
  937.                         {
  938.                             r_cycle = d;
  939.                             get_string(r_pop.tree, r_cycle, s);
  940.                             set_string(replace, RPTEXT2, s+1);
  941.                             redraw_mdobj(dial, RPTEXT2);
  942.                         }
  943.                     }
  944.                     break;
  945.         
  946.                 case RPHELP :
  947.                     menu_help(TSEARCH, MFIND);
  948.                     set_state(replace, antw, SELECTED, FALSE);
  949.                     redraw_mdobj(dial, antw);
  950.                     break;
  951.         
  952.                 default:
  953.                     close = TRUE;
  954.                     break;
  955.             }
  956.         }
  957.         close_mdial(dial);
  958.         set_state(replace, antw, SELECTED, FALSE);
  959.         if (antw == RPOK || antw == RPERSATZ)
  960.         {
  961.             get_string(replace, RPTEXT1, s_str);
  962.             get_string(replace, RPTEXT2, r_str);
  963.             if ((strcmp(s_str, r_str) == 0) && (antw == RPERSATZ))
  964.             {
  965.                 note(1, 0, RPSAME);
  966.                 return 0;
  967.             }
  968.             s_grkl    = get_state(replace,RPGRKL, SELECTED);
  969.             s_quant    = get_state(replace,RPWILD, SELECTED);
  970.             s_wort    = get_state(replace,RPWORT, SELECTED);
  971.             s_vorw = get_state(replace,RPVORW, SELECTED);
  972.             s_global = get_state(replace,RPGLOBAL, SELECTED);
  973.             s_round    = get_state(replace,RPROUND, SELECTED);
  974.     
  975.             if (get_state(replace, RPFIRST, SELECTED))
  976.                 r_modus = RP_FIRST;
  977.             else if (get_state(replace, RPALL, SELECTED))
  978.                 r_modus = RP_ALL;
  979.             else
  980.                 r_modus = RP_OPT;
  981.     
  982.             if (s_str[0] != EOS)
  983.                 insert_history(s_history, s_str);
  984.             if (r_str[0] != EOS)
  985.                 insert_history(r_history, r_str);
  986.     
  987.             im_kreis = s_round && (antw == RPOK);    /* 'im Kreis' nur bei Suchen, nicht beim Ersetzen */
  988.             set_suchmode(s_str, r_str, s_grkl, s_quant, s_vorw, s_wort, s_global, im_kreis);
  989.             return ((antw == RPOK) ? 1 : 2);
  990.         }
  991.     }
  992.     if (s_p_v)
  993.         free_popup(&s_pop);
  994.     if (r_p_v)
  995.         free_popup(&r_pop);
  996.     return 0;
  997. }
  998.  
  999. /*
  1000.  * Suchen auf Disk / in Projekt
  1001. */
  1002. bool findfile_dial(char *ff_path, bool in_prj)
  1003. {
  1004.     PATH    new_path = "", str = "";
  1005.     char     s[HIST_LEN+1];
  1006.     int    antw, cycle, d;
  1007.     bool    close = FALSE, p_v;
  1008.     MDIAL    *dial;
  1009.     POPUP    pop;
  1010.         
  1011.     save_clip();
  1012.  
  1013.     if (in_prj)                            /* Suche im Projekt */
  1014.     {
  1015.         set_string(find_obj, FFTITLE, rsc_string(FFSTR2));
  1016.         set_state(find_obj, FFSELP, DISABLED, TRUE);
  1017.         set_state(find_obj, FFREK, DISABLED, TRUE);
  1018.         set_state(find_obj, FFREK, SELECTED, FALSE);
  1019.         make_shortpath(ff_path, str, 50);
  1020.     }    
  1021.     else                                    /* Suche nach Dateien */
  1022.     {
  1023.         set_string(find_obj, FFTITLE, rsc_string(FFSTR1));
  1024.         set_state(find_obj, FFSELP, DISABLED, FALSE);
  1025.         set_state(find_obj, FFREK, DISABLED, FALSE);
  1026.         set_state(find_obj, FFREK, SELECTED, ff_rekursiv);
  1027.         strcpy(new_path, ff_path);
  1028.         if (ff_path[0] != EOS)
  1029.             make_shortpath(ff_path, str, 50);
  1030.     }
  1031.     set_string(find_obj, FFPATH, str);
  1032.     set_string(find_obj, FFMASK, ff_mask);
  1033.     set_string(find_obj, FFTEXT, s_str);
  1034.     set_state(find_obj, FFGRKL, SELECTED, s_grkl);
  1035.     set_state(find_obj, FFWILD, SELECTED, s_quant);
  1036.     set_state(find_obj, FFWORT, SELECTED, s_wort);
  1037.  
  1038.     p_v =    build_popup(s_history, &pop);
  1039.  
  1040.     /* Popup ggf. abschalten */
  1041.     set_state(find_obj, FFHIST, DISABLED, !p_v);
  1042.  
  1043.     cycle = 0;
  1044.  
  1045.     dial = open_mdial(find_obj, in_prj ? FFTEXT : FFMASK);
  1046.     if (dial != NULL)
  1047.     {
  1048.         while (!close)
  1049.         {
  1050.             antw = do_mdial(dial) & 0x7fff;
  1051.  
  1052.             switch (antw)
  1053.             {
  1054.                 case FFSTR :
  1055.                     if (p_v)
  1056.                         cycle = circle_popup(s_history, dial, find_obj, FFTEXT, cycle);
  1057.                     break;
  1058.                 case FFHIST:
  1059.                     if (p_v)
  1060.                     {
  1061.                         d = handle_popup(find_obj, FFHIST, pop.tree, 0, POP_OPEN);
  1062.                         if (d > 0)
  1063.                         {
  1064.                             cycle = d;
  1065.                             get_string(pop.tree, cycle, s);
  1066.                             set_string(find_obj, FFTEXT, s+1);
  1067.                             redraw_mdobj(dial, FFTEXT);
  1068.                         }
  1069.                     }
  1070.                     break;
  1071.  
  1072.                 case FFSELP:
  1073.                     if (select_path(new_path, rsc_string(SELPATHSTR)))
  1074.                         set_string(find_obj, FFPATH, new_path);
  1075.                     break;
  1076.     
  1077.                 case FFHELP :
  1078.                     menu_help(TSEARCH, MFIND);
  1079.                     break;
  1080.     
  1081.                 default:
  1082.                     close = TRUE;
  1083.                     break;
  1084.             }
  1085.             if (!close)
  1086.             {
  1087.                 set_state(find_obj, antw, SELECTED, FALSE);
  1088.                 redraw_mdobj(dial, antw);
  1089.             }
  1090.         }
  1091.         close_mdial(dial);
  1092.         set_state(find_obj, antw, SELECTED, FALSE);
  1093.         if (antw == FFOK)
  1094.         {
  1095.             get_string(find_obj, FFTEXT, s_str);
  1096.             get_string(find_obj, FFMASK, ff_mask);
  1097.             ff_rekursiv = get_state(find_obj, FFREK, SELECTED);
  1098.             s_grkl    = get_state(find_obj, FFGRKL, SELECTED);
  1099.             s_quant    = get_state(find_obj, FFWILD, SELECTED);
  1100.             s_wort    = get_state(find_obj, FFWORT, SELECTED);
  1101.             if (!in_prj)
  1102.                 strcpy(ff_path, new_path);
  1103.             if (s_str[0] != EOS)
  1104.                 insert_history(s_history, s_str);
  1105.             set_suchmode(s_str, "", s_grkl, s_quant, TRUE, s_wort, TRUE, FALSE);
  1106.             if (in_prj && s_str[0] == EOS)
  1107.                 return FALSE;
  1108.             else
  1109.                 return TRUE;
  1110.         }
  1111.     }
  1112.     return FALSE;
  1113. }
  1114.  
  1115.  
  1116.     
  1117. /*****************************************************************************/
  1118. /*
  1119.  * Umlaute konvertieren
  1120. */
  1121.  
  1122. static char umlaute[8][7] =
  1123. {    /* ä      Ä      ö      Ö      ü      Ü      ₧    */
  1124.     { 0x84, 0x8E, 0x94, 0x99, 0x81, 0x9A, 0x9E},    /* Atari */
  1125.     { 0xE4, 0xC4, 0xF6, 0xD6, 0xFC, 0xDC, 0xDF},    /* Latin */
  1126.     { 0x8A, 0x80, 0x9A, 0x85, 0x9F, 0x86, 0xA7},    /* Mac */
  1127.     { 0x84, 0x8E, 0x94, 0x99, 0x81, 0x9A, 0xE1},    /* PC */
  1128.     {  'a',  'A',  'o',  'O',  'u',  'U',  's'},    /* LaTeX */
  1129.     {  'a',  'A',  'o',  'O',  'u',  'U',  's'},    /* HTML */
  1130.     {  'a',  'A',  'o',  'O',  'u',  'U',  's'},    /* ASCII */
  1131. };
  1132.  
  1133.  
  1134. void change_umlaute(TEXTP t_ptr)
  1135. {
  1136.     ZEILEP    lauf;
  1137.     int        x, update;
  1138.     long        l;
  1139.     bool        cont = TRUE;
  1140.     bool        changed = FALSE;
  1141.     
  1142.     lauf = FIRST(&t_ptr->text);
  1143.     if (lauf != NULL)
  1144.     {
  1145.         x = bild_pos(t_ptr->xpos, t_ptr->cursor_line, TRUE, t_ptr->loc_opt->tabsize);
  1146.         start_aktion(rsc_string(UMLAUTSTR), TRUE, t_ptr->text.lines);
  1147.         l = 0;
  1148.         if (t_ptr->text.lines < 200)
  1149.             update = 10;
  1150.         else
  1151.             update = 100;
  1152.  
  1153.         graf_mouse(HOURGLASS, NULL);
  1154.  
  1155.         while (cont && !IS_TAIL(lauf))
  1156.         {
  1157.             if (lauf->len > 0)
  1158.             {
  1159.                 int    u, xpos, len;
  1160.                 char    c;
  1161.                     
  1162.                 xpos = 0;
  1163.                 while (xpos < lauf->len)
  1164.                 {
  1165.                     c = TEXT(lauf)[xpos];
  1166.                     if (c > 127)
  1167.                     {
  1168.                         for (u = 0; u <= 7; u++)
  1169.                             if (c == umlaute[umlaut_from][u])
  1170.                                 break;
  1171.                 
  1172.                         if (u < 7)
  1173.                         {
  1174.                             changed = TRUE;
  1175.                             if (umlaut_to == LaTeX)
  1176.                             {
  1177.                                 if (lauf->len + 1 <= MAX_LINE_LEN)
  1178.                                 {
  1179.                                     TEXT(lauf)[xpos] = '"';
  1180.                                     xpos++;
  1181.                                     *(REALLOC(&lauf, xpos, 1)) = umlaute[umlaut_to][u];
  1182.                                 }
  1183.                                 else
  1184.                                     inote(1, 0, TOOLONG, MAX_LINE_LEN);
  1185.                             }
  1186.                             else if (umlaut_to == ASCII)
  1187.                             {
  1188.                                 if (lauf->len + 1 <= MAX_LINE_LEN)
  1189.                                 {
  1190.                                     TEXT(lauf)[xpos] = umlaute[umlaut_to][u];
  1191.                                     xpos++;
  1192.                                     if (u == 6)
  1193.                                         *(REALLOC(&lauf, xpos, 1)) = 's';
  1194.                                     else
  1195.                                         *(REALLOC(&lauf, xpos, 1)) = 'e';
  1196.                                 }
  1197.                                 else
  1198.                                     inote(1, 0, TOOLONG, MAX_LINE_LEN);
  1199.                             }
  1200.                             else if (umlaut_to == HTML)
  1201.                             {
  1202.                                 /* ä ß */
  1203.                                 char    new[7] = "Xuml;";
  1204.  
  1205.                                 if (u == 6)
  1206.                                     strcpy(new, "szlig;");
  1207.                                 else
  1208.                                     new[0] = umlaute[umlaut_to][u];
  1209.                                 len = (int)strlen(new);
  1210.                                 if (lauf->len + len <= MAX_LINE_LEN)
  1211.                                 {
  1212.                                     TEXT(lauf)[xpos] = '&';
  1213.                                     xpos++;
  1214.                                     INSERT(&lauf, xpos, len, new);
  1215.                                     xpos += len-1;
  1216.                                 }
  1217.                                 else
  1218.                                     inote(1, 0, TOOLONG, MAX_LINE_LEN);
  1219.                             }
  1220.                             else
  1221.                                 TEXT(lauf)[xpos] = umlaute[umlaut_to][u];
  1222.                         }
  1223.                     }
  1224.                     xpos++;
  1225.                 } /* while xpos */
  1226.             } /* while lauf */
  1227.             NEXT(lauf);
  1228.  
  1229.             l++;
  1230.             if (l % update == 0)
  1231.                 cont = do_aktion("", l);
  1232.         }
  1233.         
  1234.         graf_mouse(ARROW, NULL);
  1235.         end_aktion();
  1236.  
  1237.         if (changed)
  1238.         {
  1239.             t_ptr->moved++;
  1240.             t_ptr->cursor_line = get_line(&t_ptr->text, t_ptr->ypos);
  1241.             t_ptr->xpos = inter_pos(x, t_ptr->cursor_line, TRUE, t_ptr->loc_opt->tabsize);
  1242.             make_chg(t_ptr->link, WT_CHANGE, 0);
  1243.             make_chg(t_ptr->link, TOTAL_CHANGE, 0);
  1244.             t_ptr->max_line = NULL;
  1245.  
  1246.             if (t_ptr->loc_opt->umbrechen)
  1247.                 total_format(t_ptr);
  1248.  
  1249.             restore_edit();
  1250.         }
  1251.     }
  1252. }
  1253.  
  1254. bool umlaut_dial(void)
  1255. {
  1256.     bool    ret = FALSE, close = FALSE;
  1257.     int    antw, new_from, new_to, d;
  1258.     MDIAL    *dial;
  1259.     char    str[30];
  1260.         
  1261.     new_from = umlaut_from;
  1262.     new_to = umlaut_to;
  1263.     if (shift_pressed())                /* bei Shift: Quelle und Ziel vertauschen */
  1264.     {
  1265.         if (umlaut_to <= PC)            /* nur einbuchstabige können umgedreht werden! */
  1266.         {
  1267.             new_from = umlaut_to;
  1268.             new_to = umlaut_from;
  1269.         }
  1270.         else
  1271.         {
  1272.             Bconout(2, 7);
  1273.             return FALSE;
  1274.         }
  1275.     }
  1276.     get_string(popups, UPFROMST + new_from, str);
  1277.     set_string(umlautkonv, UVON, str);
  1278.     get_string(popups, UPTOST + new_to, str);
  1279.     set_string(umlautkonv, UNACH, str);
  1280.  
  1281.     dial = open_mdial(umlautkonv, 0);
  1282.     if (dial != NULL)
  1283.     {
  1284.         while (!close)
  1285.         {
  1286.             antw = do_mdial(dial) & 0x7fff;
  1287.             switch (antw)
  1288.             {
  1289.                 case UVSTR :
  1290.                 case UVON :
  1291.                     if (antw == UVON)
  1292.                         d = handle_popup(umlautkonv, UVON, popups, UMLAUTPOP1, POP_OPEN);
  1293.                     else
  1294.                         d = handle_popup(umlautkonv, UVON, popups, UMLAUTPOP1, POP_CYCLE);
  1295.                     if (d > 0)
  1296.                         new_from = d - UPFROMST;
  1297.                     break;
  1298.                 case UNSTR :
  1299.                 case UNACH :
  1300.                     if (antw == UNACH)
  1301.                         d = handle_popup(umlautkonv, UNACH, popups, UMLAUTPOP2, POP_OPEN);
  1302.                     else
  1303.                         d = handle_popup(umlautkonv, UNACH, popups, UMLAUTPOP2, POP_CYCLE);
  1304.                     if (d > 0)
  1305.                         new_to = d - UPTOST;
  1306.                     break;
  1307.  
  1308.                 default:
  1309.                     close = TRUE;
  1310.                     break;
  1311.             }
  1312.         }
  1313.         set_state(umlautkonv, antw, SELECTED, FALSE);
  1314.         close_mdial(dial);
  1315.         if (antw == UKSTART)
  1316.         {
  1317.             if (new_from == new_to)
  1318.             {
  1319.                 note(1, 0, NOKONV);
  1320.                 ret = FALSE;
  1321.             }
  1322.             else
  1323.             {
  1324.                 umlaut_from = new_from;
  1325.                 umlaut_to = new_to;
  1326.                 ret = TRUE;
  1327.             }
  1328.         }
  1329.     }
  1330.     return ret;
  1331. }
  1332.