home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1993 #2 / Image.iso / wp / ehp10.zip / BLOCK_1.C < prev    next >
C/C++ Source or Header  |  1992-12-14  |  47KB  |  1,028 lines

  1. /****************************************************************/
  2. /*                                                              */
  3. /*      MODUL:  block_1.c                                       */
  4. /*                                                              */
  5. /*      FUNKTIONEN:                                             */
  6. /*              - tst_overlap (Ueberlappt Block mit Fenster ?)  */
  7. /*              - in_block (Test ob Zeichen im Block)           */
  8. /*              - dup_block (Block duplizieren)                 */
  9. /*              - shrink_line (Teil aus Zeile loeschen)         */
  10. /*              - adjust_pair (Koordinaten anpassen)            */
  11. /*              - adapt_pos (Cursorposition anpassen)           */
  12. /*              - del_rechteck (rechteckigen Block loeschen)    */
  13. /*              - del_normal (normalen Block loeschen)          */
  14. /*              - save_part (Zeilenteil kopieren)               */
  15. /*              - save_rechteck (rechteckigen Block speichern)  */
  16. /*              - save_normal (normalen Block speichern)        */
  17. /*              - ins_normal (normalen Block in Text einfuegen) */
  18. /*              - ins_rechteck (rechteckigen Block einfuegen)   */
  19. /*              - indent_block (Block ein-/ausruecken)          */
  20. /****************************************************************/
  21.  
  22. #include "defs.h"
  23.  
  24. extern char *getenv(),*mktemp(),space,*reserve_mem(),*fastzeichen();
  25. extern marker_typ marker[];
  26.  
  27. /*****************************************************************************
  28. *
  29. *  Funktion       Test, ob Block sich mit Fenster ueberlappt (tst_overlap)
  30. *  --------
  31. *
  32. *  Ergebnis     :
  33. *                   Typ          : int
  34. *                   Wertebereich : TRUE,FALSE
  35. *                   Bedeutung    : TRUE: Teil des Blockes ist in Fenster
  36. *                                        sichtbar
  37. *                                  FALSE: Block nicht sichtbar
  38. *
  39. *  Beschreibung :  Die Blockkoordinaten werden mit den Koordinaten
  40. *                  des aktuellen Fensters verglichen. Ueberlappen sich die
  41. *                  Bloecke, so wird TRUE, sonst FALSE zurueckgegeben.
  42. *
  43. ******************************************************************************/
  44.  
  45. int tst_overlap()
  46. {
  47.   /* *** interne Daten und Initialisierung *** */
  48.   register int xa = akt_winp->block.s_col,  /* Blockkoordinaten */
  49.            xe = akt_winp->block.e_col,
  50.            ya = akt_winp->block.s_line,
  51.            ye = akt_winp->block.e_line;
  52.  
  53.   if(!(ya<akt_winp->ws_line && ye<akt_winp->ws_line /* Block nicht ueber */
  54.   || ya>=akt_winp->ws_line+akt_winp->dy    /* und nicht unter Ausschnitt */
  55.   && ye>=akt_winp->ws_line+akt_winp->dy))
  56.     if(akt_winp->block.typ == BT_RECHTECK)
  57.     { /* Bei Rechteck koennen noch die Spalten geprueft werden */
  58.       if(!(xa<akt_winp->ws_col && xe<akt_winp->ws_col      /* nicht links     */
  59.       || xa>=akt_winp->ws_col+akt_winp->dx /* und nicht rechts vom Ausschnitt */
  60.       && xe>=akt_winp->ws_col+akt_winp->dx))
  61.     return(TRUE);                      /* also innerhalb */
  62.     }
  63.     else              /* normaler Block, kein Spaltentest  */
  64.       return(TRUE);   /* kein genauer Test, aber gut genug */
  65.   return(FALSE);
  66. }
  67.  
  68. /*****************************************************************************
  69. *
  70. *  Funktion       Test, ob Zeichen im Block (in_block)
  71. *  --------
  72. *
  73. *  Parameter    : y         :
  74. *                   Typ          : int
  75. *                   Wertebereich : 0-MAX_ANZ_LINES
  76. *                   Bedeutung    : Zeile, in der Zeichen steht.
  77. *
  78. *               : x         :
  79. *                   Typ          : int
  80. *                   Wertebereich : 0-MAXLENGTH
  81. *                   Bedeutung    : Spalte, in der Zeichen steht
  82. *
  83. *  Ergebnis     :
  84. *                   Typ          : int
  85. *                   Wertebereich : 0 - B_IN_BLOCK | B_FIRST_LINE | B_LAST_LINE |
  86. *                                  B_BEFORE | B_AFTER | B_LINE | B_FIRST_CHAR |
  87. *                                  B_RIGHT
  88. *                   Bedeutung    : B_IN_BLOCK: Zeichen befindet sich im Block
  89. *                                  B_FIRST_LINE: Zeichen befindet sich in
  90. *                                    der ersten Zeile des Blocks
  91. *                                  B_LAST_LINE: Zeichen befindet sich in der
  92. *                                    letzten Zeile des Blocks
  93. *                                  B_BEFORE: Zeichen steht vor dem Block
  94. *                                  B_AFTER: Zeichen steht hinter dem Block
  95. *                                  B_LINE: Zeichen steht in einer Blockzeile
  96. *                                  B_FIRST_CHAR: Zeichen ist erstes Zeichen
  97. *                                    des Blocks
  98. *                                  B_RIGHT: Zeichen steht in Blockzeile, jedoch
  99. *                                    rechts vom Block.
  100. *
  101. *  Beschreibung : Die Funktion berechnet das Verhaeltnis der uebergebenen
  102. *                 Position relativ zum Block. Dazu werden im Rueckgabewert
  103. *                 bestimmte Bits mit bestimmten Bedeutungen gesetzt bzw.
  104. *                 geloescht. Das geschieht, indem fuer jedes Bit die damit
  105. *                 verbundene Bedingung ausgewertet und das Ergebnis mit dem
  106. *                 Bitwert multipliziert wird. Das Ergebnis wird zum Rueck-
  107. *                 gabewert hinzugeODERt.
  108. *
  109. *****************************************************************************/
  110.  
  111. int in_block(y,x)
  112. register int y,x;
  113. {
  114.   /* *** interne Daten und Initialisierung *** */
  115.   register block_typ *akt_bl = &akt_winp->block; /* aktueller Block */
  116.   register int       ret=0;                      /* Rueckgabewert   */
  117.  
  118.   if(!block_defined())  /* Wenn kein Block markiert ist, dann */
  119.     return(0);          /* 0 zurueckgeben */
  120.  
  121.   ret |= B_FIRST_LINE * (y == akt_bl->s_line);
  122.   ret |= B_LAST_LINE  * (y == akt_bl->e_line);
  123.   ret |= B_BEFORE     * (y <  akt_bl->s_line || (y == akt_bl->s_line && x < akt_bl->s_col));
  124.   ret |= B_AFTER      * (y >  akt_bl->e_line || (y == akt_bl->e_line && x >= akt_bl->e_col));
  125.   ret |= B_LINE       * (y >= akt_bl->s_line &&  y <= akt_bl->e_line);
  126.   ret |= B_FIRST_CHAR * (y == akt_bl->s_line &&  x == akt_bl->s_col);
  127.  
  128.   if(akt_bl->typ == BT_RECHTECK)
  129.   {
  130.     ret |= B_RIGHT * ((ret & B_LINE) && x >= akt_bl->e_col);
  131.     ret |= B_IN_BLOCK * ((ret & B_LINE)
  132.        && x >= akt_bl->s_col && x < akt_bl->e_col);
  133.   }
  134.   else
  135.   {
  136.     ret |= B_RIGHT * ((ret & B_LAST_LINE) && x >= akt_bl->e_col);
  137.     ret |= B_IN_BLOCK * ((y == akt_bl->s_line && x >= akt_bl->s_col
  138.        && (y != akt_bl->e_line || x < akt_bl->e_col))
  139.        || (y > akt_bl->s_line && y < akt_bl->e_line)
  140.        || (y == akt_bl->e_line && x < akt_bl->e_col && (y != akt_bl->s_line
  141.        || x >= akt_bl->s_col)));
  142.   }
  143.   return(ret);
  144. }
  145.  
  146. /*****************************************************************************
  147. *
  148. *  Funktion       Block duplizieren (dup_block)
  149. *  --------
  150. *
  151. *  Parameter    : old_bl    :
  152. *                   Typ          : block_typ *
  153. *                   Wertebereich : Pointer auf block_typ
  154. *                   Bedeutung    : zu kopierender Block
  155. *
  156. *  Ergebnis     :
  157. *                   Typ          : block_typ *
  158. *                   Wertebereich : Pointer auf block_typ
  159. *                   Bedeutung    : Kopie des Blocks
  160. *
  161. *  Beschreibung : Die Funktion kopiert den uebegebenen Block und gibt einen
  162. *                 Pointer auf die Kopie zurueck
  163. *
  164. *****************************************************************************/
  165.  
  166. block_typ *dup_block(old_bl)
  167. block_typ *old_bl;
  168. {
  169.   /* *** interne Daten und Initialisierung *** */
  170.   /* new_bl zeigt auf die Struktur des neuen Blockes */
  171.   block_typ          *new_bl = (block_typ*) reserve_mem(sizeof(block_typ));
  172.   register bzeil_typ *nz,  /* Aktuelle Zeile im neuen Block */
  173.              *az;  /* Aktuelle Zeile im alten Block */
  174.  
  175.   memcpy(new_bl,old_bl,sizeof(block_typ));   /* Blockstruktur duplizieren */
  176.   /* Falls Block mindestens eine Zeile hat, Platz dafuer reservieren */
  177.   if (az = old_bl->bstart)
  178.     new_bl->bstart = nz = (bzeil_typ*) reserve_mem(sizeof(bzeil_typ));
  179.   else
  180.     new_bl->bstart = NULL;
  181.   while (az)  /* Alle Blockzeilen in Zeilenliste des neuen Blocks sichern */
  182.   {
  183.     nz->text = save_text(az->text);
  184.     if (az->next)
  185.       nz->next = (bzeil_typ*) reserve_mem(sizeof(bzeil_typ));
  186.     else
  187.       nz->next = NULL;
  188.     nz = nz->next;
  189.     az = az->next;
  190.   }
  191.   return (new_bl);
  192. }
  193.  
  194. /*****************************************************************************
  195. *
  196. *  Funktion       Teil aus Zeile loeschen (shrink_line)
  197. *  --------
  198. *
  199. *  Parameter    : anf       :
  200. *                   Typ          : int
  201. *                   Wertebereich : 0 - MAXLENGTH-1
  202. *                   Bedeutung    : Anfangsspalte
  203. *
  204. *                 ende      :
  205. *                   Typ          : int
  206. *                   Wertebereich : anf - MAXLENGTH-1
  207. *                   Bedeutung    : Erstes nicht mehr zu loeschendes Zeichen
  208. *
  209. *  Beschreibung : Die Funktion loescht in der aktuellen Zeile den Bereich von
  210. *                 anf bis ende (soweit moeglich).  Besteht die Zeile danach
  211. *                 nur noch aus Spaces, so wird die Textpointer freigegeben
  212. *                 ud durch NULL ersetzt (gemaess Konvention).
  213. *
  214. *****************************************************************************/
  215.  
  216. void shrink_line(anf,ende)
  217. int anf,ende;
  218. {
  219.   /* *** interne Daten *** */
  220.   int  len;    /* Laenge des verbleibenden Strings */
  221.   char *anfp,  /* Pointer auf erstes nicht zu uebernehmendes Zeichen */
  222.        *endep; /* Pointer auf letztes nicht zu uebernehmendes Zeichen */
  223.  
  224.   /* Wenn Zeichen wegfallen (anf!=ende), dann wird anfp der Zeiger */
  225.   /* auf das entsprechende Zeichen zugewiesen. Liegt anfp hinter   */
  226.   /* dem Zeilenende (anfp==&space), geschieht nichts.              */
  227.   if(anf != ende && (anfp = fastzeichen(anf)) != &space)
  228.   {
  229.     /* Sonst wird der Zeiger auf das zu ende gehoerende Zeichen ermittelt.    */
  230.     if((endep = fastzeichen(ende)) == &space) /* Liegt ende hinte Zeilenende, */
  231.       *anfp = '\0';              /* so wird der String einfach abgeschnitten. */
  232.     else                         /* Sonst wird der hintere zu uebernehmende   */
  233.       fwdcpy(anfp,endep);        /* Teil direkt an den vorderen kopieret.     */
  234.  
  235.     /* Hat die Zeile eine Laenge ungleich 0 und besteht sie nicht nur aus */
  236.     /* Blanks, dann wird dafuer der noetige Speicher alloziert.           */
  237.     if(akt_winp->alinep->text 
  238.     && (len=strlen(akt_winp->alinep->text)) && strspn(akt_winp->alinep->text," ") != len)
  239.     {
  240.       if(!(akt_winp->alinep->text = realloc(akt_winp->alinep->text,len+1)))
  241.     no_mem_err();            /* Kein Speicher, Fehlermeldung ausgeben */
  242.     }
  243.     else                   /* Zeile leer oder nur Blanks, Zeile freigeben */
  244.     {
  245.       line_free(akt_winp->alinep->text);
  246.       akt_winp->alinep->text = NULL;
  247.     }
  248.   }
  249. }
  250.  
  251. /*****************************************************************************
  252. *
  253. *  Funktion       Koordinaten anpassen (adjust_pair)
  254. *  --------
  255. *
  256. *  Parameter    : y         :
  257. *                   Typ          : int *
  258. *                   Wertebereich : Pointer auf Integer-Variable
  259. *                   Bedeutung    : anzupassende Zeilennummer
  260. *
  261. *                 x         :
  262. *                   Typ          : int *
  263. *                   Wertebereich : Pointer auf Integer-Variable
  264. *                   Bedeutung    : anzupassende Spaltennummer
  265. *
  266. *                 modus     :
  267. *                   Typ          : int
  268. *                   Wertebereich : AP_INSERT, AP_DELETE
  269. *                   Bedeutung    : AP_INSERT: Block wurde eingefuegt
  270. *                                  AP_DELETE: Block soll geloescht werden
  271. *
  272. *  Beschreibung : Falls sich durch ein Loeschen des Blockes (modus == AP_DELETE)
  273. *                 die uebergebenen Koordinaten veraendern wuerden, so
  274. *                 werden diese entsprechend angepasst.
  275. *                 Haben sich durch das Einfuegen des Blockes (modus == AP_INSERT)
  276. *                 die uebergebenen Koordinaten veraendert, so werden diese
  277. *                 entsprechend angepasst.
  278. *
  279. *****************************************************************************/
  280.  
  281. void adjust_pair(y,x,modus)
  282. int *y,*x,modus;
  283. {
  284.   /* *** interne Daten und Initialisierung *** */
  285.   int       ib = in_block(*y,*x);   /* Position relativ zum Block */
  286.   block_typ *bl = &akt_winp->block; /* Zeiger auf aktuellen Block */
  287.  
  288.   if(bl->typ == BT_NORMAL)    /* Normaler Block ? */
  289.   {
  290.     if(ib & B_IN_BLOCK)      /* Position jetzt innerhalb des Blocks ? */
  291.       if(modus == AP_DELETE) /* wird Block geloescht ? */
  292.       {
  293.     *y = bl->s_line; /* falls Koordinaten im Block, an Blockanfang setzen */
  294.     *x = bl->s_col;
  295.       }
  296.       else                   /* Block wird eingefuegt */
  297.       {
  298.     *y += bl->e_line - bl->s_line; /* neue Position ist um Blockhoehe nach */
  299.     if(ib & B_FIRST_LINE)          /* unten gerutscht.Falls Koor in erster */
  300.       *x += bl->e_col - bl->s_col; /* Blockzeile war, auch Spaltenposition */
  301.       }                                /* anpassen */
  302.     else                     /* Position war nicht innerhalb des Blocks */
  303.       if(ib & B_AFTER)       /* Falls dahinter, dann */
  304.     if(modus == AP_DELETE) /* beim Loeschen Blockhoehe subtrahieren */
  305.     { /* wenn letzte und erste Zeile zusammen zu lang, dann wird noetige */
  306.       *y -= bl->e_line - bl->s_line; /* anpassung in del_normal gemacht */
  307.       if(ib & B_LAST_LINE) /* Wenn Position in der letzten Zeile hinter */
  308.         if(ib & B_RIGHT)   /* dem Block liegt, dann X anpassen:         */
  309.           *x += bl->s_col - bl->e_col;
  310.         else               /* Wenn in letzter Zeile im Block, dann X    */
  311.           *x = bl->s_col;  /* auf Blockstart X setzen                   */
  312.     }
  313.     else                 /* Beim Einfuegen Blockhoehe auf Y addieren */
  314.       *y += bl->e_line - bl->s_line;
  315.   }
  316.   else           /* rechteckiger Block, y-Koordinaten werden nicht veraendert */
  317.     if(ib & B_LINE)           /* Befindet sich Position in einer Blockzeile ? */
  318.       if(modus == AP_DELETE)         /* Beim Loeschen falls rechts vom Block, */
  319.       {                              /* Blockbreite von x-Koordinate abzie-   */
  320.     if(ib & B_RIGHT)             /* hen.                                  */
  321.       *x -= bl->e_col-bl->s_col;
  322.     else                         /* Falls innerhalb des Block, x-Koordina-*/
  323.       if(ib & B_IN_BLOCK)        /* te auf Blockanfang X setzen           */
  324.         *x = bl->s_col;
  325.       }
  326.       else                           /* Soll der Block eingefuegt werden und  */
  327.     if(*x >= bl->s_col)          /* die Position liegt rechts der Start-  */
  328.       *x += bl->e_col - bl->s_col; /* spalte, dann Breite zu X addieren   */
  329. }
  330.  
  331. /*****************************************************************************
  332. *
  333. *  Funktion       Positionen anpassen (adapt_pos)
  334. *  --------
  335. *
  336. *  Parameter    : modus     :
  337. *                   Typ          : int
  338. *                   Wertebereich : AP_INSERT, AP_DELETE
  339. *                   Bedeutung    : AP_INSERT: Block wurde eingefuegt
  340. *                                  AP_DELETE: Block soll geloescht werden
  341. *
  342. *  Beschreibung : Entsprechend dem Modus werden Cursorposition, Marker und
  343. *                 letzte Position mit der Funktion adjust_pair angepasst.
  344. *
  345. *****************************************************************************/
  346.  
  347. void adapt_pos(modus)
  348. int modus;
  349. {
  350.   /* *** Interne Daten und Initialisierung *** */
  351.   int i = akt_winp->textline; /* Zwischenspeicher fuer akt. Zeilennummer */
  352.  
  353.   /* Zuerst Cursorposition: */
  354.   adjust_pair(&i,&akt_winp->screencol,modus); /* nicht &textline, damit */
  355.   gotox(i);              /* textline und alinep nicht desynchronisieren */
  356.   for(i=0;i<ANZ_MARKER;i++)  /* Alle Markerpositionen fuer aktuelles    */
  357.     if(akt_winp->wini == marker[i].window)          /* Fenster anpassen */
  358.       adjust_pair(&marker[i].line,&marker[i].col,modus);
  359.   /* Letzte Position anpassen: */
  360.   adjust_pair(&akt_winp->lastline,&akt_winp->lastcol,modus);
  361. }
  362.  
  363. /*****************************************************************************
  364. *
  365. *  Funktion       rechteckigen Block loeschen (del_rechteck)
  366. *  --------
  367. *
  368. *  Beschreibung : Der aktuelle Block wird aus der Textstruktur entfernt und
  369. *                 evtl. die Cursorpositon angepasst.
  370. *
  371. *****************************************************************************/
  372.  
  373. void del_rechteck()
  374. {
  375.   /* *** Interne Daten und Initialisierung */
  376.   zeil_typ  *old_line; /* Zwischenspeicher fuer Zeiger auf aktuelle Zeile */
  377.   int       old_num;   /* Zwischenspeicher fuer aktuelle Zeilennummer     */
  378.   block_typ *bl = &akt_winp->block; /* Zeiger auf aktuellen Block         */
  379.  
  380.   adapt_pos(AP_DELETE);   /* Cursor, Marker und letzte Position anpassen */
  381.   old_num = akt_winp->textline;   /* Cursorposition erst jetzt speichern */
  382.   old_line = akt_winp->alinep;
  383.  
  384.   /* Aus allen Blockzeilen den zum Block gehoerenden Teil loeschen */
  385.   for(gotox(bl->s_line);akt_winp->textline <= bl->e_line;down())
  386.     shrink_line(bl->s_col,bl->e_col);
  387.   akt_winp->changeflag = TRUE;  /* Text als geaendert markieren */
  388.   akt_winp->alinep = old_line;  /* Alte Cursorposition wieder   */
  389.   akt_winp->textline = old_num; /* herstellen                   */
  390. }
  391.  
  392. /*****************************************************************************
  393. *
  394. *  Funktion       normalen Block loeschen (del_normal)
  395. *  --------
  396. *
  397. *  Beschreibung : Der aktuelle normale Block wird aus der Textstruktur
  398. *                 entfernt und evtl. die Cursorpositon angepasst.
  399. *
  400. *****************************************************************************/
  401.  
  402. void del_normal()
  403. {
  404.   /* *** interne Daten und Initialisierung *** */
  405.   int                anz_del, /* Anzahl zu loeschender Zeilen   */
  406.              len,     /* Laenge der neuen ersten Zeile  */
  407.              old_num, /* Aktuelle Zeilennummer          */
  408.              old_sc,  /* Zwischenspeicher Cursorspalte  */
  409.              fll;     /* Laenge der uebriggebliebenen   */
  410.                   /* ersten Blockzeile              */
  411.   register block_typ *bl = &akt_winp->block; /* aktueller Block */
  412.   char               *ez_anf; /* Zeiger auf Blockanfang         */
  413.  
  414.   adapt_pos(AP_DELETE); /* Cursor, Marker und letzte Position anpassen */
  415.   old_num = akt_winp->textline; /* Zeilennummer merken und zum Block- */
  416.   gotox(bl->s_line);            /* start gehen */
  417.   if(!bl->laenge)               /* Block innerhalb einer Zeile */
  418.     shrink_line(bl->s_col,bl->e_col); /* Blockteil der Zeile loeschen */
  419.   else
  420.   {                          /* Block geht ueber mehrere Zeilen */
  421.     anz_del = bl->laenge-1;  /* letzte Zeile nicht vollstaendig loeschen */
  422.     if(bl->s_col)            /* erste Zeile teilweise loeschen */
  423.     {
  424.       /* Zeiger auf erstes Blockzeichen berechnen und testen, ob es hinter */
  425.       /* dem Zeilenende liegt (== &space)                                  */
  426.       if ((ez_anf = fastzeichen(bl->s_col)) != &space)
  427.       {
  428.     *ez_anf = '\0';  /* Zeile am Blockanfang abschneiden */
  429.     /* Wenn neue Laenge der Zeile == 0 oder Zeile nur noch aus Blanks */
  430.     /* besteht, dann Zeile freigeben. Sonst Platz neu allozieren      */
  431.     if(akt_winp->alinep->text
  432.     && (len=strlen(akt_winp->alinep->text))
  433.     && strspn(akt_winp->alinep->text," ") != len)
  434.     {
  435.       if(!(akt_winp->alinep->text = realloc(akt_winp->alinep->text,len + 1)))
  436.         no_mem_err(); /* Kein Speicherplatz, Fehlermeldung, Abbruch */
  437.     }
  438.     else
  439.     {
  440.       line_free(akt_winp->alinep->text);
  441.       akt_winp->alinep->text = NULL;
  442.     }
  443.       }
  444.       down();  /* In 2. Blockzeile gehen */
  445.     }
  446.     else            /* Wenn Block am Anfang einer Zeile beginnt, */
  447.       anz_del++;    /* dann erste Zeile auch loeschen            */
  448.     for(;anz_del;anz_del--)
  449.       del_line(IGNORE_COORS);   /* blockkoors werden nicht veraendert */
  450.     shrink_line(0,bl->e_col);   /* Blockteil der letzten Zeile loeschen */
  451.     if(bl->s_col)               /* Wenn Block nicht am Anfang einer Zeile */
  452.     {                           /* anfaengt, muss man die Zeilentruemmer */
  453.       up();                     /* zusammenfuegen.                      */
  454.       if(join(IGNORE_COORS)==J_TOOLONG) /* Klappte Join nicht ? */
  455.       { /* Dann ans Zeilenende stellen und Anpassung wie bei newline   */
  456.     /* vornehmen, da adapt_pos alles um eine Zeile zuviel anpasste */
  457.     if(akt_winp->screencol > (fll=fastll(akt_winp->alinep->text))
  458.     && akt_winp->textline == old_num) /* Wenn Cursor in letzter Block- */
  459.       /* zeile hinter dem Block stand, dann Cursorspalte anpassen */
  460.       akt_winp->screencol -= fll;
  461.     old_num++; /* Alte Cursorzeile sowieso anpassen */
  462.     old_sc = akt_winp->screencol; /* Cursorspalte merken */
  463.     akt_winp->screencol = fll;
  464.     nl_blockadapt();              /* Anpassungen vornehmen */
  465.     akt_winp->screencol = old_sc; /* Cursorspalte restaurieren */
  466.       }
  467.     }
  468.   }
  469.   akt_winp->changeflag = TRUE;  /* Text als geaendert markieren */
  470.   gotox(old_num);               /* Alte Zeile aufsuchen         */
  471. }
  472.  
  473. /*****************************************************************************
  474. *
  475. *  Funktion       Zeilenteil kopieren (save_part)
  476. *  --------
  477. *
  478. *  Parameter    : z         :
  479. *                   Typ          : bzeil_typ *
  480. *                   Wertebereich : Pointer auf Blockzeile
  481. *                   Bedeutung    : aktuelle Blockzeile
  482. *
  483. *               : anf       :
  484. *                   Typ          : int
  485. *                   Wertebereich : 0-MAXLENGTH
  486. *                   Bedeutung    : erstes zu kopierendes Zeichen
  487. *
  488. *               : ende      :
  489. *                   Typ          : int
  490. *                   Wertebereich : 0-MAXLENGTH
  491. *                   Bedeutung    : erstes nicht mehr zu kopierendes Zeichen
  492. *
  493. *  Beschreibung : Eine neue Blockzeile wird erzeugt und mit der aktuellen
  494. *                 verknuepft. In die neue Zeile wird der entsprechende Zeilen-
  495. *                 ausschnitt gespeichert (soweit moeglich). Ist der Ausschnitt
  496. *                 leer, so wird ein NULL-Pointer im text-Element eingetragen.
  497. *
  498. *****************************************************************************/
  499.  
  500. bzeil_typ *save_part(z,anf,ende)
  501. register bzeil_typ *z;
  502. int anf,ende;
  503. {
  504.   char *anfp,               /* Zeiger auf erstes zu uebernehmendes Zeichen  */
  505.        *endep,              /* Zeiger auf letztes zu uebernehmendes Zeichen */
  506.        buff[3*MAXLENGTH+1]; /* Puffer fuer zu kopierenden Teil              */
  507.  
  508.   /* Ein neues Element in der Blockstruktur eintragen */
  509.   z = z->next = (bzeil_typ*) reserve_mem(sizeof(bzeil_typ));
  510.   z->next = NULL;
  511.  
  512.   /* Pointer auf erstes zu uebernehmendes Zeichen ermitteln und testen, ob */
  513.   /* es hinter dem Ende der aktuellen Zeile liegt.                         */
  514.   if ((anfp = fastzeichen(anf)) == &space)
  515.     z->text = NULL;     /* Liegt es dahinter, keinen Speicher reservieren */
  516.   else    /* Sonst Ende ermitteln, testen, ob es hinter Zeilenende liegt. */
  517.   {
  518.     if ((endep = fastzeichen(ende)) == &space)              /* Dahinter ? */
  519.       z->text = save_text(anfp);        /* dann alles ab anfp uebernehmen */
  520.     else               /* Sonst zu uebernehmenden Teil in Puffer kopieren */
  521.     {
  522.       strncpy(buff,anfp,endep-anfp);
  523.       buff[endep-anfp] = '\0';   /* Pufferende markieren */
  524.       z->text = save_text(buff); /* Puffer in Blocktext uebernehmen */
  525.     }
  526.   }
  527.   return (z);
  528. }
  529.  
  530. /*****************************************************************************
  531. *
  532. *  Funktion       rechteckigen Block abspeichern (save_rechteck)
  533. *  --------
  534. *
  535. *  Ergebnis     :
  536. *                   Typ          : bzeil_typ*
  537. *                   Wertebereich : Pointer auf bzeil_typ
  538. *                   Bedeutung    : Anfang der verketteten Liste der
  539. *                                  Blockzeilen
  540. *
  541. *  Beschreibung : Der markierte rechteckige Block wird in einer verketteten
  542. *                 Liste, deren Anfang zurueckgegeben wird, abgespeichert.
  543. *                 Das laenge-Element von akt_winp->block wird auf die Zeilen-
  544. *                 anzahl gesetzt.
  545. *
  546. *****************************************************************************/
  547.  
  548. bzeil_typ *save_rechteck()
  549. {
  550.   /* *** interne Daten und Initialisietung *** */
  551.   /* z zeigt auf aktuelle Blockzeile */
  552.   bzeil_typ *z = (bzeil_typ*) reserve_mem(sizeof(bzeil_typ)),
  553.         *anf;         /* Zeiger auf leeres Dummy-Element   */
  554.   int       i,            /* Anzahl noch zu kopierender Zeilen */
  555.         old_tl = akt_winp->textline; /* Alte Zeilennummer  */
  556.   zeil_typ *old_ap = akt_winp->alinep;   /* Alter Zeilenzeiger */
  557.  
  558.   i = akt_winp->block.laenge = akt_winp->block.e_line - akt_winp->block.s_line;
  559.   (anf=z)->next = NULL;       /* Erstes Element ist leeres Element, wird wieder geloescht */
  560.  
  561.   /* Aus jeder zum Block gehoerigen Zeile wird der entsprechende Teil */
  562.   /* ausgeschnitten und in die Blockstruktur kopiert.                 */
  563.   for (gotox(akt_winp->block.s_line); i>=0; i--,down())
  564.     z = save_part(z,akt_winp->block.s_col,akt_winp->block.e_col);
  565.   z = anf->next;
  566.   free (anf);   /* zuviel alloziertes Element wieder freigeben */
  567.   akt_winp->alinep = old_ap;   /* Cursorposition restaurieren  */
  568.   akt_winp->textline = old_tl;
  569.   return (z);
  570. }
  571.  
  572. /*****************************************************************************
  573. *
  574. *  Funktion       normalen Block abspeichern (save_normal)
  575. *  --------
  576. *
  577. *  Ergebnis     :
  578. *                   Typ          : bzeil_typ*
  579. *                   Wertebereich : Pointer auf bzeil_typ
  580. *                   Bedeutung    : Anfang der verketteten Liste der
  581. *                                  Blockzeilen
  582. *
  583. *  Beschreibung : Der markierte normale Block wird in einer verketteten
  584. *                 Liste, deren Anfang zurueckgegeben wird, abgespeichert.
  585. *                 Das laenge-Element von akt_winp->block wird auf die Zeilen-
  586. *                 anzahl gesetzt.
  587. *
  588. *****************************************************************************/
  589.  
  590. bzeil_typ *save_normal()
  591. {
  592.   /* *** interne Daten und Initialisierung *** */
  593.   /* z zeigt auf die aktuelle Zeile in der Blocktextliste */
  594.   register bzeil_typ *z = (bzeil_typ*) reserve_mem(sizeof(bzeil_typ)),
  595.              *anf = z;   /* Erste Zeile in Blocktextliste */
  596.   char               *ez_anf;    /* Erstes Zeichen der Blocks     */
  597.   int                old_tl = akt_winp->textline; /* Alte Zeilennummer  */
  598.   zeil_typ           *old_ap = akt_winp->alinep;  /* Alter Zeilenzeiger */
  599.   block_typ          *bl = &akt_winp->block;      /* aktueller Block    */
  600.  
  601.   bl->laenge = bl->e_line-bl->s_line; /* Anzahl der Blockzeilen berechnen */
  602.   z->next = NULL; /* Erstes Element ist leeres Element, wird wieder geloescht */
  603.   gotox(bl->s_line);  /* Zum Blockanfang gehen */
  604.   if(bl->e_line == bl->s_line)  /* Block innerhalb einer Zeile */
  605.     /* Dann neue Zeile anlegen und entsprechenden Teil rauskopieren */
  606.     z = save_part(z,bl->s_col,bl->e_col);
  607.   else
  608.   {                 /* Wenn der Block ueber mehrere Zeilen geht, */
  609.     if(bl->s_col)   /* und der Block nicht in Spalte 0 anfaengt, */
  610.     {               /* dann eine neue Zeile anlegen.             */
  611.       z->next = (bzeil_typ*) reserve_mem(sizeof(bzeil_typ));
  612.       z = z->next;
  613.       z->next = NULL;
  614.       if ((ez_anf = fastzeichen(bl->s_col)) != &space)
  615.     z->text = save_text(ez_anf); /* Falls Blockanfang nicht hinter */
  616.       else /* Zeilenende, dann Blockteil der Zeile abspeichern, sonst  */
  617.     z->text = NULL;                   /* Zeile als leer markieren. */
  618.       down();  /* Zur naechsten blockzeile gehen */
  619.     }
  620.     while(akt_winp->textline < bl->e_line)  /* Alle komplett zum Block */
  621.     {                      /* gehoerigen Zeilen an die Liste anhaengen */
  622.       z->next = (bzeil_typ*) reserve_mem(sizeof(bzeil_typ));
  623.       z = z->next;
  624.       z->next = NULL;
  625.       z->text = save_text(akt_winp->alinep->text);
  626.       down();
  627.     }
  628.     z = save_part(z,0,bl->e_col); /* Blockteil der letzten Blockzeile */
  629.   }                               /* in Liste eintragen               */
  630.   z = anf->next;
  631.   free (anf);   /* zuviel alloziertes Element wieder freigeben */
  632.   akt_winp->alinep = old_ap;   /* Cursorposition restaurieren */
  633.   akt_winp->textline = old_tl;
  634.   return (z);
  635. }
  636.  
  637. /*****************************************************************************
  638. *
  639. *  Funktion       abgespeicherten norm. Block in Text einfuegen (ins_normal)
  640. *  --------
  641. *
  642. *  Parameter    : bl       :
  643. *                   Typ          : block_typ *
  644. *                   Wertebereich : Pointer auf block_typ
  645. *                   Bedeutung    : Einzufuegender Block
  646. *
  647. *  Ergebnis     :
  648. *                   Typ          : int
  649. *                   Wertebereich : TRUE,FALSE
  650. *                   Bedeutung    : TRUE = Einfuegen war moeglich
  651. *                                  FALSE = Einfuegen war nicht moeglich
  652. *
  653. *  Beschreibung : Der in der mit bl->bstart beginnenden Liste abgespeicherte
  654. *                 Block wird an der aktuellen Position eingefuegt, wenn dazu
  655. *                 genuegend Platz ist. Der eingefuegte Block wird
  656. *                 anschliessend zum aktuellen.
  657. *                 Die in den Text eingefuegten Textpointer der Blockzeilen
  658. *                 werden in der Blockstruktur auf NULL gesetzt, damit sie
  659. *                 nicht von block_free freigegeben werden.
  660. *
  661. *****************************************************************************/
  662.  
  663. int ins_normal(bl)
  664. block_typ *bl;
  665. {
  666.   /* *** interne Daten und Initialisierung *** */
  667.   bzeil_typ     *akt_zeile = bl->bstart;      /* Aktuelle Blockzeile    */
  668.   register int  fll, /* aktuelle Zeilenlaenge                           */
  669.         i,   /* Zaehler zum Auffuellen einer Zeile mit Blanks   */
  670.         pos, /* Startspalte des Blocks in der ersten Zeile      */
  671.         old_tl = akt_winp->textline,  /* Alte Zeilennummer      */
  672.         old_sc = akt_winp->screencol; /* Alte Spaltennummer     */
  673.   int           line_len,     /* Neue Laenge der ersten Blockzeile      */
  674.         bline_len,    /* Laenge der Blockzeile                  */
  675.         tmp_sline,    /* Zwischenspeicher fuer echten Block-    */
  676.         tmp_scol,     /* start (Zeile / Spalte)                 */
  677.         tmp_eline,    /* Zwischenspeicher fuer echtes Block-    */
  678.         tmp_ecol;     /* ende (Zeile / Spalte)                  */
  679.   char          *fzsc,        /* Zeiger auf erstes Blockzeichen         */
  680.         *rest = NULL, /* Zeiger auf Rest der Zeile, in die      */
  681.                   /* Block eingefuegt wird, nach Splitten   */
  682.         buff[3*MAXLENGTH+1]; /* Puffer fuer Zusammenfuegen der  */
  683.                      /* ersten und letzten Blockzeile   */
  684.  
  685.   if (!akt_zeile || bl->laenge<0)       /* Falls Block leer, fertig */
  686.     return (TRUE);
  687.   if (bl->laenge + akt_winp->maxline + 2 >= MAX_ANZ_LINES) /* Noch Platz ? */
  688.     return (FALSE); /* eee evtl. werden 2 Zeilen verschenkt */
  689.   check_buff(); /* Evtl. noch im Puffer enthaltene Daten in Text aufnehmen */
  690.   akt_winp->changeflag = TRUE;  /* irgendetwas muss eingefuegt werden */
  691.  
  692.   if(akt_winp->maxline <= -1)   /* Falls Text leer, eine Zeile erzeugen */
  693.     koppel_line(IGNORE_COORS);
  694.  
  695.   bline_len = fastll(akt_zeile->text);  /* Laenge der aktuellen Zeile und */
  696.   fll = fastll(akt_winp->alinep->text); /* der ersten Blockzeile merken   */
  697.  
  698.   /* Die Laenge der neuen Zeile ergibt sich aus der Summe von Cursorspalte */
  699.   /* und Laenge der ersten Blockzeile.                                     */
  700.   line_len = akt_winp->screencol + bline_len;
  701.  
  702.   bl->s_line = tmp_sline = akt_winp->textline; /* Blockkoordinaten setzen  */
  703.   bl->s_col  = tmp_scol  = akt_winp->screencol;
  704.   if (akt_winp->alinep->text)           /* Text in aktueller Zeile? */
  705.   {
  706.     /* Position relativ zum Zeilenanfang ermitteln, ab der 1. Blockzeile     */
  707.     /* eingefuegt werden soll. Steht man hinter dem Zeilenende, dann wird    */
  708.     /* direkt hinter dem Zeilenende mit der Einfuegung begonnen, sonst er-   */
  709.     /* gibt sich die Position aus der Differenz des Zeigers auf das aktuelle */
  710.     /* Zeichen und dem Zeiger auf den Zeilenanfang.                          */
  711.  
  712.     if((fzsc = fastzeichen(akt_winp->screencol)) == &space)
  713.       pos = strlen(akt_winp->alinep->text);
  714.     else
  715.       pos = fzsc - akt_winp->alinep->text;
  716.     strncpy(buff,akt_winp->alinep->text,pos);   /* Teil der Zeile vor Block  */
  717.                         /* in Puffer kopieren        */
  718.     if(fll > akt_winp->screencol)          /* Blockeinfuegen splittet Zeile, */
  719.       rest = save_text(akt_winp->alinep->text+pos); /* Rest entsteht, falls  */
  720.     else                            /* Cursor nicht hinter Zeilenende stand. */
  721.       rest = NULL;
  722.   }
  723.   else           /* aktuelle Zeile leer: */
  724.   {              /* pos wird zwar auch auf 0 gesetzt, wenn Cursor nicht am    */
  725.     pos = 0;     /* Zeilenanfang steht, wird jedoch durch Einfuegen der Spaces*/
  726.     rest = NULL; /* bis zur Cursorposition wieder korrekt angepasst. (s.u.)   */
  727.     buff[0]='\0';/* Kein Rest bei leerer Zeile, Puffer leer markieren         */
  728.   }
  729.   if (line_len <= MAXLENGTH) /* wird Zeile durch Anfuegen der */
  730.   {                          /* 1. Blockzeile zu lang ?       */
  731.     for (i = fll;i<akt_winp->screencol;i++)
  732.       buff[pos++] = ' '; /* evtl. bis Cursorposition mit Spaces auffuellen   */
  733.     if (akt_zeile->text)                /* ueberhaupt Text in 1. Blockzeile? */
  734.       strcpy(&buff[pos],akt_zeile->text); /* 1. Blockzeile an Teil der aktu- */
  735.     else                                 /* ellen Zeile im Puffer anhaengen. */
  736.       buff[pos]='\0'; /* kein Text in 1. Blockz., aktuelle Zeile ist zu Ende */
  737.     akt_zeile = akt_zeile->next;        /* Zur 2. Blockzeile */
  738.   }
  739.   else               /* Zeile wuerde zu lang werden, daher 1. Blockzeile in  */
  740.   {                  /* eigener Zeile einfuegen. Neuer Block faengt daher    */
  741.     tmp_sline++;     /* eine Zeile spaeter an                                */
  742.     tmp_scol = 0;
  743.   }
  744.   line_free(akt_winp->alinep->text);        /* Aktuelle Zeile durch neue   */
  745.   akt_winp->alinep->text = save_text(buff); /* Zeile ersetzen.             */
  746.  
  747.   /* Alle restlichen Blockzeilen werden in die Textstruktur eingefuegt */
  748.   while (akt_zeile)
  749.   {
  750.     koppel_line(IGNORE_COORS);                /* damit die uebernommene Zeile*/
  751.     akt_winp->alinep->text = akt_zeile->text; /* nicht von block_free freige-*/
  752.     akt_zeile->text = NULL;                   /* geben wird, text auf NULL.  */
  753.     akt_zeile = akt_zeile->next;
  754.   }
  755.   bl->e_line = tmp_eline = akt_winp->textline; /* Blockendkoordinaten setzen  */
  756.   bl->e_col = tmp_ecol = fastll(akt_winp->alinep->text);
  757.  
  758.   /* Wenn durch das Splitten der ersten Zeile ein Rest entstanden ist, dann */
  759.   /* wird versucht, den Rest an die letzte Blockzeile anzuhaengen. Wuerde   */
  760.   /* die Zeile dadurch zu lang, wird der Rest in eine eigene Zeile geschrie-*/
  761.   /* ben.                                                                   */
  762.   if(rest)
  763.     if (bl->e_col + (fll = fastll(rest)) <= MAXLENGTH) /* nicht zu lang ?   */
  764.       if (akt_winp->alinep->text)
  765.       {
  766.     strcpy(buff,akt_winp->alinep->text); /* beide Teile in buff zusam-  */
  767.     strcat(buff,rest);                   /* menkopieren.                */
  768.     free(rest);                          /* Rest freigeben              */
  769.     free(akt_winp->alinep->text);        /* Neu entstandene Zeile in    */
  770.     akt_winp->alinep->text = save_text(buff); /* Textstruktur eintragen */
  771.       }
  772.       else                                   /* War die aktuelle Zeile leer,*/
  773.     akt_winp->alinep->text = rest;       /* dann einfach Rest eintragen */
  774.     else                                     /* Zeile waere zu lang geworden*/
  775.     {
  776.       koppel_line(IGNORE_COORS);             /* Neue Zeile erzeugen         */
  777.       akt_winp->alinep->text = rest;         /* Rest separat abspeichern    */
  778.       bl->e_line++;    /* Fuer adapt_pos Blockende temporaer "manipulieren" */
  779.       bl->e_col = 0;
  780.     }
  781.  
  782.   /* Eingefügten Block zum aktuellen machen, damit adapt_pos mit den */
  783.   /* richtigen Koordinaten rechnet.                                  */
  784.   memcpy(&akt_winp->block,bl,sizeof(block_typ));
  785.   adapt_pos(AP_INSERT);          /* Marker etc. anpassen */
  786.   bl->s_line = tmp_sline;        /* Echte Blockstart- und Endkoordinaten */
  787.   bl->s_col  = tmp_scol;         /* restaurieren */
  788.   bl->e_line = tmp_eline;
  789.   bl->e_col  = tmp_ecol;
  790.   /* Jetzt angepaßte Werte in den aktuellen Block übernehmen */
  791.   memcpy(&akt_winp->block,bl,sizeof(block_typ));
  792.   gotox (old_tl);                /* Cursorposition restaurieren */
  793.   akt_winp->screencol = old_sc;  /* Cursorspalte bleibt gleich */
  794.   check_underl();   /* evtl. wegen Unterstr. screencol und textcol anpassen */
  795.   return (TRUE);
  796. }
  797.  
  798. /*****************************************************************************
  799. *
  800. *  Funktion    abgespeicherten recht. Block in Text einfuegen (ins_rechteck)
  801. *  --------
  802. *
  803. *  Parameter    : bl       :
  804. *                   Typ          : block_typ *
  805. *                   Wertebereich : Pointer auf block_typ
  806. *                   Bedeutung    : Einzufuegender Block
  807. *
  808. *  Ergebnis     :
  809. *                   Typ          : int
  810. *                   Wertebereich : TRUE,FALSE
  811. *                   Bedeutung    : TRUE = Einfuegen war moeglich
  812. *                                  FALSE = Einfuegen war nicht moeglich
  813. *
  814. *  Beschreibung : Der in der mit bl->bstart beginnenden Liste abgespeicherte
  815. *                 Block wird an der aktuellen Position eingefuegt, wenn dazu
  816. *                 genuegend Platz ist. Der eingefuegte Block wird
  817. *                 anschliessend zum aktuellen.
  818. *
  819. *****************************************************************************/
  820.  
  821. int ins_rechteck(bl)
  822. register block_typ *bl;
  823. {
  824.   /* *** interne Daten und Initialisierung *** */
  825.   register bzeil_typ *akt_zeile = bl->bstart;      /* Aktueller Block    */
  826.   register int       i,        /* Zaehler zum Auffuellen mit Blanks      */
  827.              diff;     /* Anzahl einzufuegender Zeilen           */
  828.   int                line_len, /* Laenge einer Textzeile                 */
  829.              old_tl = akt_winp->textline,  /* alte Zeilennummer  */
  830.              old_sc = akt_winp->screencol; /* alte Spaltennummer */
  831.   zeil_typ           *old_ap = akt_winp->alinep;   /* alter Zeilenzeiger */
  832.   register char      *tp,      /* Index fuer Textpuffer (buff)           */
  833.              *fzsc;    /* Zeiger auf Zeichen, wo eingefuegt wird */
  834.   char               buff[3*MAXLENGTH+1]; /* Puffer zum Zusammenfuegen   */
  835.                       /* der Zeilenbruchstuecke      */
  836.  
  837.   if (!akt_zeile || bl->laenge<0)          /* Falls Block leer, fertig */
  838.     return (TRUE);
  839.   check_buff();      /* Evtl. Pufferinhalt in Textstruktur uebernehmen */
  840.   if(akt_winp->maxline <= -1)  /* Falls Text leer, eine Zeile erzeugen */
  841.     koppel_line(IGNORE_COORS);
  842.  
  843.   /* Es werden alle Zeilen, in die Blockteile eingefuegt werden, darauf */
  844.   /* untersucht, ob durch die Einfuegung die maximale Zeilenlaenge      */
  845.   /* ueberschritten wuerde. Stellt man bei der Zeilenlaengenberechnung  */
  846.   /* fest, dass der Block hinter dem Zeilenende eingefuegt werden soll, */
  847.   /* dann wird als Zeilenlaenge die Cursorposition verwendet.           */
  848.   do
  849.   {
  850.     if((line_len = fastll(akt_winp->alinep->text)) < akt_winp->screencol)
  851.       line_len = akt_winp->screencol;
  852.     if (line_len + bl->e_col - bl->s_col > MAXLENGTH)
  853.       return (FALSE);
  854.   }while ((akt_zeile = akt_zeile->next) && down());
  855.  
  856.   /* Falls zu viele Zeilen eingefuegt werden muessten, FALSE zurueckgeben. */
  857.   if ((diff=old_tl+bl->laenge-akt_winp->textline) + akt_winp->maxline
  858.   >= MAX_ANZ_LINES)
  859.     return (FALSE);
  860.   akt_winp->changeflag = TRUE; /* Text als geaendert markieren */
  861.   while (diff--)
  862.     koppel_line(IGNORE_COORS); /* Falls Text zu kurz, fehlende Zeilen anhaengen */
  863.   akt_winp->textline = old_tl;                /* Cursorposition restaurieren */
  864.   akt_winp->alinep = old_ap;
  865.   akt_winp->screencol = old_sc; /* auch screencol, da von koppel_line geloescht */
  866.  
  867.   bl->e_col += akt_winp->screencol - bl->s_col; /* Blockkoordinaten eintragen */
  868.   bl->s_col  = akt_winp->screencol;
  869.   bl->e_line = bl->s_line = akt_winp->textline;
  870.  
  871.   /* Jetzt Pufferzeilen in Textzeilen hineinkopieren */
  872.   akt_zeile = bl->bstart;
  873.   do
  874.   {
  875.     if ((fzsc = fastzeichen(akt_winp->screencol)) == &space)
  876.     { /* Falls nach Zeilenende angehaengt werden muss */
  877.       if(akt_winp->alinep->text)
  878.       {
  879.     strcpy (buff,akt_winp->alinep->text); /* Ganze Zeile in Puffer kopieren */
  880.     tp = buff+strlen(buff);               /* tp hinter Ende setzen */
  881.       }
  882.       else
  883.     tp = buff;       /* Falls Zeile leer, nichts kopieren */
  884.       for (i=fastll(akt_winp->alinep->text);i<akt_winp->screencol;i++)
  885.     *tp++ = ' ';    /* Puffer mit Spaces bis zum Blockanfang auffuellen */
  886.       *tp = '\0';       /* Puffer mit '\0' abschliessen */
  887.     }
  888.     else /* Falls nicht ans Zeilenende anhaengen, ersten Teil der Zeile kopieren */
  889.     {
  890.       strncpy(buff,akt_winp->alinep->text,fzsc-akt_winp->alinep->text);
  891.       buff[fzsc-akt_winp->alinep->text] = '\0';
  892.       tp = buff+(fzsc-akt_winp->alinep->text);
  893.     }
  894.     if (akt_zeile->text)            /* Steht etwas in der Pufferzeile */
  895.     {
  896.       strcat(buff,akt_zeile->text); /* Ja, dann an Puffer anhaengen */
  897.       tp += strlen(akt_zeile->text);
  898.     }
  899.     for (i=fastll(buff);i<bl->e_col;i++) /* Evtl. Puffer bis e_col mit Spaces */
  900.       *tp++ = ' ';                    /* auffuellen, falls Blockzeile zu kurz */
  901.     *tp = '\0';
  902.     if (fzsc != &space) /* Falls in aktueller Zeile noch Rest, diesen anhaengen */
  903.       strcat (buff,fzsc);
  904.     line_free(akt_winp->alinep->text);        /* alte Zeile freigeben */
  905.     akt_winp->alinep->text = save_text(buff); /* neue Zeile abspeichern */
  906.     down();                                   /* naechste Zeile */
  907.     bl->e_line++;
  908.   }while (akt_zeile=akt_zeile->next); /* Bis letzte Zeile des Blocks eingefuegt */
  909.   bl->e_line--;                       /* e_line ist immer letzte Blockzeile    */
  910.  
  911.   /* Eingefügten Block zum aktuellen machen, damit adapt_pos mit den */
  912.   /* richtigen Koordinaten rechnet.                                  */
  913.   memcpy(&akt_winp->block,bl,sizeof(block_typ));
  914.   adapt_pos(AP_INSERT);               /* Marker etc. anpassen                  */
  915.   akt_winp->textline = old_tl;        /* Cursorposition restaurieren           */
  916.   akt_winp->alinep = old_ap; /* Anschliessend testen, ob aktuelles Zeichen     */
  917.   check_underl();  /* unterstrichen ist und evtl. screencol u. textcol anpassen*/
  918.   return (TRUE);
  919. }
  920.  
  921. /*****************************************************************************
  922. *
  923. *  Funktion       aktuellen Block ein/ausruecken (indent_block)
  924. *  --------
  925. *
  926. *  Parameter    :
  927. *                   Typ          : int
  928. *                   Wertebereich : -MAXLENGTH - MAXLENGTH
  929. *                   Bedeutung    : Anzahl der Spalten, um die eingerueckt
  930. *                                  werden soll
  931. *
  932. *  Ergebnis     :
  933. *                   Typ          : int
  934. *                   Wertebereich : TRUE,FALSE
  935. *                   Bedeutung    : TRUE = Einruecken war moeglich
  936. *                                  FALSE = Einruecken war nicht moeglich
  937. *
  938. *  Beschreibung : Der aktuelle Block wird um weite Spalten nach rechts ein-
  939. *                 gerueckt. Ist weite negativ wird der Block daher nach links
  940. *                 verschoben.  Wuerde durch des Einruecken eine Zeile zu lang,
  941. *                 wird nicht eingerueckt.
  942. *
  943. *****************************************************************************/
  944.  
  945. int indent_block(weite)
  946. register int weite;
  947. {
  948.   /* *** interne Daten und Initialisierung *** */
  949.   int          i,      /* Schleifenzaehler zur Erzeugung des Leerstring */
  950.            /* ib gibt die Position des Cursors relativ zum Block an */
  951.            ib=in_block(akt_winp->textline,akt_winp->screencol);
  952.   register int ie_line = akt_winp->block.e_line,  /* Letzte Blockzeile  */
  953.            old_sc = akt_winp->screencol; /* Alte Cursorspalte       */
  954.   register int old_tl = akt_winp->textline;  /* Alte Cursorzeile        */
  955.   zeil_typ     *old_ap = akt_winp->alinep;   /* Alter Zeilenzeiger      */
  956.   char         leer[MAXLENGTH+1],            /* Puffer fuer Leerstring  */
  957.            buff[3*MAXLENGTH+1],          /* Puffer zum Zusammenfue- */
  958.                          /* von Leerstring und Zeile*/
  959.            *hilf; /* Zeiger in Textzeile bei Einruecken nach links  */
  960.  
  961.   if(!akt_winp->block.e_col)
  962.     ie_line--;             /* falls Blockende am Zeilenanfang, letzte Zeile */
  963.   gotox(akt_winp->block.s_line); /* nicht mit einruecken! */
  964.   if (weite > 0)
  965.   {    /* Wenn Blockzeilen nach rechts verschoben werden, */
  966.     do /* testen, ob Zeile durch Einruecken nach rechts zu lang wuerde */
  967.     {
  968.       if (fastll(akt_winp->alinep->text) + weite > MAXLENGTH)
  969.       {
  970.     akt_winp->alinep = old_ap;    /* Wenn ja, Cursor restaurieren, */
  971.     akt_winp->textline = old_tl;  /* Fehlermeldung ausgeben und    */
  972.     pe_or(PROMPT_INDNTLONG);
  973.     return (FALSE);               /* Funktion verlassen            */
  974.       }
  975.     } while (akt_winp->textline < ie_line && down());
  976.  
  977.     for (i=weite-1;i>=0;i--)
  978.       leer[i] = ' ';    /* String mit Spaces erzeugen, der vor die Zeile */
  979.     leer[weite] = '\0'; /* kopiert wird.                                 */
  980.     gotox(akt_winp->block.s_line);
  981.   }
  982.  
  983.   do
  984.   {
  985.     if (akt_winp->alinep->text)
  986.       if (weite > 0) /* bei Einruecken nach rechts String mit Spaces vor */
  987.       {              /* aktuelle Zeile kopieren                          */
  988.     strcpy(buff,leer);
  989.     strcat(buff,akt_winp->alinep->text);
  990.     free(akt_winp->alinep->text);
  991.     akt_winp->alinep->text = save_text(buff);
  992.       }
  993.       else
  994.       { /* bei Einruecken nach links die ersten <weite> Zeichen verwerfen */
  995.     if ((hilf=fastzeichen(-1 * weite)) == &space)
  996.       hilf = NULL;
  997.     else
  998.       hilf = save_text(hilf);
  999.     free(akt_winp->alinep->text);
  1000.     akt_winp->alinep->text = hilf;
  1001.       }
  1002.   } while (akt_winp->textline < ie_line && down());
  1003.  
  1004.   akt_winp->alinep = old_ap;    /* Cursorposition restaurieren */
  1005.   akt_winp->textline = old_tl;
  1006.   akt_winp->screencol = old_sc;
  1007.  
  1008.   if (ib & B_LINE) /* Falls Cursor in Blockzeile steht, X-Position anpassen */
  1009.   {
  1010.     if (weite > 0 && akt_winp->screencol < MAXLENGTH-weite)
  1011.       akt_winp->screencol += weite;
  1012.     else
  1013.       if (weite < 0 && akt_winp->screencol >= -1 * weite)
  1014.     akt_winp->screencol += weite;
  1015.   }
  1016.  
  1017.   if((akt_winp->block.s_col += weite) < 0)  /* Blockkoordinaten X anpassen */
  1018.     akt_winp->block.s_col = 0;
  1019.   if((akt_winp->block.e_col += weite) < 0)
  1020.     akt_winp->block.e_col = 0;
  1021.   if(akt_winp->screencol < akt_winp->ws_col) /* Evtl. Fensterinhalt anpassen */
  1022.     akt_winp->ws_col = akt_winp->screencol;
  1023.   else
  1024.     if(akt_winp->screencol >= akt_winp->ws_col + akt_winp->dx)
  1025.       akt_winp->ws_col = akt_winp->screencol - akt_winp->dx + 1;
  1026.   return (TRUE);
  1027. }
  1028.