/****************************************************************************/ /* ** H E L P . C ** ** Aliohjelmia avustusten tekemiseen. ** ** Aliohjelmat: ** alusta_help - alustaa help-systeemin valitulle ohjelmalle ** vapauta_help - lopettaa helpin käytön ** help - tulostaa valitun help-tekstin jos ** aihe hakasuluissa. Jollei ole, tulostetaan ** kutsuparametri sellaisenaan ** help_aihe - tulostaa valitun teksin. Jos teksti ** ei ole hakasuluissa, lisätään ne ** help_hakemisto - helpin selailutilaan valitun aiheen kohdalta ** tarvittaessa lisätään aiheeseen hakasulut ** ** Tekijä: Vesa Lappalainen 6.12.1993 ** Muutettu: 30.1.1994 ** Mitä muutettu: + tiedostoa etsitään ** 1) oletushakemisto ** 2) alkup. hakemisto. ** Muutettu: 14.1.1996 ** Mitä muutettu: + jos muualla käytetään muunnettua lue_jonoa, niin nyt ** help toimii tämän kanssa paremmin. ** + voi paremmin hakea vajaalla hakusanalla ** ** Muutettu: 28.12.2001/vl ** Mita muutettu: Lisatty vakion DOSOUT tutkiminen. Jos vakio maritelty ** muutetaan ANSI-merkit OEM-merkeiksi tulostuksessa. ** ** Käyttö ks. help.h ** */ #include #include #include "mjonot.h" #include "help.h" #define SISALLYS "[SISÄLLYS]" #define HELP_TARKENNIN ".hlp" #define AIHE_ALKU '[' #define AIHE_LOPPU ']' #define AIHE_ALKU_JONO "[" #define AIHE_LOPPU_JONO "]" #define HELP_KOMMENTTI ";" #define RIVEJA 23 static char *help_nimi = NULL; static char help_file[80]; /****************************************************************************/ /* Virheilmoitukset: */ static const char *NULL_NIMI = "Ohjelman nimi on NULL!"; static const char *EI_TIEDOSTOA = "Ei löydy help-tiedostoa!"; static const char *EI_ALUSTETTU = "Help-tiedostoa ei ole alustettu!"; static int riveja=0; /****************************************************************************/ void alusta_help_rivit(void) { riveja = 0; } /****************************************************************************/ static int lisaa_riveja(void) /* Lisätään rivejä ja palutetaan tieto siitä, joko raja ylittyi. */ { riveja++; return ( riveja >= RIVEJA ); } /****************************************************************************/ static int stop_oli_just(void) { return riveja == 0; } /****************************************************************************/ static void tyhjia_riveja(int n) { int i; for (i=0; i"); lue_jono(N_S(apu)); } tyhjia_riveja(tyhjia); apu[1]=0; if ( apu[0] == 0 ) return 0; return lopetus(apu); } /****************************************************************************/ static int help_printf_n(const char *p, int n) { char format[10]; if ( strncmp(p,HELP_KOMMENTTI,strlen(HELP_KOMMENTTI)) == 0 ) return 0; if ( strncmp(p,HELP_STOP_JONO,strlen(HELP_STOP_JONO)) == 0 ) return help_stop(0); if ( n == 0 ) return 0; sprintf(format,"%%%d.%ds",n,n); /* format = %10.10s */ printf(format,p); if ( p[n-1]=='\n' && lisaa_riveja() && help_stop(0) ) return 1; return 0; } /****************************************************************************/ static int help_printf(const char *teksti) /* Helpin tulostus. ** Palauttaa 1 jos pitää lopettaa. ** Tässä on laskuri helpin pysäyttämiseksi sopivin välein. ** Siksi kaikki rivinvaihdot erotellaan erikseen tulostettavaksi. ** Jos rivi alkaa "#" ei tätä tulosteta, vaan pysäytetään tulostus. ** Jos rivi alkaa ";" ei sitä tulosteta. ----------------------------------------------------------------------------*/ { const char *p=teksti; int lf; while ( ( lf = paikka(p,'\n') ) >= 0 ) { if ( help_printf_n(p,lf+1) ) return 1; p += lf+1; } return help_printf_n(p,strlen(p)); } /****************************************************************************/ /* Koska tulostus lukee tiedostosta rivejä liian pitkälle, täytyy */ /* viimeinen tulostumaton rivi olla etsimiselle jemmassa. Muutoin */ /* peräkkäisiä aiheita ei saada tulostettua */ static char rivi[90]=""; #ifdef DOSOUT # include "dout.h" #endif /****************************************************************************/ static int tulosta_f(FILE *f) /* Tulostetaan valmiiksi avattua help-tiedostoa nykykohdasta kunnes ** tulee seuraavan aiheen otsikko. ** Jos tulee #, pysäytetään tulostus ** Palautetaan 1 jos tulostus pitää lopettaa. ** ----------------------------------------------------------------------------*/ { while (1) { rivi[0] = 0; if ( f_lue_jono(f,N_S(rivi)) < OLETUS ) return 0; if ( rivi[0] == AIHE_ALKU ) return 0; /* Tämä etsi_seuraava_aihe käytettäväksi */ liita_jono(N_S(rivi),"\n"); #ifdef DOSOUT vaihdaOEMp(rivi); #endif if ( help_printf(rivi) ) return 1; } } /****************************************************************************/ static FILE *etsi_seuraava_aihe(FILE *f, const char *aihe) /* Etsitään avatusta tiedostosta seuraava aihetta vastaavan kohdan alku. ** Tutkitaan ensin tulosta_f jäljiltä jäänyt viimeinen rivi. ** Tähän pitäisi vaihtaa pikahakutaulukon käyttö. ----------------------------------------------------------------------------*/ { char iaihe[90],*p; if ( !f ) return NULL; kopioi_jono(N_S(iaihe),aihe); jono_isoksi(iaihe); while (1) { if ( rivi[0]==0 && f_lue_jono(f,N_S(rivi)) < OLETUS ) { fclose(f); return NULL; } if ( ( p = strstr(rivi,HELP_KOMMENTTI) ) != NULL ) *p=0; jono_isoksi(poista_tyhjat(rivi)); if ( wildmat(rivi,iaihe) == 0 ) return f; rivi[0] = 0; /* Jotta luetaan ihan oikeasti seuraava rivi. */ } } /****************************************************************************/ static FILE *etsi_1_aihe(const char *aihe) /* Etsitään aihetta vastaavan kohdan alku help-tiedostosta. ** Avataan tiedosto ja liikutaan oikeaan kohtaan. Kutsuvan ** aliohjelman velvollisuus on sitten sulkea tiedosto. ----------------------------------------------------------------------------*/ { FILE *f = fopen(help_nimi,"rt"); if ( !f ) return NULL; rivi[0] = 0; return etsi_seuraava_aihe(f,aihe); } /****************************************************************************/ int sulje(FILE *f, int paluu) { if ( f ) fclose(f); f = NULL; return paluu; } /****************************************************************************/ static int tulosta_aihe(const char *aihe, int viim, int tyhjia_aluksi) /* viim = Tuleeko pysähdys viimeisen aiheen jälkeen ** tyhjia_aluksi = montako tyhjää riviä tulostuksen aluksi. Jos != 0 ** niin nollataan samalla rivilaskuri. ** Palautetaan 0 = OK, 1 = pitää lopettaa, 2 = aihetta ei löydy. ----------------------------------------------------------------------------*/ { int paluu; FILE *f = etsi_1_aihe(aihe); if ( !f ) return 2; if ( tyhjia_aluksi ) tyhjia_riveja(tyhjia_aluksi); while ( f ) { paluu = tulosta_f(f); f = etsi_seuraava_aihe(f,aihe); if ( f && help_stop(3) ) return sulje(f,1); } sulje(f,0); if ( viim && help_stop(3) ) return 1; return paluu; } /****************************************************************************/ static int help_virhe(const char *virhe) { help_printf(virhe); help_printf("\n#"); return 1; } /****************************************************************************/ static const char *aiheeksi(const char *aihe,const char *sis, const char *loppu) /* Lisätään aiheeseen sis ennen hakasulkua ja loppu hakasulun jälkeen ** Esim. kissa t * => [kissat]* */ { static char Aihe[60]=AIHE_ALKU_JONO; const char *p = aihe; int viim; if ( p[0] == AIHE_ALKU ) p++; kopioi_jono(Aihe+1,sizeof(Aihe)-1,p); viim = strlen(Aihe)-1; if ( Aihe[viim] == AIHE_LOPPU ) Aihe[viim] = 0; liita_jono(N_S(Aihe),sis); liita_jono(N_S(Aihe),AIHE_LOPPU_JONO); liita_jono(N_S(Aihe),loppu); return Aihe; } /****************************************************************************/ int /* 0 = teksti löytyi ja tulostettiin */ help_hakemisto( /* muut = virhenumeroita */ const char *alku /* s Aihe, josta tulostus aloitetaan */ ) /* Funktiolla pyöritetään helpin sisällysluetteloon perustuvaa toimintaa ** Pyöritys aloitetaan joko valitusta aiheesta tai Sisällysluettelosta ** alku jonon ei ole pakko sisältää []-merkkejä, ne lisätään tarvittaessa ----------------------------------------------------------------------------*/ { static char s[60]; const char *sis; int paluu; if ( help_nimi == NULL ) return help_virhe(EI_ALUSTETTU); if ( ( paluu = tulosta_aihe(alku ? aiheeksi(alku,"","") : SISALLYS,0,3) ) == 1 ) return 1; while ( lue_jono_oletus( "Valitse aihe (voi olla myös *)",0,0,s,N_S(s)) >= OLETUS ) { if ( lopetus(s) ) return 1; if ( laske_merkit(s,"*?") > 0 ) sis = ""; else sis = "*"; if ( tulosta_aihe(aiheeksi(s,sis,""),0,3) == 1 ) return 1; } return paluu; } /****************************************************************************/ int /* 0 = teksti löytyi ja tulostettiin */ help_aihe( /* muut = virhenumeroita */ const char *aihe /* s Tulostettavan aiheen otsikko. */ ) /* ** Funktiolla tulostetaan aiheen mukainen help-teksti. Jos tekstiä ** ei löydy, palautetaan != 0 ** Jos aihe ei ala [ -merkillä lisätään merkit. ----------------------------------------------------------------------------*/ { if ( help_nimi == NULL ) return help_virhe(EI_ALUSTETTU); if ( aihe == NULL ) return help_hakemisto(NULL); return tulosta_aihe(aiheeksi(aihe,"","*"),0,0); } /****************************************************************************/ int /* 0 = teksti löytyi ja tulostettiin */ help( /* muut = virhenumeroita */ const char *aihe /* s Tulostettavan aiheen otsikko. */ ) /* ** Funktiolla tulostetaan aiheen mukainen help-teksti. Jos tekstiä ** ei löydy, palautetaan != 0 ** Jos aihe ei ala [ -merkillä, tulostetaan teksti sellaisenaan. ** Aihe voi sisätää myös jokereita * ja ?, jolloin tulostetaan maskiin ** täsmäävät aiheet. ** Jos aihe == "#", niin pysähdytään. ** Jos aihe == NULL pyöreitetään help-hakua. ----------------------------------------------------------------------------*/ { if ( help_nimi == NULL ) return help_virhe(EI_ALUSTETTU); if ( aihe == NULL ) return help_hakemisto(NULL); if ( aihe[0] != '[' ) { /* Jos ei aihe */ help_printf(aihe); return 0; } return tulosta_aihe(aihe,0,0); } /****************************************************************************/ void /* */ vapauta_help(void) /* helpin lopettamistoimet */ /* ** Funktiolla tehdään helpin lopettamiseksi tarvittavat toimenpiteet ** Funktioon pitäisi lisätä pikahauktaulukon vapautus ----------------------------------------------------------------------------*/ { help_nimi = NULL; } /****************************************************************************/ int /* 0 = alustus onnistui */ alusta_help( /* muut = virhe alustuksessa */ const char *ohjelma /* s Ohjelman nimi (tiedosto ohjelma.HLP) */ ) /* ** Funktiolla alustetaan avustussysteemi. ** Jos avustustiedostoa ei ole, ilmoitetaan tästä ja palutetaan virhe nro. ** Tiedostoa etsitään oletushakemistosta ja sitten ohjelman alkuperäisestä ** hakemistosta. ** Funktioon pitäisi vielä täydentää pikahakutaulukon luominen. ----------------------------------------------------------------------------*/ { FILE *f = NULL; char *p; int i; vapauta_help(); if ( ohjelma == NULL ) return help_virhe(NULL_NIMI); kopioi_jono(N_S(help_file),ohjelma); jono_pieneksi(help_file); if ( ( p = strstr(help_file,".exe") ) != NULL ) *p = 0; liita_jono(N_S(help_file),HELP_TARKENNIN); help_nimi = help_file; for (i=strlen(help_file)-1; i>=0; i--) /* Oletushakemistossa oleva nimi */ if ( strchr("\\/",help_file[i]) ) { i++; break; } if ( i > 0 ) { /* Nimestä saatiin hakemisto pois, yritetään tätä. */ f = fopen(help_file+i,"rt"); if ( f ) help_nimi = help_file+i; } if ( !f ) f = fopen(help_nimi,"rt"); if ( !f ) { vapauta_help(); return help_virhe(EI_TIEDOSTOA); } /* Tässä pitäsi täyttää pikahakutaulukko */ fclose(f); return 0; /* Help-löytyi ja alustettu! */ }