home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / ehp14cs.zip / km.c < prev    next >
Text File  |  1994-12-10  |  27KB  |  725 lines

  1. #include "curses.h"  /* includiert stdlib.h */
  2. #include <stdio.h>
  3. #include <string.h>
  4.  
  5. #define MAX_COMM_LEN 10  /* maximale Laenge einer Tastenkombination */
  6. #define MAX_COMM_ANZ 200 /* maximale Anzahl Kommandos */
  7.  
  8. #ifdef GERMAN
  9. #define PROMPT_NUMBERMISSING "Anzahl der Kombinationen nicht in Datei!\r\n"
  10. #define PROMPT_TOOFEWCOMBS   "Nicht genügend Tastenkombinationen!\r\n"
  11. #define PROMPT_ERROR         "Tastenbelegungsdatei fehlerhaft, Programm wird beendet!\r\n"
  12. #define PROMPT_ERRWRITE      "Tastenfile nicht schreibbar!\r\n"
  13. #define PROMPT_NOBAK         "Konnte keine Sicherungskopie des Tastenfiles anlegen. Datei wird überschieben.\r\n"
  14. #define PROMPT_NUMBERCHANGE  "Welchen Nummer wollen Sie ändern (-1 fuer Ende)? "
  15. #define PROMPT_OLDSTRING     "alter String: %s\r\n"
  16. #define PROMPT_STRING        "String eingeben: "
  17. #define PROMPT_OLDCOMB       "Alte Kombination (dezimal): "
  18. #define PROMPT_COMMAND       "\r\nKommando: %s\n"
  19. #define PROMPT_KEYS          "\r\nGeben Sie die Tastaturcodes ein: (/ fuer Ende)\r\n"
  20. #define PROMPT_NEWCOMB       "Eingegebene Kombination (dezimal): "
  21. #define PROMPT_CONFLICT      "Kombination ist nicht eindeutig, gerät in Konflikt mit Befehl %hd\r\nBisherige Kombination bleibt erhalten!\n\n\r"
  22. #define PROMPT_KEYABORT      "Bitte eine Taste drücken (a=Abbruch)...\r\n"
  23. #define PROMPT_KEY           "Bitte eine Taste drücken... \r\n"
  24. #define PROMPT_MENU1         "1) Tastenkombinationen aendern\r\n"
  25. #define PROMPT_MENU2         "2) Hilfstexte aendern\r\n"
  26. #define PROMPT_MENU3         "3) Befehlsnamen anzeigen\r\n"
  27. #define PROMPT_MENU4         "4) Ende (Tastaturdatei abspeichern)\r\n"
  28. #define PROMPT_MENU5         "Welche Alternative wuenschen Sie (1-4) ? "
  29. #else
  30. #define PROMPT_NUMBERMISSING "Number of combinations not in file!\r\n"
  31. #define PROMPT_TOOFEWCOMBS   "Too few combinations!\r\n"
  32. #define PROMPT_ERROR         "Keyboardfile erroneous, program exits!\r\n"
  33. #define PROMPT_ERRWRITE      "Error writing keyboard file\r\n"
  34. #define PROMPT_NOBAK         "Error creating backup of keyboard file. File will be overwritten!\r\n"
  35. #define PROMPT_NUMBERCHANGE  "Which number do you want to change (-1 for exit)? "
  36. #define PROMPT_OLDSTRING     "old string: %s\r\n"
  37. #define PROMPT_STRING        "Enter string: "
  38. #define PROMPT_OLDCOMB       "Old combination (decimal): "
  39. #define PROMPT_COMMAND       "\r\nCommand: %s\n"
  40. #define PROMPT_KEYS          "\r\nEnter new combination: (/ is terminator)\r\n"
  41. #define PROMPT_NEWCOMB       "Entered combination (decimal): "
  42. #define PROMPT_CONFLICT      "Ambiguous combination, conflicts with number %hd\r\nPrevious combination remains unchanged!\n\n\r"
  43. #define PROMPT_KEYABORT      "Please hit a key (a=abort)...\r\n"
  44. #define PROMPT_KEY           "Please hit a key...\r\n"
  45. #define PROMPT_MENU1         "1) Change key combinations\r\n"
  46. #define PROMPT_MENU2         "2) Change helptexts\r\n"
  47. #define PROMPT_MENU3         "3) Show command names\r\n"
  48. #define PROMPT_MENU4         "4) Exit (save keyboard file)\r\n"
  49. #define PROMPT_MENU5         "Enter your choice (1-4) : "
  50. #endif
  51.  
  52. typedef struct s3
  53. {
  54.   short int blen;
  55.   short int befehl[MAX_COMM_LEN];
  56.   char  *info_text;
  57. }comm_typ;
  58.  
  59. /* *** globale Daten *** */
  60. comm_typ  comm_feld [MAX_COMM_ANZ];  /* Feld der Tastenkombinationen */
  61. char      *it_feld[MAX_COMM_ANZ];    /* Pointertabelle fuer Hilfstrings */
  62. short int anz,                       /* Anzahl der Tastenkombinationen */
  63.       n_info;                    /* Anzahl der Info-Strings */
  64. char      *kom_names[MAX_COMM_ANZ] = /* Namen der Kommandos */
  65. #ifdef GERMAN
  66.       { "Refresh","Zum Zeilenanfang","Zum Zeilenende","Halbe Seite hoch",
  67.         "Halbe Seite runter","Zeichen unter Cursor loeschen",
  68.         "Zeichen links vom Cursor loeschen","Zum Fensteranfang",
  69.         "Zum Fensterende","Einfuege-/Ueberschreibmodus aendern",
  70.         "Zum Dateianfang","Zum Dateiende","Wort loeschen",
  71.         "Wort nach links","Wort nach rechts","Nach rechts","Nach links",
  72.         "Nach oben","Nach unten","Seite hoch","Seite runter",
  73.         "Naechste Zeile","Zeile loeschen",
  74.         "Datei in aktuelles Fenster laden",
  75.         "Aktuelles Fenster abspeichern",
  76.         "Verlassen ohne Sichern ohne Loadfile",
  77.         "Controlcode einfuegen","Anzeigen der Hilfstexte ein-/ausschalten",
  78.         "Fenster bewegen","Fentsergroesse aendern","Zum naechsten Fenster",
  79.         "Zum vorherigen Fenster","Fenster per Nummer anspringen",
  80.         "Fenster oeffnen","Fenster schliessen",
  81.         "Zeile per Nummer anspringen",
  82.         "Verlassen mit Abspeichern ohne Loadfile","Suchen","Ersetzen",
  83.         "Unterstreichung an/aus","Fensterinhalt eine Zeile hoch",
  84.         "Fensterinhalt eine Zeile runter",
  85.         "Aktuelle Zeile zur obersten Fensterzeile machen",
  86.         "Aktuelle Zeile zur mittleren Fensterzeile machen",
  87.         "Aktuelle Zeile zur untersten Fensterzeile machen",
  88.         "Bis zum Zeilenende loeschen","Fenstergroesse wechseln",
  89.         "Suchen/Ersetzen wiederholen","Kommando(s) wiederholen",
  90.         "Suchen/Ersetzen wiederholen","Zeilen verknuepfen",
  91.         "Zeile vor aktueller einfuegen","Autoindent an/aus","Tabulator",
  92.         "Tabulatorlaenge festlegen","Tabkomprimierungsmodus an/aus",
  93.         "Blockanfang setzen","Blockende normaler Block setzen",
  94.         "Blockende rechteckiger Block setzen","Blockmarkierung loeschen",
  95.         "Block loeschen","Block kopieren","Block verschieben",
  96.         "Block in Paste-Puffer kopieren","Paste-Puffer in Text kopieren",
  97.         "Block einruecken","Block aus Datei lesen",
  98.         "Block in Datei schreiben","Zum Blockende","Zum Blockanfang",
  99.         "Blockhervorhebung an/aus","Block an Filter uebergeben",
  100.         "Marker setzen","Marker anspringen","Zur letzten Position",
  101.         "Zeile hinter der aktuellen einfuegen",
  102.         "Fenster per Dateiname anspringen",
  103.         "Datei im aktuellen Fenster umbenennen","Tabulator rueckwaerts",
  104.         "Sicherungskopie an/aus","Macro definieren/ausfuehren",
  105.         "Geloeschte Zeile wiederherstellen","Shell-Modus an/aus",
  106.         "Verlassen mit Abspeichern mit Loadfile",
  107.         "Verlassen ohne Abspeichern mit Loadfile",
  108.         "Aktuelles Zeichen loeschen", "Reguläre Ausdrücke an/aus",
  109.         "Passende Klammer finden", "Cursor in Bildschirmmitte",
  110.         "Alle geänderten Dateien sichern", "Absatz formatieren",
  111.         "Automatischer Zeilenumbruch an/aus" };
  112. #else
  113.       { "refresh","to beginning of line","to end of line",
  114.         "half page up", "half page down","delete current character",
  115.         "delete character left to cursor","to top of window",
  116.         "to bottom of window","toggle insert/overwrite",
  117.         "to beginning of file","to end of file","delete word",
  118.         "word left","word right","one character right",
  119.         "one character left", "one line up","one line down","page up",
  120.         "page down", "new line", "delete line",
  121.         "load file in current window", "save current window",
  122.         "quit without save without loadfile", "insert control character",
  123.         "toggle helptext display", "move window","change windowsize",
  124.         "to next window", "to previous window",
  125.         "switch to window by number", "open window","close window",
  126.         "goto line by number", "quit with save without loadfile",
  127.         "find","replace", "toggle underline",
  128.         "move text one line up", "move text one line down",
  129.         "make current line top line", "make current line middle line",
  130.         "make current line lowest line", "delete to end of line",
  131.         "toggle windowsize", "repeat find/replace",
  132.         "repeat command sequence", "repeat find/replace",
  133.         "join lines", "insert line before current","toggle autoindent",
  134.         "tab", "set tablength","toggle tabcompression",
  135.         "mark beginning of block","mark end of normal block",
  136.         "mark end of rectangular block","unmark block",
  137.         "delete block","copy block","move block",
  138.         "cut block","paste block", "indent block","read block from file",
  139.         "write block to file","goto end of block" ,
  140.         "goto beginning of block", "toggle blockhighlighting",
  141.         "pass block to filter", "set marker","goto marker",
  142.         "goto last position", "insert line after current",
  143.         "switch to window by filename",
  144.         "rename file in current window","tab backwards",
  145.         "toggle creation of .bak-files","define/execute macro",
  146.         "undelete line","toggle shell-mode", 
  147.         "quit with save and loadfile", "quit without save with loadfile",
  148.         "delete current character", "regular expressions on/off",
  149.         "goto matching parenthesis", "cursor to middle of window",
  150.         "save all modified files", "reflow paragraph",
  151.         "toggle automatic linebreak mode" };
  152. #endif
  153.  
  154. #ifndef OWN_CURSES
  155. /******************************************************************************
  156. *
  157. * Funktion    : Fatale Fehlermeldung ausgeben (fatal)
  158. * -------------
  159. *
  160. * Parameter   : s           :
  161. *                 Typ          : char *
  162. *                 Wertebereich : Pointer auf ASCII-Zeichenkette
  163. *                 Bedeutung    : Auszugebende Fehlermeldung
  164. *
  165. * Bescheibung : Der bergene String s wird ausgegeben, das Programm mit dem
  166. *               Fehlercode 1 abgebrochen.
  167. *
  168. ******************************************************************************/
  169.  
  170. void fatal(s)
  171. char *s;
  172. {
  173. #ifdef GERMAN
  174.   printf("\r\nFATAL: %s\r\nProgramm wird abgebrochen\r\n",s);
  175. #else
  176.   printf("\r\nFATAL: %s\r\naborting program\r\n",s);
  177. #endif
  178.   exit(1);
  179. }
  180. #endif
  181.  
  182. /******************************************************************************
  183. *
  184. * Funktion     : Speicher reservieren (reserve_mem)
  185. * --------------
  186. *
  187. * Parameter    : n           :
  188. *                  Typ          : int
  189. *                  Wertebereich : 0-MAXINT
  190. *                  Bedeutung    : Laenge des zu reservierenden Bereichs
  191. *
  192. * Ergebnis     :
  193. *                  Typ          : char *
  194. *                  Wertebereich : != NULL
  195. *                  Bedeutung    : Zeiger auf reservierten Bereich
  196. *
  197. * Beschreibung : Ist noch genug Speicher frei, wird der gewuenschte Bereich
  198. *                angefordert und der Pointer auf den Bereich zurueckgegeben.
  199. *                Ansonsten wird die Curses-Fuktion fatal aufgerufen, die
  200. *                zum Abbruch des Programms fuehrt.
  201. *
  202. ******************************************************************************/
  203.  
  204. char *reserve_mem(n)
  205. {
  206.   char *p;
  207.  
  208.   if(p = malloc(n))
  209.     return(p);
  210.   else
  211. #ifdef GERMAN
  212.     fatal("Kein Speicherplatz mehr ");
  213. #else
  214.     fatal("Out of memory ");
  215. #endif
  216. }
  217.  
  218. /*****************************************************************************
  219. *
  220. *  Funktion       Hilfstexte-Array neu anordnen (rearrange_it)
  221. *  --------
  222. *
  223. *  Beschreibung : Durch die Bearbeitung des Tastenbelegungsfiles können
  224. *                 Hilfetexte überflüssig geworden sein. Dadurch würden
  225. *                 bei unverändertem Ablegen von it_feld in der Datei
  226. *                 beim nächsten Einlesen zu wenig Hilfstexte gelesen.
  227. *                 Es wird also zunächst für alle Hilfstexte geprüft,
  228. *                 ob sie noch von mindestens einem Kommando benötigt werden.
  229. *                 Ist dies der Fall, so werden sie als zu übernehmend
  230. *                 markiert.
  231. *                 Anschließend werden die als nicht zu übernehmend
  232. *                 markierten Hilfstexte aus dem Array gelöscht und die
  233. *                 weiter hinten stehenden werden entsprechend nach
  234. *                 vorne verschoben.
  235. *
  236. *****************************************************************************/
  237.  
  238. void rearrange_it ()
  239. {
  240.   int  i, /* Laufindex für Tastenkombinationen */
  241.        j, k; /* Laufindex für Hilfstexte */
  242.   char *take_it = reserve_mem (n_info); /* String zu übernehmen ? */
  243.  
  244.   /* initialisiere take_it und shift: */
  245.   for (j=0; j<n_info; j++)
  246.     take_it [j] = FALSE;
  247.   for (i=0; i<anz; i++)
  248.     for (j=0; j<n_info; j++)
  249.       if (comm_feld [i].info_text == it_feld [j])
  250.     if (take_it [j])
  251.       break;
  252.     else
  253.     {
  254.       take_it [j] = TRUE;
  255.       break;
  256.     }
  257.  
  258.   /* Jetzt das Feld zusammenschrumpfen */
  259.   j = 0;
  260.   while (j<n_info)
  261.   {
  262.     if (!take_it [j])           /* Hilfstext nicht übernehmen? */
  263.     {
  264.       n_info--;                 /* Eine Kombination weniger    */
  265.       for (k=j; k<n_info; k++)  /* Rest ranziehen              */
  266.       {
  267.     it_feld [k] = it_feld [k+1];
  268.     take_it [k] = take_it [k+1];
  269.       }
  270.     }
  271.     else
  272.       j++;
  273.   }
  274. }
  275.  
  276. /*****************************************************************************
  277. *
  278. *  Funktion       Tastenbelegung einlesen (lies_tasten)
  279. *  --------
  280. *
  281. *  Beschreibung : Aus der Datei tasten.inf wird die Tastaturbelegung ge-
  282. *                 laden. Dabei werden die Zeiger auf die Strings zunaechst
  283. *                 als Indices in die Tabelle geladen, die Anzahl der aus
  284. *                 der Datei zu ladenden Strings wird mitgezaehlt. Nachdem
  285. *                 alle Kombinationen eingelesen sind, wird die Stringtabelle
  286. *                 in das Array it_feld eingelesen.
  287. *
  288. *****************************************************************************/
  289.  
  290. void lies_tasten()
  291. {
  292.   FILE      *f;          /* Zeiger fuer Tastenbelegungsdatei */
  293.   short int i,           /* Schleifenzaehler */
  294.         j,           /* Schleifenzaehler */
  295.         index[MAX_COMM_ANZ];  /* Zwischenspeicher fuer Hilfstextnummern */
  296.   char      *hilf,       /* Hilfszeiger fuer Hilfstexte */
  297.         dummy [256]; /* String zum Einlesen der Hilfstexte */
  298.  
  299.   if (!(f = fopen ("tasten.inf","rb")))
  300.   {
  301.     anz = n_info = 0;
  302.     return;
  303.   }
  304.   if(fread(&anz,sizeof(short int),1,f) != 1) /* Anzahl der Befehle einlesen */
  305.   {
  306.     printf(PROMPT_NUMBERMISSING);
  307.     gets(0);
  308.     endwin();
  309.     exit(1);
  310.   }
  311.   anz++; /* In Datei steht letzter Index, also ist Anzahl 1 hoeher */
  312.   for (n_info=i=0;i<anz;i++) /* Alle Kombinationen einlesen */
  313.   {
  314.     /* Zuerst die Laenge des aktuellen Befehls einlesen */
  315.     if(fread (&comm_feld[i].blen,sizeof(short int),1,f) < 1)
  316.     {
  317.       printf(PROMPT_TOOFEWCOMBS);
  318.       gets(0);
  319.       endwin();
  320.       exit(1);
  321.     }
  322.     /* Jetzt Befehl selber einlesen */
  323.     fread (comm_feld[i].befehl,sizeof(short int),comm_feld[i].blen,f);
  324.     fread (&index[i],sizeof(short int),1,f); /* Index fuer Hilfstext */
  325.     comm_feld[i].info_text = NULL;
  326.     if(index[i] > -1)  /* Ueberhaupt Hilfstext fuer diesen Befehl ? */
  327.       for (n_info++,j=0;j<i;j++) /* Ja, dann checken, ob ein anderer */
  328.     if (index[j] == index[i]) /* Befehl schon diesen String hat. */
  329.     {
  330.       n_info--;     /* Nur einen weiteren String einlesen,  */
  331.       break;        /* falls neuer Index                    */
  332.     }
  333.   }
  334.   for (i=0;i<n_info;i++)  /* Hilfstexte einlesen */
  335.   {
  336.     if (!fgets (dummy,255,f))
  337.     {
  338.       printf(PROMPT_ERROR);
  339.       gets(0);
  340.       endwin();
  341.       exit(1);
  342.     }
  343.     dummy[strlen(dummy)-1] = '\0';              /* \n abschneiden */
  344.     it_feld[i] = hilf = strcpy(reserve_mem(strlen(dummy)+1),dummy);
  345.     for (j=0;j<=anz;j++)  /* Zeiger auf Hilfstext in comm_feld eintragen */
  346.       if (index[j] == i)
  347.     comm_feld[j].info_text = hilf;
  348.   }
  349.   fclose (f);
  350. }
  351.  
  352. /*****************************************************************************
  353. *
  354. *  Funktion       Tastenbelegung in Datei schreiben (schreib_tasten)
  355. *  --------
  356. *
  357. *  Beschreibung :
  358. *
  359. *****************************************************************************/
  360.  
  361. void schreib_tasten()
  362. {
  363.   FILE      *f;    /* Pointer fuer Ausgabedatei */
  364.   short int i,     /* Schleifenzaehler fuer Infotexte */
  365.         j,     /* Schleifenzaehler fuer Kommandos und String */
  366.         index; /* Stringindex des aktuellen Hilfstextes */
  367.  
  368.   unlink ("tasten.bak"); /* Fehlercode wird ignoriert */
  369.   if (rename ("tasten.inf", "tasten.bak"))
  370.     printf(PROMPT_NOBAK);
  371.   if (!(f = fopen ("tasten.inf","wb")))
  372.   {
  373.     printf(PROMPT_ERRWRITE);
  374.     exit(1);
  375.   }
  376.  
  377.   rearrange_it (); /* Es werden nicht mehr benötigte Info-Texte aus dem
  378.               Array gelöscht und das Array entsprechend
  379.               zusammengeschrumpft. Das ist nötig, damit nicht
  380.               beim Lesen der Datei zu wenig Texte eingelesen werden.*/
  381.   anz--; /* Es wird der letzte Index in die Datei geschrieben */
  382.   fwrite(&anz,sizeof(short int),1,f); /* Anzahl der Kombinationen schreiben */
  383.   anz++;
  384.   for(j=0;j<anz;j++) /* Alle Kombinationsstrings schreiben */
  385.   {
  386.     index = -1; /* Noch kein Info-String */
  387.     for(i=0;i<n_info;i++) /* Auf welchen String zeigt die Kombination ? */
  388.       if(it_feld[i] == comm_feld[j].info_text)
  389.       {
  390.     index = i; /* Stringindex merken */
  391.     break;
  392.       }
  393.     /* Zuerst die Laenge der Kombination, dann die Kombination selber */
  394.     /* und dann den Stringindex in die Datei schreiben */
  395.     fwrite(&comm_feld[j].blen,sizeof(short int),1,f);
  396.     fwrite(comm_feld[j].befehl,sizeof(short int),comm_feld[j].blen,f);
  397.     fwrite(&index,sizeof(short int),1,f);
  398.   }
  399.  
  400.   for(j=0;j<n_info;j++) /* Alle Infotexte schreiben */
  401.     fprintf(f,"%s\n",it_feld[j]);
  402.   fclose(f);
  403. }
  404.  
  405. /*****************************************************************************
  406. *
  407. *  Funktion       Infotexte aendern (change_strings)
  408. *  --------
  409. *
  410. *  Beschreibung : Der User gibt die Nummer des zu aendernden Strings ein.
  411. *                 Daraufhin bekommt er den alten String angezeigt. Er gibt
  412. *                 den neuen ein, der in it_feld an der Stelle des alten
  413. *                 eingetragen wird.
  414. *
  415. *****************************************************************************/
  416.  
  417. void change_strings()
  418. {
  419.   short int index,       /* Nummer des Strings */
  420.         j;           /* Zaehler zum Durchlaufen des Kommandoarrays */
  421.              /* und der Stringtabelle */
  422.   char      string[MAX_COMM_ANZ], /* Puffer fuer neuen String */
  423.         *old_text;   /* Zwischenspeicher fuer Adresse alter String */
  424.  
  425.   while(1)
  426.   {
  427.     for(j=0;j<n_info;j++) /* Hilfstexte anzeigen */
  428.       printw("%d.:  %s\r\n",j,it_feld[j]);
  429.     printw(PROMPT_NUMBERCHANGE); refresh();
  430.     scanw("%hd\n",&index);  /* Stringnummer einlesen */
  431.  
  432.     if(index >= n_info)   /* Keinen neuen String anlegen */
  433.       continue;
  434.     if(index == -1)       /* Abbruch bei -1 */
  435.       break;
  436.  
  437.     printw(PROMPT_OLDSTRING,it_feld[index]);
  438.     printw(PROMPT_STRING);refresh();
  439.     getstr(string);   /* Neuen String in Puffer einlesen */
  440.     free(old_text = it_feld[index]); /* Alten freigeben, Adresse merken */
  441.     /* Neuen String in dafuer allozierten Speicher kopieren und neue */
  442.     /* Adresse in it_feld eintragen */
  443.     it_feld[index] = strcpy(reserve_mem(strlen(string)+1),string);
  444.  
  445.     /* Zeigt der Stringzeiger eines anderen Kommandos auf den geaenderten */
  446.     /* String, dann wird auch dieser Zeiger auf den neuen String gesetzt. */
  447.     for(j=0;j<anz;j++)
  448.       if(comm_feld[j].info_text == old_text)
  449.     comm_feld[j].info_text = it_feld[index];
  450.   }
  451. }
  452.  
  453.  
  454. /*****************************************************************************
  455. *
  456. *  Funktion       Curses initialisieren (init)
  457. *  --------
  458. *
  459. *  Beschreibung : Curses wird aktiviert, das Terminal in den raw-mode
  460. *                 gesetzt, die Sondertasten und das Scrolling zugelassen.
  461. *
  462. *****************************************************************************/
  463.  
  464. void init()
  465. {
  466. #ifdef OS2
  467.   set_os2_raw (TRUE);       /* !!! muß erste Aktion sein !!! */
  468. #endif
  469.   initscr();
  470.   scrollok(stdscr,TRUE);
  471.   nonl();
  472. }
  473.  
  474. /*****************************************************************************
  475. *
  476. *  Funktion       Kommandostring aendern (change_kom)
  477. *  --------
  478. *
  479. *  Parameter    : index     :
  480. *                   Typ          : short int
  481. *                   Wertebereich : 0-anz
  482. *                   Bedeutung    : Nummer des zu aendernden Kommandos
  483. *
  484. *  Ergebnis     :
  485. *                   Typ          : int
  486. *                   Wertebereich : TRUE, FALSE
  487. *                   Bedeutung    : TRUE: Kombination war eindeutig
  488. *                                  FALSE: Kombination geriet in Konflikt
  489. *
  490. *  Beschreibung : Die alte Kombination wird angezeigt. Dann wird die neue
  491. *                 Kombination in das Feld temp eingelesen. Anschliessend
  492. *                 wird die neue Kombination auf ihre Eindeutigkeit getestet.
  493. *
  494. *****************************************************************************/
  495.  
  496. int change_kom(index)
  497. short int index;
  498. {
  499.   short int temp[MAX_COMM_LEN], /* Puffer zum Einlesen der Kombination */
  500.         i,                  /* Schleifenzaehler */
  501.         j,                  /* Schleifenzaehler fuer Tasten in temp */
  502.         k;                  /* Schleifenzaehler fuer Eindeutigkeitscheck */
  503.   char      string[MAX_COMM_ANZ]; /* Puffer fuer Eingabe Hilfstext */
  504.  
  505.   printw(PROMPT_OLDCOMB);
  506.   for(i=0;i<comm_feld[index].blen;i++)
  507.     printw("%d ",comm_feld[index].befehl[i]);
  508.  
  509.   printw(PROMPT_COMMAND, kom_names [index]);
  510.   printw(PROMPT_KEYS);
  511.   refresh();
  512.  
  513.   /* Befehl einlesen. Erreicht j den maximalen Index, so muss j noch   */
  514.   /* inkrementiert werden, da die nachfolgende Schleife davon ausgeht, */
  515.   /* dass j auch nach dem Lesen des / ionkrementiert wurde.            */
  516.   j=0;
  517.   noecho();
  518.   raw();
  519.   while((temp[j++] = getch()) != (short int) '/'
  520.      && (j < MAX_COMM_LEN || (j++,0)));
  521.   echo();
  522.   noraw();
  523.  
  524.   /* Eingegebene Kombination anzeigen: */
  525.   printw(PROMPT_NEWCOMB);
  526.   for(i=0;i<j-1;i++)
  527.     printw("%d ",temp[i]);
  528.   printw("\r\n");
  529.  
  530.   /* Befehl auf Eindeutigkeit checken */
  531.   for(j--,i=0;i<anz;i++)       /* j auf '/' setzen */
  532.     if(i != index) /* Bei aktueller Kombination nicht testen */
  533.     {
  534.       /* k auf das Ende des kuerzeren Kommandos setzen */
  535.       /* Solange wiederholen, bis k<0 oder Kommandos ungleich */
  536.       for(k=(comm_feld[i].blen > j ? j : comm_feld[i].blen)-1;
  537.       k >= 0 && comm_feld[i].befehl[k] == temp[k]; k--);
  538.       if(k == -1)   /* ein String Teil des anderen oder Strings identisch? */
  539.       {
  540.     printw(PROMPT_CONFLICT,i);
  541.     return(FALSE);
  542.       }
  543.     }
  544.   printw("\r\n");
  545.   /* Befehl eindeutig, dann Kombination im comm_feld uebernehmen */
  546.   memcpy(comm_feld[index].befehl,temp,j * sizeof(short int));
  547.  
  548.   if((comm_feld[index].blen = j) > 1) /* Bei Kommandos, die laenger */
  549.   { /* als ein Zeichen sind, wird nach einem Hilfstext gefragt.     */
  550.     for(j=0;j<n_info;j++) /* Hilfstexte anzeigen */
  551.       printw("%d.:  %s\r\n",j,it_feld[j]);
  552.     printw("\r\nString-Index (-1 fuer keinen String): ");refresh();
  553.     scanw("%hd",&j); /* Index fuer Hilfsstring zum Kommando einlesen */
  554.     if(j != -1) /* Wird Hilfsstring gewuenscht ? */
  555.     {
  556.       if(j >= n_info)  /* Neuer String ? */
  557.       {
  558.     printw(PROMPT_STRING); refresh(); /* Dann einlesen */
  559.     getstr(string);
  560.     it_feld[j = n_info++] = strcpy(reserve_mem(strlen(string)+1),string);
  561.       }
  562.       comm_feld[index].info_text = it_feld[j]; /* Stringzeiger eintragen */
  563.     }
  564.   }
  565.   else
  566.     comm_feld[index].info_text = NULL; /* Kein String, dann NULL eintragen */
  567.   return(TRUE);
  568. }
  569.  
  570. /******************************************************************************
  571. *
  572. * Funktion     : Eingabe neuer Tastenkombinationen steuern (hndl_koms)
  573. * --------------
  574. *
  575. * Beschreibung : Es wird nach der Nummer des zu aendernden Kommandos gefragt.
  576. *                Gibt der User eine Zahl ungleich -1 an, so wird die ent-
  577. *                sprechende Tastenkombination eingelesen. Ist die Nummer
  578. *                zu groa, wird sie auf die Nummer der ersten nicht belegten
  579. *                Kombination gesetzt.
  580. *                Gibt der User -1 ein, so wird die Funktion beendet.
  581. *
  582. ******************************************************************************/
  583.  
  584. void hndl_koms()
  585. {
  586.   short int index;
  587.  
  588.   do
  589.   {
  590.     printw(PROMPT_NUMBERCHANGE);
  591.     refresh();
  592.     scanw("%hd",&index);   /* Nummer der Kombination einlesen */
  593.     if(index == -1)        /* Bei -1 Schleife abbrechen       */
  594.       break;
  595.  
  596.     if(index >= anz)  /* Falls Nummer zu groa, eine Kombination mehr, */
  597.     {                 /* neue Kombination einlesen */
  598.       if(!change_kom(anz++)) /* Konflikt, dann anz wieder runter, da */
  599.     anz--;               /* keine neue Kombination entstand */
  600.     }
  601.     else
  602.       change_kom(index);
  603.   } while (1);
  604. }
  605.  
  606. /******************************************************************************
  607. *
  608. * Funktion     : Kommandonamen anzeigen (show_names)
  609. * --------------
  610. *
  611. * Beschreibung : Die Kommandonamen werden angezeigt. Ist der Bildschirm
  612. *                voll, wird ein Tastendruck erwartet.
  613. *
  614. ******************************************************************************/
  615.  
  616. void show_names()
  617. {
  618.   int i;
  619.  
  620.   for (i=0;i<anz;i++)
  621.   {
  622.     if(!((i+1)%20))  /* Bildschirm voll ? */
  623.     {
  624.       printw(PROMPT_KEYABORT);
  625.       refresh();
  626.       noecho();
  627.       raw();
  628.       if(getch() == 'a')
  629.       {
  630.     echo();
  631.     noraw();
  632.     break; /* Bei a for-Schleife abbrechen */
  633.       }
  634.       echo();
  635.       noraw();
  636.     }
  637.     printw("%3d : %s\r\n",i,kom_names[i]); /* Kommandonamen anzeigen */
  638.   }
  639.   refresh();
  640.   if((i+1)%20) /* Zum Abschluß nochmals auf Tastendruck warten */
  641.   {
  642.     printw(PROMPT_KEY);
  643.     refresh();
  644.     noecho();
  645.     raw();
  646.     getch();
  647.     noraw();
  648.     echo();
  649.   }
  650. }
  651.  
  652. /******************************************************************************
  653. *
  654. * Funktion     : Menue (menue)
  655. * --------------
  656. *
  657. * Ergebnis     :
  658. *                  Typ          : int
  659. *                  Wertebereich : 1-4
  660. *                  Bedeutung    : Gewaehlte Alternative
  661. *
  662. * Beschreibung : Die Alternativen werden angezeigt, der Nutzer mua eine
  663. *                auswaehlen. Die Nummer der ausgewaehlten Alternative wird
  664. *                als Integer zurueckgegeben.
  665. *
  666. ******************************************************************************/
  667.  
  668. int menue()
  669. {
  670.   char c;
  671.   
  672.   printw(PROMPT_MENU1);
  673.   printw(PROMPT_MENU2);
  674.   printw(PROMPT_MENU3);
  675.   printw(PROMPT_MENU4);
  676.   printw(PROMPT_MENU5);
  677.   refresh();
  678.   noecho();
  679.   raw();
  680.   while((c = getch()) < '1' && c > '4');
  681.   echo();
  682.   noraw();
  683.   printw("%c\r\n",c);
  684.   refresh();
  685.   return(c-'0');
  686. }
  687.  
  688. /*****************************************************************************
  689. *
  690. *  Funktion       Hauptprogramm (main)
  691. *  --------
  692. *
  693. *  Beschreibung : Curses wird initialisiert, die alte Tastaturbeledung aus
  694. *                 der Datei tasten.inf gelesen. Dann kann der User Tasten-
  695. *                 kombinationen aendern. Anschlieaend koennen die Hilfs-
  696. *                 texte geaendert werden. Ist das abgeschlossen, wird die
  697. *                 neue Tastaturbelegung in die Datei zurueckgeschrieben.
  698. *
  699. *****************************************************************************/
  700.  
  701. int main()
  702. {
  703.   int alt;
  704.  
  705.   init();
  706.   lies_tasten(); /* Bisherigen Tastenkombinationen einlesen */
  707.   do
  708.   {
  709.     switch(alt=menue()) /* Nutzereingabe lesen */
  710.     {
  711.       case 1:
  712.     hndl_koms();   /* Tastenkombinationen aendern */
  713.     break;
  714.       case 2:
  715.     change_strings(); /* Evtl. Stringinhalte aendern */
  716.     break;
  717.       case 3:
  718.     show_names(); /* Namen der Komandos anzeigen */
  719.     break;
  720.     }
  721.   } while (alt != 4); /* Solange, bis der User ENDE wuenscht */
  722.   endwin();
  723.   schreib_tasten(); /* Tastenbelegung wieder in Datei zurueckschreiben */
  724. }
  725.