home *** CD-ROM | disk | FTP | other *** search
/ M.u.C.S. Disc 2000 / MUCS2000.iso / anwend / qed453 / src / umbruch.c < prev    next >
C/C++ Source or Header  |  1998-03-15  |  11KB  |  452 lines

  1. #include "global.h"
  2. #include "ausgabe.h"
  3. #include "block.h"
  4. #include "clipbrd.h"
  5. #include "edit.h"
  6. #include "memory.h"
  7. #include "set.h"
  8. #include "tasten.h"
  9. #include "text.h"
  10. #include "window.h"
  11. #include "umbruch.h"
  12.  
  13. /* Muessen am Anfang jeden Umbruchs gesetzt werden */
  14. static bool    tab;
  15. static int        tab_size, lineal_len;
  16. static SET        umbruch_set;
  17.  
  18. static bool Absatz        (ZEILEP col);
  19. static bool too_short    (TEXTP t_ptr, ZEILEP col, long y);
  20. static bool too_long     (TEXTP t_ptr, ZEILEP col, long y);
  21.  
  22. void save_absatz(TEXTP t_ptr)
  23. /* Es werden LZ und TABs am Absatzende gelöscht */
  24. /* und im Absatz hinzugefügt                            */
  25. {
  26.     bool        action = FALSE;
  27.     int        i;
  28.     char        c;
  29.     ZEILEP    lauf;
  30.  
  31.     setcpy(umbruch_set,t_ptr->loc_opt->umbruch_set);/* !! Mu₧ gesetzt werden !! */
  32.     setincl(umbruch_set,' ');                                /* wenigstens das */
  33.     lauf = FIRST(&t_ptr->text);
  34.     while (!IS_TAIL(lauf))
  35.     {
  36.         if (IS_ABSATZ(lauf))                    /* Absatz => LZ und TAB löschen */
  37.         {
  38.             for (i=lauf->len; (--i)>=0 ; )
  39.             {
  40.                 c = TEXT(lauf)[i];
  41.                 if (c!=' ' && c!='\t') break;
  42.             }
  43.             i++;
  44.             if (i<lauf->len)        /* Zeile verkürzen */
  45.             {
  46.                 REALLOC(&lauf,i,i-lauf->len);
  47.                 action = TRUE;
  48.             }
  49.         }
  50.         else                                /* Nicht Absatz => LZ anhängen */
  51.         {
  52.             c = TEXT(lauf)[lauf->len-1];
  53.             if (!setin(umbruch_set,c) && lauf->len < MAX_LINE_LEN)
  54.             {
  55.                 *REALLOC(&lauf,lauf->len,1) = ' ';
  56.                 action = TRUE;
  57.             }
  58.         }
  59.         NEXT(lauf);
  60.     }
  61.     if (action)        /* Es wurde etwas verändert */
  62.     {
  63.         make_chg(t_ptr->link,TOTAL_CHANGE,0);
  64.         t_ptr->moved++;
  65.         lauf = t_ptr->cursor_line = get_line(&t_ptr->text,t_ptr->ypos);
  66.         if (t_ptr->xpos>lauf->len)
  67.         {
  68.             t_ptr->xpos = lauf->len;
  69.             make_chg(t_ptr->link,POS_CHANGE,0);
  70.         }
  71.     }
  72. }
  73.  
  74. static bool Absatz(ZEILEP col)
  75. /* TRUE : Die Zeile ist die letzte Zeile eines Absatz */
  76. /* FALSE : sonst                                                    */
  77. {
  78.     int    col_len = col->len;
  79.     char    c = TEXT(col)[col_len-1];
  80.  
  81.     return (col_len==0 || IS_LAST(col) || !setin(umbruch_set,c));
  82. }
  83.  
  84. void make_absatz(TEXTP t_ptr)
  85. /* Absatzmarkierungen anbringen oder löschen */
  86. {
  87.     ZEILEP lauf;
  88.  
  89.     setcpy(umbruch_set,t_ptr->loc_opt->umbruch_set);/* !! Mu₧ gesetzt werden !! */
  90.     setincl(umbruch_set,' ');                                /* wenigstens das */
  91.     lauf = FIRST(&t_ptr->text);
  92.     if (t_ptr->loc_opt->umbrechen)
  93.         while (!IS_TAIL(lauf))
  94.         {
  95.             if (Absatz(lauf))
  96.                 lauf->info |= ABSATZ;
  97.             else
  98.                 lauf->info &= (~ABSATZ);        /* z.B. CR setzt immer Bit */
  99.             NEXT(lauf);
  100.         }
  101.     else
  102.         while (!IS_TAIL(lauf))
  103.         {
  104.             lauf->info &= (~ABSATZ);
  105.             NEXT(lauf);
  106.         }
  107. }
  108.  
  109. static int long_brk(ZEILEP col)
  110. /* Zeile ist zu lang. Wo soll sie abgebrochen werden (mind. ein Wort) */
  111. {
  112.     int    off, pos;
  113.     char    c, *str;
  114.  
  115.     off = col_offset(col);
  116.     pos = inter_pos(lineal_len,col,tab,tab_size);
  117.     str = TEXT(col)+pos;
  118.     pos--;
  119.     c = *(--str);
  120.    if (!setin(umbruch_set,c))
  121.         while (pos>off && setin(umbruch_set,c))                    /* Wortende suchen */
  122.         {
  123.             pos--;
  124.             c = *(--str);
  125.         }
  126.     while (pos>off && !setin(umbruch_set,c))                        /* Wortanfang suchen */
  127.     {
  128.         pos--;
  129.         c = *(--str);
  130.     }
  131.     if (pos<=off)                                                            /* nach rechts */
  132.     {
  133.         pos = inter_pos(lineal_len,col,tab,tab_size);
  134.         str = TEXT(col)+pos;
  135.         c = *str++;
  136.         while (pos<=col->len && setin(umbruch_set,c))            /* Wortanf suchen */
  137.         {
  138.             pos++;
  139.             c = *str++;
  140.         }
  141.         while (pos<=col->len && !setin(umbruch_set,c))            /* Wortende suchen */
  142.         {
  143.             pos++;
  144.             c = *str++;
  145.         }
  146.         while (pos<=col->len && setin(umbruch_set,c))            /* Wortanf suchen */
  147.         {
  148.             pos++;
  149.             c = *str++;
  150.         }
  151.         if (pos>=col->len)
  152.             return 0;                                                        /* nichts machen */
  153.     }
  154.     else
  155.         pos++;
  156.     return pos;
  157. }
  158.  
  159. static int short_brk(ZEILEP col, int len)
  160. /* Einer Zeile fehlen Zeichen, sie ist jetzt im Bild len lang */
  161. /* Wo soll der Nachfolger (col) hochgezogen werden (mind. ein Wort) */
  162. {
  163.     char    *str, c;
  164.     int    pos, merk_pos;
  165.  
  166.     pos = col_offset(col);
  167.     str = TEXT(col)+pos;
  168.     merk_pos = -1;
  169.     if (!tab)
  170.     {
  171.         while (TRUE)
  172.         {
  173.             if (pos>=col->len) return col->len;                    /* ganze Zeile */
  174.             c = *str++;
  175.             pos++;
  176.             len++;
  177.             if (len>lineal_len) break;                                /* jetzt reichts */
  178.             if (setin(umbruch_set,c))
  179.                 merk_pos = pos;
  180.         }
  181.     }
  182.     else
  183.     {
  184.         int tabH;
  185.  
  186.         tabH = tab_size-(len%tab_size);
  187.         while (TRUE)
  188.         {
  189.             if (pos>=col->len) return col->len;                    /* ganze Zeile */
  190.             c = *str++;
  191.             pos++;
  192.             if (c=='\t')
  193.             {
  194.                 len += tabH;
  195.                 tabH = tab_size;
  196.             }
  197.             else
  198.             {
  199.                 len++;
  200.                 if ((--tabH)==0) tabH = tab_size;
  201.             }
  202.             if (len>lineal_len) break;                                /* jetzt reichts */
  203.             if (setin(umbruch_set,c))
  204.                 merk_pos = pos;
  205.         }
  206.     }
  207.     if (merk_pos>0) pos = merk_pos;
  208.     else pos = 0;                                                        /* nichts zu machen */
  209.     return(pos);
  210. }
  211.  
  212. /* !!! cursor_line mu₧ hinterher entsprechend ypos gesetzt werden !!! */
  213. static bool too_long(TEXTP t_ptr, ZEILEP col, long y)
  214. {
  215.     int    i, len, off;
  216.     bool    absatz, weiter, changed;
  217.  
  218.     changed = FALSE;
  219.     weiter = FALSE;
  220.     while (bild_len(col,t_ptr->loc_opt->tab,t_ptr->loc_opt->tabsize)>lineal_len)                            /* Zeile zu lang */
  221.     {
  222.         i = long_brk(col);                                        /* wo abbrechen */
  223.         if (i==0)
  224.         {
  225.             weiter = FALSE;
  226.             break;
  227.         }
  228.         absatz = IS_ABSATZ(col);
  229.         len = col->len-i;                                            /* soviel abschneiden */
  230.         if (absatz || col->nachf->len + len >= MAX_LINE_LEN)    /* col_split */
  231.         {
  232.             ZEILEP help;
  233.  
  234.             col_split(&col,i);
  235.             t_ptr->text.lines++;
  236.             if (t_ptr->ypos>y) t_ptr->ypos++;
  237.             help = col->nachf;
  238.             off = col_einrucken(&help);
  239.             if (t_ptr->ypos==y && t_ptr->xpos>i)            /* Cursor umbrechen */
  240.             {
  241.                 t_ptr->ypos++;
  242.                 t_ptr->xpos -= (i-off);
  243.             }
  244.             weiter = TRUE;
  245.         }
  246.         else                                                            /* Text rumschieben */
  247.         {
  248.             ZEILEP help = col->nachf;
  249.  
  250.             off = col_offset(help);
  251.             INSERT(&help,off,len,TEXT(col)+i);                /* Next verlängern */
  252.             REALLOC(&col,i,-len);                                /* Zeile kürzen */
  253.             if (t_ptr->ypos==y+1 && t_ptr->xpos>off)        /* Cursor verschieben */
  254.             {
  255.                 t_ptr->xpos += len;
  256.             }
  257.             if (t_ptr->ypos==y && t_ptr->xpos>i)            /* Cursor umbrechen */
  258.             {
  259.                 t_ptr->ypos++;
  260.                 t_ptr->xpos -= (i-off);
  261.             }
  262.             weiter = FALSE;
  263.         }
  264.         NEXT(col);                                                    /* nächste Zeile zu lang? */
  265.         y++;
  266.         changed = TRUE;
  267.     }
  268.     if (weiter) too_short(t_ptr,col,y);                        /* nächste Zeile zu kurz? */
  269.     return (changed);
  270. }
  271.  
  272. /* !!! cursor_line mu₧ hinterher entsprechend ypos gesetzt werden !!! */
  273. static bool too_short(TEXTP t_ptr, ZEILEP col, long y)
  274. {
  275.     int    len, off;
  276.     ZEILEP    next_col;
  277.     bool    changed;
  278.  
  279.     changed = FALSE;
  280.     tab = t_ptr->loc_opt->tab;
  281.     tab_size = t_ptr->loc_opt->tabsize;
  282.     while (bild_len(col,t_ptr->loc_opt->tab,t_ptr->loc_opt->tabsize)<lineal_len && !(IS_ABSATZ(col)) && col->nachf->len > 0)
  283.     {
  284.         next_col = col->nachf;
  285.         len = short_brk(next_col,bild_len(col,t_ptr->loc_opt->tab,t_ptr->loc_opt->tabsize));
  286.         if (len==0) break;                                        /* nichts zu machen */
  287.         off = col_offset(next_col);
  288.         if (len==next_col->len)                                    /* ganze Zeile hochziehen */
  289.         {
  290.             if (t_ptr->ypos==y+1)                                /* Cursor hochziehen */
  291.             {
  292.                 t_ptr->ypos--;
  293.                 t_ptr->xpos += (col->len-off);
  294.             }
  295.             if (t_ptr->ypos>y+1) t_ptr->ypos--;
  296.             REALLOC(&next_col,0,-off);
  297.             col_concate(&col);
  298.             t_ptr->text.lines--;                                    /* gleiche Zeile nochmal */
  299.         }
  300.         else                                                            /* teilweise hochziehen */
  301.         {
  302.             len -= off;
  303.             if (t_ptr->ypos==y+1 && t_ptr->xpos>=off)
  304.             {
  305.                 if (t_ptr->xpos<off+len)
  306.                 {
  307.                     t_ptr->ypos--;
  308.                     t_ptr->xpos += (col->len-off);
  309.                 }
  310.                 else
  311.                     t_ptr->xpos -= len;
  312.             }
  313.             INSERT(&col,col->len,len,TEXT(next_col)+off);/* Zeile verlängern */
  314.             REALLOC(&next_col,off,-len);                        /* Zeile verkürzen */
  315.             col = next_col;                                        /* nächste Zeile weiter */
  316.             y++;
  317.         }
  318.         changed = TRUE;
  319.     }
  320.     return(changed);
  321. }
  322.  
  323. void umbruch(TEXTP t_ptr)
  324. {
  325.     long y = t_ptr->ypos;
  326.  
  327.     setcpy(umbruch_set,t_ptr->loc_opt->umbruch_set);/* !! Mu₧ gesetzt werden !! */
  328.     setincl(umbruch_set,' ');                                /* wenigstens das */
  329.     tab = t_ptr->loc_opt->tab;
  330.     tab_size = t_ptr->loc_opt->tabsize;
  331.     lineal_len = t_ptr->loc_opt->lineal_len;
  332.     if (too_long(t_ptr, t_ptr->cursor_line, t_ptr->ypos))
  333.     {
  334.         t_ptr->cursor_line = get_line(&t_ptr->text,t_ptr->ypos);
  335.         t_ptr->moved++;
  336.         make_chg(t_ptr->link,POS_CHANGE,0);
  337.         make_chg(t_ptr->link,TOTAL_CHANGE,y);
  338.         clr_undo();
  339.     }
  340.     else if (too_short(t_ptr, t_ptr->cursor_line, t_ptr->ypos))
  341.     {
  342.         t_ptr->cursor_line = get_line(&t_ptr->text,t_ptr->ypos);
  343.         t_ptr->moved++;
  344.         make_chg(t_ptr->link,POS_CHANGE,0);
  345.         make_chg(t_ptr->link,TOTAL_CHANGE,y);
  346.         clr_undo();
  347.     }
  348. }
  349.  
  350. void format(TEXTP t_ptr)
  351. {
  352.     ZEILEP    lauf;
  353.     long    y, start_y;
  354.     bool    change;
  355.  
  356.     setcpy(umbruch_set,t_ptr->loc_opt->umbruch_set);/* !! Mu₧ gesetzt werden !! */
  357.     setincl(umbruch_set,' ');                                /* wenigstens das */
  358.     tab = t_ptr->loc_opt->tab;
  359.     tab_size = t_ptr->loc_opt->tabsize;
  360.     lineal_len = t_ptr->loc_opt->lineal_len;
  361.     change = FALSE;
  362.     lauf = t_ptr->cursor_line;
  363.     y = t_ptr->ypos;
  364.     if (y)
  365.     {
  366.         y--;
  367.         VORG(lauf);
  368.         while ((y > 0) && !(IS_ABSATZ(lauf)))
  369.         {
  370.             y--;
  371.             VORG(lauf);
  372.         }
  373.         if (y)
  374.         {
  375.             y++;
  376.             NEXT(lauf);
  377.         }
  378.     }
  379.     /* lauf zeigt jetzt auf die erste Zeile des Absatz */
  380.     start_y = y;
  381.     lauf = lauf->vorg;    /* Einen davor, weil akt. Zeile geändert wird */
  382.     while(TRUE)
  383.     {
  384.         if (!too_long(t_ptr, lauf->nachf,y))
  385.         {
  386.             if (too_short(t_ptr, lauf->nachf,y))
  387.                 change = TRUE;
  388.         }
  389.         else
  390.             change = TRUE;
  391.  
  392.         y++;
  393.         NEXT(lauf);
  394.         if (IS_ABSATZ(lauf))
  395.             break;
  396.     }
  397.     if (change)
  398.     {
  399.         t_ptr->cursor_line = get_line(&t_ptr->text,t_ptr->ypos);
  400.         t_ptr->moved++;
  401.         make_chg(t_ptr->link,POS_CHANGE,0);
  402.         make_chg(t_ptr->link,TOTAL_CHANGE,start_y);
  403.         clr_undo();
  404.     }
  405. }
  406.  
  407. void total_format(TEXTP t_ptr)
  408. {
  409.     ZEILEP    lauf;
  410.     long    y;
  411.     bool    change;
  412.  
  413.     setcpy(umbruch_set,t_ptr->loc_opt->umbruch_set);/* !! Mu₧ gesetzt werden !! */
  414.     setincl(umbruch_set,' ');                                /* wenigstens das */
  415.     tab = t_ptr->loc_opt->tab;
  416.     tab_size = t_ptr->loc_opt->tabsize;
  417.     lineal_len = t_ptr->loc_opt->lineal_len;
  418.     change = FALSE;
  419.     graf_mouse(HOURGLASS, NULL);
  420.     lauf = FIRST(&t_ptr->text);
  421.     y = 0;
  422.     while (!IS_TAIL(lauf))
  423.     {
  424.         /* lauf zeigt jetzt auf die erste Zeile des Absatz */
  425.         lauf = lauf->vorg;    /* Einen davor, weil akt. Zeile geändert wird */
  426.         while(TRUE)
  427.         {
  428.             if (!too_long(t_ptr, lauf->nachf,y))
  429.             {
  430.                 if (too_short(t_ptr, lauf->nachf,y))
  431.                     change = TRUE;
  432.             }
  433.             else
  434.                 change = TRUE;
  435.             y++;
  436.             NEXT(lauf);
  437.             if (IS_ABSATZ(lauf))
  438.                 break;
  439.         }
  440.         NEXT(lauf);
  441.     }
  442.     if (change)
  443.     {
  444.         t_ptr->cursor_line = get_line(&t_ptr->text,t_ptr->ypos);
  445.         t_ptr->moved++;
  446.         make_chg(t_ptr->link,POS_CHANGE,0);
  447.         make_chg(t_ptr->link,TOTAL_CHANGE,0);
  448.         clr_undo();
  449.     }
  450.     graf_mouse(ARROW, NULL);
  451. }
  452.