Sain valmiiksi uuden version käyttöliittymästä. Rutiini on aika pitkä, joten ajattelin käydä sen läpi vähän yksityiskohtaisemmin kuin edelliset koodinpätkät.
Kaikki oikeudet tietenkin pidätetään. Viimeinen versio ohjelmasta löytyy seuraavasta linkistä: moijari.com:5002
Linkissä on muuten tämä uusi versio, toivotaan, ettei se kaatuile… Linkissä on edellisen postin sisään lokkaantuminen. Anna käyttäjätunnukseksi testi ja salasanaksi testaus.
Edit: Lisätty save nappula jatkon tekstiin ja koodiin. Lisätty loppuun otsakkeen ja rivien tulostusrutiinit.
Rutiini käy läpi seuraavat vaiheet
- nappuloiden käsittely
- HTML otsakkeen tulostus (HTTP/1.0, Location, Server, Date jne.)
- terttu sanan valikon tulostus
- ylärivin nappuloiden tulostus
- vierasavainten käsittely (aiemmassa postissa)
- Save nappulan rutiini
- otsakeiden kenttien luku tertusta
- rivien kenttien tietojen luku tertusta
- Fetch nappulan käsittely ensimmäinen käsittely
- Prev ja Next nappuloiden endimmäinen käsittely
- Submit, Display, Change ja Save nappuloiden käsittely
- Fetch, Prev ja Next nappuloiden toinen yhteinen osa
- tulosta otsake
- tulosta rivit
- vapauta käytetyt muistialueet.
Koodissa on vähän enemmän kommentteja kun tavallisesti. Ohjelman viimeinen versio linkki toimii taas. Vierasavainten käsittelypostissa mainitut muutokset löytyy kappaleessa eivät ole vielä paikallaan.
void html_sovellus(char *sovellus)
{
int comp;
char temps[512];
unsigned char *criteria;
unsigned char *bonesheaderdata,*bonesheaderdatacriteria;
unsigned char *boneslinesdata,*boneslinesdatacriteria;
unsigned char *memberid[64];
unsigned char timebuf[128];
unsigned char *ucp;
time_t now;
struct set *setheaderfields, *sethf;
struct set *setlinesfields, *setlf;
struct set *setheaderdata, *sethd;
struct set *setscreendata, *setsd;
struct set *setlinesdata, *setld;
struct set *setprev,*setnext;
bonesheaderdatacriteria=NULL;
boneslinesdatacriteria=NULL;
setheaderfields=NULL, sethf=NULL;
setlinesfields=NULL, setlf=NULL;
setheaderdata=NULL, sethd=NULL;
setscreendata=NULL, setsd=NULL,
setlinesdata=NULL, setld=NULL;
setprev=NULL,setnext=NULL;
*func='\0';
; luetaan parametreistä func parametri
set_get_element("func",&comp,func,htmlparams);
if(*func=='\0') {
strcpy(func,"");
}
if(!strcmp(func,"Terttu"))
strcpy(func,"");
; Nappuloiden käsittely
if(!exists_session_var("mode"))
strcpy(mode,"Display");
else {
ucp=NULL;
get_session_var("mode",&ucp);
strcpy(mode,ucp);
}
; Func kentässä on ylärivin nappulan toiminnon nimi
; (Fetch, Prev, Next, Display, Change, Save jne.)
; Mode kentän mukaan otsakkeen ja rivien tulostuksessa
; tulostetaan vain katselu(Display) tai muuttelu(Change)
; kenttiä. Lisäksi mode vaikuttaa siihen tulostetaanko
; rivit lohkoon ylimääräisiä rivejä rivien lisäystä
; varten.
;
; Suomeksi:
;
; Fetch, Prev ja Next nappulat antavat katselunäytön,
; muuttaaksesi tietoja voit painaa Change nappulaa.
;
; Submit, Reset ja Save eivät vaikuta näyttömuotoon,
; eli jos olit ennen nappulaa muuttamassa, näyttö
; säilyy muutosmoodissa, jos olit display moodissa,
; näyttö säilyy muuttelumoodissa.
;
; Display ja change nappulat vaikuttavat vain
; näyttötilaan (katselu, muutos).
;
; Fetch, Prev ja Next nappulat lukevat tietoja
; tertusta. Ja muuttavat näyttötilaksi katselutilan
;
; Save nappula kutsuu skk_save rutiinia, joka lisää
; nappulan lokin loppuun(nyt). Muut rutiinin
; tehtävät on vielä auki
;
if(!strcmp(func,"Fetch")) {
strcpy(mode,"Display");
} else if(!strcmp(func,"Prev") ) {
strcpy(mode,"Display");
} else if(!strcmp(func,"Next") ) {
strcpy(mode,"Display");
} else if(!strcmp(func,"Submit")) {
/* ei vaikuta modeen */
} else if(!strcmp(func,"Reset")) {
} else if(!strcmp(func,"Display") ) {
strcpy(mode,"Display");
} else if(!strcmp(func,"Change")) {
strcpy(mode,"Change");
} else if(!strcmp(func,"Save")) {
/* Save ei vaikuta näyttöön */
}
if(mode==NULL) {
strcpy(mode,"Display");
set_session_var("mode",mode);
} else
set_session_var("mode",mode);
; Tulostetaan html otsake. Html otsakkeessa
; ensimmäisessä osassa on html:n rivien lukumäärä.
; Tämän takia ensimmäinen ja toinen osa tulostetaan
; erikseen (html1 ja html2 muuttujat). html_printf
; löytyy aiemmasta postista.
html=html1;
html[0]='\0';
html_printf("HTTP/1.0 200 OK\r\n");
html_printf("Location: \r\n");
html_printf("Server: %s\r\n",programname);
now = time(NULL);
strftime(timebuf, sizeof(timebuf), HTMLTIMEFORMAT, gmtime(&now));
html_printf("Date: %s\r\n",timebuf);
html=html2;
html[0]='\0';
html_printf("\n<!DOCTYPE html>\r\n");
html_printf("<html lang=\"fi\">");
html_printf("<head>");
html_printf("<meta charset=\"UTF-8\">");
html_printf("<title>Terttu</title>",clientname);
html_printf("<meta name=\"author\" content=\"Jari Kuivaniemi\">");
html_printf("<link href=\"terttu.css\" rel=\"stylesheet\" type=\"text/css\">");
#ifdef OLD1
html_printf("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=\"UTF-8\">");
#endif
html_printf("</head>");
html_printf("<body>");
html_printf("<form action=\"%s\" method=\"post\">",sovellus);
html_printf("<input type=\"hidden\" name=\"sessionid\" value=\"%s\">",sessionid);
html_printf("<nav>");
html_printf("<ul>");
html_printf("<li>Terttu");
html_printf("<ul>");
; Tulostaa terttu sanan valikon.
html_sovellus_menu();
html_printf("</ul></li>");
; Tulostaa ylärivin nappulat
html_print_buttons();
html_printf("</ul>");
html_printf("</nav>");
html_printf("<table border=\"0\">");
html_printf("<td>");
; Selvittää foreign key yhteydet ja täyttää kentät.
set_find_foreigns(sovellus,setscreen); /* JariK 20150920 */
; Save nappula suorittaa skk_save rutiinin. Lisäksi
; tarvitaan varmaankin tarkistuksia tiedoille (katso
; set_find_foreigns / tietovirrat.
;
; Aluksi Save nappi kirjoittaa tietueet lokiin, jossa
; sama tieto voi olla ajallisesti eri aikoina useampaan
; kertaan. skk_fetch:stä ilmeisesti tulee uusi versio,
; joka lukee lokia. Ilmeisesti viimeisin versio valitaan
; näytölle. Jatkossa poimintaehdosta (esim
; asiakasnumero=1000) voisi muodostaa tiiviste-
; merkkijonon, jonka nimiseen tiedostoon kaikki
; asiakasta tai muuta objektia koskevat tiedot
; laitetaan. Asiakasluettelo (kaikki tietueet,
; joissa on asiakasnumero kenttä) voisi olla
; saatavilla pelkästä 'asiakasnumero' tiivistettynä
; sanasta tehdystä tiedostosta.
;
if(!strcmp(func,"Save")) {
skk_save(setscreen);
}
; Haetaan otsakkeen kenttien nimet ja muodostetaan
; otsakkeen hakuun käytettävä lause (bonesheaderdata)
rowid=0;
sprintf(temps,"'sovellus'=\"%s\", 'chapter'=\"header\", 'memberid', 'memberlength'",sovellus); /* Added memberlength. JariK 20140209 */
skk_fetch2(&setheaderfields,temps,skk);
bonesheaderdata=NULL;
sethf=setheaderfields;
while(sethf!=NULL) {
set_get_element("memberid",&comp,memberid,sethf->data);
set_add_element(&bonesheaderdata,memberid); /* Collect fieldnames to fieldsh */
sethf=sethf->next;
}
; Haetaan rivikenttien nimet ja muodostetaan rividatan
; hakuun tarvittava lause.
sprintf(temps,"'sovellus'=\"%s\", 'chapter'=\"lines\", 'memberid', 'memberlength'",sovellus); /* JariK 20140127 */
skk_fetch3(&setlinesfields,temps,skk); /* Changed to version 2. JariK 20140214 to version 3. JariK 20140303 */
boneslinesdata=NULL;
setlf=setlinesfields; /* sovellus, chapter="header", memberid */
while(setlf!=NULL) {
set_get_element("memberid",&comp,memberid,setlf->data);
set_add_element(&boneslinesdata,memberid); /* Collect fieldnames to fieldsh */
setlf=setlf->next;
}
; Tämä on fetch nappulan ensimmäinen vaihe. Fetch
; nappula lukee näytön otsakkeen kenttien arvot.
;
; Arvoja käytetään fetch, prev ja next nappuloiden
; valikoimien otsaketietueiden valinnassa.
; Fetch tallettaa kenttien arvot istuntomuuttujan
; findmatch arvoksi.
;
; Lopuksi Fetchissä luetaan tuo otsakeketju ja
; palautetaan ketjun ensimmäinen otsikko sethd
; muuttujassa.
if(!strcmp(func,"Fetch")) { /* JariK 20140220 */
setscreendata=NULL;
/* skkuser contains fields filled by user (see parameter reading)
* fieldsh contains names of header fields.
*/
skk_fetch_sets(&setscreendata,bonesheaderdata,setscreen);
setsd=setscreendata;
criteria=NULL;
while(setsd!=NULL) {
set_copy_filled(&criteria,setsd->data);
setsd=setsd->next;
}
if(setscreendata!=NULL) /* Free also. JariK 20140221 */
set_free(setscreendata);
setscreendata=NULL;
bonesheaderdatacriteria=NULL;
set_copy_all(&bonesheaderdatacriteria,criteria);
set_copy_all(&bonesheaderdatacriteria,bonesheaderdata);
set_session_var("findmatch",bonesheaderdatacriteria);
if(criteria!=NULL)
free(criteria);
criteria=NULL;
setheaderdata=NULL;
skk_fetch_sets(&setheaderdata,bonesheaderdatacriteria,skk->first);
sethd=setheaderdata;
}
; Prev ja next nappulat lukevat näytöltä tämän hetkisen
; otsake tietueen kentät. Seuraavaksi hartaan Fetchin
; saamat valintakriteerit findmatch ympäristö-
; muuttujasta. Sitten luetaan valintakriteerien
; mukaiset tiedot tertusta. Seuraavaksi
if((!strcmp(func,"Prev") || /* JariK 20140223 */
!strcmp(func,"Next")) &&
exists_session_var("findmatch")) { /* JariK 20140223 */
skk_fetch_sets(&setscreendata,bonesheaderdata,setscreen); /* Ennen set_fetch. JariK 20150920 */
setsd=setscreendata;
criteria=NULL;
while(setsd!=NULL) {
set_copy_filled(&criteria,setsd->data);
setsd=setsd->next;
}
if(setsd!=NULL)
set_free(setsd);
setsd=NULL;
/* Luetaan fetchin tallettama kenttä, joka sisältää
* otsakkeen kentät fetchin painamisen ajalta.
* Esim selaa asiakkaan tilauksia jos asiakasnumero
* on täytetty.
*/
get_session_var("findmatch",&bonesheaderdatacriteria);
setheaderdata=NULL;
skk_fetch_sets(&setheaderdata,bonesheaderdatacriteria,skk->first);
setnext=setheaderdata; /* has next row. JariK 20140226 */
sethd=NULL; /* has new current row. JariK 20140226 */
setprev=NULL; /* has previous row. JariK 20140226 */
while(setnext!=NULL) {
; Kun arvot mätsäävät ruudulla prev tai next
; nappulan painamisen aikana olleisiin tietoihin,
; näytetään seuraavaksi joko tätä tietuetta edeltävä
; tai seuraava otsikko.
if(!set_match2(setnext->data,criteria)) {
if(!strcmp(func,"Prev")) {
if(setprev!=NULL) {
sethd=setprev;
} else {
sethd=setnext;
}
break;
} else if(!strcmp(func,"Next")) {
if(setnext->next!=NULL) {
sethd=setnext->next;
} else {
sethd=setnext;
}
break;
}
}
setprev=setnext;
setnext=setnext->next;
}
/* Ei mätsäävää tietuetta, otetaan eka (esim fetch, reset, next) 20150929 JariK */
if(sethd==NULL)
sethd=setheaderdata;
}
; Submit, Change, Display ja Save nappuloilla luetaan
; vain ruudulla olevat tiedot uudestaan
; tulostettavaksi.
if(!strcmp(func,"Submit") ||
!strcmp(func,"Change") ||
!strcmp(func,"Display") ||
!strcmp(func,"Save") ) {
setheaderdata=NULL;
skk_fetch_sets(&setheaderdata,bonesheaderdata,setscreen);
setlinesdata=NULL;
skk_fetch_sets(&setlinesdata,boneslinesdata,setscreen);
setld=setlinesdata;
}
if(!strcmp(func,"Fetch") ||
!strcmp(func,"Prev") ||
!strcmp(func,"Next")) {
boneslinesdatacriteria=NULL;
if(sethd!=NULL)
set_copy_all(&boneslinesdatacriteria,sethd->data);
set_copy_all(&boneslinesdatacriteria,boneslinesdata);
setlinesdata=NULL;
skk_fetch_sets(&setlinesdata,boneslinesdatacriteria,skk->first);
setld=setlinesdata;
}
sethf=setheaderfields; /* sovellus, chapter="header", memberid */
if(setheaderfields!=NULL)
html_print_header(sethd,setheaderfields,mode); /* Ennen sethd->data */
setlf=setlinesfields; /* sovellus, chapter="lines", memberid */
setld=setlinesdata;
html_print_lines(setld, setlinesfields,mode);
html_printf("</td>");
html_printf("</tr>");
html_printf("</table>");
set_debug_foreigns(sovellus,setscreen);
html_printf("</body>");
html_printf("</form>");
html_printf("</html>");
html_printf("\n\n");
; Vapautetaan käytössä olleet muistialueet
if(bonesheaderdata!=NULL)
free(bonesheaderdata);
bonesheaderdata=NULL;
if(bonesheaderdatacriteria!=NULL)
free(bonesheaderdatacriteria);
bonesheaderdatacriteria=NULL;
if(setheaderfields!=NULL)
set_free(setheaderfields);
setheaderfields=NULL;
if(setlinesfields!=NULL)
set_free(setlinesfields);
setlinesfields=NULL;
if(setheaderdata!=NULL)
set_free(setheaderdata);
setheaderdata=NULL;
if(setlinesdata!=NULL)
set_free(setlinesdata);
setlinesdata=NULL;
}
int html_print_header(struct set *set, struct set *setheaderfields,char *mode)
{
struct set *sethf;
html_printf("<div id=\"header\">");
html_printf("<table border=\"0\">");
sethf=setheaderfields;
; Tulostetaan kentän nimi arvopareja kaikille
; otsakkeen kentille.
while(sethf!=NULL) {
html_printf("<tr>");
html_printf("<td>");
html_print_fieldname(set,sethf->data,mode);
html_printf("</td><td>");
html_print_fieldvalue(set,sethf->data,mode);
html_printf("</td>");
sethf=sethf->next;
html_printf("</tr>");
}
html_printf("</table>");
html_printf("</div>");
}
int html_print_lines(struct set *setlinesdata, struct set *setlinesfields,char *mode)
{
int comp,lines;
char memberid[64],memberlength[10],value[128];
struct set *setlf;
struct set *setld;
html_printf("<div id=\"lines\">");
html_printf("<table border=\"0\">");
html_printf("<tr>");
; Tulostetaan kentän nimet taulukon yläriville.
setlf=setlinesfields;
while(setlf!=NULL) {
set_get_element("memberid",&comp,memberid,setlf->data);
html_printf("<td>");
html_printf("%s",memberid); /* Little bugfix JariK 31012014 */
html_printf("</td>");
setlf=setlf->next;
}
html_printf("</tr>");
rowid++;
lines=0;
; Selataan rividata läpi, ja kirjoitetaan yksi rivi
; joka tietueelle.
setld=setlinesdata;
while(setld!=NULL) {
html_printf("<tr>");
; Tulostetaan riville kaikki kentät.
setlf=setlinesfields;
while(setlf!=NULL) {
set_get_element("memberid",&comp,memberid,setlf->data); /* Get fieldname */
set_get_element("memberlength",&comp,memberlength,setlf->data);
set_get_element(memberid,&comp,value,setld->data); /* Get data */
html_printf("<td>");
html_printf("<input type=\"text\" value=\"%s\" name=\"%s%c%d\" size=\"%s\" id=\"programbuttonlines\"",
value,memberid,rowidchar,rowid,memberlength);
if(mode !=NULL && !strcmp(mode,"Display"))
html_printf(" readonly");
html_printf(">",
value,memberid,rowidchar,rowid,memberlength);
html_printf("</td>");
setlf=setlf->next;
}
html_printf("</tr>");
rowid++;
lines++;
setld=setld->next;
}
; Muuttelu tilassa tulostetaan tyhjiä rivejä, niin
; että kokonaisrivien määrä on 10 (esim 1 täytetty
; ja 9 tyhjää. Yli kymmenen rivin tapahtumissa oli
; ajatus että tulostetaan vain yksi ylimääräinen
; rivi. Kun se täytetään enter tuo uuden tyhjän rivin.
; sitä ei ole tässä.
if(mode!=NULL && !strcmp(mode,"Change")) {
while(lines<10) {
html_printf("<tr>");
setlf=setlinesfields;
while(setlf!=NULL) {
set_get_element("memberid",&comp,memberid,setlf->data); /* Get fieldname */
set_get_element("memberlength",&comp,memberlength,setlf->data);
html_printf("<td>");
html_printf("<input type=\"text\" value=\"\" name=\"%s%c%d\" size=\"%s\" id=\"programbuttonlines\">",
memberid,rowidchar,rowid,memberlength);
html_printf("</td>");
setlf=setlf->next;
}
html_printf("</tr>");
rowid++;
lines++;
}
}
}
int html_print_fieldname(struct set *set, char *sethf,char *mode)
{
int comp;
char memberid[64];
; Tulostetaan kentän nimi.
set_get_element("memberid",&comp,memberid,sethf);
html_printf("%s",memberid);
}
int html_print_fieldvalue(struct set *set, char *setf,char *mode)
{
int comp;
char memberid[64],memberlength[10],value[128];
set_get_element("memberid",&comp,memberid,setf);
set_get_element("memberlength",&comp,memberlength,setf);
; Tulostetaan kentän arvo. Tässä tehdään input lause
; syöttöluukkua varten. Lisäksi iffi näyttökentälle.
*value='\0';
if(set!=NULL && set->data!=NULL)
set_get_element(memberid,&comp,value,set->data); /* Added data to header. JariK 20140216 */
html_printf("<input type=\"text\" value=\"%s\" name=\"%s%c%d\" size=\"%s\" id=\"programbuttonheader\"",
value,memberid,rowidchar,rowid,memberlength);
if(mode !=NULL && !strcmp(mode,"Display"))
html_printf(" readonly");
html_printf("><br>");
}