home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / ehp14cs.zip / main.c < prev    next >
C/C++ Source or Header  |  1995-09-11  |  39KB  |  1,048 lines

  1. /****************************************************************/
  2. /*                                                              */
  3. /*      MODUL:  main.c                                          */
  4. /*                                                              */
  5. /*      FUNKTIONEN:                                             */
  6. /*              - pe_or (Fehlertext ausgeben ohne refresh)      */
  7. /*              - print_err (Fehlertext ausgeben)               */
  8. /*              - wart_ret (warte auf RETURN)                   */
  9. /*              - no_mem_err (Fehlermeldung, wenn kein Speicher)*/
  10. /*              - reserve_mem (Speicher reservieren)            */
  11. /*              - save_text (Textzeile sichern)                 */
  12. /*              - line_free (Zeile freigeben)                   */
  13. /*              - revcpy (String von hinten kopieren)           */
  14. /*              - fwdcpy (String von vorne kopieren)            */
  15. /*              - swap_int (zwei integer vertauschen)           */
  16. /*              - ja_nein (Lese JA/NEIN Abfrage)                */
  17. /*              - set_lines_cols (Zeilen- und Spaltenz.ermitteln*/
  18. /*              - check_env (Environment checken)               */
  19. /*              - catchsig (Signal abfangen)                    */
  20. /*              - init (initialisieren)                         */
  21. /*              - ende (Editor beenden)                         */
  22. /*              - save_all (alle geaenderten Texte abspeichern) */
  23. /*              - alles_frei (alle Speicherbereiche freigeben)  */
  24. /*              - do_wildcard_expansion (Wildcards expandieren) */
  25. /*              - hndl_params (Parameter verarbeiten)           */
  26. /*              - main (Hauptprogramm)                          */
  27. /*                                                              */
  28. /****************************************************************/
  29.  
  30. #define aktdef  /* Damit in defs.h nicht lokales als extern deklariert wird */
  31.  
  32. #ifdef OS2
  33. #define INCL_DOSPROCESS
  34. #define INCL_DOSSEMAPHORES
  35. #include <os2.h>
  36. #else
  37. #pragma inline
  38. #include <dir.h>
  39. #endif
  40. #include "defs.h"
  41. #include "regex.h"
  42. #include <signal.h>
  43.  
  44. extern char *getenv(),*sd_line,helpflag;
  45. #undef getch()
  46. extern int read_config();
  47. #ifdef MOUSE
  48. #ifdef OS2
  49. extern char mouse_active;
  50. extern short int mouse_handle;
  51. extern TID mouse_ThreadID;
  52. #endif /* OS2 */
  53. #endif /* MOUSE */
  54.  
  55. void wart_ret(), ende(int, char);
  56.  
  57. /* *** globale Daten und Initialisierung *** */
  58. win_typ    *akt_winp;            /* Aktuelles Fenster                     */
  59. WINDOW     *status;              /* Statusfenster                         */
  60. short int  aktcode;              /* Aktueller Befehlstastencode           */
  61. short int  *keystack,            /* Zeiger auf aktuelles Pufferzeichen    */
  62.        *e_keystack,          /* Zeiger auf Pufferende                 */
  63.        mc_index;             /* Anzahl der Tastenkombinationen-1      */
  64. int        ks_index = -1;        /* Index des aktuellen Puffers           */
  65. int        blockattr,            /* Attribut zum Highlighten eines Blocks */
  66.        ersetzaddr,           /* Attribut fuer zu ersetzenden String   */
  67.        def_tab = STD_TAB;    /* Laenge eines Tabulatorsprungs         */
  68. char       highblockflag = TRUE, /* Sollen Bloecke gehighlighted werden ? */
  69.        backupflag=TRUE,      /* Es sollen .bak-Files erzeugt werden   */
  70.        regexflag=TRUE,       /* Es soll Patternmatching angew. werden */
  71.        linebrkflag=FALSE,    /* Automatischer Zeilenumbruch p.d. aus  */
  72.        def_aiflag = FALSE;   /* Normalerweise kein Autoindent         */
  73. char       *conffile = PF_CONFIG,/* Pfad der Config-Datei                 */
  74.        *loadfile = PF_LOAD;  /* Pfad des Loadfiles                    */
  75. block_typ  global_block;         /* Paste-Puffer fuer globalen Block      */
  76. marker_typ marker[ANZ_MARKER];   /* Feld fuer alle Marker                 */
  77. puff_typ   macro[ANZ_MACROS];    /* Feld fuer alle Macros                 */
  78. char       clear_buff = FALSE,   /* soll Puffer bei naechsten newwgetch() */
  79.                  /* geloescht werden? Wurde Brk gedrückt? */
  80.        *tasten_inf = PF_TASTEN; /* Name des Tastenbelegungsfiles      */
  81. #ifdef OS2
  82. HMTX       sem_handle;           /* Handle für Semaphor, der Zusammelspiel*/
  83. #else                            /* von Tastatur uns Maus synchronisiert  */
  84. long       old_int;              /* Zwischenspeicher Vektor des Break-Ints*/
  85. #endif
  86.  
  87. /*****************************************************************************
  88. *
  89. *  Funktion       Fehlertext ausgeben ohne setz_cursor() (pe_or)
  90. *  --------
  91. *
  92. *  Parameter    : fehlertext:
  93. *                   Typ          : char*
  94. *                   Wertebereich : Pointer auf ASCII-Zeichenkette
  95. *                   Bedeutung    : Auszugebender Fehlertext
  96. *
  97. *  Beschreibung : Der Fehlertext wird mit print_stat() ausgegeben, anschlie-
  98. *                 ssend wird ein wart_ret ausgefuehrt, dann wird das Status-
  99. *                 fenster geloescht.
  100. *
  101. *****************************************************************************/
  102.  
  103. void pe_or(fehlertext)
  104. char *fehlertext;
  105. {
  106.   print_stat(fehlertext);  /* Text im Statusfenster anzeigen */
  107.   wart_ret();              /* Auf RETURN warten              */
  108.   clear_stat();            /* Statuszeile wieder loeschen    */
  109. }
  110.  
  111. /*****************************************************************************
  112. *
  113. *  Funktion       Fehlertext ausgeben (print_err)
  114. *  --------
  115. *
  116. *  Parameter    : fehlertext:
  117. *                   Typ          : char*
  118. *                   Wertebereich : Pointer auf ASCII-Zeichenkette
  119. *                   Bedeutung    : Auszugebender Fehlertext
  120. *
  121. *  Beschreibung : Der Fehlertext wird mit pe_or ausgegeben, anschliessend
  122. *                 wird der Cursor wieder positioniert.
  123. *
  124. *****************************************************************************/
  125.  
  126. void print_err(fehlertext)
  127. char *fehlertext;
  128. {
  129.   pe_or(fehlertext);    /* Fehlermeldung ausgeben und auf RETURN warten */
  130.   if(akt_winp->winp)    /* nur wenn schon ein window angefordert wurde  */
  131.     setz_cursor(W_AKT); /* s. koppel_win() */
  132. }
  133.  
  134. /*****************************************************************************
  135. *
  136. *  Funktion       warte auf RETURN (wart_ret)
  137. *  --------
  138. *
  139. *  Beschreibung : Der Text " Bitte RETURN druecken..." wird in der
  140. *                 Statuszeile ausgegeben, anschliessend wird auf RETURN
  141. *                 gewartet.
  142. *
  143. *****************************************************************************/
  144.  
  145. void wart_ret()
  146. {
  147.   /* *** interne Daten *** */
  148.   char dummy; /* "String", der mit read_stat eingelesen wird */
  149.  
  150.   print_stat (PROMPT_ENTER);
  151.   read_stat(&dummy,0,GS_ANY); /* String der Laenge 0 einlesen */
  152.   clear_stat();               /* Statuszeile wieder loeschen  */
  153. }
  154.  
  155. /*****************************************************************************
  156. *
  157. *  Funktion       "Kein Speicher" - Fehlermeldung (no_mem_err)
  158. *  --------
  159. *
  160. *  Beschreibung : Eine Fehlermeldung wird ausgegeben und nach einer Rueck-
  161. *                 frage die Dateien gespeichert und das Programm beendet.
  162. *
  163. *****************************************************************************/
  164.  
  165. void no_mem_err()
  166. {
  167.   win_typ *w = akt_winp->next->next; /* Zum Freigeben der Fenster */
  168.  
  169.   while(w!=akt_winp)  /* Alle WINDOW-Strukturen aller Fenster freigeben */
  170.   {                   /* um Speicherplatz zu gewinnen */
  171.     delwin(w->winp); /* Damit Fenster nicht nochmals von delwin freigegeben */
  172.     w->winp = NULL;  /* wird, Pointer auf NULL setzen */
  173.     w = w->next;     /* Zum nächsten Fenster */
  174.   }
  175.   clear_stat();
  176.   print_stat(PROMPT_OUTOFMEM);
  177.   if(ja_nein(PROMPT_SAVE)) /* Abfrage */
  178.     save_all();                  /* Alle geaenderten Dateien sichern */
  179.   ende(1, TRUE);  /* Editor beenden, Rueckgabewert 1 */
  180. }
  181.  
  182. /*****************************************************************************
  183. *
  184. *  Funktion       Speicher reservieren (reserve_mem)
  185. *  --------
  186. *
  187. *  Parameter    : laenge    :
  188. *                   Typ          : int
  189. *                   Wertebereich : 0 - MAX_INT
  190. *                   Bedeutung    : Laenge des zu reservierenden Speicher-
  191. *                                  bereiches in Bytes
  192. *
  193. *  Ergebnis     :
  194. *                   Typ          : char*
  195. *                   Wertebereich : Pointer auf Speicherbereich
  196. *                   Bedeutung    : Pointer auf reservierten Speicherbereich
  197. *
  198. *  Beschreibung : Es wird versucht, ueber malloc den angeforderten Speicher-
  199. *                 bereich zu allozieren. Falls dies fehlschlaegt, wird
  200. *                 eine Fehlermeldung ausgegeben, alle Files gesichert und
  201. *                 das Programm abgebrochen.
  202. *
  203. *****************************************************************************/
  204.  
  205. char *reserve_mem (laenge)
  206. int laenge;
  207. {
  208.   /* *** interne Daten *** */
  209.   register char *hilf; /* Rueckgabewert der Funktion */
  210.  
  211.   if (hilf = malloc (laenge)) /* Speicher anfordern */
  212.     return (hilf); /* klappte, Adresse zurueckgeben */
  213.   else             /* Sonst Fehlermeldung und Ende  */
  214.     no_mem_err();
  215. }
  216.  
  217. /*****************************************************************************
  218. *
  219. *  Funktion       Textzeile sichern (save_text)
  220. *  --------
  221. *
  222. *  Parameter    : txt       :
  223. *                   Typ          : char*
  224. *                   Wertebereich : Pointer auf ASCII-Zeichenkette
  225. *                   Bedeutung    : Zu sichernder String
  226. *
  227. *  Ergebnis     :
  228. *                   Typ          : char*
  229. *                   Wertebereich : Pointer auf ASCII-Zeichenkette
  230. *                   Bedeutung    : Pointer auf gesicherten String
  231. *
  232. *  Beschreibung : Fuer den uebergebenen String wird, falls der String
  233. *                 eine Laenge ungleich 0 hat und txt != NULL ist, Speicher
  234. *                 alloziert, der uebergebene String wird dorthin kopiert
  235. *                 und der Pointer auf den Bereich zurueckgegeben.
  236. *                 Ist die Stringlaenge 0 oder txt NULL, so wird ein
  237. *                 NULL-Pointer zurueckgegeben.
  238. *
  239. *****************************************************************************/
  240.  
  241. char *save_text(txt)
  242. register char *txt;
  243. {
  244.   /* *** interne Daten *** */
  245.   register int len; /* Laenge des abzuspeichernden Textes */
  246.  
  247.   if (!txt) /* Falls String leer, NULL-Pointer zurueckgeben */
  248.     return (NULL);
  249.   return ((len=strlen(txt))?strcpy(reserve_mem(len+1),txt):NULL);
  250. }
  251.  
  252. /*****************************************************************************
  253. *
  254. *  Funktion       Zeile freigeben (line_free)
  255. *  --------
  256. *
  257. *  Parameter    : txt       :
  258. *                   Typ          : char*
  259. *                   Wertebereich : Pointer auf ASCII-Zeichenkette
  260. *                   Bedeutung    : Freizugebende Zeile
  261. *
  262. *  Beschreibung : Falls der Pointer nicht gleich NULL ist, wird der Spei-
  263. *                 cherbereich, auf den er zeigt, freigegeben.
  264. *
  265. *****************************************************************************/
  266.  
  267. void line_free(txt)
  268. char *txt;
  269. {
  270.   if(txt)
  271.     free(txt);
  272. }
  273.  
  274. /*****************************************************************************
  275. *
  276. *  Funktion       String von hinten kopieren (revcpy)
  277. *  --------
  278. *
  279. *  Parameter    : s1         :
  280. *                   Typ          : char *
  281. *                   Wertebereich : Pointer auf Speicherbereich
  282. *                   Bedeutung    : Platz, an den zu kopierender String
  283. *                                  kopiert wird
  284. *                 s2         :
  285. *                   Typ          : char *
  286. *                   Wertebereich : Pointer auf ASCII-Zeichenkette
  287. *                   Bedeutung    : zu kopierender String
  288. *
  289. *  Ergebnis     :
  290. *                   Typ          : char *
  291. *                   Wertebereich : Pointer auf ASCII-Zeichenkette
  292. *                   Bedeutung    : s1
  293. *
  294. *  Beschreibung : s2 wird, von hinten beginnend, nach s1 kopiert.  Dies ist
  295. *                 zum Beispiel nuetzlich, wenn s2 und s1 gemeinsame Speicher-
  296. *                 bereiche haben und s2 nach s1 beginnt.
  297. *
  298. *****************************************************************************/
  299.  
  300. char *revcpy(s1,s2)
  301. register char *s1,*s2;
  302. {
  303.   /* *** interne Daten und Initialierung *** */
  304.   register char *s2e = s2 + strlen(s2); /* Zeiger auf Stringende */
  305.  
  306.   for(s1+=s2e-s2;s2e >= s2;*s1-- = *s2e--);
  307.   return(s1);
  308. }
  309.  
  310. /*****************************************************************************
  311. *
  312. *  Funktion       String vorwaerts kopieren (fwdcpy)
  313. *  --------
  314. *
  315. *  Parameter    : s1         :
  316. *                   Typ          : char *
  317. *                   Wertebereich : Pointer auf Speicherbereich
  318. *                   Bedeutung    : Platz, an den zu kopierender String
  319. *                                  kopiert wird
  320. *                 s2         :
  321. *                   Typ          : char *
  322. *                   Wertebereich : Pointer auf ASCII-Zeichenkette
  323. *                   Bedeutung    : zu kopierender String
  324. *
  325. *  Ergebnis     :
  326. *                   Typ          : char *
  327. *                   Wertebereich : Pointer auf ASCII-Zeichenkette
  328. *                   Bedeutung    : s1
  329. *
  330. *  Beschreibung : s2 wird, von vorne beginnend, nach s1 kopiert.
  331. *                 Diese Funktion wird bei ueberlappenden Strings benoetigt,
  332. *                 da strcpy keine Garantie fuer die Kopierrichtung gibt.
  333. *
  334. *****************************************************************************/
  335.  
  336. char *fwdcpy(s1,s2)
  337. register char *s1,*s2;
  338. {
  339.   if(!s2)                       /* wie strcpy */
  340.   {
  341.     if(s1)
  342.       *s1 = '\0';
  343.   }
  344.   else
  345.     while (*s1++ = *s2++);
  346.   return(s1);
  347. }
  348.  
  349. /*****************************************************************************
  350. *
  351. *  Funktion       Zwei Integer vertauschen (swap_int)
  352. *  --------
  353. *
  354. *  Parameter    : a         :
  355. *                   Typ          : int *
  356. *                   Wertebereich : Pointer auf Integer
  357. *                   Bedeutung    : zu vertauschender Integer
  358. *
  359. *               : b         :
  360. *                   Typ          : int *
  361. *                   Wertebereich : Pointer auf Integer
  362. *                   Bedeutung    : zu vertauschender Integer
  363. *
  364. *  Beschreibung : Die Integer, auf die die Pointer a und b zeigen, werden
  365. *                 mittels einer Hilfsvariable vertauscht.
  366. *
  367. ******************************************************************************/
  368.  
  369. void swap_int(a,b)
  370. int *a,*b;
  371. {
  372.   /* *** interne Daten *** */
  373.   int hilf; /* Hilfsvariable zum Vertauschen */
  374.  
  375.   hilf = *a;
  376.   *a = *b;
  377.   *b = hilf;
  378. }
  379.  
  380. /*****************************************************************************
  381. *
  382. *  Funktion       Lese JA/NEIN Abfrage (ja_nein)
  383. *  --------
  384. *
  385. *  Parameter    : s         :
  386. *                   Typ          : char *
  387. *                   Wertebereich : Pointer auf ASCII-Zeichenkette
  388. *                   Bedeutung    : Text der Abfrage
  389. *
  390. *  Ergebnis     :
  391. *                   Typ          : int
  392. *                   Wertebereich : TRUE,FALSE
  393. *                   Bedeutung    : Ergebnis der Abfrage: ja = TRUE
  394. *                                                        nein = FALSE
  395. *
  396. *  Beschreibung : s wird in der Statuszeile ausgegeben, danach ein Zeichen,
  397. *                 terminiert durch RETURN eingelesen. Ist das Zeichen nicht
  398. *                 in "JjNn" wird die Abfrage wiederholt.  Es wird FALSE
  399. *                 zurueckgegeben, falls das Zeichen 'n' oder 'N' war,
  400. *                 ansonsten ist der Returnwert TRUE.
  401. *
  402. *****************************************************************************/
  403.  
  404. int ja_nein (s)
  405. char *s;
  406. {
  407.   /* *** interne Daten *** */
  408.   short int jn; /* einzulesendes Zeichen */
  409.  
  410.   print_stat (s);           /* Uebergebenen String ausgeben   */
  411.   print_stat(PROMPT_YES_NO);  /* Zusatz anhaengen               */
  412.   nodelay(status,TRUE); /* Fenster wg. Maus auf NODELAY schalten */
  413.   do                        /* Solange ein Zeichen lesen, bis */
  414.   { jn = newwgetch(status); /* es eins von j,J,y,Y,n,N ist        */
  415. #ifdef OS2
  416.     if (jn == -1)
  417.       DosSleep (10);
  418. #endif
  419.   } while (!strchr ("jny,YJN",(char)jn));
  420.   nodelay(status,FALSE);  /* Wieder DELAY einschalten */
  421.   clear_stat();             /* Statuszeile wieder loeschen    */
  422.  
  423.   if (jn == 'n' || jn == 'N')
  424.     return (FALSE);
  425.   return (TRUE);
  426. }
  427.  
  428. #ifdef OWN_CURSES
  429. /******************************************************************************
  430. *
  431. * Funktion     : Zeilen- und Spaltenzahl ermitteln (set_lines_cols)
  432. * --------------
  433. *
  434. * Parameter    : modus       :
  435. *                  Typ          : char *
  436. *                  Wertebereich : Pointer auf ASCII-Zeichenkette
  437. *                  Bedeutung    : Aus der Umgebungsvariablen EHPINIT
  438. *                                 extrahierter Teil
  439. *
  440. * Beschreibung : Der aus der Umgebungsvariable stammende Teil hinter
  441. *                dem Bezeichner "screen" muß die Syntax <Spalten>x<Zeilen>
  442. *                haben. Das 'x' darf auch groa geschrieben sein.
  443. *                Ist der übergebene String syntaktisch korrekt so werden die
  444. *                Curses-Variablen LINES und COLS entsprechend gesetzt.
  445. *
  446. ******************************************************************************/
  447.  
  448. void set_lines_cols(modus)
  449. char *modus;
  450. {
  451.   char *zeil_str; /* Zeiger auf Tokenteil, der Zeilenzahl angibt */
  452.   int  lines,     /* Anzahl der Bildschirmzeilen */
  453.        cols;      /* Anzahl der Bildschirmspalten */
  454.  
  455.   if(!(zeil_str = strchr(modus,'x')) && !(zeil_str = strchr(modus,'X')))
  456.     return;  /* Falsches Format, Bildschirmgröße wird nicht verändert */
  457.   *zeil_str++ = '\0'; /* 'x' bzw. 'X' löschen, String in 2 Teile teilen */
  458.   cols = atoi(modus); /* Erste Zahl steht für die Spaltenangabe */
  459.   if(cols != 40 && cols != 80 && cols != 100 && cols != 132) /* Es werden nur die */
  460.     return;            /* Spaltenzahlen 40, 80, 100 und 132 unterstützt */
  461.   lines = atoi(zeil_str); /* Zweite Zahl des Strings steht für Zeilenangabe */
  462.   LINES = lines; /* Curses-Variablen LINES und COLS setzen */
  463.   COLS  = cols;
  464. }
  465. #endif
  466.  
  467. /*****************************************************************************
  468. *
  469. *  Funktion       Integer aus EHPINIT lesen (int_from_env)
  470. *  --------
  471. *
  472. *  Beschreibung : Es wird vorausgesetzt, daß strtok bereits auf der
  473. *                 Umgebungsvariablen ausgeführt wurde, so daß ein erneuter
  474. *                 Aufruf mit NULL als Parameter das nächste Token liefert.
  475. *                 Ist kein weiteres Token vorhanden, so wird stillschweigend
  476. *                 0 zurückgeliefert. Ansonsten wird das Token mit atoi in
  477. *                 einen int konvertiert und das Ergebnis zurückgeliefert.
  478. *
  479. ****************************************************************************/
  480.  
  481. int int_from_env ()
  482. {
  483.   int result = 0;
  484.   char *tok = strtok ((char*) NULL, " ");
  485.   if (tok)
  486.     result = atoi(tok);
  487.   return result;
  488. }
  489.  
  490. /*****************************************************************************
  491. *
  492. *  Funktion       Environment checken (check_env)
  493. *  --------
  494. *
  495. *  Beschreibung : Die Umgebungsvariable EHPINIT wird in der Umgebung gesucht.
  496. *                 Wird sie gefunden, so wird der Inhalt analysiert.
  497. *                 Folgende Token haben folgenden Effekt:
  498. *                   deftab <n>   : Default-Tablaenge auf <n> setzen
  499. *                   nohelp       : Hilfstexte defaultmaessig ausgeschaltet
  500. *                   autoind      : Autoindentmodus defaultmaessig eingesch.
  501. *                   noshowblock  : Blockhervorhebung defaultmaessig eing.
  502. *                   conffile <f> : Name des Config-Files auf <f> setzen
  503. *                   loadfile <f> : Name des Load-Files auf <f> setzen
  504. *                   nobak        : Defaultmaessig keine .bak-Files
  505. *                   screen <mode>: Bildschirmgröße in Zeilen und Spalten
  506. *                   keys <f>     : Name des Tastaturbeschreibungsfiles = <f>
  507. *                   noregex      : Reguläre Ausdrücke beim Suchen ausgesch.
  508. *                   linebrk      : Autom. Zeilenumbruch eingeschaltet
  509. *
  510. ****************************************************************************/
  511.  
  512. void check_env()
  513. {
  514.   /* *** interne Daten *** */ 
  515.   char *ehp_init, /* Zeiger auf Inhalt der Umgebungsvariable     */
  516.        *copy_of_ehp_init,
  517.        *konv,     /* Zeiger zur Konvertierung in Kleinbuchstaben */
  518.        *token;    /* Zeiger auf aktuellen Parameter              */
  519.   int  i;         /* Integerwert der Tablaenge                   */
  520.  
  521.   if(ehp_init = getenv("EHPINIT"))
  522.   {
  523.     copy_of_ehp_init = strcpy(reserve_mem(strlen(ehp_init)+1), ehp_init);
  524.     ehp_init = copy_of_ehp_init;
  525.     while(token = strtok(ehp_init," "))
  526.     {
  527.       ehp_init = NULL;  /* fuer strtok */
  528.       for (konv = token; *konv; konv++)
  529.     *konv = tolower (*konv); /* Token in Kleinbuchstaben konvertieren */
  530.       if(!strcmp("deftab",token))
  531.       {
  532.     if((i = int_from_env()) > 0 && i < MAXLENGTH)
  533.       def_tab = i;
  534.       }
  535.       else if(!strcmp("nohelp",token))
  536.     helpflag = FALSE;
  537.       else if(!strcmp("autoind",token))
  538.     def_aiflag = TRUE;
  539.       else if(!strcmp("noshowblock",token))
  540.     highblockflag = FALSE;
  541.       else if(!strcmp("conffile",token))
  542.       {
  543.     if(!(token = strtok(ehp_init," ")))
  544.       break;        /* war letzter token */
  545.     conffile = token;
  546.       }
  547.       else if(!strcmp("loadfile",token))
  548.       {
  549.     if(!(token = strtok(ehp_init," ")))
  550.       break;        /* war letzter token */
  551.     loadfile = token;
  552.       }
  553.       else if(!strcmp("nobak",token))
  554.       backupflag = FALSE;
  555.  
  556. #ifdef OWN_CURSES /* Bildschirmgröße und Farben lassen sich nur mit dem
  557.              eigenen Curses anpassen ! */
  558.       else if(!strcmp("screen",token))
  559.       {
  560.     if(!(token = strtok(ehp_init," ")))
  561.       break;        /* war letzter token */
  562.     set_lines_cols(token); /* Bildschirmgröße setzen */
  563.       }
  564.       else if(!strcmp("clr_text", token))
  565.     STD_ATTR = int_from_env();
  566.       else if(!strcmp("clr_frame", token))
  567.     A_STANDOUT = int_from_env();
  568.       else if(!strcmp("clr_block", token))
  569.     A_BOLD = int_from_env();
  570.       else if(!strcmp("clr_under", token))
  571.     A_UNDERLINE = int_from_env();
  572. #endif
  573.       else if(!strcmp("keys", token))
  574.       {
  575.     if(!(token = strtok(ehp_init," ")))
  576.       break;      /* war letzer Token */
  577.     tasten_inf = strcpy(reserve_mem (strlen(token)+1),token);
  578.       }
  579.       else if(!strcmp("noregex", token))
  580.     regexflag = FALSE;
  581.       else if(!strcmp("linebrk", token))
  582.     linebrkflag = TRUE;
  583.     }
  584.     free (copy_of_ehp_init);
  585.   }
  586. }
  587.  
  588. /******************************************************************************
  589. *
  590. * Funktion     : Signal abfangen (catchsig)
  591. * --------------
  592. *
  593. * Beschreibung : Diese Funktion wird beim Auftreten des Break-Interruptes
  594. *                (Nummer 27) aufgerufen. Es wird das clear_buff-Flag gesetzt,
  595. *                wodurch beim nächsten Aufruf von newwgetch alle Puffer und
  596. *                Macros abgebrochen werden.
  597. *
  598. ******************************************************************************/
  599.  
  600. void catchsig(sig)
  601. int sig;
  602. {
  603.   /* Um ein waehrend der Abarbeitung dieser Routine auftretendes */
  604.   /* Signal abzufangen, wird das Signal auf SIG_IGN umgeleitet   */
  605.  
  606.   signal(sig,SIG_IGN);
  607. #ifdef OS2
  608.   if(sig == SIGINT || sig == SIGQUIT || sig == SIGBREAK)
  609. #else
  610.   if(sig == SIGINT || sig == SIGTERM)
  611. #endif
  612.     clear_buff = TRUE;  /* Macro- und Repeatpuffer loeschen */
  613.   else
  614.   {
  615.     if(ja_nein(PROMPT_FATAL))
  616.       save_all();
  617.     ende(sig, TRUE);     /* Speicherbereiche werden automatisch */
  618.   }                      /* vom Betriebssystem freigegeben      */
  619.   signal(sig, catchsig); /* Adresse dieser Funktion wieder eintragen */
  620. }
  621.  
  622. /*****************************************************************************
  623. *
  624. *  Funktion       initialisieren (init)
  625. *  --------
  626. *
  627. *  Beschreibung : Die CURSES-Funktionen initscr(),noecho() und raw() werden
  628. *                 aufgerufen, um CURSES zu initialisieren, echo abzuschalten,
  629. *                 und die Abfrage von einzelnen Zeichen zu ermoeglichen.
  630. *                 Dann wird das Dummyelement der Windowliste initialisiert.
  631. *                 Es ist _w_i_c_h_t_i_g, daa check_env von initscr aufgerufen wird.
  632. *                 In check_env werden nämlich evtl. die Variablen LINES
  633. *                 und COLS angepaat, was vor der Bildschirminitalisierung
  634. *                 stattfinden mua. Ebenfalls in initscr können sich diese
  635. *                 beiden Werte nochmals ändern.
  636. *
  637. *****************************************************************************/
  638.  
  639. void init()
  640. {
  641.   /* *** interne Daten *** */
  642.   int i;    /* Fuer Eingabe der Terminaltypen */
  643.  
  644.   /* Pruefen, ob IO des Prozesses umgelenkt wurde */
  645.   if(!isatty(0) || !isatty(1) || !isatty(2))
  646.   {
  647.     fputs(PROMPT_IO_REDIR,stderr);
  648.     exit(1);
  649.   }
  650.  
  651. #ifdef OS2
  652.   set_os2_raw (TRUE);       /* !!! muß erste Aktion sein !!! */
  653. #endif
  654.   check_env();              /* Umgebungsvariable bearbeiten */
  655.   initscr();                /* Curses "einschalten" */
  656.   noecho();
  657.   raw(); /* Zeichen direkt, keine Signale verarbeiten */
  658.   nonl(); /* \r soll nicht in \n umgewandelt werden */
  659.   status = newwin(1,COLS,LINES-1,0); /* Statusfenster oeffnen */
  660.   lies_tasten();        /* Tastaturbelegung laden */
  661.   akt_winp = (win_typ*) reserve_mem (sizeof (win_typ)); /* Dummyfenster */
  662.   akt_winp->next = akt_winp->prev = akt_winp;           /* allozieren   */
  663.   akt_winp->filename = NULL; /* damit print_err testen kann, ob es */
  664.   akt_winp->winp = NULL;     /* schon ein Fenster gibt */
  665.  
  666.   /* Terminal stellt zu ersetzende Begriffe blinkend dar, */
  667.   /* Bloecke halbhell.                                    */
  668.   ersetzaddr = A_BLINK;
  669.   blockattr = A_BOLD;
  670.  
  671.   global_block.e_line = global_block.s_line = -1;
  672.   global_block.bstart = NULL;   /* PASTE-Puffer leer */
  673.   for(i=0;i<ANZ_MARKER;i++)     /* Marker loeschen   */
  674.     marker[i].window = marker[i].line = marker[i].col = -1;
  675.   for(i=0;i<ANZ_MACROS;i++)     /* Macros loeschen   */
  676.     macro[i].begin = macro[i].end = NULL;
  677. #ifdef MOUSE
  678.   init_mouse();
  679. #endif
  680.  
  681.   signal (SIGINT, catchsig); /* kommt wohl nicht durch, da CTRL-c im raw- */
  682. #ifdef OS2
  683.   signal (SIGBUS, catchsig); /* Modus nicht als Signal verarbeitet wird.  */
  684.   signal (SIGQUIT, catchsig);
  685.   signal (SIGBREAK, catchsig);
  686.   /* Jetzt muß der Semaphor erzeugt werden, der verhindert, daß sich von der
  687.      Maus und von der Tastatur empfangene Kommandos behindern. Dieser Sema-
  688.      phor wird als "owned" geöffnet, muß also erst "released" werden, damit
  689.      ein Kommando akzeptiert werden kann. */
  690.   DosCreateMutexSem (NULL, &sem_handle, DC_SEM_SHARED, TRUE);
  691. #else
  692.   signal (SIGABRT, catchsig);
  693.   signal (SIGTERM, catchsig);
  694.   signal (SIGSEGV, catchsig);
  695. #endif
  696. /*  re_set_syntax (RE_INTERVALS); */
  697. }
  698.  
  699. /*****************************************************************************
  700. *
  701. *  Funktion       editor beenden (ende)
  702. *  --------
  703. *
  704. *  Parameter    : r         :
  705. *                   Typ          : int
  706. *                   Wertebereich : -MAX_INT - +MAX_INT
  707. *                   Bedeutung    : Rueckgabewert des Programms
  708. *
  709. *                 wait_mouse: (Nur OS/2)
  710. *                   Typ          : char
  711. *                   Wertebereich : FALSE, TRUE
  712. *                   Bedeutung    : TRUE:  Warte auf die Beendigung des
  713. *                                         Mausthreads
  714. *                                  FALSE: Nicht auf Mausthread warten.
  715. *
  716. *  Beschreibung : Die Fenster werden mittels endwin() geschlossen und danach
  717. *                 exit aufgerufen.
  718. *
  719. *****************************************************************************/
  720.  
  721. void ende(int r, char wait_mouse)
  722. {
  723.   clear();      /* Bildschirm loeschen */
  724.   refresh();
  725.   endwin();     /* Curses beenden */
  726. #ifdef MOUSE
  727. #ifdef OS2
  728.   mouse_active = FALSE;  /* Maus nicht mehr benötigt */
  729.   /* Durch Setzen von mouse_active=FALSE beendet sich der Mouse-Thread
  730.      selbständig und die Maus wird geschlossen. Hier muß dann nur noch
  731.      auf die Terminierung des Threads gewartet werden. */
  732.   if (wait_mouse)
  733.     DosWaitThread (&mouse_ThreadID, DCWW_WAIT);
  734. #else
  735.   set_mouse_int(0); /* Mausroutine maskieren */
  736. #endif
  737. #endif
  738. #ifndef OS2
  739.   *(long*)(27*4) = old_int; /* Vektor des Break-Interruptes restaurieren */
  740. #endif
  741.   exit(r);
  742. }
  743.  
  744.  
  745. /*****************************************************************************
  746. *
  747. *  Funktion       pruefen, ob Texte geaendert wurden
  748. *  --------
  749. *
  750. *  Ergebnis     : TRUE: Es wurde mindestens eine Datei geaendert
  751. *                 FALSE: Alle Dateien sind ungeaendert
  752. *
  753. *  Beschreibung : Es wird ueber alle bestehenden Fenster iteriert und
  754. *                 das changeflag geprueft. Ist eines TRUE, so wird
  755. *                 sofort mit TRUE zurueckgekehrt.
  756. *
  757. *****************************************************************************/
  758.  
  759. int did_anything_change()
  760. {
  761.   win_typ *p = akt_winp->next->next;
  762.  
  763.   while (p != akt_winp->next)
  764.   {
  765.     if (p->changeflag)
  766.       return TRUE;
  767.     p = p->next;
  768.   }
  769.   return FALSE;
  770. }
  771.  
  772. /*****************************************************************************
  773. *
  774. *  Funktion       alle geaenderten Texte abspeichern (save_all)
  775. *  --------
  776. *
  777. *  Ergebnis     : TRUE: alle Dateien konnten abgespeichert werden.
  778. *                 FALSE: nicht alle Dateien ...
  779. *
  780. *  Beschreibung : Die zu den Fenstern gehoerigen Files werden abgespeichert,
  781. *                 sofern sie veraendert wurden.
  782. *
  783. *****************************************************************************/
  784.  
  785. int save_all()
  786. {
  787.   /* *** interne Daten und Initialisierung *** */
  788.   int     no_errflag = TRUE;   /* Zeigt Fehler beim Abspeichern an */
  789.   win_typ *d = akt_winp->next; /* Zeiger auf Dummy-Fenster         */
  790.  
  791.   check_buff();
  792.   akt_winp = d->next;
  793.   while (akt_winp != d)
  794.   {
  795.     if(akt_winp->changeflag && !schreib_file())
  796.       no_errflag = FALSE; /* schreib_file lieferte Fehler */
  797.     akt_winp = akt_winp->next;
  798.   }
  799.   akt_winp = d->prev; /* akt_winp restaurieren */
  800.   return(no_errflag);
  801. }
  802.  
  803. /*****************************************************************************
  804. *
  805. *  Funktion       Text und Fenster freigeben (alles_frei)
  806. *  --------
  807. *
  808. *  Beschreibung : Der fuer Texte und Fenster allozierte Speicherplatz wird
  809. *                 freigegeben.
  810. *
  811. *****************************************************************************/
  812.  
  813. void alles_frei()
  814. {
  815.   while(akt_winp != akt_winp->next)     /* noch ein Fenster da? */
  816.   {
  817.     free_text();  /* Text des Fensters freigeben */
  818.     delwin(akt_winp->winp); /* Fenster fuer Curses freigeben */
  819.     gb_win_frei(); /* gb_win_frei loescht Fenster aus Liste und */
  820.   }                /* macht akt_winp zu ->prev */
  821.   if(global_block.bstart)     /* globalen Block evtl. freigeben */
  822.     block_free(&global_block.bstart);
  823.   line_free(sd_line);      /* zuletzt geloeschte Zeile freigeben */
  824.   free(akt_winp);          /* dummy auch freigeben */
  825. }
  826.  
  827. #ifndef OS2
  828. /*****************************************************************************
  829. *
  830. *  Funktion       Wildcards expandieren (do_wildcard_expansion)
  831. *  --------
  832. *
  833. *  Parameter    : argc         :
  834. *                   Typ          : int *
  835. *                   Wertebereich : Zeiger auf Integer
  836. *                   Bedeutung    : Zeiger auf bisherige Anzahl der Parameter
  837. *
  838. *                 argv         :
  839. *                   Typ          : char **[]
  840. *                   Wertebereich : Pointer auf Pointer auf Array von Pointer
  841. *                                  auf Parametern
  842. *                   Bedeutung    : 1. Parameter: Programmname
  843. *                                  restliche Parameter: zu expandierende
  844. *                                  Dateinamen
  845. *
  846. *  Beschreibung : Mittels der Funktionen findfirst und findnext werden
  847. *                 die als Parameter angegebenen Dateinamenmuster zu
  848. *                 vollständigen Dateinamen expandiert. argc aud argv
  849. *                 werden auf das entstehende Erbebnis gesetzt, das keine
  850. *                 Wildcards mehr enthält.
  851. *
  852. *****************************************************************************/
  853.  
  854. void do_wildcard_expansion(argc, argv)
  855. int *argc;
  856. char **argv[];
  857. {
  858.   int ende,               /* Kein weiteres File zum Pattern ?        */
  859.       complete_length,    /* Summe aller Stringlängen                */
  860.       new_argc,           /* Neue Parameteranzahl                    */
  861.       new_argv_index,     /* Index in neues Argumentarray            */
  862.       argv_index;         /* Index in argv, zählt die Dateiparameter */
  863.   struct ffblk file_info; /* Struktur für findfirst und findnext     */
  864.   struct filenamelist     /* Für die Konstruktion der neuen Liste    */
  865.   {
  866.     char                *name;
  867.     struct filenamelist *next;
  868.   } *p, *q, *first;       /* Laufzeiger und Listenstart              */
  869.   char **new_argv;        /* Neues Feld für Parameter                */
  870.  
  871.   if (*argc > 1) /* Nur etwas machen, wenn auch Parameter angegeben wurden */
  872.   {
  873.     /* Zunächst ein Dummy-Element für die Namenliste anlegen: */
  874.     first = p = (struct filenamelist *) reserve_mem (sizeof (struct filenamelist));
  875.     p->next = NULL;
  876.     argv_index = 0;
  877.     new_argc = 1; /* Zumindest der Kommandoname */
  878.     complete_length = strlen ((*argv) [0]); /* Länge des Kommandos ! */
  879.     while (++argv_index < *argc)
  880.     {
  881.       ende = findfirst ((*argv) [argv_index], &file_info, 0);
  882.       if (ende)
  883.       { /* Überhaupt keinen passenden Namen, dann neue Datei! */
  884.     p->next =
  885.       (struct filenamelist *) reserve_mem (sizeof (struct filenamelist));
  886.     p = p->next;
  887.     p->next = NULL;
  888.     p->name = strcpy ((char*) reserve_mem (strlen((*argv)[argv_index])+1),
  889.               (*argv) [argv_index]);
  890.     complete_length += strlen ((*argv) [argv_index]) + 1;
  891.     new_argc++;
  892.       }
  893.       else
  894.     while (!ende)
  895.     {
  896.       p->next = 
  897.         (struct filenamelist *) reserve_mem (sizeof (struct filenamelist));
  898.       p = p->next;
  899.       p->next = NULL;
  900.       p->name = strcpy ((char*) reserve_mem(strlen (file_info.ff_name)+1),
  901.                 file_info.ff_name);
  902.       complete_length += strlen (file_info.ff_name) + 1;
  903.       new_argc++;
  904.       ende = findnext (&file_info);
  905.     }
  906.     }
  907.  
  908.     /* Jetzt die aufgebaute Liste in ein Array vom Typ char *[] verwandeln */
  909.     /* Achtung: Letzter Pointer muß NULL-Pointer sein! */
  910.     new_argv = (char **) reserve_mem ((new_argc+1) * sizeof (char*));
  911.     new_argv[0] = (*argv)[0];
  912.     new_argv_index = 1;
  913.     p = first->next;
  914.     while (p)
  915.     {
  916.       new_argv [new_argv_index++] = p->name;
  917.       p = p->next;
  918.     }
  919.     new_argv [new_argv_index] = NULL; /* Am Ende der Argumentliste muß ein NULL-Pointer stehen */
  920.     *argc = new_argc;
  921.     *argv = new_argv;
  922.     /* Jetzt temporäre Liste freigeben! */
  923.     p = first;
  924.     while (p)
  925.     {
  926.       q = p->next;
  927.       free (p);
  928.       p = q;
  929.     }
  930.   }
  931. }
  932. #endif
  933.  
  934.  
  935.  
  936. /*****************************************************************************
  937. *
  938. *  Funktion       parameter verarbeiten (hndl_params)
  939. *  --------
  940. *
  941. *  Parameter    : argc         :
  942. *                   Typ          : int
  943. *                   Wertebereich : 1 - maxint
  944. *                   Bedeutung    : Anzahl der Parameter
  945. *
  946. *                 argv         :
  947. *                   Typ          : char **
  948. *                   Wertebereich : Pointer auf Array von Pointer auf
  949. *                                  Parametern
  950. *                   Bedeutung    : 1. Parameter: Programmname
  951. *                                  restliche Parameter: zu edierende Dateien
  952. *
  953. *                 anz_files    :
  954. *                   Typ          : int
  955. *                   Wertebereich : 0 - maxint
  956. *                   Bedeutung    : Anzahl der schon eingelesenen Dateien
  957. *
  958. *  Beschreibung : Die Kommandozeilenparameter werden als Filenamen interpre-
  959. *                 tiert und in den Editor geladen.
  960. *                 Konnten keine Files geladen werden, so wird das Programm
  961. *                 abgebrochen.
  962. *
  963. *****************************************************************************/
  964.  
  965. void hndl_params(argc,argv,anz_files)
  966. int argc,anz_files;
  967. char **argv;
  968. {
  969. #ifdef OS2                  /* OS/2 stellt _wildcard zur Verfügung, */
  970.   _wildcard (&argc, &argv); /* um Patterns zu expandieren */
  971. #else
  972.   do_wildcard_expansion (&argc, &argv);
  973. #endif
  974.   if(argc>1)   /* Wurden Parameter angegeben ? */
  975.   {
  976.     while(--argc) /* Fuer jeden Parameter ein Fenster oeffnen */
  977.     {
  978.       if (koppel_win())
  979.       {
  980.     akt_winp->filename = save_text(argv[argc]);
  981.     akt_winp->block.bstart = (bzeil_typ*) NULL;
  982.     if(!lies_file()) /* und versuchen, die Datei zu laden */
  983.     {
  984.       free(akt_winp->dummyp);
  985.       gb_win_frei(); /* klappt das nicht, Fenster wieder schliessen */
  986.     }
  987.     else
  988.     {
  989.       anz_files++;   /* Sonst Anzahl der geladenen Files erhoehen */
  990.       open_window(); /* und Fenster initialisieren */
  991.     }
  992.       }
  993.       else /* Konnte Fenster nicht geoeffnet werden, Fehlermeldung */
  994.       {
  995.     print_err(W_COUNT_ERRTEXT);
  996.     break;
  997.       }
  998.     }
  999.     if(!anz_files) /* Wenn keines der angegebenen Files geladen werden  */
  1000.     {              /* konnte, Fehlermeldung ausgeben und Editor beenden */
  1001.       print_stat(PROMPT_NO_FILE);
  1002.       wart_ret();
  1003.       ende(0, TRUE);
  1004.     }
  1005.     setz_cursor(W_AKT);  /* falls letzte Datei nicht geladen werden konnte, */
  1006.   }                 /* wird kein setz_cursor gemacht */
  1007.   else              /* Wurden keine Parameter angegeben und konnte    */
  1008.     if(!anz_files && !laden()) /* kein File geladen werden, versuchen */
  1009.       ende(0, TRUE);   /* Dateinamen vom User zu holen. Falls Fehler, Ende */
  1010. }
  1011.  
  1012.  
  1013. /*****************************************************************************
  1014. *
  1015. *  Funktion       main (main)
  1016. *  --------
  1017. *
  1018. *  Parameter    : argc         :
  1019. *                   Typ          : int
  1020. *                   Wertebereich : 1 - maxint
  1021. *                   Bedeutung    : Anzahl der Parameter
  1022. *
  1023. *  Parameter    : argv         :
  1024. *                   Typ          : char **
  1025. *                   Wertebereich : Pointer auf Array von Pointer auf
  1026. *                                  Parametern
  1027. *                   Bedeutung    : 1. Parameter: Programmname
  1028. *                                  restliche Parameter: zu edierende Dateien
  1029. *
  1030. *  Beschreibung : main() startet den Editor und enthaelt die Hauptschleife, die
  1031. *                 einen Befehl holt und diesen ausfuehrt, bis das Programm
  1032. *                 beendet werden soll.
  1033. *
  1034. *****************************************************************************/
  1035.  
  1036. int main (argc,argv)
  1037. int argc;
  1038. char **argv;
  1039. {
  1040.   /* The following is for debugging purposes only: */
  1041.   init();  /* Tastaturbelegung laden, Variablen initialisieren, Umgebungs- */
  1042.        /* variable bearbeiten, Signale abfangen, Curses initialisieren */
  1043.   hndl_params(argc,argv,read_config(argc)); /* Config-Datei lesen und Para-*/
  1044.                         /* meter auswerten             */
  1045.   while (1)
  1046.     auswertung (aktcode = taste(akt_winp->winp)); /* Tastenkombination lesen */
  1047. }                                                 /* und auswerten           */
  1048.