home *** CD-ROM | disk | FTP | other *** search
/ Mega Top 1 / os2_top1.zip / os2_top1 / APPS / EDITORS / EHP12 / TEXT_2.C < prev    next >
C/C++ Source or Header  |  1993-11-16  |  47KB  |  1,159 lines

  1. /****************************************************************/
  2. /*                                                              */
  3. /*      MODUL:  text_2.c                                        */
  4. /*                                                              */
  5. /*      FUNKTIONEN:                                             */
  6. /*              - textbeginn (an textbeginn)                    */
  7. /*              - textende (an textende)                        */
  8. /*              - lines_down (anzahl von zeilen runter)         */
  9. /*              - lines_up (anzahl von zeilen hoch)             */
  10. /*              - screen_up (eine fenstergroesse hoch)          */
  11. /*              - screen_down (eine fenstergroesse runter)      */
  12. /*              - half_up (halbe fenstergroesse hoch)           */
  13. /*              - half_down (halbe fenstergroesse runter)       */
  14. /*              - insert (zeichen an akt. position einfuegen)   */
  15. /*              - enter_char (Zeichen an aktuelle Pos. kop.)    */
  16. /*              - koppel_line (Neue Zeile in Text einkoppeln)   */
  17. /*              - new_line (zeile splitten)                     */
  18. /*              - del_line (Zeile loeschen)                     */
  19. /*              - gotox (gehe zu Zeile X)                       */
  20. /*              - indent_line (aktuelle Zeile einruecken)       */
  21. /*              - fastleft (in Zeile ein Zeichen nach links)    */
  22. /*              - fastright (in Zeile ein Zeichen nach rechts)  */
  23. /*              - fastll (Zeilenlaenge der aktuellen Zeile)     */
  24. /*              - fastzeichen (Hole Zeichen aus akt. Zeile)     */
  25. /*              - fastzeile (hole aktuelle Zeile uhne Unterstr.)*/
  26. /*              - put_zeile (Zeile in Datei schreiben)          */
  27. /*              - schreib_file (Schreib File auf Platte)        */
  28. /*              - tab_in_buff (Tab in Puffer einfuegen)         */
  29. /*              - lies_file (Datei einlesen)                    */
  30. /*              - free_text (Text freigeben)                    */
  31. /*              - save_delline (aktuelle zeile sichern)         */
  32. /*              - rest_delline (gespeicherte Zeile einfuegen)   */
  33. /****************************************************************/
  34.  
  35. #include "defs.h"
  36.  
  37. extern char backupflag;
  38. extern marker_typ marker[];
  39.  
  40. /* *** globale Daten und Initialisierung *** */
  41. extern char linebuff [3*MAXLENGTH+1], /* Zeilenpuffer                  */
  42.         bufflag,         /* Flag, ob linebuff belegt ist           */
  43.         *sd_line,        /* Zwischenspeicher fuer geloeschte Zeile */
  44.         space;           /* Globales Leerzeichen                   */
  45. char        *fastzeichen();
  46.  
  47. /****************************************************************
  48. *
  49. * FUNKTION:     textbeginn()    (an textanfang)
  50. * ERGEBNIS:     TRUE,FALSE
  51. * BESCHREIBUNG: - die erste zeile wird zur aktuellen
  52. *****************************************************************/
  53.  
  54. int textbeginn()
  55. {
  56.   check_buff();  /* evtl. Pufferinhalt in Text uebernehmen */
  57.   if(akt_winp->maxline >= 0)    /* nur wenn Datei nicht leer */
  58.   { /* Da dummy vor der ersten Zeile, ist erste Zeile Nachfolger von dummy */
  59.     akt_winp->alinep = akt_winp->dummyp->next;
  60.     akt_winp->textline = 0;
  61.     return(TRUE);
  62.   }
  63.   return(FALSE);
  64. }
  65.  
  66.  
  67. /****************************************************************
  68. *
  69. * FUNKTION:     textende()      (an textende)
  70. * ERGEBNIS:     TRUE
  71. * BESCHREIBUNG: - die letzte zeile wird zur aktuellen
  72. *****************************************************************/
  73.  
  74. int textende()
  75. {
  76.   check_buff(); /* evtl. Pufferinhalt in Text uebernehmen */
  77.   /* dummy steht hinter letzter, also ist letzte Vorgaenger von dummy */
  78.   akt_winp->alinep = akt_winp->dummyp->prev;
  79.   akt_winp->textline = akt_winp->maxline;
  80.   return(TRUE);
  81. }
  82.  
  83.  
  84. /****************************************************************
  85. *
  86. * FUNKTION:     lines_down()    (anzahl von zeilen runter)
  87. *
  88. * PARAMETER:    int anz: anzahl zu ueberspringender zeilen
  89. * ERGEBNIS:     int: anzahl der wirklich uebersprungenen zeilen
  90. * BESCHREIBUNG: - es wird versucht, anz zeilen im text nach unten
  91. *               zu springen.
  92. *****************************************************************/
  93.  
  94. int lines_down(anz)
  95. register int anz;
  96. {
  97.   /* *** interne Daten und Initialisierung *** */
  98.   register int hilf = anz; /* Zwischenspeicher fuer Parameter */
  99.  
  100.   if (anz > 0 && akt_winp->maxline >=0)
  101.   {
  102.     check_buff(); /* evtl. Pufferinhalt in Text uebernehmen */
  103.  
  104.     while(anz-- && (akt_winp->textline < akt_winp->maxline))
  105.     {
  106.       akt_winp->textline++;
  107.       akt_winp->alinep = akt_winp->alinep->next;
  108.     }
  109.     return(hilf-anz-1);
  110.   }
  111.   return (0);
  112. }
  113.  
  114.  
  115. /****************************************************************
  116. *
  117. * FUNKTION:     lines_up()      (anzahl von zeilen hoch)
  118. *
  119. * PARAMETER:    int anz: anzahl zu ueberspringender zeilen
  120. * ERGEBNIS:     int: anzahl der wirklich uebersprungenen zeilen
  121. * BESCHREIBUNG: - es wird versucht, anz zeilen im text nach oben
  122. *               zu springen.
  123. *****************************************************************/
  124.  
  125. int lines_up(anz)
  126. register int anz;
  127. {
  128.   /* *** interne Daten und Initialisierung *** */
  129.   register int hilf = anz; /* Zwischenspeicher fuer Parameter */
  130.  
  131.   if (anz > 0 && akt_winp->maxline >= 0)
  132.   {
  133.     check_buff(); /* evtl. Pufferinhalt in Text uebernehmen */
  134.  
  135.     while(anz-- && akt_winp->textline)
  136.     {
  137.       akt_winp->textline--;
  138.       akt_winp->alinep = akt_winp->alinep->prev;
  139.     }
  140.     return(hilf-anz-1);
  141.   }
  142.   return (0);
  143. }
  144.  
  145.  
  146. /****************************************************************
  147. *
  148. * FUNKTION:     screen_up()     (eine bildschirmseite hoch)
  149. *
  150. * ERGEBNIS:     int: anzahl der wirklich uebersprungenen zeilen
  151. * BESCHREIBUNG: - es wird versucht, eine bildschirmseite im text
  152. *               nach oben zu springen.
  153. *****************************************************************/
  154.  
  155. int screen_up()
  156. {
  157.   return(lines_up(akt_winp->dy));
  158. }
  159.  
  160.  
  161. /****************************************************************
  162. *
  163. * FUNKTION:     screen_down()   (eine bildschirmseite runter)
  164. *
  165. * ERGEBNIS:     int: anzahl der wirklich uebersprungenen zeilen
  166. * BESCHREIBUNG: - es wird versucht, eine bildschirmseite im text
  167. *               nach unten zu springen.
  168. *****************************************************************/
  169.  
  170. int screen_down()
  171. {
  172.   return(lines_down(akt_winp->dy));
  173. }
  174.  
  175. /****************************************************************
  176. *
  177. * FUNKTION:     half_up()       (eine halbe bildschirmseite hoch)
  178. *
  179. * ERGEBNIS:     int: anzahl der wirklich uebersprungenen zeilen
  180. * BESCHREIBUNG: - es wird versucht, eine halbe bildschirmseite
  181. *               im text nach oben zu springen.
  182. *****************************************************************/
  183.  
  184. int half_up()
  185. {
  186.   return(lines_up(akt_winp->dy / 2));
  187. }
  188.  
  189.  
  190. /****************************************************************
  191. *
  192. * FUNKTION:     half_down()     (eine halbe bildschirmseite runter)
  193. *
  194. * ERGEBNIS:     int: anzahl der wirklich uebersprungenen zeilen
  195. * BESCHREIBUNG: - es wird versucht, eine halbe bildschirmseite
  196. *               im text nach unten zu springen.
  197. *****************************************************************/
  198.  
  199. int half_down()
  200. {
  201.   return(lines_down(akt_winp->dy / 2));
  202. }
  203.  
  204. /****************************************************************
  205. *
  206. * FUNKTION:     insert()        (zeichen einfuegen)
  207. *
  208. * PARAMETER:    int n: anzahl einzufuegender zeichen
  209. * ERGEBNIS:     int: Anzahl tatsaechlich eingefuegter Zeichen
  210. * BESCHREIBUNG: - fuer n zeichen wird ab der aktuellen position
  211. *               platz geschaffen
  212. *               - die Anzahl der tatsaechlich eingefuegten
  213. *               Zeichen wird zurueckgegeben
  214. *****************************************************************/
  215.  
  216. int insert(n)
  217. register int n;
  218. {
  219.   /* *** interne Daten und Initialisierung *** */
  220.   register int n2 = 0, /* Anzahl wirklich einzufuegender Positionen */
  221.            old_sc = akt_winp->screencol, /* alte Cursorspalte   */
  222.            old_tc; /* alte Cursorspalte intern                  */
  223.  
  224.   fill_buff(); /* sicherstellen, dass aktuelle Zeile im Puffer ist */
  225.   old_tc = akt_winp->textcol; /* Cursorspalte merken */
  226.   eol(); /* Falls hinter Zeilenend nicht genug Platz fuer n Zeichen, */
  227.   if((n2 = MAXLENGTH - akt_winp->screencol) > n) /* dann weniger einfuegen */
  228.     n2 = n;                      /* Im Unterstreich-Modus pro Zeichen 3 */
  229.   n2 *= 1+2*akt_winp->underflag; /* Bytes einfuegen. */
  230.   akt_winp->textcol = old_tc;    /* Cursorspalte merken */
  231.   akt_winp->screencol = old_sc;
  232.   if(n2)                         /* noch platz da ? */
  233.   {
  234.     akt_winp->changeflag = TRUE;  /* Text als geaendert markieren */
  235.     linebuff[3*MAXLENGTH-n2] = '\0'; /* Neues Ende setzen */
  236.     /* Ab Cursor alles um n2 Postionen nach rects */
  237.     revcpy(&linebuff[akt_winp->textcol+n2],&linebuff[akt_winp->textcol]);
  238.     /* Falls die Anzahl einzufuegender Zeichen groesser als die Laenge
  239.       des zu verschiebenden Textes ist, wird '\0' nicht durch revcpy
  240.       ueberschrieben. Dies muss man dann hier nachholen.               */
  241.     if (n2 > 3*MAXLENGTH-n2-akt_winp->textcol)
  242.       linebuff[3*MAXLENGTH-n2] = ' ';     /* Blockgrenzen in screencol-Mass */
  243.     insdel_blockadapt(n2/(1+2*akt_winp->underflag)); /* anpassen */
  244.   }
  245.   return(n2 / (1 + 2*akt_winp->underflag));
  246. }
  247.  
  248. /****************************************************************
  249. *
  250. * FUNKTION:     enter_char()    (zeichen an aktuelle pos kopieren)
  251. *
  252. * PARAMETER:    char c: einzufuegendes zeichen
  253. * ERGEBNIS:     TRUE/FALSE
  254. * BESCHREIBUNG: - das zeichen c wird an die aktuelle position ko-
  255. *               piert
  256. *               - danach wird check_underl() aufgerufen
  257. *               - das neue Zeichen wird angezeigt und evtl. der
  258. *               Bildschirm gescrollt
  259. *****************************************************************/
  260.  
  261. int enter_char(c)
  262. register char c;
  263. {
  264.   /* *** interne Daten und Initialisierung *** */
  265.   register int cu_ret = FALSE; /* Rueckgabewert der check_underl()-Funktion */
  266.  
  267.   fill_buff(); /* sicherstellen, dass aktuelle Zeile im Puffer ist */
  268.   if(akt_winp->screencol < MAXLENGTH) /* Nur wenn Cursor nicht hinter */
  269.   {                                   /* Zeilenende steht             */
  270.     akt_winp->changeflag = TRUE; /* Text als geaendert markieren */
  271.     if(akt_winp->underflag) /* Unterstreichung aktiv ? */
  272.     {                       /* Dann vor dem Zeichen _ und  einsetzen */
  273.       linebuff[akt_winp->textcol] = '_';
  274.       linebuff[akt_winp->textcol+1] = '';
  275.       linebuff[akt_winp->textcol+2] = c;
  276.     }
  277.     else
  278.     {
  279.       linebuff[akt_winp->textcol] = c;
  280.       cu_ret = check_underl(); /* pruefen ob Unterstreichung entstanden ist */
  281.     }
  282.     if (akt_winp->screencol-akt_winp->ws_col >= akt_winp->dx-1)
  283.     { /* Testen, ob horizontal gescrollt werden muss */
  284.       /* Wenn ja, dann normal die voreingestellte Weite. Sollte diese */
  285.       /* groesser als die Fensterbreite sein, dann 1/4 Fensterbreite  */
  286.       akt_winp->ws_col += EC_SCROLL_WIDTH < akt_winp->dx ?
  287.               EC_SCROLL_WIDTH : akt_winp->dx / 4 + 1;
  288.       if(akt_winp->ws_col >= MAXLENGTH) /* Zu weit, dann eins zurueck */
  289.     akt_winp->ws_col = MAXLENGTH-1;
  290.       show_win(W_AKT);  /* Fensterinhalt neu anzeigen */
  291.       fill_buff(); /* aktuelle Zeile wieder in Puffer kopieren */
  292.     }
  293.     else  /* Wenn nicht gescrollt werden musste: */
  294.       if (cu_ret) /*Bei neu entstandener Unterstreichung Zeile neu anzeigen */
  295.     lineout(akt_winp->textline-akt_winp->ws_line);
  296.       else        /* Sonst nur neu eingefuegtes Zeichen */
  297.     fastcharout(akt_winp->textline-akt_winp->ws_line,
  298.             akt_winp->screencol-akt_winp->ws_col,
  299.             linebuff+akt_winp->textcol,akt_winp->insflag?INSERT:PUT);
  300.     akt_winp->textcol+= 1+2*akt_winp->underflag;
  301.     akt_winp->screencol++; /* Cursorspalte anpassen */
  302.     return(TRUE);
  303.   }
  304.   return(FALSE); /* Cursor stand hinter dem Zeilenende */
  305. }
  306.  
  307. /*****************************************************************************
  308. *
  309. *  Funktion      Neue Zeile in Text einkoppeln (koppel_line)
  310. *  --------
  311. *
  312. *  Parameter    : modus     :
  313. *                   Typ          : int
  314. *                   Wertebereich : ADAPT_COORS,IGNORE_COORS
  315. *                   Bedeutung    : ADAPT_COORS:  Block- und Markerpositionen
  316. *                                  sowie letzte Position werden angepasst
  317. *                                  IGNORE_COORS: ... werden nicht angepasst
  318. *
  319. *  Beschreibung : Fuer eine neue Zeile wird Speicherplatz alloziert.
  320. *                 Anschliessend wird das Element korrekt hinter alinep
  321. *                 eingehaengt. Die neu eingefuegte Zeile wird zur
  322. *                 aktuellen Zeile.
  323. *                 Abhaengig vom Modus wird nl_blockadapt aufgerufen
  324. *
  325. *****************************************************************************/
  326.  
  327. void koppel_line(modus)
  328. int modus;
  329. {
  330.   /* *** interne Daten und Initialisierung *** */
  331.   register zeil_typ *zeile = (zeil_typ*) reserve_mem(sizeof(zeil_typ));
  332.        /* zeile zeigt auf neu eingehaengte Zeile */
  333.  
  334.   if(modus == ADAPT_COORS)    /* evtl. Blockkoordinaten anpassen */
  335.     nl_blockadapt();
  336.   zeile->prev = akt_winp->alinep;       /* in Liste einhaengen      */
  337.   zeile->next = akt_winp->alinep->next;
  338.   zeile->next->prev = zeile;
  339.   akt_winp->alinep->next = zeile;
  340.   akt_winp->alinep = zeile;
  341.   akt_winp->alinep->text = NULL;        /* Zeile als leer markieren */
  342.   akt_winp->textcol = akt_winp->screencol = 0; /* Cursor in Spalte 0 */
  343.   akt_winp->maxline++;  /* Zeilenzahl und Cursorzeile haben sich erhoeht */
  344.   akt_winp->textline++;
  345.   akt_winp->changeflag = TRUE; /* Text wurde geaendert */
  346. }
  347.  
  348. /****************************************************************
  349. *
  350. * FUNKTION:     new_line()      (zeile splitten)
  351. *
  352. * ERGEBNIS:       TRUE, FALSE
  353. * BESCHREIBUNG: - die aktuelle zeile wird an der aktuellen po-
  354. *               sition gespalten und der rechte teil in eine
  355. *               neue, der aktuellen zeile nachfolgenden zeile
  356. *               kopiert
  357. *               - diese neue zeile wird dann zur aktuellen zeile,
  358. *               wobei der cursor in die erste spalte gesetzt
  359. *               wird
  360. *               - Wenn durch das Einfuegen der neuen Zeile das
  361. *               Zeilenlimit ueberschritten wuerde, wird keine
  362. *               Zeile eingefuegt und FALSE zurueckgegeben.
  363. *               Sonst ist der RETURN-Wert TRUE.
  364. *
  365. *****************************************************************/
  366.  
  367. int new_line()
  368. {
  369.   /* *** interne Daten und Initialisierung *** */
  370.   register char *zeil_anf, /* Zeiger auf Anfang der neuen Zeile        */
  371.         *ltext;    /* Zeiger auf aktuelle Zeile                */
  372.   int           old_sc = akt_winp->screencol, /* alte Cursorspalte     */
  373.         y;         /* Zeilennummer absolut auf Bildschirm      */
  374.   short int     rc;        /* Zeichen, mit dem Rahmen restauriert wird */
  375.  
  376.   if(akt_winp->maxline < MAX_ANZ_LINES - 1)
  377.   {
  378.     check_buff();                       /* eventuell Puffer in Text zurueck */
  379.     ltext = akt_winp->alinep->text;
  380.     zeil_anf = fastzeichen(akt_winp->screencol);/* Anfang neuer Zeile holen */
  381.     koppel_line(ADAPT_COORS);   /* Eine neue Zeile erzeugen */
  382.     if(zeil_anf != &space)   /* wenn nicht am Zeilenende gesplittet wurde */
  383.     {
  384.       y = akt_winp->textline-akt_winp->ws_line;
  385.       wmove(akt_winp->winp, /* Zur Cursorposition auf Bildschirm */
  386.         y,old_sc-akt_winp->ws_col+1);
  387.       /* Die Cursorposition liegt nun in der Zeile vor der aktuellen Zeile,
  388.      da koppel_line die neue Zeile zur aktuellen macht. */
  389.       wclrtoeol(akt_winp->winp); /* Rest der aktuellen Zeile loeschen */
  390.       if(y == 1)
  391.       rc = REST_ARR_UP | 256*A_STANDOUT;
  392.     else
  393.       if(y == akt_winp->dy)
  394.         rc = REST_ARR_DN | 256*A_STANDOUT;
  395.       else
  396.         rc = REST_CHAR | 256*A_STANDOUT;
  397.       mvwaddch(akt_winp->winp,y,
  398.            akt_winp->dx+1,rc); /* Rechten Rahmen restaurieren */
  399.       akt_winp->alinep->text = save_text(zeil_anf);/* neue zeile abspeichern*/
  400.       *zeil_anf = '\0';  /* ende alte zeile setzen und neue alte Zeile */
  401.       akt_winp->alinep->prev->text = save_text(ltext);  /* abspeichern */
  402.       free(ltext);                              /* alte zeile freigeben   */
  403.     }
  404.     return (TRUE);                              /* Einfuegen hat geklappt */
  405.   }
  406.   return (FALSE);
  407. }
  408.  
  409. /*****************************************************************************
  410. *
  411. *  Funktion       Zeile loeschen (del_line)
  412. *  --------
  413. *
  414. *  Parameter    : modus     :
  415. *                   Typ          : int
  416. *                   Wertebereich : IGNORE_COORS, ADAPT_COORS
  417. *                   Bedeutung    : IGNORE_COORS: del_line wird von Blockfunktion
  418. *                                  aufgerufen
  419. *                                  ADAPT_COORS: del_line wird nicht von einer
  420. *                                  Blockfunktion aufgerufen
  421. *
  422. *  Ergebnis     :
  423. *                   Typ          : int
  424. *                   Wertebereich : NO_LINE_DEL,LAST_LINE_DEL,OTHER_LINE_DEL
  425. *                   Bedeutung    : NO_LINE_DEL : Konnte keine Zeile loeschen
  426. *                                  OTHER_LINE_DEL : Zeile ungleich letzter
  427. *                                                   geloescht
  428. *                                  LAST_LINE_DEL : Letzte Zeile geloescht
  429. *
  430. *  Beschreibung : Die aktuelle Zeile wird aus der Zeilenliste ausgekoppelt
  431. *                 und der dafuer reservierte Speicherplatz freigegeben.
  432. *                 Wird die letzte Zeile des Textes geloescht, dann wird der
  433. *                 Cursor intern um eine Zeile nach oben bewegt und LAST_LINE_DEL
  434. *                 zurueckgegeben.
  435. *                 Wird die Zeile von einer Blockfunktion, z.B. del_normal
  436. *                 aufgerufen, so wird nicht dl_blockadapt aufgerufen, da
  437. *                 schon die Blockfunktion die Anpassung der Marker und der
  438. *                 letzten Position vornimmt.
  439. *
  440. *****************************************************************************/
  441.  
  442. int del_line(modus)
  443. int modus;
  444. {
  445.   /* *** interne Daten *** */
  446.   register zeil_typ *zeile; /* Zeiger auf nachfolgende Zeile */
  447.  
  448.   if (akt_winp->textline != -1)               /* Dummyzeile nicht loeschen */
  449.   {
  450.     akt_winp->changeflag = TRUE;  /* Text als veraendert markieren */
  451.     if(modus == ADAPT_COORS)      /* evtl. Blockgrenzen anpassen */
  452.       dl_blockadapt();
  453.     bufflag = FALSE;                    /* Pufferinhalt ist egal */
  454.     /* Zeile aus Textliste auskoppeln */
  455.     akt_winp->alinep->next->prev = akt_winp->alinep->prev;
  456.     akt_winp->alinep->prev->next = zeile = akt_winp->alinep->next;
  457.     line_free(akt_winp->alinep->text);  /* Zeile freigeben */
  458.     free (akt_winp->alinep);
  459.     akt_winp->alinep = zeile;
  460.     if (akt_winp->textline == akt_winp->maxline--)   /* unterste Textzeile? */
  461.     {
  462.       if(akt_winp->maxline == -1)                 /* allerletzte Textzeile? */
  463.       {
  464.     akt_winp->textline--;                        /* textline auf -1 */
  465.     akt_winp->screencol = 0;
  466.       }
  467.       else
  468.     up();                                         /* eins hoch */
  469.       return (LAST_LINE_DEL);
  470.     }
  471.     return (OTHER_LINE_DEL);
  472.   }
  473.   return (NO_LINE_DEL);
  474. }
  475.  
  476. /*****************************************************************************
  477. *
  478. *  Funktion       Gehe zu Zeile x (gotox)
  479. *  --------
  480. *
  481. *  Parameter    : zeile     :
  482. *                   Typ          : int
  483. *                   Wertebereich : 1-MAX_ANZ_LINES
  484. *                   Bedeutung    : Zeile, die angesprungen werden soll.
  485. *
  486. *  Beschreibung : Es wird getestet, welcher Weg zur uebergebenen Zeile der
  487. *                 kuerzeste ist : vom Start, vom Ende oder von der aktuellen
  488. *                 Zeile aus. Ueber diesen Weg wird dann alinep des aktuellen
  489. *                 Windows gesetzt. textline wird korrekt angepaßt.
  490. *
  491. *****************************************************************************/
  492.  
  493. void gotox (zeile)
  494. register int zeile;
  495. {
  496.   /* *** interne Daten *** */
  497.   register int dist; /* Entfernung zur gewuenschten Zeile */
  498.  
  499.   if(akt_winp->maxline < 0) /* Text leer, dann raus */
  500.     return;
  501.   if(zeile > akt_winp->maxline) /* Zeilennummer zu gross, dann */
  502.     zeile = akt_winp->maxline;  /* zur letzten Zeile           */
  503.   if(zeile < 0)   /* Wenn Zeilennummer kleiner als 0, dann zur ersten */
  504.     zeile = 0;
  505.  
  506.   dist = akt_winp->textline - zeile; /* Entfernung berechnen */
  507.   check_buff(); /* Puffer in Text falls man in aktueller Zeile bleibt */
  508.   /* Pruefen, ob es guenstig ist, von der aktuellen Postion loszulaufen */
  509.   if (abs(dist) <= zeile && abs(dist) <= akt_winp->maxline-zeile)
  510.     if (dist < 0)              /* Abhaengig vom Vorzeichen von dist */
  511.       lines_down (abs(dist));  /* hoch oder runter gehen */
  512.     else
  513.       lines_up   (abs(dist));
  514.   else /* Es bietet sich an, vom Anfang oder vom Ende loszulaufen */
  515.   {
  516.     akt_winp->alinep = akt_winp->dummyp;
  517.     if (zeile < akt_winp->maxline-zeile) /* besser vom Anfang ? */
  518.     {
  519.       akt_winp->textline = -1;           /* dann vorwaerts */
  520.       lines_down (zeile+1);
  521.     }
  522.     else                                 /* sonst rueckwaerts */
  523.     {
  524.       akt_winp->textline = akt_winp->maxline+1;
  525.       lines_up (akt_winp->maxline-zeile+1);
  526.     }
  527.   }
  528. }
  529.  
  530. /*****************************************************************************
  531. *
  532. *  Funktion       aktuelle  Zeile einruecken (indent_line)
  533. *  --------
  534. *
  535. *  Beschreibung : Die aktuelle Zeile wird so eingerueckt, dass die Zeile
  536. *                 am Anfang soviele Blanks enthaelt wie die darueberliegende.
  537. *
  538. *****************************************************************************/
  539.  
  540. void indent_line()
  541. {
  542.   /* *** interne Daten und Initialisierung *** */
  543.   register int i,     /* Loopvariable fuer Marker und Blanks */
  544.            anz=0; /* Zaehler fuer Einrueckungsweite */
  545.   int          sc=akt_winp->screencol; /* Zwischenspeicher fuer Cursorspalte */
  546.   char         *txt,  /* Zeiger auf vorangehende Zeile  */
  547.            *txt2; /* Zeiger in neuen Zeilenstring   */
  548.  
  549.   check_buff(); /* sicherstellen, dass Pufferinhalt im Text ist */
  550.   if (txt = akt_winp->alinep->prev->text)
  551.   { /* Wenn vorhergehende Zeile nicht leer, dann fuehrende Blanks zaehlen */
  552.     while(*txt == ' ' && fastright(&txt,1))
  553.       anz++;    /* Zaehlen, wie weit eingerueckt wird */
  554.  
  555.     swap_int(&akt_winp->screencol,&sc); /* Alte Cursorspalte zur neuen machen */
  556.     insdel_blockadapt(anz); /* Block, lastpos und Marker anpassen */
  557.     swap_int(&akt_winp->screencol,&sc); /* Cursor wieder an neuen Zeilenstart */
  558.  
  559.     if(akt_winp->alinep->text) /* Wenn einzurueckende Zeile nicht leer: */
  560.     { /* Platz fer Zeile und einzufuegende Blanks allozieren */
  561.       txt2 = txt = reserve_mem(strlen(akt_winp->alinep->text)
  562.               + akt_winp->screencol+1);
  563.       for(i=0;i<akt_winp->screencol;i++)   /* Blanks eintragen */
  564.     *txt2++ = ' ';
  565.       strcpy(txt2,akt_winp->alinep->text); /* Alte Zeile dranhaengen */
  566.       free(akt_winp->alinep->text);   /* Alte Zeile freigeben */
  567.       akt_winp->alinep->text = txt;
  568.     }
  569.   }
  570. }
  571.  
  572. /*****************************************************************************
  573. *
  574. *  Funktion       in Zeile Anzahl Zeichen nach links (fastleft)
  575. *  --------
  576. *
  577. *  Parameter    : zeile     :
  578. *                   Typ          : char**
  579. *                   Wertebereich : Doppelpointer auf ASCII-Zeichenkette
  580. *                   Bedeutung    : Character, ab dem nach links bewegt werden
  581. *                                  soll. Muss auf einen Character in
  582. *                                  akt_winp->alinep->text zeigen.
  583. *
  584. *  Parameter    : anzahl    :
  585. *                   Typ          : int
  586. *                   Wertebereich : 0-MAXLENGTH
  587. *                   Bedeutung    : Anzahl der Positionen, um die nach links
  588. *                                  gegangen werden soll.
  589. *
  590. *  Ergebnis     :
  591. *                   Typ          : int
  592. *                   Wertebereich : TRUE, FALSE
  593. *                   Bedeutung    : TRUE : konnte anzahl Zeichen nach links
  594. *                                  FALSE: konnte nicht anzahl Zeichen nach
  595. *                                         links
  596. *
  597. *  Beschreibung : Der pointer auf den String (*zeile) wird unter Berueck-
  598. *                 sichtigung von unterstrichenen Zeichen so oft nach links
  599. *                 bewegt, bis die vorgegebene Anzahl erreicht ist oder
  600. *                 man am linken Zeilenrand angekommen ist.
  601. *                 akt_winp->screencol wird angepasst.
  602. *
  603. *****************************************************************************/
  604.  
  605. int fastleft(zeile,anzahl)
  606. register char **zeile;
  607. register int  anzahl;
  608. {
  609.   while (anzahl--)
  610.   {
  611.     if (*zeile > akt_winp->alinep->text)  /* Zeilenanfang ? */
  612.     {
  613.       if (*zeile-2 >= akt_winp->alinep->text    /* Steht man auf einem      */
  614.       && *(*zeile-1)=='' && *(*zeile-2)=='_') /* unterstrichenem Zeichen? */
  615.     *zeile -= 3;   /* Dann 3 nach links, */
  616.       else
  617.     (*zeile)--;    /* sonst nur 1 nach links */
  618.       akt_winp->screencol--;  /* screencol anpassen */
  619.     }
  620.     else
  621.       return (FALSE);   /* Zeilenanfang, also FALSE zurueckgeben */
  622.   }
  623.   return (TRUE); /* Konnte anzahl Zeichen nach rechts, also TRUE zurueck */
  624. }
  625.  
  626. /*****************************************************************************
  627. *
  628. *  Funktion       in Zeile Anzahl Zeichen nach rechts (fastright)
  629. *  --------
  630. *
  631. *  Parameter    : zeile     :
  632. *                   Typ          : char**
  633. *                   Wertebereich : Doppelpointer auf ASCII-Zeichenkette
  634. *                   Bedeutung    : Character, ab dem nach rechts bewegt werden
  635. *                                  soll. Muss auf einen Character in
  636. *                                  akt_winp->alinep->text zeigen.
  637. *
  638. *  Parameter    : anzahl    :
  639. *                   Typ          : int
  640. *                   Wertebereich : 0-MAXLENGTH
  641. *                   Bedeutung    : Anzahl der Positionen, um die nach rechts
  642. *                                  gegangen werden soll.
  643. *
  644. *  Ergebnis     :
  645. *                   Typ          : int
  646. *                   Wertebereich : TRUE, FALSE
  647. *                   Bedeutung    : TRUE : konnte anzahl Zeichen nach rechts
  648. *                                  FALSE: konnte nicht anzahl Zeichen nach
  649. *                                         rechts
  650. *
  651. *  Beschreibung : Der pointer auf den String (*zeile) wird unter Berueck-
  652. *                 sichtigung von unterstrichenen Zeichen so oft nach rechts
  653. *                 bewegt, bis die vorgegebene Anzahl erreicht ist oder
  654. *                 man am rechten Zeilenrand angekommen ist.
  655. *                 akt_winp->screencol wird angepasst.
  656. *
  657. *****************************************************************************/
  658.  
  659. int fastright(zeile,anzahl)
  660. register char **zeile;
  661. register int  anzahl;
  662. {
  663.   while (anzahl--)
  664.   {
  665.     if (*(*zeile+1))  /* Zeilenende ? */
  666.     {
  667.       akt_winp->screencol++; /* screencol anpassen */
  668.       (*zeile)++; /* rechts davon _^H, dann noch 2 Positionen weiter */
  669.       if (**zeile=='_' && *(*zeile+1)=='' && *(*zeile+2))
  670.     *zeile += 2;
  671.     }
  672.     else
  673.       return (FALSE);   /* Zeilenende, also FALSE zurueckgeben */
  674.   }
  675.   return (TRUE); /* Konnte anzahl Zeichen nach rechts, also TRUE zurueck */
  676. }
  677.  
  678. /*****************************************************************************
  679. *
  680. *  Funktion       Zeilenlaenge der aktuellen Zeile berechnen (fastll)
  681. *  --------
  682. *
  683. *  Parameter    : txt       :
  684. *                   Typ          : char*
  685. *                   Wertebereich : Pointer auf ASCII-Zeichenkette
  686. *                   Bedeutung    : String, vom dem Laenge in screencol-Mass
  687. *                                  berechnet werden soll.
  688. *
  689. *  Ergebnis     :
  690. *                   Typ          : int
  691. *                   Wertebereich : 0-MAXLENGTH
  692. *                   Bedeutung    : Laenge der aktuellen Zeile in screencol-Mass
  693. *
  694. *  Beschreibung : Die aktuelle Zeile (akt_winp->alinep->text) wird bis zum
  695. *                 Ende durchgegangen, wobei berechnet wird, welche screencol-
  696. *                 position das Zeilenende hat.
  697. *
  698. *****************************************************************************/
  699.  
  700. int fastll(txt)
  701. register char *txt;
  702. {
  703.   /* *** interne Daten und Initialisierung *** */
  704.   register int sc = 0; /* vorlaeufiger return-Wert */
  705.  
  706.   if (!txt)      /* Zeile leer ? */
  707.     return (0);
  708.   while (*txt)  /* Zeilenende ? */
  709.   {
  710.     sc++;
  711.     if (*txt++ == '_' && *txt=='' && txt[1])
  712.       txt += 2; /* bei unterstrichenem Zeichen insgesamt 3 nach rechts */
  713.   }
  714.   return (sc);   /* Zeilenlaenge in screencol-Mass zurueckgeben */
  715. }
  716.  
  717. /*****************************************************************************
  718. *
  719. *  Funktion       hole zeichen aus aktueller zeile (fastzeichen)
  720. *  --------
  721. *
  722. *  Parameter    : n         :
  723. *                   Typ          : int
  724. *                   Wertebereich : 0 - MAXLENGTH-1
  725. *                   Bedeutung    : index des zu ermittelnden Zeichens
  726. *
  727. *  Ergebnis     :
  728. *                   Typ          : char*
  729. *                   Wertebereich : Pointer auf ASCII-Zeichen
  730. *                   Bedeutung    : Zeichen an Position n (s.u.)
  731. *
  732. *  Beschreibung : Die aktuelle Zeile wird bis zur Position n durchlaufen,
  733. *                 wobei _^Hx als ein Zeichen gewertet wird. Daher ist der
  734. *                 Rueckgabewert auch ein Pointer, da ein unterstrichenes
  735. *                 Zeichen mit dem _ beginnt und aus drei Codes besteht.
  736. *                 Ist die Zeile leer oder wird versucht, vor oder hinter der
  737. *                 Zeile zuzugreifen, wird die Addresse der Variablen
  738. *                 space zurueckgeliefert, die ein Leerzeichen enthaelt.
  739. *
  740. *****************************************************************************/
  741.  
  742. char *fastzeichen(n)
  743. register int n;
  744. {
  745.   /* *** interne Daten *** */
  746.   register int  sc;     /* Zaehler fuer Durchlaufen der Zeile */
  747.   register char *zeile; /* Zeiger auf aktuellen Zeilentext    */
  748.  
  749.   check_buff(); /* sicherstellen, dass Pufferinhalt im Text ist */
  750.  
  751.   /* Wenn Zeile leer ist oder n hinters Zeilenende oder vor den       */
  752.   /* Zeilenanfang zeigt, dann die Adresse des globalsn Blanks zurueck */
  753.   if (!(zeile = akt_winp->alinep->text) || (n > MAXLENGTH) || (n < 0))
  754.     return(&space);
  755.  
  756.   for(sc=0;(sc<n) && *zeile;sc++)  /* Zeile durchlaufen */
  757.     if(*zeile++ == '_' && *zeile == '' && zeile[1])
  758.       zeile+=2;
  759.  
  760.   if(!*zeile)        /* Zeilenende erreicht, dann Adresse des */
  761.     return(&space);  /* globalen Blanks zurueckgeben          */
  762.  
  763.   return(zeile);     /* Sonst das Zeichen, auf dem man steht  */
  764. }
  765.  
  766. /*****************************************************************************
  767. *
  768. *  Funktion       hole aktuelle Zeile uhne Unterstreichung (fastzeile)
  769. *  --------
  770. *
  771. *  Parameter    : p         :
  772. *                   Typ          : zeil_typ*
  773. *                   Wertebereich : Pointer auf Zeilenstruktur
  774. *                   Bedeutung    : Zeigt auf zu zu konvertierende Zeile
  775. *
  776. *  Ergebnis     :
  777. *                   Typ          : char*
  778. *                   Wertebereich : Pointer auf ASCII-Zeichen
  779. *                   Bedeutung    : Zeiger auf konvertierte Zeile
  780. *                                  Achtung: statischer Puffer!!!
  781. *
  782. *  Beschreibung : Die aktuelle Zeile wird nötigenfalls aus dem Puffer in
  783. *                 den Text übernommen. Bemerkung: alinep wird dabei nicht
  784. *                 verändert, so daß Parameter Gültigkeit behält.
  785. *                 Anschließend wird in den lokalen
  786. *                 statischen Puffer eine Kopie der angegebenen Zeile
  787. *                 gezogen, die jedoch keine
  788. *                 Unterstreichung enthält. Ist die aktuelle Zeile leer
  789. *                 (text pointer ist NULL), so wird in die erste Position
  790. *                 des Puffers ein '\0' geschrieben.
  791. *
  792. *****************************************************************************/
  793.  
  794. char *fastzeile(p)
  795. zeil_typ *p;
  796. {
  797.   /* *** interne Daten *** */
  798.   register int  sc;     /* Zaehler fuer Durchlaufen der Zeile */
  799.   register char *zeile; /* Zeiger auf aktuellen Zeilentext    */
  800.   static   char buf [BUFFSIZE]; /* Puffer, in dem Zeile zurückkommt */
  801.  
  802.   check_buff(); /* sicherstellen, dass Pufferinhalt im Text ist */
  803.  
  804.   if (!(zeile = p->text))
  805.     *buf = '\0';
  806.   else
  807.   {
  808.     sc = 0;
  809.     while (*zeile)
  810.     {
  811.       if(*zeile == '_' && zeile [1] == '' && zeile[2])
  812.     zeile+=2;
  813.       buf [sc++] = *zeile++;
  814.     }
  815.     buf [sc] = '\0';  /* String terminieren */
  816.   }
  817.   return(buf);
  818. }
  819.  
  820. /*****************************************************************************
  821. *
  822. *  Funktion       Zeile in Datei schreiben (put_zeile)
  823. *  --------
  824. *
  825. *  Parameter    : line      :
  826. *                   Typ          : char *
  827. *                   Wertebereich : Pointer auf ASCII-Zeichenkette
  828. *                   Bedeutung    : zu schreibende Zeile
  829. *
  830. *                 f         :
  831. *                   Typ          : FILE *
  832. *                   Wertebereich : Dateipointer
  833. *                   Bedeutung    : Datei, in die Zeile geschrieben werden soll
  834. *
  835. *  Beschreibung : Die Zeile wird in die Datei geschrieben. Abhaengig von
  836. *                 akt_winp->tabflag werden Spaces am Anfang - wenn moeglich -
  837. *                 zu Tabs komprimiert.
  838. *
  839. *****************************************************************************/
  840.  
  841. void put_zeile(line,f)
  842. register char *line;
  843. FILE *f;
  844. {
  845.   /* *** interne Daten und Initialisierung *** */
  846.   register int i,            /* Schleifenzaehler fuer Tabschreiben */
  847.            anz_spaces=0; /* Zaehler fuer fuehrende Blanks      */
  848.  
  849.   if(akt_winp->tabflag) /* Wenn Spaces zu Tabs komprimiert werden sollen: */
  850.   {
  851.     while(*line++ == ' ') /* Spaces am Zeilenanfang zaehlen */
  852.       anz_spaces++;
  853.     for(i=anz_spaces/STD_TAB;i>0;i--)  /* Tabs in Datei schreiben */
  854.       fputc('\t',f);
  855.     line -= anz_spaces%STD_TAB + 1;  /* Nichtkomprimierte Spaces schreiben */
  856.   }
  857.   fputs(line,f); /* Rest der Zeile in Datei schreiben */
  858. }
  859.  
  860. /*****************************************************************************
  861. *
  862. *  Funktion       Schreib File auf Platte (schreib_file)
  863. *  --------
  864. *
  865. *  Ergebnis     :   Typ          : int
  866. *                   Wertebereich : TRUE,FALSE
  867. *                   Bedeutung    : Flag, ob Operation erfolgreich
  868. *
  869. *  Beschreibung : Der im aktuellen Fenster stehende Text wird in die
  870. *                 Datei geschrieben, deren Name in der Window-Struktur
  871. *                 angegeben ist. NULL-Pointer werden in Leerzeilen kon-
  872. *                 vertiert.
  873. *
  874. *****************************************************************************/
  875.  
  876. int schreib_file ()
  877. {
  878.   /* *** interne Daten *** */
  879.   FILE     *f;  /* Pointer fuer Schreibdatei                        */
  880.   zeil_typ *tp; /* Zeiger auf aktuelle Zeile                        */
  881.   int      len; /* Laenge des Filenamens vor Anhaengen von .bak     */
  882.   char     *fn, /* Zeiger auf Dateinamen ohne Pfad                  */
  883.        *sc, /* Zur Suche des Punktes im Filenamen               */
  884.        buff[MAXLENGTH+1]; /* fuer Fehlermeldungen und Filenamen */
  885.  
  886.   if (akt_winp->read_only)
  887.   {
  888.     sprintf(buff,PROMPT_WRTPROT,akt_winp->filename);
  889.     pe_or(buff);
  890.     return (FALSE);
  891.   }
  892.   check_buff(); /* Pufferinhalt evtl. in Text uebernehmen */
  893.   sprintf(buff,PROMPT_SAVING,akt_winp->filename);
  894.   print_stat(buff);
  895.   if(backupflag && !access(akt_winp->filename,2))   /* write permission? */
  896.   {                   /* .bak erzeugen */
  897.     strcpy(buff,akt_winp->filename);
  898. #ifdef OS2  /* OS/2 verkraftet auch xxx.c.bak !!! */
  899.     strcat(buff,".bak");
  900. #else
  901.     if(sc = strchr(fn=sname(buff),'.')) /* Punkt im Filenamen suchen */
  902.       len = sc-fn;      /* Falls gefunden, ist Länge die Länge bis zum Punkt */
  903.     else                /* Sonst ist es die gesamte Länge des Filenamens */
  904.       len = strlen(fn); /* Kann nicht länger als 8 Zeichen sein. */
  905.     strcpy(&fn[len],".bak");  /* Filename des .bak-Files erzeugen */
  906. #endif
  907.     unlink(buff);     /* falls schon ein .bak gleichen Namens existiert */
  908.     rename(akt_winp->filename,buff);   /* Datei in ...bak umbenennen */
  909.   }
  910.   if (f = fopen (akt_winp->filename,"w"))
  911.   {
  912.     for (tp = akt_winp->dummyp->next; tp != akt_winp->dummyp; tp = tp->next)
  913.     { /* Alle Zeilen durchgehen und in die Datei schreiben */
  914.       if (tp->text)
  915.     put_zeile(tp->text,f);
  916.       putc('\n',f);
  917.     }
  918.   }
  919.   else  /* Fehler beim Oeffnen der Datei */
  920.   {
  921.     clear_stat();
  922.     print_stat(PROMPT_ERRWRITE);
  923.     pe_or(akt_winp->filename);
  924.     return(FALSE);
  925.   }
  926.   akt_winp->changeflag = FALSE;               /* changeflag zuruecksetzen */
  927.   fclose(f);
  928.   chmod(akt_winp->filename,akt_winp->attribs); /* Modus korrekt setzen */
  929.   clear_stat();
  930.   return(TRUE);
  931. }
  932.  
  933.  
  934. /*****************************************************************************
  935. *
  936. *  Funktion       Tab in Puffer einfuegen (tab_in_buff)
  937. *  --------
  938. *
  939. *  Parameter    : buff      :
  940. *                   Typ          : char *
  941. *                   Wertebereich : Pointer auf char-Puffer
  942. *                   Bedeutung    : Puffer, in den Tab eingefuegt werden soll
  943. *
  944. *                 sc        :
  945. *                   Typ          : int *
  946. *                   Wertebereich : Pointer auf Integer
  947. *                   Bedeutung    : aktuelle Bildschirmposition im Puffer
  948. *
  949. *                 count     :
  950. *                   Typ          : int *
  951. *                   Wertebereich : Pointer auf Integer
  952. *                   Bedeutung    : aktuelle Position im Puffer
  953. *
  954. *  Beschreibung : Bis zur naechsten Tab-Position werden im Puffer Spaces einge-
  955. *                 fuegt.
  956. *
  957. *****************************************************************************/
  958.  
  959. void tab_in_buff(buff,sc,count)
  960. register char *buff;
  961. register int *sc,*count;
  962. {
  963.   do
  964.   {
  965.     buff[(*count)++] = ' ';
  966.   } while(++*sc % STD_TAB && *sc < MAXLENGTH);
  967. }
  968.  
  969. /*****************************************************************************
  970. *
  971. *  Funktion       Datei einlesen (lies_file)
  972. *  --------
  973. *
  974. *  Beschreibung : In die Fensterstruktur des aktuellen Fensters wird der
  975. *                 Text aus der Datei, deren Name in filename steht, geladen.
  976. *                 Evtl. vorkommende Tabs werden expandiert.
  977. *
  978. *****************************************************************************/
  979.  
  980. int lies_file()
  981. {
  982.   /* *** interne Daten *** */
  983.   FILE        *f;     /* Zeiger fuer Ausgabedatei                       */
  984.   char        buff[3*MAXLENGTH+2],   /* Eingabepuffer                   */
  985.           buff2[3*MAXLENGTH+2],  /* Ausgabepuffer                   */
  986.           nlflag; /* Flag zeigt an ob komplette Zeile gelesen wurde */
  987.   int         len,    /* Laenge der eingelesenen Zeile                  */
  988.           in,     /* Index in Eingabepuffer                         */
  989.           out,    /* Index in Ausgabepuffer                         */
  990.           sc;     /* Zeilenlaenge in screencol-Mass                 */
  991.   struct stat f_info; /* Zum Einlesen der Dateiattribute                */
  992.  
  993.   /* Dummyelement fuer Textstruktur allozieren */
  994.   akt_winp->dummyp = (zeil_typ*) reserve_mem (sizeof (zeil_typ));
  995.   akt_winp->dummyp->prev = akt_winp->dummyp->next = akt_winp->alinep = akt_winp->dummyp;
  996.   akt_winp->dummyp->text = NULL;
  997.  
  998.   /* Cursorposition und andere Variablen initialisieren */
  999.   akt_winp->textline = akt_winp->maxline = -1;
  1000.   akt_winp->screencol = akt_winp->textcol = 0;
  1001.   akt_winp->attribs = STD_FATTR;
  1002.   akt_winp->read_only = FALSE;
  1003.   akt_winp->changeflag = FALSE;
  1004.  
  1005.   if (!(f = fopen (akt_winp->filename,"r")))
  1006.   {
  1007.     sprintf(buff,PROMPT_ASKNEW,akt_winp->filename);
  1008.     return (ja_nein(buff));
  1009.   }
  1010.   sprintf(buff,PROMPT_LOADING,akt_winp->filename);
  1011.   print_stat(buff);
  1012.   if (access(akt_winp->filename,2))  /* Testen, ob Datei schreibgeschuetzt */
  1013.     akt_winp->read_only = TRUE;      /* und evtl. vermerken */
  1014.   if (!stat(akt_winp->filename,&f_info)) /* Fileattribute bestimmen */
  1015.     akt_winp->attribs = f_info.st_mode & (S_IWRITE | S_IREAD);
  1016.  
  1017.   out = sc = 0;
  1018.   while (fgets(buff,3*MAXLENGTH + 1,f) && akt_winp->maxline < MAX_ANZ_LINES-1)
  1019.   { /* Zeile einlesen, testen ob das ging und ob maximale */
  1020.     /* Zeilenanzahl erreicht ist */
  1021.     if(buff[(len = strlen(buff))-1] == '\n')
  1022.     { /* testen, ob eine komplette Zeile eingelesen wurde */
  1023.       nlflag = TRUE;  /* Wenn ja, nlflag setzen */
  1024.       buff[--len] = '\0'; /* und '\n' streichen */
  1025.     }
  1026.     else /* Wenn keine komplette Zeile eingelesen werden konnte */
  1027.       nlflag = FALSE;
  1028.     in = 0;
  1029.     while(in < len)
  1030.     {
  1031.       if (buff[in] == '_' && buff[in+1] == '' && buff[in+2])
  1032.       { /* Wurde ein unterstrichenes Zeichen gelesen, dann den Unter-  */
  1033.     buff2[out++] = buff[in++];  /* strich und das Backspace ueber- */
  1034.     buff2[out++] = buff[in++];  /* nehmen */
  1035.       }
  1036.       if(buff[in] == '\t')   /* Tab ? */
  1037.     tab_in_buff(buff2,&sc,&out);
  1038.       else   /* kein Tab, dann Zeichen in Puffer uebernehmen */
  1039.       {
  1040.     buff2[out++] = buff[in];
  1041.     sc++;  /* Screencol-Laenge der Zeile erhoehen */
  1042.       }
  1043.       in++;    /* Naechstes Zeichen aus Eingabepuffer */
  1044.       if(sc == MAXLENGTH)       /* Aufbereitete Zeile voll ? */
  1045.       {
  1046.     buff2[out] = '\0'; /* Dann Puffer abschliessen */
  1047.     sc = out = 0;      /* Zeile eintragen und neue Zeile anfangen */
  1048.     koppel_line(IGNORE_COORS); /* Marker und lastpos sind eh korrupt */
  1049.     akt_winp->changeflag = FALSE; /* Falls reserve_mem hängt, soll */
  1050.                       /* Text nicht abgespeichert werden */
  1051.     akt_winp->alinep->text = save_text (buff2);
  1052.       }
  1053.     }
  1054.     if(nlflag && !(!sc && len)) /* volle Zeilen nicht doppelt eintragen */
  1055.     {
  1056.       buff2[out] = '\0';  /* Puffer abschliessen, eintragen und neue */
  1057.       sc = out = 0;       /* Zeile anfangen */
  1058.       koppel_line(IGNORE_COORS);
  1059.       akt_winp->changeflag = FALSE; /* Kommentar s.o. */
  1060.       akt_winp->alinep->text = save_text(buff2);
  1061.     }               /* buff wird durch fgets besetzt. Schlaegt fgets fehl, */
  1062.     buff[0] = '\0'; /* ist buff[0]=='\0', sonst nicht. Bricht Schleife     */
  1063.   }            /* nicht wegen fgets ab, dann war das Zeilenlimit erreicht. */
  1064.  
  1065.   /* Wurde die letzte Zeile nicht mit \n abgeschlossen, dann wurde die     */
  1066.   /* Zeile noch nicht in den Text eingetragen sondern steht noch in buff2. */
  1067.   if(out)
  1068.   {
  1069.     buff2[out] = '\0'; /* Puffer abschliessen und eintragen */
  1070.     koppel_line(IGNORE_COORS);
  1071.     akt_winp->changeflag = FALSE; /* Kommentar s.o. */
  1072.     akt_winp->alinep->text= save_text(buff2);
  1073.   }
  1074.  
  1075.   clear_stat();
  1076.   if (buff[0] && akt_winp->maxline >= MAX_ANZ_LINES - 1)
  1077.     print_err(PROMPT_FILETOLNG);
  1078.   fclose(f);
  1079.   akt_winp->alinep = akt_winp->dummyp->next; /* Erste Zeile zur aktuellen */
  1080.   akt_winp->textline = akt_winp->maxline != -1 ? 0 : -1;    /* machen */
  1081.   return (TRUE); /* Kein Fehler, Fenster kann geoeffnet werden */
  1082. }
  1083.  
  1084. /*****************************************************************************
  1085. *
  1086. *  Funktion       Text freigeben (free_text)
  1087. *  --------
  1088. *
  1089. *  Beschreibung : Der zum aktuellen Fenster gehoerige Text, inklusive
  1090. *                 akt_winp->dummyp, wird freigegeben.
  1091. *
  1092. *****************************************************************************/
  1093.  
  1094. void free_text()
  1095. {
  1096.   /* *** interne Daten *** */
  1097.   register zeil_typ *n; /* Zeiger auf naechste freizugebende Zeile */
  1098.  
  1099.   akt_winp->alinep = akt_winp->dummyp;
  1100.   do
  1101.   {
  1102.     line_free(akt_winp->alinep->text); /* Text freigeben */
  1103.     n = akt_winp->alinep->next;        /* Zeiger auf naechste Zeile merken */
  1104.     free(akt_winp->alinep);            /* Zeilenstruktur freigeben */
  1105.   }while((akt_winp->alinep = n) != akt_winp->dummyp);
  1106. }
  1107.  
  1108. /*****************************************************************************
  1109. *
  1110. *  Funktion       aktuelle Zeile abspeichern (save_delline)
  1111. *  --------
  1112. *
  1113. *  Beschreibung :  Der text-Pointer der alten Zeile wird in sd_line ge-
  1114. *                  speichert und anschliessend auf NULL gesetzt. Diese
  1115. *                  Funktion wird in do_delline() vor del_line aufgerufen.
  1116. *                  Der Speicherbereich, auf den sd_line zeigt, wird vorher
  1117. *                  mittels line_free() freigegeben.
  1118. *
  1119. *****************************************************************************/
  1120.  
  1121. void save_delline()
  1122. {
  1123.   line_free(sd_line); /* Alte gespeicherte geloeschte Zeile verwerfen */
  1124.   check_buff();  /* evtl. Pufferinhalt in den Text uebernehmen */
  1125.   sd_line = akt_winp->alinep->text; /* text sichern */
  1126.   akt_winp->alinep->text = NULL; /* funktioniert, da Zeile sowieso */
  1127. }                                /* geloescht wird */
  1128.  
  1129. /*****************************************************************************
  1130. *
  1131. *  Funktion       Gespeicherte Zeile wiederherstellen (rest_delline)
  1132. *  --------
  1133. *
  1134. *  Beschreibung : Die mit save_delline gespeicherte Zeile wird in den Text
  1135. *                 vor der aktuellen Zeile eingefuegt. Die neue Zeile wird
  1136. *                 zur aktuellen.  Es wird eine Kopie der gespeicherten Zeile
  1137. *                 angelegt, so dass die Zeile ggf. mehrmals eingefuegt werden
  1138. *                 kann.
  1139. *
  1140. *****************************************************************************/
  1141.  
  1142. void rest_delline()
  1143. {
  1144.   int old_sc = akt_winp->screencol; /* Zwischenspeicher Screencol */
  1145.  
  1146.   if(akt_winp->maxline < MAX_ANZ_LINES-1)
  1147.   { /* Noch Platz fuer Wiederherstellung der geloeschten Zeile ? */
  1148.     check_buff();  /* Pufferinhalt evtl. in Text uebernehmen */
  1149.     if(akt_winp->alinep != akt_winp->dummyp)
  1150.     { /* Wenn Datei Zeilen enthaelt, dann eine Zeile hoch */
  1151.       akt_winp->textline--; /* nummer bleibt gleich, da neue z. = alte z. */
  1152.       akt_winp->alinep = akt_winp->alinep->prev;
  1153.     }
  1154.     koppel_line(ADAPT_COORS); /* Neue Zeile einfuegen, Block anpassen */
  1155.     akt_winp->alinep->text = save_text(sd_line); /* mehrmals einfuegen */
  1156.     akt_winp->screencol = old_sc; /* Screencol restaurieren */
  1157.   } /* nur moeglich, wenn sichergestellt ist, dass sd_line gleichbleibt */
  1158. }
  1159.