home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / ehp14cs.zip / text_1.c < prev    next >
Text File  |  1995-07-07  |  29KB  |  747 lines

  1. /****************************************************************/
  2. /*                                                              */
  3. /*      MODUL:  text_1.c                                        */
  4. /*                                                              */
  5. /*      FUNKTIONEN:                                             */
  6. /*              - copy_to_buff (zeile in puffer kopieren)       */
  7. /*              - copy_from_buf (puffer zurueckschreiben)       */
  8. /*              - check_buff (evtl. puffer zurueckschreiben)    */
  9. /*              - fill_buff (evtl. Puffer besetzen)             */
  10. /*              - is_last (prüfe, ob Cursor an/hinter Z.-ende)  */
  11. /*              - ul_char (ist aktuelles Zeichen unterstr. ?)   */
  12. /*              - akt_zeichen (aktuelles zeichen ermitteln)     */
  13. /*              - right (ein zeichen nach rechts)               */
  14. /*              - left (ein zeichen nach links)                 */
  15. /*              - wortende (testen, ob zeichen worttrenner)     */
  16. /*              - word_left (ein wort links)                    */
  17. /*              - bol (an zeilenanfang)                         */
  18. /*              - eol (an zeilenende)                           */
  19. /*              - word_right (ein wort rechts)                  */
  20. /*              - check_underl (teste auf _^H)                  */
  21. /*              - delete (aktuelles zeichen loeschen)           */
  22. /*              - mdelete (mehrere Zeichen loeschen)            */
  23. /*              - backspace (zeichen links loeschen)            */
  24. /*              - delete_word (wort rechts loeschen)            */
  25. /*              - delete_eol (Rest der Zeile loeschen)          */
  26. /*              - join (Zeilen verknuepfen)                     */
  27. /*              - up (eine zeile hoch)                          */
  28. /*              - down (eine zeile runter)                      */
  29. /****************************************************************/
  30.  
  31. #include "defs.h"
  32.  
  33. extern char backupflag;
  34. extern marker_typ marker[];
  35.  
  36. /* *** globale Daten und Initialisierung *** */
  37. char linebuff [3*MAXLENGTH+1]; /* Zeilenpuffer                  */
  38. char        bufflag = FALSE;   /* Flag, ob linebuff belegt ist           */
  39. char        *sd_line=NULL,     /* Zwischenspeicher fuer geloeschte Zeile */
  40.         space=' ';         /* Globales Leerzeichen                   */
  41. char        *fastzeichen();
  42.  
  43. /****************************************************************
  44. *
  45. * FUNKTION:     copy_to_buff()  (zeile in puffer kopieren)
  46. *
  47. * BESCHREIBUNG: - die aktuelle zeile wird nach linebuff kopiert;
  48. *               ist der textpointer NULL, so wird ein leerer
  49. *               puffer angelegt
  50. *               - dann wird der puffer bis zur maximallanege mit
  51. *               spaces aufgefuellt
  52. *               - das aktuelle zeichen wird gemaess
  53. *               akt_winp->screencol gesetzt
  54. *               - bufflag wird auf TRUE gesetzt
  55. *****************************************************************/
  56.  
  57. void copy_to_buff()
  58. {
  59.   /* *** interne Daten *** */
  60.   register int i; /* Zaehler fuer zu kopierende Zeichen */
  61.  
  62.   if (akt_winp->maxline == -1)  /* Wenn Datei leer, dann neue   */
  63.     new_line();                 /* Zeile einfuegen.             */
  64.   bufflag = TRUE;               /* Puffer als belegt markieren  */
  65.   if(akt_winp->alinep->text)    /* wenn Zeile nicht leer, dann     */
  66.     strcpy(linebuff,akt_winp->alinep->text); /* in Puffer kopieren */
  67.   else
  68.     linebuff[0] = '\0';         /* Sonst Pufferinhalt loeschen */
  69.  
  70.   /* Rest des Puffers mit Blanks auffuellen */
  71.   for (i=strlen (linebuff);i<3*MAXLENGTH;linebuff[i++] = ' ');
  72.   linebuff [3*MAXLENGTH] = '\0';/* Puffer ist mit '\0' terminiert */
  73.   i = akt_winp->screencol;      /* bildschirmpos. speichern */
  74.  
  75.   /* Jetzt textcol setzen. Dazu screencol mal right aufrufen */
  76.   for (akt_winp->screencol = akt_winp->textcol = 0;i>0;i--)
  77.     right();
  78. }
  79.  
  80.  
  81. /****************************************************************
  82. *
  83. * FUNKTION:     copy_from_buf() (zeile zurueckschreiben)
  84. *
  85. * BESCHREIBUNG: - der inhalt von linebuff wird in die aktuelle
  86. *               zeile zurueckkopiert, dabei werden evtl. spaces
  87. *               am ende geloescht
  88. *               - ist die zeile leer, so wird der textpointer
  89. *               auf NULL gesetzt
  90. *****************************************************************/
  91.  
  92. void copy_from_buf()
  93. {
  94.   /* *** interne Daten *** */
  95.   register int i; /* Zaehler fuer Zeichen im Puffer */
  96.  
  97.   bufflag = FALSE; /* Puffer als leer markieren */
  98.   /* abschliessende Blanks skippen */
  99.   for (i=3*MAXLENGTH-1;i>=0 && linebuff [i] == ' ';i--);
  100.   /* Falls letztes Zeichen der Zeile ein unterstrichenes Space ist, so
  101.      wuerde der Puffer normal ein Zeichen zu frueh abgeschnitten. Diesen
  102.      Fall muss man also hier testen. */
  103.   if (i>0 && linebuff[i-1]=='_' && linebuff[i]=='')
  104.     linebuff[i+2] = '\0';
  105.   else
  106.     linebuff[i+1] = '\0';
  107.   line_free(akt_winp->alinep->text);            /* aktuelle Zeile durch  */
  108.   akt_winp->alinep->text = save_text(linebuff); /* Pufferinhalt ersetzen */
  109. }
  110.  
  111.  
  112. /****************************************************************
  113. *
  114. * FUNKTION:     check_buff()    (puffer evtl. zurueckschreiben)
  115. *
  116. * BESCHREIBUNG: - falls bufflag TRUE ist, wird copy_from_buf()
  117. *               aufgerufen
  118. *               - bufflag wird auf FALSE gesetzt
  119. *****************************************************************/
  120.  
  121. void check_buff()
  122. {
  123.   if (bufflag)
  124.     copy_from_buf(); /* Pufferinhalt in aktuelle Zeile uebernehmen */
  125. }
  126.  
  127. /****************************************************************
  128. *
  129. * FUNKTION:     fill_buff() (Puffer evtl. mit aktueller Zeile laden)
  130. *
  131. * BESCHREIBUNG: - falls bufflag FALSE ist, wird copy_to_buff()
  132. *               aufgerufen
  133. *****************************************************************/
  134.  
  135. void fill_buff()
  136. {
  137.   if (!bufflag)
  138.     copy_to_buff(); /* aktuelle Zeile in Puffer kopieren */
  139. }
  140.  
  141. /****************************************************************
  142. *
  143. * FUNKTION:     is_last()         (an/hinter letzter Position in Zeile?)
  144. * ERGEBNIS:     TRUE,FALSE
  145. * BESCHREIBUNG: - Von der Cursorposition aus wird getestet, ob
  146. *                 nach rechts hin nur Blanks stehen, falls die aktuelle
  147. *                 Zeile schon im Puffer ist. Ansonsten wird mit
  148. *                 fastzeichen() auf &space getestet.
  149. *               - stand man am oder hinterm Zeilenende, so wird 
  150. *               TRUE, sonst FALSE zurueckgeliefert.
  151. *****************************************************************/
  152.  
  153. int is_last()
  154. {
  155.   /* *** lokale Daten *** */
  156.   char result = TRUE; /* Ergebnis */
  157.   int  i;             /* Zählvariable zum Durchlaufen des Zeilenpuffers */
  158.  
  159.   if (bufflag) /* Zeile im Puffer, also Puffer auf Spaces testen */
  160.   {
  161.     for (i=akt_winp->textcol; result && i<3*MAXLENGTH; i++)
  162.       result = (linebuff [i] == ' '); 
  163.     return result; 
  164.   }
  165.   else /* Zeile steht nicht im Zeilenpuffer, dann liefert fastzeichen()
  166.       &space, wenn Zeile leer / Cursor hinter Zeilenende steht */
  167.     return fastzeichen(akt_winp->screencol) == &space;
  168. }
  169.  
  170. /****************************************************************
  171. *
  172. * FUNKTION:     ist aktuelles zeichen unterstrichen? (ul_char)
  173. *
  174. * BESCHREIBUNG: - Es wird fill_buff aufgerufen.
  175. *               - ist das aktuelle zeichen unterstrichen, wird
  176. *               TRUE, sonst FALSE zurueckgeliefert
  177. *****************************************************************/
  178.  
  179. int ul_char()
  180. {
  181.   fill_buff(); /* Evtl. Zeile in Puffer kopieren */
  182.   if(linebuff[akt_winp->textcol] == '_'
  183.   && linebuff[akt_winp->textcol+1] == '' && linebuff[akt_winp->textcol+2])
  184.     return(TRUE);
  185.   return(FALSE);
  186. }
  187.  
  188. /****************************************************************
  189. *
  190. * FUNKTION:     akt_zeichen()   (aktuelles zeichen holen)
  191. *
  192. * BESCHREIBUNG: - Es wird fill_buff aufgerufen
  193. *               - das aktuelle zeichen wird zurueckgegeben
  194. *               - auch unterstrichene zeichen werden
  195. *               beruecksichtigt
  196. *****************************************************************/
  197.  
  198. char akt_zeichen()
  199. {
  200.   fill_buff(); /* evtl. aktuelle Zeile in Puffer kopieren */
  201.   if (ul_char()) /* Zeichen unterstrichen ? Dann 2 weiter rechts, da vor */
  202.     return (linebuff[akt_winp->textcol+2]); /* Zeichen _  steht. */
  203.   else
  204.     return(linebuff[akt_winp->textcol]); /* sonst an aktueller Pos. */
  205. }
  206.  
  207.  
  208. /****************************************************************
  209. *
  210. * FUNKTION:     right()         (ein zeichen rechts)
  211. * ERGEBNIS:     TRUE,FALSE
  212. * BESCHREIBUNG: - Es wird fill_buff aufgerufen
  213. *               - screencol wird um 1 inkrementiert
  214. *               - textcol wird auf den index des naechsten zeichens
  215. *               gesetzt (auch unterstrichene werden beruecksichtigt)
  216. *               - konnte nicht nach rechts gegangen werden, wird
  217. *               FALSE, sonst TRUE zurueckgeliefert.
  218. *****************************************************************/
  219.  
  220. int right()
  221. {
  222.   fill_buff(); /* evtl. aktuelle Zeile in Puffer kopieren */
  223.   if (akt_winp->screencol < MAXLENGTH) /* geht's noch nach rechts ? */
  224.   {
  225.     akt_winp->screencol++;
  226.     if (ul_char())            /* ist das aktuelle Zeichen unterstrichen, */
  227.       akt_winp->textcol += 3; /* muss intern Spalte um 3 erhoeht werden, */
  228.     else                      /* da '_' und '' geskippt werden muessen  */
  229.       akt_winp->textcol++;
  230.     return(TRUE);
  231.   }
  232.   return(FALSE);
  233. }
  234.  
  235.  
  236. /****************************************************************
  237. *
  238. * FUNKTION:     left()          (ein zeichen links)
  239. * ERGEBNIS:     TRUE,FALSE
  240. * BESCHREIBUNG: - Es wird fill_buff aufgerufen
  241. *               - screencol wird um 1 dekrementiert
  242. *               - textcol wird auf den index des vorigen zeichens
  243. *               gesetzt (auch unterstrichene werden beruecksichtigt)
  244. *               - konnte die aktuelle position nicht um einen schritt
  245. *               nach links bewegt werden, wird FALSE, sonst TRUE
  246. *               zurueckgeliefert.
  247. *****************************************************************/
  248.  
  249. int left()
  250. {
  251.   fill_buff(); /* evtl. aktuelle Zeile in Puffer kopieren */
  252.   if (akt_winp->textcol > 0) /* geht's noch nach links ? */
  253.   {
  254.     akt_winp->screencol--;
  255.     if (akt_winp->textcol >= 3) /* kann das anzuspringende Zeichen unter- */
  256.                 /* strichen sein ? */
  257.       if (linebuff [akt_winp->textcol-3] == '_' /* ist es denn auch */
  258.       && linebuff [akt_winp->textcol-2] == '') /* unterstrichen ?  */
  259.     akt_winp->textcol -= 3; /* ja, dann intern um 3 nach links  */
  260.       else
  261.     akt_winp->textcol--;    /* sonst nur um 1 nach links */
  262.     else
  263.       akt_winp->textcol--;
  264.     return(TRUE);
  265.   }
  266.   return(FALSE);
  267. }
  268.  
  269.  
  270. /****************************************************************
  271. *
  272. * FUNKTION:     wortende()  (ist zeichen worttrenner?)
  273. *
  274. * PARAMETER:    - char c : zu ueberpruefendes zeichen
  275. * ERGEBNIS:     - TRUE oder FALSE
  276. * BESCHREIBUNG: - es wird ueberprueft, ob c ein worttrennzeichen
  277. *               ist und entsprechend TRUE oder FALSE zurueckge-
  278. *               geben
  279. *****************************************************************/
  280.  
  281. int wortende (c)
  282. char c;
  283. {
  284.   return ((int) strchr (" \t.,#:;|@$&()[]{}!?\"'`/\\<>-+*^=",c));
  285. }
  286.  
  287. /****************************************************************
  288. *
  289. * FUNKTION:     word_left()     (ein wort links)
  290. * ERGEBNIS:     TRUE,FALSE
  291. * BESCHREIBUNG: - Aufeinanderfolgende Worttrenner außer Whitespaces
  292. *                 werden als Wort angesehen.
  293. *               - Whitespaces links von Cursor werden uebersprungen
  294. *               - anschliessend werden screencol und textcol auf
  295. *                 den beginn des naechsten wortes gesetzt
  296. *****************************************************************/
  297.  
  298. int word_left()
  299. {
  300.   /* *** interne Daten und Initialisierung *** */
  301.   register int old_sc = akt_winp->screencol, /* Zwischenspeicher Spalte */
  302.            ging=FALSE;           /* Rueckgabewert der Funktion left */
  303.        char c,                   /* aktuelles Zeichen               */
  304.         sep_word;            /* Wort besteht aus Worttrennern   */
  305.  
  306.   /* Zuerst Leerzeichen links vom Cursor ueberspringen */
  307.   while (left() && ((c = akt_zeichen()) == ' ' || c == '\t'));
  308.   sep_word = wortende(c);
  309.   while ((sep_word ? wortende (c=akt_zeichen()) && c != ' ' && c != '\t'
  310.            : !wortende(akt_zeichen()))
  311.      && (ging=left()));
  312.   if (ging)  /* Wenn man vor den Wortanfang gehen konnte, dann wieder */
  313.     right(); /* eins nach rechts auf den Wortanfang. */
  314.   if(old_sc == akt_winp->screencol) /* Cursorspalte restaurieren */
  315.     return(FALSE);
  316.   return(TRUE);
  317. }
  318.  
  319.  
  320. /****************************************************************
  321. *
  322. * FUNKTION:     bol()   (an Zeilenanfang)
  323. *
  324. * BESCHREIBUNG: - es wird zum Zeilenanfang gesprungen
  325. *****************************************************************/
  326.  
  327. void bol()
  328. {
  329.   akt_winp->screencol = akt_winp->textcol = 0;
  330. }
  331.  
  332.  
  333. /****************************************************************
  334. *
  335. * FUNKTION:     eol()   (an Zeilenende)
  336. *
  337. * BESCHREIBUNG: - Es wird fill_buff aufgerufen
  338. *               - es wird zum Zeilenende gesprungen
  339. *               - spaces am ende werden ignoriert
  340. *****************************************************************/
  341.  
  342. void eol()
  343. {
  344.   /* *** interne Daten *** */
  345.   register int i; /* Index fuer linebuff */
  346.  
  347.   fill_buff(); /* evtl. aktuelle Zeile in Puffer kopieren */
  348.   for (i=3*MAXLENGTH-1;linebuff [i] == ' ';i--);
  349.   i++; /* Hinter letztes Zeichen gehen */
  350.   bol();  /* vom Anfang der Zeile so oft nach rechts, bis Cursor in */
  351.   while (akt_winp->textcol < i) /* richtiger interner Spalte steht. */
  352.     right();              /* Dadurch hat textcol den richtigen Wert */
  353. }
  354.  
  355. /****************************************************************
  356. *
  357. * FUNKTION:     word_right()    (ein wort rechts)
  358. * ERGEBNIS:     TRUE,FALSE
  359. * BESCHREIBUNG: - es wird bis zum wortende gesprungen
  360. *               - ist aktuelles Zeichen ein Worttrenner, so wird
  361. *                 bis zum ersten nicht-Worttrenner gesprungen.
  362. *               - folgende spaces oder tabs werden ebenfalls
  363. *                 uebersprungen
  364. *               - Beachte: Es darf nie nach links gesprungen werden
  365. *                 (Abhängigkeit zu do_tab())
  366. *****************************************************************/
  367.  
  368. int word_right()
  369. {
  370.   /* *** interne Daten *** */
  371.   register int  old_sc,   /* Zwischenspeicher Cursorspalte auf Biildschirm */
  372.         old_tc;   /* Zwischenspeicher Cursorspalte intern          */
  373.   register char az,       /* aktuelles Zeichen               */
  374.         sep_word; /* Besteht Wort aus Worttrennern ? */
  375.  
  376.   fill_buff(); /* evtl. aktuelle Zeile in Puffer kopieren */
  377.   old_sc = akt_winp->screencol; /* Cursorposition merken */
  378.   old_tc = akt_winp->textcol;
  379.   sep_word = wortende (akt_zeichen()); /* Steht man auf Worttrenner? */
  380.   while ((az=akt_zeichen())
  381.     && (sep_word ? wortende (az) && az != ' ' && az != '\t'
  382.              : !wortende (az)) && right());
  383.   /* Jetzt die dem Wort folgenden Blanks und Tabs skippen */
  384.   while ((((az=akt_zeichen()) == ' ') || (az == '\t')) && right());
  385.  
  386.   if(akt_winp->screencol == MAXLENGTH) /* steht man am rechten */
  387.   { /* Rand, dann gehe zum eigentlichen Zeilenende. */
  388.     eol();
  389.     if (akt_winp->screencol < old_sc) 
  390.     {  /* es darf nie nach links gegangen werden ! */
  391.        akt_winp->screencol = old_sc;
  392.        akt_winp->textcol   = old_tc;
  393.     }
  394.     return (akt_winp->screencol != old_sc); /* Hat man sich bewegt? */
  395.   }
  396.   else 
  397.     return(TRUE);
  398. }
  399.  
  400.  
  401. /****************************************************************
  402. *
  403. * FUNKTION:     check_underl()  (teste auf _^H kombination)
  404. * ERGEBNIS:     TRUE, FALSE
  405. * BESCHREIBUNG: - falls das aktuelle Zeichen ein Backspace und
  406. *               das vorhergehende ein _ ist, oder das aktuelle
  407. *               Zeichen das zu unterstreichende und die Zeichen
  408. *               davor _ und  sind, werden screencol und
  409. *               textcol so dekrementiert, dass sie auf
  410. *               das _ zeigen
  411. *               - Falls ein solcher Fall auftrat, wird mit
  412. *               der Funktion lineout() die aktuelle Zeile auf dem
  413. *               Bildschirm restauriert und TRUE zurueckgegeben.
  414. *               Ansonsten wird FALSE zurueckgegeben.
  415. *
  416. *****************************************************************/
  417.  
  418. int check_underl()
  419. {
  420.   fill_buff(); /* evtl. aktuelle Zeile in Puffer kopieren */
  421.   if(akt_winp->textcol && linebuff[akt_winp->textcol+1] /* noch 2 Zeichen da ? */
  422.   && !strncmp(&linebuff[akt_winp->textcol-1],"_",2))       /* ^H eingefuegt? */
  423.   {
  424.     if (in_block(akt_winp->textline,akt_winp->screencol) & B_FIRST_CHAR)
  425.       insdel_blockadapt(-1);  /* Blockgrenzen anpassen (eee stimmt nicht ganz) */
  426.     else
  427.       insdel_blockadapt(-2);
  428.     akt_winp->textcol--;   /* Cursorposition korrigieren, da Cursor immer */
  429.     akt_winp->screencol--; /* auf dem Unterstrich stehen muss             */
  430.     return (TRUE);
  431.   }
  432.   else
  433.     if (!strncmp(&linebuff[akt_winp->textcol],"_",2) /* _ eingefuegt ? */
  434.     && linebuff [akt_winp->textcol+2]) /* und ein Zeichen dahinter ? */
  435.     {
  436.       insdel_blockadapt(-2); /* Blockgrenzen anpassen */
  437.       return (TRUE);
  438.     }
  439.   return (FALSE);
  440. }
  441.  
  442.  
  443. /****************************************************************
  444. *
  445. * FUNKTION:     delete()        (loesche aktuelles zeichen)
  446. * ERGEBNIS:     TRUE,FALSE
  447. * BESCHREIBUNG: - falls das aktuelle Zeichen nicht das Endzeichen
  448. *               ist, wird es geloescht (unterstrichene zeichen
  449. *               werden beruecksichtigt)
  450. *               - Die Blockgrenzen werden angepaßt
  451. *               - der restliche text wird rangezogen
  452. *               - danach wird check_underl() aufgerufen
  453. *****************************************************************/
  454.  
  455. int delete()
  456. {
  457.   /* *** interne Daten *** */
  458.   register char *in,     /* Zieladresse beim Verschieben  */
  459.         *out;    /* Startadresse beim Verschieben */
  460.   register int  anz_del; /* Anzahl zu loeschender Zeichen */
  461.  
  462.   if (akt_zeichen()) /* Letztes Zeichen (Abschlussnull) ? */
  463.   { /* akt_zeichen kopiert evtl. auch die Zeile in den Puffer */
  464.     insdel_blockadapt(-1); /* Blockgrenzen anpassen */
  465.     in = (out = &linebuff[akt_winp->textcol]) + (anz_del = 1 + 2*ul_char());
  466.     fwdcpy(out,in); /* Alles rechts vom Cursor eins ranziehen */
  467.     check_underl(); /* Ist dadurch ein neues unterstrichenes Zeichen entstd., */
  468.             /* wird alles korrekt angepasst */
  469.     /* Ende des Zeilenpuffers mit Blanks besetzen, Abschlußnull bleibt
  470.        erhalten */
  471.     strncpy(&linebuff[3*MAXLENGTH-anz_del],"   ",anz_del);
  472.     akt_winp->changeflag = TRUE; /* Text als geaendert markieren */
  473.     return(TRUE);
  474.   }
  475.   return(FALSE);
  476. }
  477.  
  478. /*****************************************************************************
  479. *
  480. *  Funktion       mehrere Zeichen loeschen (mdelete)
  481. *  --------
  482. *
  483. *  Parameter    : n         :
  484. *                   Typ          : int
  485. *                   Wertebereich : 0 - MAXLENGTH
  486. *                   Bedeutung    : Anzahl zu loeschender Zeilen
  487. *
  488. *  Beschreibung : Es wird versucht, eine bestimmte Anzahl Zeichen von der
  489. *                 aktuellen Position ab zu loeschen. Ist dies nicht moeglich,
  490. *                 so werden so viele als moeglich geloescht.
  491. *
  492. *****************************************************************************/
  493.  
  494. void mdelete(n)
  495. int n;
  496. {
  497.   /* *** interne Daten und Initialisierung *** */
  498.   register char *p;        /* Zeiger in linebuff zum Auffuellen mit Blanks */
  499.   register int  i,         /* Anzahl loeschbarer Zeichen                   */
  500.         old_sc = akt_winp->screencol, /* alte Cursorspalte         */
  501.         old_tc;    /* alte Cursorspalte intern                     */
  502.  
  503.   fill_buff(); /* evtl. aktuelle Zeile in Puffer kopieren */
  504.   old_tc = akt_winp->textcol; /* Cursorspalte merken */
  505.   insdel_blockadapt(-n); /* Blockgrenzen anpassen */
  506.   for(i=0;i<n;i++) /* Berechnen, wieviele Zeichen geloescht */
  507.     if(!right())   /* werden koennen */
  508.       break;
  509.   /* kann maximal i Zeichen loeschen */
  510.   if(i)
  511.   {
  512.     akt_winp->changeflag = TRUE; /* Text als geaendert markieren */
  513.     /* Jetzt Zeilenrest nach links verschieben */
  514.     fwdcpy(&linebuff[old_tc],&linebuff[akt_winp->textcol]);
  515.     /* Ende des Puffers wieder mit Blanks besetzen */
  516.     p = linebuff + old_tc + strlen(linebuff + old_tc);
  517.     for(i = akt_winp->textcol - old_tc;i>0;i--)
  518.       *p++ = ' ';
  519.     *p='\0';
  520.   }
  521.   akt_winp->screencol = old_sc; /* Cursorspalte restaurieren */
  522.   akt_winp->textcol = old_tc;
  523. }
  524.  
  525. /****************************************************************
  526. *
  527. * FUNKTION:     backspace()     (loesche linkes zeichen)
  528. * ERGEBNIS:     TRUE,FALSE
  529. * BESCHREIBUNG: - falls der cursor sich nicht am linken rand be-
  530. *               findet, wird das links vom aktuellen zeichen be-
  531. *               findliche zeichen geloescht (mittels delete)
  532. *               - die aktuelle position ist nach backspace die des
  533. *               geloeschten zeichens
  534. *****************************************************************/
  535.  
  536. int backspace()
  537. {
  538.   if(left() && delete())
  539.     return(TRUE);
  540.   return(FALSE);
  541. }
  542.  
  543. /****************************************************************
  544. *
  545. * FUNKTION:     delete_word()   (wort loeschen)
  546. * ERGEBNIS:     TRUE,FALSE
  547. * BESCHREIBUNG: - das aktuelle zeichen wird deletet
  548. *               - solange, wie das aktuelle zeichen kein wort-
  549. *               trenner ist, wird es geloescht
  550.                - Ausnahme: Das aktuelle Word begann mit einem
  551. *                 Worttrenner. In diesem Fall wird bis zum ersten
  552. *                 Leerzeichen oder nicht-Worttrenner geloescht.
  553. *               - folgende spaces und tabs werden ebenfalls ge-
  554. *               loescht
  555. *               - Durch die Verwendung von delete() werden die
  556. *               Blockgrenzen korrekt angepaßt
  557. *****************************************************************/
  558.  
  559. int delete_word()
  560. {
  561.   /* *** interne Daten *** */
  562.   int           old_sc,  /* Alte Cursorposition Spalte            */
  563.         old_tc;  /* Alte Cursorposition Spalte intern     */
  564.  
  565.   fill_buff();
  566.   old_sc = akt_winp->screencol; /* Cursorspalte merken */
  567.   old_tc = akt_winp->textcol;
  568.  
  569.   /* Alle Zeichen bis zum naechsten Wort skippen */
  570.   if (word_right())
  571.   {
  572.     swap_int(&old_sc,&akt_winp->screencol); /* Zur Anfangsposition zurueck */
  573.     akt_winp->textcol = old_tc;
  574.     mdelete(old_sc - akt_winp->screencol);  /* geskippte Zeichen loeschen */
  575.     return TRUE;
  576.   }
  577.   return FALSE;
  578. }
  579.  
  580. /****************************************************************
  581. *
  582. * FUNKTION:     delete_eol()    (Rest der Zeile loeschen)
  583. * ERGEBNIS:     TRUE, FALSE
  584. * BESCHREIBUNG: - Abhaengig von Bufflag wird entweder der Puffer-
  585. *               rest mit Blanks ueberschrieben oder an der ak-
  586. *               tuellen Position eine '\0' geschrieben. In diesem
  587. *               Fall wird fuer die neu entstandene Zeile neuer
  588. *               Speicher alloziert.
  589. *               - Falls sich die Zeile veraendert hat, wird TRUE,
  590. *               sonst FALSE zurueckgegeben.
  591. *****************************************************************/
  592.  
  593. int delete_eol()
  594. {
  595.   /* *** interne Daten *** */
  596.   register char *hilf,
  597.         *alt_poi;
  598.   register int  i;
  599.  
  600.   /* Steht Zeile schon im Puffer, dann im Puffer den Rest blanken */
  601.   if (bufflag)
  602.   {
  603.     for (i=akt_winp->textcol;i<3*MAXLENGTH;i++)
  604.       linebuff[i]=' ';
  605.     return (akt_winp->changeflag = TRUE);
  606.   }
  607.   else  /* Steht Zeile nicht im Puffer, dann Zeile selber modifizieren */
  608.   {
  609.     if (akt_winp->alinep->text)
  610.       if ((hilf=fastzeichen(akt_winp->screencol)) != &space)
  611.       {
  612.     if (hilf==akt_winp->alinep->text) /* ab erstem Zeichen, dann */
  613.     {                                 /* Zeilenihalt komplett loeschen */
  614.       free(akt_winp->alinep->text);
  615.       akt_winp->alinep->text = NULL;
  616.     }
  617.     else                              /* Sonst Zeile an Cursorposition */
  618.     {                                 /* abschneiden und neu sichern */
  619.       *hilf='\0';
  620.       alt_poi = akt_winp->alinep->text;
  621.       akt_winp->alinep->text = save_text(alt_poi);
  622.       free (alt_poi);
  623.     }
  624.     return (akt_winp->changeflag = TRUE);
  625.       }
  626.   }
  627.   return (FALSE);
  628. }
  629.  
  630. /*****************************************************************************
  631. *
  632. *  Funktion       Zeilen verknuepfen (join)
  633. *  --------
  634. *
  635. *  Parameter    : modus     :
  636. *                   Typ          : int
  637. *                   Wertebereich : IGNORE_COORS, ADAPT_COORS
  638. *                   Bedeutung    : IGNORE_COORS: join wird von Blockfunktion
  639. *                                  aufgerufen (wichtig fuer Aufruf del_line)
  640. *                                  ADAPT_COORS: join wird nicht von einer
  641. *                                  Blockfunktion aufgerufen
  642. *  Ergebnis     :
  643. *                   Typ          : int
  644. *                   Wertebereich : J_OK, J_TOOLONG, J_LASTLINE
  645. *                   Bedeutung    : J_OK      : Hat geklappt
  646. *                                  J_TOOLONG : Ging nicht, neue Zeile zu lang
  647. *                                  J_LASTLINE: Ging nicht, keine Zeile mehr
  648. *
  649. *  Beschreibung : Die nachfolgende Zeile wird an die aktuelle Zeile angehaengt.
  650. *                 Wird die Zeile dadurch zu lang oder existiert keine nach-
  651. *                 folgende Zeile, so wird der entsprechende Fehlerwert zu-
  652. *                 rueckgegeben. Die Cursorposition bleibt unverändert.
  653. *
  654. *****************************************************************************/ 
  655.  
  656. int join(modus)
  657. int modus;
  658. {
  659.   /* *** interne Daten *** */
  660.   register int  l1,  /* Laenge der aktuellen Zeile       */
  661.         ib;  /* Cursorposition relativ zum Block */
  662.   register char *z1, /* Zeiger auf aktuelle Zeile        */
  663.         *z2; /* Zeiger auf nachfolgende Zeile    */
  664.  
  665.   check_buff();  /* evtl. Pufferinhalt in Text uebernehmen */
  666.   if (!(z1 = akt_winp->alinep->text)
  667.   && akt_winp->alinep->next != akt_winp->dummyp)
  668.     del_line(modus);          /* akt. zeile ist leer und nicht letzte z. */
  669.   else
  670.   {
  671.     if (down())         /* akt. zeile nicht letzte zeile? */
  672.     {
  673.       if (!(z2 = akt_winp->alinep->text)) /* naechste z. leer? */
  674.       {
  675.     if(del_line(modus) != LAST_LINE_DEL) /* wenn letzte Zeile geloescht */
  676.       up();                              /* machte del_line selbst up() */
  677.       }
  678.       else /* Wenn nachfolgende Zeile nicht leer war */
  679.       {
  680.     /* Blockspalten muessen evtl. bei normalem Block angepasst werden */
  681.     if(modus == ADAPT_COORS && block_defined()
  682.     && akt_winp->block.typ == BT_NORMAL)
  683.     {
  684.       ib = in_block(akt_winp->textline,akt_winp->screencol);
  685.       if(ib & B_FIRST_LINE) /* Enthaelt anzuhaengende Zeile Blockanfang ?  */
  686.       {                                      /* Ja, dann Laenge der ersten */
  687.         akt_winp->block.s_col += fastll(z1); /* Zeile aufaddieren          */
  688.         akt_winp->block.s_line--;            /* Block faengt eine Zeile    */
  689.       }                                      /* weiter oben an.            */
  690.       if(ib & B_LAST_LINE) /* Blockende in anzuhaengender Zeile ? */
  691.       {
  692.         akt_winp->block.e_col += fastll(z1); /* s.o. */
  693.         akt_winp->block.e_line--;
  694.       }
  695.     }
  696.  
  697.     up(); /* Wieder in urspruengliche Zeile zurueck */
  698.     if (fastll(z2) + fastll(z1) < MAXLENGTH) /* Neue Zeile zu lang ? */
  699.     { /* (Man verschenkt hier ein Zeichen (< statt <=), damit */
  700.       /* do_join() keine Probleme beim nachträglichen Einfügen */
  701.       /* eines Leerzeichens bekommt). */
  702.       /* Nein, dann Platz fuer neue Zeile schaffen */
  703.       /* und neue Zeile in Text eintragen          */
  704.       akt_winp->alinep->text = reserve_mem((l1=strlen(z1))+strlen(z2)+1);
  705.       strcpy(akt_winp->alinep->text,z1); /* Aktuelle Zeile und nach- */
  706.       strcpy(akt_winp->alinep->text + l1,z2); /* folgende zusammenkop. */
  707.       free(z1);
  708.       down();
  709.       if(del_line(modus) != LAST_LINE_DEL)       /* s.o. */
  710.         up();
  711.       return (J_OK);
  712.     }
  713.     else /* Wenn Zeile zu lang geworden waere */
  714.       return (J_TOOLONG);
  715.       }
  716.     }
  717.     else        /* Konnte keine Zeile nach unten gehen */
  718.       return (J_LASTLINE);
  719.   }
  720.   return (J_OK);
  721. }
  722.  
  723. /****************************************************************
  724. *
  725. * FUNKTION:     up()    (eine zeile hoch)
  726. *
  727. * BESCHREIBUNG: - die vorherige zeile wird zur aktuellen
  728. *****************************************************************/
  729.  
  730. int up()
  731. {
  732.   return(lines_up(1));
  733. }
  734.  
  735.  
  736. /****************************************************************
  737. *
  738. * FUNKTION:     down()  (eine zeile runter)
  739. *
  740. * BESCHREIBUNG: - die nachfolgende zeile wird zur aktuellen
  741. *****************************************************************/
  742.  
  743. int down()
  744. {
  745.   return(lines_down(1));
  746. }
  747.