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>"); }