00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #define _TEXTPRO_SOURCE_
00045
00046 #include "setup.h"
00047
00048 #include <stdio.h>
00049 #define _STDIO_INCLUDED_
00050 #include <ctype.h>
00051 #include <string.h>
00052
00053 #include "argacces.h"
00054 #include "commline.h"
00055 #include "envrnmnt.h"
00056 #include "extnfunc.h"
00057 #include "memalloc.h"
00058 #include "router.h"
00059 #include "sysdep.h"
00060
00061 #include "textpro.h"
00062
00063 #if TEXTPRO_FUNCTIONS || HELP_FUNCTIONS
00064
00065 #define NAMESIZE 80
00066 #define NULLCHAR '\0'
00067 #define BLANK (' ')
00068 #define TAB ('\t')
00069 #define LNFEED ('\n')
00070
00071
00072
00073
00074 #define NORMAL 0
00075 #define NO_FILE -10
00076 #define NEW_FILE -15
00077 #define OLD_FILE -20
00078
00079 #define NO_TOPIC -25
00080 #define EXIT -30
00081 #define BRANCH_UP -35
00082 #define BRANCH_DOWN -40
00083
00084
00085
00086
00087 #define MENU -45
00088 #define INFO -50
00089
00090
00091
00092
00093 struct entries
00094 {
00095 int level;
00096 int type;
00097 char name[NAMESIZE];
00098 long int offset;
00099 struct entries *child;
00100 struct entries *parent;
00101 struct entries *next;
00102 };
00103
00104
00105
00106
00107 struct lists
00108 {
00109 char file[NAMESIZE];
00110 struct entries *topics;
00111 struct entries *curr_menu;
00112 struct lists *next;
00113 };
00114
00115
00116
00117
00118 #define BDELIM "BEGIN-ENTRY-"
00119 #define BDLEN 12
00120 #define EDELIM "END-ENTRY"
00121 #define EDLEN 9
00122 #define BFORMAT "%d%1s%12s%s"
00123 #define LIT_DELIM ('$')
00124
00125
00126
00127
00128
00129
00130
00131
00132 #define OPEN_READ "r"
00133
00134 #define TEXTPRO_DATA 8
00135
00136 struct textProcessingData
00137 {
00138 struct lists *headings;
00139 struct entries *parent;
00140 #if HELP_FUNCTIONS
00141 int HELP_INIT;
00142 char *help_file;
00143 #endif
00144 };
00145
00146 #define TextProcessingData(theEnv) ((struct textProcessingData *) GetEnvironmentData(theEnv,TEXTPRO_DATA))
00147
00148 int TextLookupFetch(void *,char *);
00149 int TextLookupToss(void *,char *);
00150 static FILE *GetEntries(void *,char *,char **,char *,int *);
00151 static FILE *GetCurrentMenu(void *,char *,int *);
00152 static char *grab_string(void *,FILE *,char *,int);
00153
00154 static int findstr(char *,char *);
00155 static void upper(char *);
00156 static struct lists *NewFetchFile(void *,char *);
00157 static struct entries *AllocateEntryNode(void *,FILE *,char *,char *,int);
00158 static int AttachLeaf(void *,struct lists *,struct entries *,FILE *,char *,int);
00159 static long LookupEntry(void *,char *,char **,char *,int *);
00160 static void TossFunction(void *,struct entries *);
00161 static void DeallocateTextProcessingData(void *);
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 globle int TextLookupFetch(
00191 void *theEnv,
00192 char *file)
00193 {
00194 FILE *fp;
00195 char str[256];
00196 int INFO_BEGIN, INFO_END;
00197 struct lists *lnode;
00198 struct entries *enode;
00199 int line_ct;
00200 int entries_ct;
00201
00202 fp = GenOpen(theEnv,file,OPEN_READ);
00203
00204 if (fp == NULL)
00205 {
00206 PrintErrorID(theEnv,"TEXTPRO",1,FALSE);
00207 EnvPrintRouter(theEnv,WERROR,"Could not open file \"");
00208 EnvPrintRouter(theEnv,WERROR,file);
00209 EnvPrintRouter(theEnv,WERROR,"\".\n");
00210 return(-1);
00211 }
00212
00213 if ((lnode = NewFetchFile(theEnv,file)) == NULL)
00214 {
00215 GenClose(theEnv,fp);
00216
00217 PrintErrorID(theEnv,"TEXTPRO",2,FALSE);
00218 EnvPrintRouter(theEnv,WERROR,"File \"");
00219 EnvPrintRouter(theEnv,WERROR,file);
00220 EnvPrintRouter(theEnv,WERROR,"\" already loaded.\n");
00221 return(-1);
00222 }
00223
00224
00225
00226
00227 line_ct = 0;
00228 entries_ct = 0;
00229
00230 INFO_BEGIN = FALSE;
00231 INFO_END = TRUE;
00232 while (fgets(str,256,fp) != NULL)
00233 {
00234 line_ct++;
00235
00236
00237
00238
00239
00240 if ((str[0] != LIT_DELIM) || (str[1] != LIT_DELIM))
00241 {
00242 if (findstr(str,EDELIM) >= 0)
00243 {
00244 if (INFO_BEGIN == TRUE)
00245 {
00246 INFO_BEGIN = FALSE;
00247 INFO_END = TRUE;
00248 entries_ct++;
00249 }
00250 else
00251 {
00252 GenClose(theEnv,fp);
00253 TextLookupToss(theEnv,file);
00254 PrintErrorID(theEnv,"TEXTPRO",8,FALSE);
00255 EnvPrintRouter(theEnv,WERROR,"Line ");
00256 PrintLongInteger(theEnv,WERROR,line_ct);
00257 EnvPrintRouter(theEnv,WERROR," : Unmatched end marker.\n");
00258 return(-1);
00259 }
00260 }
00261 else if (findstr(str,BDELIM) >= 0)
00262 {
00263 if (INFO_END == TRUE)
00264 {
00265 INFO_END = FALSE;
00266 INFO_BEGIN = TRUE;
00267 }
00268 else
00269 {
00270 GenClose(theEnv,fp);
00271 TextLookupToss(theEnv,file);
00272
00273 PrintErrorID(theEnv,"TEXTPRO",4,FALSE);
00274 EnvPrintRouter(theEnv,WERROR,"Line ");
00275 PrintLongInteger(theEnv,WERROR,line_ct);
00276 EnvPrintRouter(theEnv,WERROR," : Previous entry not closed.\n");
00277
00278 return(-1);
00279 }
00280
00281 if ((enode=AllocateEntryNode(theEnv,fp,file,str,line_ct))==NULL)
00282 return(-1);
00283
00284
00285
00286
00287 if (AttachLeaf(theEnv,lnode,enode,fp,file,line_ct) == FALSE)
00288 return(-1);
00289 }
00290 }
00291 }
00292 GenClose(theEnv,fp);
00293 if (INFO_END == FALSE)
00294 {
00295 TextLookupToss(theEnv,file);
00296
00297 PrintErrorID(theEnv,"TEXTPRO",4,FALSE);
00298 EnvPrintRouter(theEnv,WERROR,"Line ");
00299 PrintLongInteger(theEnv,WERROR,line_ct);
00300 EnvPrintRouter(theEnv,WERROR," : Previous entry not closed.\n");
00301
00302 return(-1);
00303 }
00304 if (entries_ct == 0)
00305 TextLookupToss(theEnv,file);
00306 return(entries_ct);
00307 }
00308
00309
00310
00311
00312
00313
00314
00315
00316 globle int TextLookupToss(
00317 void *theEnv,
00318 char *file)
00319 {
00320 struct lists *plptr, *clptr;
00321 int l_flag;
00322
00323 clptr = TextProcessingData(theEnv)->headings;
00324 plptr = clptr;
00325 if (clptr != NULL)
00326 if (strcmp(clptr->file,file) != 0)
00327 l_flag = 1;
00328 else
00329 l_flag = 0;
00330 else
00331 l_flag = 0;
00332 while (l_flag > 0)
00333 {
00334 plptr = clptr;
00335 clptr = clptr->next;
00336 if (clptr != NULL)
00337 if (strcmp(clptr->file,file) != 0)
00338 l_flag = 1;
00339 else
00340 l_flag = 0;
00341 else
00342 l_flag = 0;
00343 }
00344 if (clptr == NULL)
00345 return(FALSE);
00346
00347 TossFunction(theEnv,clptr->topics);
00348
00349 if (plptr == clptr)
00350 TextProcessingData(theEnv)->headings = clptr->next;
00351 else
00352 plptr->next = clptr->next;
00353 rm(theEnv,(void *) clptr,(int) sizeof(struct lists));
00354 return(TRUE);
00355 }
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 static FILE *GetEntries(
00371 void *theEnv,
00372 char *file,
00373 char **menu,
00374 char *name,
00375 int *code)
00376 {
00377 FILE *fp;
00378 long int offset;
00379
00380 offset = LookupEntry(theEnv,file,menu,name,code);
00381 if (offset < 0)
00382 return(NULL);
00383 fp = GenOpen(theEnv,file,OPEN_READ);
00384 if (fp == NULL)
00385 {
00386 *code = NO_FILE;
00387 return(NULL);
00388 }
00389 if (fseek(fp,offset,0) < 0)
00390 {
00391 GenClose(theEnv,fp);
00392 *code = NO_FILE;
00393 return(NULL);
00394 }
00395 return(fp);
00396 }
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 static FILE *GetCurrentMenu(
00409 void *theEnv,
00410 char *file,
00411 int *status)
00412 {
00413 struct lists *lptr;
00414 FILE *fp;
00415 int l_flag;
00416
00417
00418
00419
00420 lptr = TextProcessingData(theEnv)->headings;
00421 if (lptr != NULL)
00422 if (strcmp(lptr->file,file) != 0)
00423 l_flag = 1;
00424 else
00425 l_flag = 0;
00426 else
00427 l_flag = 0;
00428 while (l_flag > 0)
00429 {
00430 lptr = lptr->next;
00431 if (lptr != NULL)
00432 if (strcmp(lptr->file,file) != 0)
00433 l_flag = 1;
00434 else
00435 l_flag = 0;
00436 else
00437 l_flag = 0;
00438 }
00439 if (lptr == NULL)
00440 {
00441 *status = NO_FILE;
00442 return(NULL);
00443 }
00444
00445
00446
00447
00448 if (lptr->curr_menu == NULL)
00449 {
00450 *status = NO_TOPIC;
00451 return(NULL);
00452 }
00453 if ((fp = GenOpen(theEnv,file,OPEN_READ)) == NULL)
00454 {
00455 *status = NO_FILE;
00456 return(NULL);
00457 }
00458 if (fseek(fp,lptr->curr_menu->offset,0) < 0)
00459 {
00460 GenClose(theEnv,fp);
00461 *status = NO_FILE;
00462 return(NULL);
00463 }
00464 *status = NORMAL;
00465 return(fp);
00466 }
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 static char *grab_string(
00485 void *theEnv,
00486 FILE *fp,
00487 char *buf,
00488 int bufsize)
00489 {
00490 if (fgets(buf,bufsize,fp) == NULL)
00491 {
00492 GenClose(theEnv,fp);
00493 return(NULL);
00494 }
00495 if ((buf[0] == LIT_DELIM) && (buf[1] == LIT_DELIM))
00496 {
00497 buf[0] = BLANK;
00498 buf[1] = BLANK;
00499 }
00500 else if (findstr(buf,EDELIM) >= 0)
00501 {
00502 buf = NULL;
00503 GenClose(theEnv,fp);
00504 }
00505 return(buf);
00506 }
00507
00508
00509
00510
00511
00512
00513
00514
00515 static int findstr(
00516 char *s,
00517 char *t)
00518 {
00519 int i,j,k;
00520
00521 for (i = 0; s[i] != '\0'; i++)
00522 {
00523 for (j = i, k = 0; t[k] != '\0' && s[j] == t[k]; j++, k++) ;
00524 if ((t[k] == '\0') && (k != 0))
00525 return(i);
00526 }
00527 return(-1);
00528 }
00529
00530
00531
00532
00533
00534
00535 static void upper(
00536 char *str)
00537 {
00538 int theIndex;
00539
00540 for (theIndex = 0 ; str[theIndex] != NULLCHAR; theIndex++)
00541 if (islower(str[theIndex])) str[theIndex] = (char) toupper(str[theIndex]);
00542 }
00543
00544
00545
00546
00547
00548
00549
00550
00551 static struct lists *NewFetchFile(
00552 void *theEnv,
00553 char *file)
00554 {
00555 struct lists *lptr = NULL, *lnode;
00556
00557 if (TextProcessingData(theEnv)->headings != NULL)
00558 {
00559 lptr = TextProcessingData(theEnv)->headings;
00560 while (lptr->next != NULL)
00561 {
00562 if (strcmp(lptr->file,file) == 0)
00563 return(NULL);
00564 lptr = lptr->next;
00565 }
00566 if (strcmp(lptr->file,file) == 0)
00567 return(NULL);
00568 }
00569 lnode = (struct lists *) gm2(theEnv,(int) sizeof(struct lists));
00570 genstrcpy(lnode->file,file);
00571 lnode->topics = NULL;
00572 lnode->curr_menu = NULL;
00573 lnode->next = NULL;
00574 if (TextProcessingData(theEnv)->headings == NULL)
00575 TextProcessingData(theEnv)->headings = lnode;
00576 else
00577 lptr->next = lnode;
00578 return(lnode);
00579 }
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598 static struct entries *AllocateEntryNode(
00599 void *theEnv,
00600 FILE *fp,
00601 char *file,
00602 char *str,
00603 int line_ct)
00604 {
00605 struct entries *enode;
00606 char bmarker[BDLEN+1],
00607 t_code[2];
00608
00609
00610
00611
00612
00613
00614 enode = (struct entries *) gm2(theEnv,(int) sizeof(struct entries));
00615 if (sscanf(str,BFORMAT,
00616 &enode->level,t_code,bmarker,enode->name) != 4)
00617 {
00618 rm(theEnv,(void *) enode,(int) sizeof(struct entries));
00619 GenClose(theEnv,fp);
00620 TextLookupToss(theEnv,file);
00621
00622 PrintErrorID(theEnv,"TEXTPRO",5,FALSE);
00623 EnvPrintRouter(theEnv,WERROR,"Line ");
00624 PrintLongInteger(theEnv,WERROR,line_ct);
00625 EnvPrintRouter(theEnv,WERROR," : Invalid delimeter string.\n");
00626
00627 return(NULL);
00628 }
00629 if (t_code[0] == 'M')
00630 enode->type = MENU;
00631 else if (t_code[0] == 'I')
00632 enode->type = INFO;
00633 else
00634 {
00635 rm(theEnv,(void *) enode,(int) sizeof(struct entries));
00636 GenClose(theEnv,fp);
00637 TextLookupToss(theEnv,file);
00638
00639 PrintErrorID(theEnv,"TEXTPRO",6,FALSE);
00640 EnvPrintRouter(theEnv,WERROR,"Line ");
00641 PrintLongInteger(theEnv,WERROR,line_ct);
00642 EnvPrintRouter(theEnv,WERROR," : Invalid entry type.\n");
00643
00644 return(NULL);
00645 }
00646 if (strcmp(bmarker,BDELIM) != 0)
00647 {
00648 rm(theEnv,(void *) enode,(int) sizeof(struct entries));
00649 GenClose(theEnv,fp);
00650 TextLookupToss(theEnv,file);
00651
00652 PrintErrorID(theEnv,"TEXTPRO",5,FALSE);
00653 EnvPrintRouter(theEnv,WERROR,"Line ");
00654 PrintLongInteger(theEnv,WERROR,line_ct);
00655 EnvPrintRouter(theEnv,WERROR," : Invalid delimeter string.\n");
00656
00657 return(NULL);
00658 }
00659
00660
00661
00662
00663
00664
00665 ungetc(getc(fp),fp);
00666 enode->offset = ftell(fp);
00667
00668 enode->parent = NULL;
00669 enode->child = NULL;
00670 enode->next = NULL;
00671 upper(enode->name);
00672
00673 return(enode);
00674 }
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692 static int AttachLeaf(
00693 void *theEnv,
00694 struct lists *lnode,
00695 struct entries *enode,
00696 FILE *fp,
00697 char *file,
00698 int line_ct)
00699 {
00700 int p_flag;
00701
00702
00703
00704
00705
00706 if (lnode->topics == NULL)
00707 lnode->topics = enode;
00708
00709
00710
00711
00712 else if (enode->level > TextProcessingData(theEnv)->parent->level)
00713 if (TextProcessingData(theEnv)->parent->type == MENU)
00714 {
00715 enode->parent = TextProcessingData(theEnv)->parent;
00716 TextProcessingData(theEnv)->parent->child = enode;
00717 }
00718 else
00719 {
00720 rm(theEnv,(void *) enode,(int) sizeof(struct entries));
00721 GenClose(theEnv,fp);
00722 TextLookupToss(theEnv,file);
00723
00724 PrintErrorID(theEnv,"TEXTPRO",7,FALSE);
00725 EnvPrintRouter(theEnv,WERROR,"Line ");
00726 PrintLongInteger(theEnv,WERROR,line_ct);
00727 EnvPrintRouter(theEnv,WERROR," : Non-menu entries cannot have subtopics.\n");
00728
00729 return(FALSE);
00730 }
00731
00732
00733
00734 else if (enode->level == TextProcessingData(theEnv)->parent->level)
00735 {
00736 enode->parent = TextProcessingData(theEnv)->parent->parent;
00737 enode->next = TextProcessingData(theEnv)->parent->next;
00738 TextProcessingData(theEnv)->parent->next = enode;
00739 }
00740
00741
00742
00743
00744 else
00745 {
00746 if (TextProcessingData(theEnv)->parent != NULL)
00747 p_flag = 1;
00748 else
00749 p_flag = 0;
00750 while (p_flag > 0)
00751 {
00752 TextProcessingData(theEnv)->parent = TextProcessingData(theEnv)->parent->parent;
00753 if (TextProcessingData(theEnv)->parent != NULL)
00754 if (enode->level < TextProcessingData(theEnv)->parent->level)
00755 p_flag = 1;
00756 else
00757 p_flag = 0;
00758 else
00759 p_flag = 0;
00760 }
00761 if (TextProcessingData(theEnv)->parent != NULL)
00762
00763
00764
00765
00766 if (TextProcessingData(theEnv)->parent->level < enode->level)
00767 {
00768 enode->parent = TextProcessingData(theEnv)->parent;
00769 enode->next = TextProcessingData(theEnv)->parent->child;
00770 TextProcessingData(theEnv)->parent->child = enode;
00771 }
00772
00773
00774
00775
00776 else
00777 {
00778 enode->parent = TextProcessingData(theEnv)->parent->parent;
00779 enode->next = TextProcessingData(theEnv)->parent->next;
00780 TextProcessingData(theEnv)->parent->next = enode;
00781 }
00782
00783
00784
00785
00786 else
00787 {
00788 enode->parent = NULL;
00789 enode->next = lnode->topics;
00790 lnode->topics = enode;
00791 }
00792 }
00793 TextProcessingData(theEnv)->parent = enode;
00794 return(TRUE);
00795 }
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816 static long int LookupEntry(
00817 void *theEnv,
00818 char *file,
00819 char **menu,
00820 char *name,
00821 int *code)
00822 {
00823 struct lists *lptr;
00824 struct entries *eptr;
00825 int l_flag, e_flag;
00826
00827
00828
00829
00830 lptr = TextProcessingData(theEnv)->headings;
00831 if (lptr != NULL)
00832 if (strcmp(lptr->file,file) != 0)
00833 l_flag = 1;
00834 else
00835 l_flag = 0;
00836 else
00837 l_flag = 0;
00838 while (l_flag > 0)
00839 {
00840 lptr = lptr->next;
00841 if (lptr != NULL)
00842 if (strcmp(lptr->file,file) != 0)
00843 l_flag = 1;
00844 else
00845 l_flag = 0;
00846 else
00847 l_flag = 0;
00848 }
00849 if (lptr == NULL)
00850 {
00851 *code = NO_FILE;
00852 return(-1);
00853 }
00854
00855
00856
00857
00858
00859 if (name == NULL)
00860 {
00861 if (lptr->curr_menu == NULL)
00862 {
00863 *code = EXIT;
00864 return(-1);
00865 }
00866 else
00867 {
00868 if (lptr->curr_menu->parent == NULL)
00869 {
00870 *code = EXIT;
00871 lptr->curr_menu = NULL;
00872 *menu = NULL;
00873 return(-1);
00874 }
00875 lptr->curr_menu = lptr->curr_menu->parent;
00876 *code = BRANCH_UP;
00877 *menu = lptr->curr_menu->name;
00878 return(lptr->curr_menu->offset);
00879 }
00880 }
00881
00882
00883
00884
00885 upper(name);
00886 if (lptr->curr_menu != NULL)
00887 eptr = lptr->curr_menu->child;
00888 else
00889 eptr = lptr->topics;
00890 if (eptr != NULL)
00891 if (findstr(eptr->name,name) == 0)
00892 e_flag = 0;
00893 else
00894 e_flag = 1;
00895 else
00896 e_flag = 0;
00897 while (e_flag > 0)
00898 {
00899 eptr = eptr->next;
00900 if (eptr != NULL)
00901 if (findstr(eptr->name,name) == 0)
00902 e_flag = 0;
00903 else
00904 e_flag = 1;
00905 else
00906 e_flag = 0;
00907 }
00908
00909
00910
00911
00912 if (eptr == NULL)
00913 {
00914 *code = NO_TOPIC;
00915 if (lptr->curr_menu != NULL)
00916 {
00917 *menu = lptr->curr_menu->name;
00918 return(lptr->curr_menu->offset);
00919 }
00920 return(-1);
00921 }
00922
00923
00924
00925
00926 if (eptr->type == MENU)
00927 {
00928 *code = BRANCH_DOWN;
00929 lptr->curr_menu = eptr;
00930 }
00931 else
00932 *code = NORMAL;
00933
00934 if (lptr->curr_menu != NULL)
00935 *menu = lptr->curr_menu->name;
00936 return(eptr->offset);
00937 }
00938
00939
00940
00941
00942
00943
00944 static void TossFunction(
00945 void *theEnv,
00946 struct entries *eptr)
00947 {
00948 struct entries *prev;
00949
00950 while (eptr != NULL)
00951 {
00952 if (eptr->child != NULL)
00953 TossFunction(theEnv,eptr->child);
00954 prev = eptr;
00955 eptr = eptr->next;
00956 rm(theEnv,(void *) prev,(int) sizeof(struct entries));
00957 }
00958 }
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978 #define SCREEN_LN 22
00979
00980
00981
00982
00983
00984 struct topics
00985 {
00986 char name[NAMESIZE];
00987 struct topics *end_list;
00988 struct topics *next;
00989 };
00990
00991
00992
00993
00994
00995
00996
00997 #if HELP_FUNCTIONS
00998 static int RecognizeHelpRouters(void *,char *);
00999 static int HelpPrint(void *,char *,char *);
01000 static int HelpGetc(void *,char *);
01001 static int HelpUngetc(void *,int,char *);
01002 static struct topics *AskForNewHelpTopic(void *,struct topics *,char **);
01003 #endif
01004
01005 static struct topics *GetCommandLineTopics(void *);
01006 static FILE *FindTopicInEntries(void *,char *,struct topics *,char **,int *);
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029 #if HELP_FUNCTIONS
01030
01031 globle void HelpFunction(
01032 void *theEnv)
01033 {
01034 int status;
01035 FILE *fp;
01036 struct topics *main_topic,
01037 *tptr;
01038 char buf[256],
01039 *menu[1];
01040 #if ! WINDOW_INTERFACE
01041 char termbuf[2];
01042 int line_cnt;
01043 #endif
01044
01045 if (TextProcessingData(theEnv)->HELP_INIT == FALSE)
01046 {
01047 if (TextProcessingData(theEnv)->help_file == NULL)
01048 {
01049 TextProcessingData(theEnv)->help_file = (char *) gm2(theEnv,strlen(HELP_DEFAULT) + 1);
01050 genstrcpy(TextProcessingData(theEnv)->help_file,HELP_DEFAULT);
01051 }
01052 EnvPrintRouter(theEnv,WDIALOG,"Loading help file entries from ");
01053 EnvPrintRouter(theEnv,WDIALOG,TextProcessingData(theEnv)->help_file);
01054 EnvPrintRouter(theEnv,WDIALOG,".\nPlease wait...\n");
01055 status = TextLookupFetch(theEnv,TextProcessingData(theEnv)->help_file);
01056 if (status <= 0)
01057 {
01058 return;
01059 }
01060 else
01061 {
01062
01063
01064
01065 EnvAddRouter(theEnv,"whelp",10,RecognizeHelpRouters,HelpPrint,
01066 HelpGetc,HelpUngetc,NULL);
01067 TextProcessingData(theEnv)->HELP_INIT = TRUE;
01068 }
01069 }
01070
01071 EnvActivateRouter(theEnv,"whelp");
01072
01073
01074
01075
01076
01077
01078 main_topic = (struct topics *) gm2(theEnv,(int) sizeof(struct topics));
01079 genstrcpy(main_topic->name,"MAIN");
01080 main_topic->next = GetCommandLineTopics(theEnv);
01081 main_topic->end_list = NULL;
01082
01083 EnvPrintRouter(theEnv,"whelp","\n");
01084
01085
01086
01087
01088 do
01089 {
01090 fp = FindTopicInEntries(theEnv,TextProcessingData(theEnv)->help_file,main_topic,menu,&status);
01091 if (status == NO_FILE)
01092 {
01093 PrintErrorID(theEnv,"TEXTPRO",1,FALSE);
01094 EnvPrintRouter(theEnv,WERROR,"Unable to access help file.\n");
01095 break;
01096 }
01097 if (status == EXIT)
01098 break;
01099 if (status == NO_TOPIC)
01100 {
01101 if (fp == NULL)
01102 {
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112 EnvPrintRouter(theEnv,"whelp","Root entry \"MAIN\" not found in ");
01113 EnvPrintRouter(theEnv,"whelp",TextProcessingData(theEnv)->help_file);
01114 EnvPrintRouter(theEnv,"whelp",".\nSee external documentation.\n");
01115 break;
01116 }
01117 EnvPrintRouter(theEnv,"whelp","\nSorry, no information available.\n\n");
01118 }
01119 if (status != BRANCH_UP)
01120 {
01121 #if ! WINDOW_INTERFACE
01122 line_cnt = 0;
01123 #endif
01124
01125
01126
01127
01128
01129
01130
01131 while (grab_string(theEnv,fp,buf,256) != NULL)
01132 {
01133 #if ! WINDOW_INTERFACE
01134 if (line_cnt >= (SCREEN_LN + 1))
01135 {
01136 EnvPrintRouter(theEnv,"whelp","PRESS <RETURN> FOR MORE. ");
01137 EnvPrintRouter(theEnv,"whelp","PRESS <A>,<RETURN> TO ABORT.");
01138 RouterData(theEnv)->CommandBufferInputCount = 0;
01139 RouterData(theEnv)->AwaitingInput = TRUE;
01140 do
01141 {
01142 termbuf[0] = (char) EnvGetcRouter(theEnv,"whelp");
01143 if (termbuf[0] != LNFEED)
01144 {
01145 if (termbuf[0] == 'a')
01146 termbuf[0] = 'A';
01147 if (termbuf[0] != '\b')
01148 RouterData(theEnv)->CommandBufferInputCount++;
01149 else if (RouterData(theEnv)->CommandBufferInputCount != 0)
01150 RouterData(theEnv)->CommandBufferInputCount--;
01151 termbuf[1] = (char) EnvGetcRouter(theEnv,"whelp");
01152 }
01153 }
01154 while ((termbuf[0] != LNFEED) &&
01155 (termbuf[0] != 'A'));
01156 RouterData(theEnv)->CommandBufferInputCount = 0;
01157 RouterData(theEnv)->AwaitingInput = FALSE;
01158 line_cnt = 0;
01159 if (termbuf[0] == 'A')
01160 {
01161 GenClose(theEnv,fp);
01162 break;
01163 }
01164 }
01165 line_cnt++;
01166 #endif
01167 EnvPrintRouter(theEnv,"whelp",buf);
01168 }
01169 }
01170 else if (fp != NULL)
01171
01172
01173
01174
01175 GenClose(theEnv,fp);
01176
01177 main_topic = AskForNewHelpTopic(theEnv,main_topic,menu);
01178 if (EvaluationData(theEnv)->HaltExecution)
01179 {
01180 while (status != EXIT)
01181 if ((fp = GetEntries(theEnv,TextProcessingData(theEnv)->help_file,menu,NULL,&status)) != NULL)
01182 GenClose(theEnv,fp);
01183 }
01184 } while (status != EXIT);
01185 EnvDeactivateRouter(theEnv,"whelp");
01186
01187
01188
01189
01190 while (main_topic != NULL)
01191 {
01192 tptr = main_topic;
01193 main_topic = main_topic->next;
01194 rm(theEnv,(void *) tptr,(int) sizeof(struct topics));
01195 }
01196 }
01197
01198
01199
01200
01201
01202
01203
01204
01205 globle void HelpPathFunction(
01206 void *theEnv)
01207 {
01208 char *help_name;
01209 DATA_OBJECT arg_ptr;
01210
01211 if (EnvRtnArgCount(theEnv) == 0)
01212 {
01213 EnvPrintRouter(theEnv,WDIALOG,"The current help entries file is ");
01214 if (TextProcessingData(theEnv)->help_file != NULL)
01215 EnvPrintRouter(theEnv,WDIALOG,TextProcessingData(theEnv)->help_file);
01216 else
01217 EnvPrintRouter(theEnv,WDIALOG,HELP_DEFAULT);
01218 EnvPrintRouter(theEnv,WDIALOG,"\n");
01219 }
01220 else
01221 {
01222 if (TextProcessingData(theEnv)->help_file != NULL)
01223 {
01224 if (TextProcessingData(theEnv)->HELP_INIT == TRUE)
01225 {
01226 EnvPrintRouter(theEnv,WDIALOG,"Releasing help entries from file ");
01227 EnvPrintRouter(theEnv,WDIALOG,TextProcessingData(theEnv)->help_file);
01228 EnvPrintRouter(theEnv,WDIALOG,"...\n");
01229 TextLookupToss(theEnv,TextProcessingData(theEnv)->help_file);
01230 EnvDeleteRouter(theEnv,"whelp");
01231 TextProcessingData(theEnv)->HELP_INIT = FALSE;
01232 }
01233 rm(theEnv,(void *) TextProcessingData(theEnv)->help_file,strlen(TextProcessingData(theEnv)->help_file) + 1);
01234 }
01235 if (EnvArgTypeCheck(theEnv,"help-path",1,SYMBOL_OR_STRING,&arg_ptr) == FALSE) return;
01236 help_name = DOToString(arg_ptr);
01237 TextProcessingData(theEnv)->help_file = (char *) gm2(theEnv,strlen(help_name) + 1);
01238 genstrcpy(TextProcessingData(theEnv)->help_file,help_name);
01239 EnvPrintRouter(theEnv,WDIALOG,"Help entries file reset to ");
01240 EnvPrintRouter(theEnv,WDIALOG,help_name);
01241 EnvPrintRouter(theEnv,WDIALOG,"\n");
01242 }
01243 }
01244
01245 #endif
01246
01247 #if TEXTPRO_FUNCTIONS
01248
01249
01250
01251
01252
01253
01254
01255
01256 globle void FetchCommand(
01257 void *theEnv,
01258 DATA_OBJECT *result)
01259 {
01260 int load_ct;
01261 DATA_OBJECT arg_ptr;
01262
01263 result->type = SYMBOL;
01264 result->value = EnvFalseSymbol(theEnv);
01265 if (EnvArgTypeCheck(theEnv,"fetch",1,SYMBOL_OR_STRING,&arg_ptr) == FALSE)
01266 return;
01267 load_ct = TextLookupFetch(theEnv,DOToString(arg_ptr));
01268 if (load_ct <= 0)
01269 {
01270 if (load_ct == 0)
01271 {
01272 PrintErrorID(theEnv,"TEXTPRO",3,FALSE);
01273 EnvPrintRouter(theEnv,WERROR,"No entries found.\n");
01274 }
01275
01276 return;
01277 }
01278 result->type = INTEGER;
01279 result->value = (void *) EnvAddLong(theEnv,(long long) load_ct);
01280 }
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299 globle int PrintRegionCommand(
01300 void *theEnv)
01301 {
01302 struct topics *params,
01303 *tptr;
01304 char buf[256];
01305 FILE *fp;
01306 char *menu[1];
01307 int status,
01308 com_code;
01309
01310 params = GetCommandLineTopics(theEnv);
01311 fp = FindTopicInEntries(theEnv,params->next->name,params->next->next,menu,&status);
01312 if ((status != NO_FILE) && (status != NO_TOPIC) && (status != EXIT))
01313 {
01314 if (strcmp(params->name,"t") == 0)
01315 genstrcpy(params->name,"stdout");
01316 EnvPrintRouter(theEnv,params->name,"\n");
01317 while (grab_string(theEnv,fp,buf,256) != NULL)
01318 EnvPrintRouter(theEnv,params->name,buf);
01319 com_code = TRUE;
01320 }
01321 else
01322 {
01323
01324
01325
01326
01327
01328
01329 if (fp != NULL)
01330 GenClose(theEnv,fp);
01331 com_code = FALSE;
01332 }
01333
01334
01335
01336
01337 while (params != NULL)
01338 {
01339 tptr = params;
01340 params = params->next;
01341 rm(theEnv,(void *) tptr,(int) sizeof(struct topics));
01342 }
01343 return(com_code);
01344 }
01345
01346
01347
01348
01349 globle void *GetRegionCommand(
01350 void *theEnv)
01351 {
01352 struct topics *params,
01353 *tptr;
01354 char buf[256];
01355 FILE *fp;
01356 char *menu[1];
01357 int status;
01358 char *theString = NULL;
01359 void *theResult;
01360 size_t oldPos = 0;
01361 size_t oldMax = 0;
01362 size_t sLength;
01363
01364 params = GetCommandLineTopics(theEnv);
01365 fp = FindTopicInEntries(theEnv,params->name,params->next,menu,&status);
01366 if ((status != NO_FILE) && (status != NO_TOPIC) && (status != EXIT))
01367 {
01368 while (grab_string(theEnv,fp,buf,256) != NULL)
01369 theString = AppendToString(theEnv,buf,theString,&oldPos,&oldMax);
01370 }
01371 else
01372 {
01373
01374
01375
01376
01377
01378
01379 if (fp != NULL)
01380 GenClose(theEnv,fp);
01381 }
01382
01383
01384
01385
01386 while (params != NULL)
01387 {
01388 tptr = params;
01389 params = params->next;
01390 rm(theEnv,(void *) tptr,(int) sizeof(struct topics));
01391 }
01392
01393 if (theString == NULL)
01394 { theResult = EnvAddSymbol(theEnv,""); }
01395 else
01396 {
01397 sLength = strlen(theString);
01398 if ((sLength > 0) &&
01399 (((theString[sLength-1] == '\r') && (theString[sLength-2] == '\n'))
01400 ||
01401 ((theString[sLength-1] == '\n') && (theString[sLength-2] == '\r'))))
01402 { theString[sLength-2] = 0; }
01403 theResult = EnvAddSymbol(theEnv,theString);
01404 }
01405
01406 if (theString != NULL)
01407 { genfree(theEnv,theString,oldMax); }
01408
01409 return(theResult);
01410 }
01411
01412
01413
01414
01415
01416
01417
01418
01419 globle int TossCommand(
01420 void *theEnv)
01421 {
01422 char *file;
01423 DATA_OBJECT arg_ptr;
01424
01425 if (EnvArgTypeCheck(theEnv,"toss",1,SYMBOL_OR_STRING,&arg_ptr) == FALSE)
01426 return (FALSE);
01427 file = DOToString(arg_ptr);
01428
01429 #if HELP_FUNCTIONS
01430
01431 if (TextProcessingData(theEnv)->help_file != NULL)
01432 if ((strcmp(file,TextProcessingData(theEnv)->help_file) == 0) && (TextProcessingData(theEnv)->HELP_INIT == TRUE))
01433 {
01434 rm(theEnv,(void *) TextProcessingData(theEnv)->help_file,strlen(TextProcessingData(theEnv)->help_file) + 1);
01435 TextProcessingData(theEnv)->help_file = NULL;
01436 TextProcessingData(theEnv)->HELP_INIT = FALSE;
01437 EnvDeleteRouter(theEnv,"whelp");
01438 }
01439
01440 #endif
01441
01442 return(TextLookupToss(theEnv,file));
01443 }
01444
01445 #endif
01446
01447
01448
01449
01450
01451
01452 #if HELP_FUNCTIONS
01453
01454 #if WIN_BTC
01455 #pragma argsused
01456 #endif
01457 static int RecognizeHelpRouters(
01458 void *theEnv,
01459 char *log_name)
01460 {
01461 #if MAC_MCW || WIN_MCW || MAC_XCD
01462 #pragma unused(theEnv)
01463 #endif
01464
01465 if (strcmp(log_name,"whelp") == 0)
01466 return(TRUE);
01467 return(FALSE);
01468 }
01469
01470 #if WIN_BTC
01471 #pragma argsused
01472 #endif
01473 static int HelpPrint(
01474 void *theEnv,
01475 char *log_name,
01476 char *str)
01477 {
01478 #if MAC_MCW || WIN_MCW || MAC_XCD
01479 #pragma unused(log_name)
01480 #endif
01481
01482 EnvPrintRouter(theEnv,"stdout",str);
01483 return(1);
01484 }
01485
01486 #if WIN_BTC
01487 #pragma argsused
01488 #endif
01489 static int HelpGetc(
01490 void *theEnv,
01491 char *log_name)
01492 {
01493 #if MAC_MCW || WIN_MCW || MAC_XCD
01494 #pragma unused(log_name)
01495 #endif
01496
01497 return(EnvGetcRouter(theEnv,"stdin"));
01498 }
01499
01500 #if WIN_BTC
01501 #pragma argsused
01502 #endif
01503 static int HelpUngetc(
01504 void *theEnv,
01505 int ch,
01506 char *log_name)
01507 {
01508 #if MAC_MCW || WIN_MCW || MAC_XCD
01509 #pragma unused(log_name)
01510 #endif
01511
01512 return(EnvUngetcRouter(theEnv,ch,"stdin"));
01513 }
01514
01515 #endif
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531 static struct topics *GetCommandLineTopics(
01532 void *theEnv)
01533 {
01534 int topic_num,
01535 theIndex;
01536 struct topics *head,
01537 *tnode,
01538 *tptr;
01539 DATA_OBJECT val;
01540
01541 head = NULL;
01542 topic_num = EnvRtnArgCount(theEnv);
01543 for (theIndex = 1; theIndex <= topic_num; theIndex++)
01544 {
01545 tnode = (struct topics *) gm2(theEnv,(int) sizeof(struct topics));
01546 EnvRtnUnknown(theEnv,theIndex,&val);
01547 if ((GetType(val) == SYMBOL) || (GetType(val) == STRING))
01548 genstrncpy(tnode->name,DOToString(val),NAMESIZE-1);
01549 else if (GetType(val) == FLOAT)
01550 genstrncpy(tnode->name,FloatToString(theEnv,DOToDouble(val)),NAMESIZE-1);
01551 else if (GetType(val) == INTEGER)
01552 genstrncpy(tnode->name,LongIntegerToString(theEnv,DOToLong(val)),NAMESIZE-1);
01553 else
01554 genstrncpy(tnode->name,"***ERROR***",NAMESIZE-1);
01555 tnode->next = NULL;
01556 tnode->end_list = NULL;
01557 if (head == NULL)
01558 head = tnode;
01559 else
01560 {
01561 tptr = head;
01562 while (tptr->next != NULL)
01563 tptr = tptr->next;
01564 tptr->next = tnode;
01565 }
01566 }
01567 return(head);
01568 }
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581 #if HELP_FUNCTIONS
01582
01583 static struct topics *AskForNewHelpTopic(
01584 void *theEnv,
01585 struct topics *old_list,
01586 char **menu)
01587 {
01588 int theIndex, cnt;
01589 struct topics *tmain,
01590 *tnode,
01591 *tptr;
01592 char list[256],
01593 name[NAMESIZE];
01594
01595
01596
01597
01598 EnvPrintRouter(theEnv,"whelp",*menu);
01599 EnvPrintRouter(theEnv,"whelp"," Topic? ");
01600 RouterData(theEnv)->CommandBufferInputCount = 0;
01601 RouterData(theEnv)->AwaitingInput = TRUE;
01602 for ( theIndex = 0;
01603 ((list[theIndex] = (char) EnvGetcRouter(theEnv,"whelp")) != LNFEED) && (theIndex < 254);
01604 theIndex++ , RouterData(theEnv)->CommandBufferInputCount++)
01605 {
01606 if (EvaluationData(theEnv)->HaltExecution)
01607 break;
01608 if (list[theIndex] == TAB)
01609 list[theIndex] = BLANK;
01610 else if ((list[theIndex] == '\b') && (theIndex != 0))
01611 {
01612 theIndex -= 2;
01613 RouterData(theEnv)->CommandBufferInputCount -= 2;
01614 }
01615 }
01616 #if VAX_VMS
01617 EnvPrintRouter(theEnv,"whelp","\n");
01618 #endif
01619
01620 RouterData(theEnv)->CommandBufferInputCount = 0;
01621 RouterData(theEnv)->AwaitingInput = FALSE;
01622 if (EvaluationData(theEnv)->HaltExecution)
01623 {
01624 EnvPrintRouter(theEnv,"whelp","\n");
01625 old_list->end_list = old_list;
01626 return(old_list);
01627 }
01628 list[theIndex] = BLANK;
01629 list[theIndex+1] = NULLCHAR;
01630
01631
01632
01633
01634 tmain = old_list;
01635 theIndex = 0; cnt = 0;
01636 while (list[theIndex] != NULLCHAR)
01637 {
01638 if ((list[theIndex] != BLANK) && (cnt < NAMESIZE))
01639 name[cnt++] = list[theIndex++];
01640 else if (cnt > 0)
01641 {
01642 while ((list[theIndex] != BLANK) && (list[theIndex] != NULLCHAR))
01643 theIndex++;
01644 name[cnt] = NULLCHAR;
01645 cnt = 0;
01646
01647
01648
01649
01650 if (old_list != NULL)
01651 {
01652 genstrcpy(old_list->name,name);
01653 old_list = old_list->next;
01654 }
01655 else
01656 {
01657 tnode = (struct topics *) gm2(theEnv,(int) sizeof(struct topics));
01658 genstrcpy(tnode->name,name);
01659 tnode->next = NULL;
01660 tnode->end_list = NULL;
01661 if (tmain == NULL)
01662 tmain = tnode;
01663 else
01664 {
01665 tptr = tmain;
01666 while (tptr->next != NULL)
01667 tptr = tptr->next;
01668 tptr->next = tnode;
01669 }
01670 }
01671 }
01672 else
01673 theIndex++;
01674 }
01675
01676
01677
01678
01679 tmain->end_list = old_list;
01680 return(tmain);
01681 }
01682
01683
01684 #endif
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700 static FILE *FindTopicInEntries(
01701 void *theEnv,
01702 char *file,
01703 struct topics *main_topic,
01704 char **menu,
01705 int *status)
01706 {
01707 FILE *fp = NULL;
01708 struct topics *tptr,
01709 *end_list;
01710
01711 if (main_topic != NULL)
01712 end_list = main_topic->end_list;
01713 else
01714 end_list = NULL;
01715 tptr = main_topic;
01716 if (tptr != end_list)
01717 do
01718 {
01719 if (fp != NULL)
01720 GenClose(theEnv,fp);
01721
01722
01723
01724
01725 if (strcmp(tptr->name,"^") == 0)
01726 fp = GetEntries(theEnv,file,menu,NULL,status);
01727
01728
01729
01730
01731 else if ((strcmp(tptr->name,"?") == 0) && (tptr->next == end_list))
01732 fp = GetCurrentMenu(theEnv,file,status);
01733
01734
01735
01736
01737 else
01738 fp = GetEntries(theEnv,file,menu,tptr->name,status);
01739
01740 if ((*status == NO_FILE) || (*status == NO_TOPIC))
01741 break;
01742 tptr = tptr->next;
01743 } while (tptr != end_list);
01744 else
01745
01746
01747
01748 fp = GetEntries(theEnv,file,menu,NULL,status);
01749
01750 return(fp);
01751 }
01752
01753
01754
01755
01756 globle void HelpFunctionDefinitions(
01757 void *theEnv)
01758 {
01759 AllocateEnvironmentData(theEnv,TEXTPRO_DATA,sizeof(struct textProcessingData),DeallocateTextProcessingData);
01760 #if ! RUN_TIME
01761 #if HELP_FUNCTIONS
01762 EnvDefineFunction2(theEnv,"help",'v',PTIEF HelpFunction,"HelpFunction",NULL);
01763 EnvDefineFunction2(theEnv,"help-path",'v',PTIEF HelpPathFunction,"HelpPathFunction","*1k");
01764 #endif
01765
01766 #if TEXTPRO_FUNCTIONS
01767 EnvDefineFunction2(theEnv,"fetch",'u', PTIEF FetchCommand,"FetchCommand","11k");
01768 EnvDefineFunction2(theEnv,"toss",'b', PTIEF TossCommand,"TossCommand","11k");
01769 EnvDefineFunction2(theEnv,"print-region",'b', PTIEF PrintRegionCommand,"PrintRegionCommand","2**wk");
01770 EnvDefineFunction2(theEnv,"get-region",'s', PTIEF GetRegionCommand,"GetRegionCommand","1**k");
01771 #endif
01772 #endif
01773 }
01774
01775
01776
01777
01778
01779 static void DeallocateTextProcessingData(
01780 void *theEnv)
01781 {
01782 struct lists *nextptr, *clptr;
01783
01784 clptr = TextProcessingData(theEnv)->headings;
01785 while (clptr != NULL)
01786 {
01787 nextptr = clptr->next;
01788
01789 TossFunction(theEnv,clptr->topics);
01790 rm(theEnv,(void *) clptr,(int) sizeof(struct lists));
01791
01792 clptr = nextptr;
01793 }
01794
01795 #if HELP_FUNCTIONS
01796 if (TextProcessingData(theEnv)->help_file != NULL)
01797 {
01798 rm(theEnv,TextProcessingData(theEnv)->help_file,
01799 strlen(TextProcessingData(theEnv)->help_file) + 1);
01800 }
01801 #endif
01802 }
01803
01804
01805 #endif
01806