Diff for /capa/capa51/pProj/capaCgiUtils.c between versions 1.3 and 1.18

version 1.3, 1999/10/13 20:05:00 version 1.18, 2000/06/30 21:36:16
Line 1 Line 1
   /* Most of the web output generation routines.
      Copyright (C) 1992-2000 Michigan State University
   
      The CAPA system is free software; you can redistribute it and/or
      modify it under the terms of the GNU Library General Public License as
      published by the Free Software Foundation; either version 2 of the
      License, or (at your option) any later version.
   
      The CAPA system is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      Library General Public License for more details.
   
      You should have received a copy of the GNU Library General Public
      License along with the CAPA system; see the file COPYING.  If not,
      write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      Boston, MA 02111-1307, USA.  */
   
 /* ===================================================================== */  /* ===================================================================== */
 /*   copyrighted by Isaac Tsai, 1998, 1999, 2000    */  
 /* ===================================================================== */  /* ===================================================================== */
 #include <stdio.h>  #include <stdio.h>
 #include <ctype.h>  #include <ctype.h>
Line 229  void web_printheader(FILE *out) Line 246  void web_printheader(FILE *out)
     fprintf(out,"<HTML><HEAD>\n");      fprintf(out,"<HTML><HEAD>\n");
     fprintf(out,"<BODY BGCOLOR=\"#FFFFFF\" LINK=\"#0000EE\" VLINK=\"#EE1100\">\n");      fprintf(out,"<BODY BGCOLOR=\"#FFFFFF\" LINK=\"#0000EE\" VLINK=\"#EE1100\">\n");
   }    }
   
 #ifdef  CAPA_WEB  
   fprintf(out,"<!-- capasbin, CAPA Version %s, %s -->\n",  
   CAPA_VER,COMPILE_DATE);  
 #else  
   fprintf(out,"<!-- capahtml, CAPA Version %s, %s -->\n",  
   CAPA_VER,COMPILE_DATE);  
 #endif  
 }  }
   
 void web_printfooter(FILE *out)  void web_printfooter(FILE *out)
Line 404  void w_get_responses(int x,int q_idx,cha Line 413  void w_get_responses(int x,int q_idx,cha
       sscanf(g_entries[x].name,"INPUT%d",&q_idx);        sscanf(g_entries[x].name,"INPUT%d",&q_idx);
       if( q_idx > 0 && q_idx < MAX_PROBLEM_CNT ) {        if( q_idx > 0 && q_idx < MAX_PROBLEM_CNT ) {
  if ( ! is_all_ws(g_entries[x].val) ) {   if ( ! is_all_ws(g_entries[x].val) ) {
   leng = strlen(g_entries[x].val) + 1;  
   g_stu_ans_pp[q_idx] = (StudentAnswer_t *)capa_malloc(sizeof(StudentAnswer_t),1);    g_stu_ans_pp[q_idx] = (StudentAnswer_t *)capa_malloc(sizeof(StudentAnswer_t),1);
   (g_stu_ans_pp[q_idx])->a_idx  = 1;    (g_stu_ans_pp[q_idx])->a_idx  = 1;
   (g_stu_ans_pp[q_idx])->a_str  = strsave(g_entries[x].val);    (g_stu_ans_pp[q_idx])->a_str  = strsave(g_entries[x].val);
   if (leng > ANSWER_STRING_LENG)   
     (g_stu_ans_pp[q_idx])->a_str[ANSWER_STRING_LENG] = '\0';  
   (g_stu_ans_pp[q_idx])->a_next = NULL;    (g_stu_ans_pp[q_idx])->a_next = NULL;
   trim_response_ws((g_stu_ans_pp[q_idx])->a_str);    trim_response_ws((g_stu_ans_pp[q_idx])->a_str);
  }   }
Line 424  void w_get_responses(int x,int q_idx,cha Line 430  void w_get_responses(int x,int q_idx,cha
       if( q_idx > 0 && q_idx < MAX_PROBLEM_CNT ) {        if( q_idx > 0 && q_idx < MAX_PROBLEM_CNT ) {
  if ( ! is_all_ws(g_entries[x].val) ) {    if ( ! is_all_ws(g_entries[x].val) ) { 
   StudentAnswer_t *sa_p;    StudentAnswer_t *sa_p;
   leng = strlen(g_entries[x].val) + 1;  
   sa_p = (StudentAnswer_t *)capa_malloc(sizeof(StudentAnswer_t),1);    sa_p = (StudentAnswer_t *)capa_malloc(sizeof(StudentAnswer_t),1);
   sa_p->a_idx  = sub_idx;    sa_p->a_idx  = sub_idx;
   sa_p->a_str  = strsave(g_entries[x].val);    sa_p->a_str  = strsave(g_entries[x].val);
   if (leng > ANSWER_STRING_LENG) sa_p->a_str[ANSWER_STRING_LENG] = '\0';  
   sa_p->a_next = NULL;    sa_p->a_next = NULL;
     trim_response_ws(sa_p->a_str);
   if( g_stu_ans_pp[q_idx] == NULL ) {    if( g_stu_ans_pp[q_idx] == NULL ) {
     g_stu_ans_pp[q_idx] = sa_p;      g_stu_ans_pp[q_idx] = sa_p;
   } else {     } else { 
Line 451  void w_get_responses(int x,int q_idx,cha Line 456  void w_get_responses(int x,int q_idx,cha
     if( index(g_entries[x].name, ',' ) == NULL ) {  /* only one answer */      if( index(g_entries[x].name, ',' ) == NULL ) {  /* only one answer */
       sscanf(g_entries[x].name,"LAST%d",&q_idx);        sscanf(g_entries[x].name,"LAST%d",&q_idx);
       if( q_idx > 0 && q_idx < MAX_PROBLEM_CNT ) {        if( q_idx > 0 && q_idx < MAX_PROBLEM_CNT ) {
  leng = strlen(g_entries[x].val) + 1;  
  sa_p = (StudentAnswer_t *)capa_malloc(sizeof(StudentAnswer_t),1);   sa_p = (StudentAnswer_t *)capa_malloc(sizeof(StudentAnswer_t),1);
  sa_p->a_idx  = 1;   sa_p->a_idx  = 1;
  sa_p->a_str  = strsave(g_entries[x].val);   sa_p->a_str  = strsave(g_entries[x].val);
  if (leng > ANSWER_STRING_LENG) sa_p->a_str[ANSWER_STRING_LENG] = '\0';  
  sa_p->a_next = NULL;   sa_p->a_next = NULL;
  g_last_ans_pp[q_idx] = sa_p;   g_last_ans_pp[q_idx] = sa_p;
       }        }
     } else {      } else {
       sscanf(g_entries[x].name,"LAST%d,%d",&q_idx,&sub_idx);        sscanf(g_entries[x].name,"LAST%d,%d",&q_idx,&sub_idx);
       if( q_idx > 0 && q_idx < MAX_PROBLEM_CNT ) {        if( q_idx > 0 && q_idx < MAX_PROBLEM_CNT ) {
  leng = strlen(g_entries[x].val) + 1;  
  sa_p = (StudentAnswer_t *)capa_malloc(sizeof(StudentAnswer_t),1);   sa_p = (StudentAnswer_t *)capa_malloc(sizeof(StudentAnswer_t),1);
  sa_p->a_idx  = sub_idx;   sa_p->a_idx  = sub_idx;
  sa_p->a_str  = strsave(g_entries[x].val);   sa_p->a_str  = strsave(g_entries[x].val);
  if (leng > ANSWER_STRING_LENG) sa_p->a_str[ANSWER_STRING_LENG] = '\0';  
  sa_p->a_next = NULL;   sa_p->a_next = NULL;
  if( g_last_ans_pp[q_idx] == NULL) {   if( g_last_ans_pp[q_idx] == NULL) {
   g_last_ans_pp[q_idx] = sa_p;    g_last_ans_pp[q_idx] = sa_p;
Line 798  and have entered you student id correctl Line 799  and have entered you student id correctl
   return (error);    return (error);
 }  }
   
   void append_qtext_addbr(new_str) char *new_str;
   {
     int ii,jj,len;
     char *br_added;
     if (new_str==NULL) return;
     len=strlen(new_str);
     br_added=capa_malloc(len*5,sizeof(char));
     for (ii=0,jj=0;ii<len;ii++) {
       if (new_str[ii] == '\n') {
         br_added[jj]='<';jj++;br_added[jj]='b';jj++;br_added[jj]='r';jj++;
         br_added[jj]='>';jj++;br_added[jj]='\n';jj++;
       } else {
         br_added[jj]=new_str[ii];jj++;
       }
     }
     br_added[jj]='\0';
     append_qtext(br_added);
     capa_mfree(br_added);
   }
   void append_qtext_addbr2(new_str) char *new_str;
   {
     char *br="<br>\n";
     char single[2];
     int ii,len;
     single[0]='\0';single[1]='\0';
     if (new_str==NULL) return;
     len=strlen(new_str);
     for (ii=0;ii<len;ii++) {
       if (new_str[ii] == '\n') {
         append_qtext(br);
       } else {
         single[0]=new_str[ii];
         append_qtext(single);
       }
     }
   }
 /* ============================================================================= */  /* ============================================================================= */
 void        append_qtext(new_str) char *new_str;  void        append_qtext(new_str) char *new_str;
 {  {
Line 809  void        append_qtext(new_str) char * Line 846  void        append_qtext(new_str) char *
   len,g_qchar_cnt,g_qsize);    len,g_qchar_cnt,g_qsize);
   fflush(g_cgi);    fflush(g_cgi);
 #endif /* CGI_DBUG */      #endif /* CGI_DBUG */    
   if (g_qchar_cnt+len>g_qsize-1) {    if (g_qchar_cnt+len>g_qsize-3) {
     char *temp_text;      char *temp_text;
     g_qsize=(g_qchar_cnt+len)*2;      g_qsize=(g_qchar_cnt+len)*2;
     temp_text=capa_malloc(g_qsize,sizeof(char));      temp_text=capa_malloc(g_qsize,sizeof(char));
     strncpy(temp_text,g_question_txt,g_qchar_cnt);      strncpy(temp_text,g_question_txt,g_qchar_cnt);
       temp_text[g_qchar_cnt]='\0';
     capa_mfree(g_question_txt);      capa_mfree(g_question_txt);
     g_question_txt=temp_text;      g_question_txt=temp_text;
       /*
       g_qsize=(g_qchar_cnt+len)*2;
       g_question_txt=realloc(g_question_txt,g_qsize);
       */
   }    }
   for(ii=0;ii<len;ii++) {    for(ii=0;ii<len;ii++) {
     g_question_txt[g_qchar_cnt+ii]=new_str[ii];      g_question_txt[g_qchar_cnt+ii]=new_str[ii];
   }    }
   g_qchar_cnt += len;    g_qchar_cnt += len;
   g_question_txt[g_qchar_cnt+1]='\0';    g_question_txt[g_qchar_cnt]='\0';
 #ifdef CGI_DBUG  #ifdef CGI_DBUG
   fprintf(g_cgi,"after: len %d; g_qchar_cnt %d; g_qsize %d\n",len,g_qchar_cnt,g_qsize);    fprintf(g_cgi,"after: len %d; g_qchar_cnt %d; g_qsize %d; strlen(g_question_txt):%d\n",len,g_qchar_cnt,g_qsize,strlen(g_question_txt));
   fflush(g_cgi);    fflush(g_cgi);
 #endif /* CGI_DBUG */      #endif /* CGI_DBUG */    
 }  }
Line 837  void        append_stext(new_str) char * Line 879  void        append_stext(new_str) char *
   new_str,len,g_schar_cnt,g_ssize);    new_str,len,g_schar_cnt,g_ssize);
   fflush(g_cgi);    fflush(g_cgi);
 #endif /* CGI_DBUG */      #endif /* CGI_DBUG */    
   if (g_schar_cnt+len>g_ssize-1) {    if (g_schar_cnt+len>g_ssize-2) {
     char *temp_text;      char *temp_text;
     g_ssize=(g_schar_cnt+len)*2;      g_ssize=(g_schar_cnt+len)*2;
     temp_text=capa_malloc(g_ssize,sizeof(char));      temp_text=capa_malloc(g_ssize,sizeof(char));
Line 1043  print_mainmenu(class,sn,pin)char *class; Line 1085  print_mainmenu(class,sn,pin)char *class;
     fprintf(stdout,"<input type=\"submit\" value=\"Display Quiz summary\" ></form>\n");      fprintf(stdout,"<input type=\"submit\" value=\"Display Quiz summary\" ></form>\n");
   }    }
   outcome = check_termscore_option();    outcome = check_termscore_option();
   fprintf(stdout,"<!-- Outcome of check_termscore_option()=%d --!>\n",outcome);    fprintf(stdout,"<!-- Outcome of check_termscore_option()=%d -->\n",outcome);
   /*Termscore Button*/    /*Termscore Button*/
   if( outcome ) {    if( outcome ) {
     fprintf(stdout,"<li><form method=\"post\" ");      fprintf(stdout,"<li><form method=\"post\" ");
     sprintf(buf,"action=\"http://%s/%s/capahtml\">",serverName,g_cgibin_path);     sprintf(buf,"action=\"http://%s/%s/%s/capasbin\">",serverName,g_cgibin_path,g_cowner);
     fprintf(stdout,"%s\n", buf);      fprintf(stdout,"%s\n", buf);
     fprintf(stdout,"<input type=\"hidden\" name=\"CLASS\" value=\"%s\">\n",class);      fprintf(stdout,"<input type=\"hidden\" name=\"CLASS\" value=\"%s\">\n",class);
     fprintf(stdout,"<input type=\"hidden\" name=\"SNUM\" value=\"%s\">\n",sn);      fprintf(stdout,"<input type=\"hidden\" name=\"SNUM\" value=\"%s\">\n",sn);
Line 1071  print_page_header(mode,num_quest) int mo Line 1113  print_page_header(mode,num_quest) int mo
   char *serverName;    char *serverName;
   int    configResult,term_summary_button=1;    int    configResult,term_summary_button=1;
   
     buf[0]='\0';
     discussdir[0]='\0';
   serverName=getenv("SERVER_NAME");    serverName=getenv("SERVER_NAME");
   if (!serverName) {    if (!serverName) {
     fprintf(stdout,"Enviroment variable SERVER_NAME not set.\n");      fprintf(stdout,"Enviroment variable SERVER_NAME not set.\n");
Line 1309  char *class_dir; char *c_owner;char *cla Line 1353  char *class_dir; char *c_owner;char *cla
   char          cmp_ans[MAX_BUFFER_SIZE],date_str[DATE_BUFFER];    char          cmp_ans[MAX_BUFFER_SIZE],date_str[DATE_BUFFER];
   time_t        curtime;    time_t        curtime;
   char         *serverName;    char         *serverName;
     char         *c_ans;
   
   serverName=getenv("SERVER_NAME");    serverName=getenv("SERVER_NAME");
   if (!serverName) {    if (!serverName) {
Line 1385  char *class_dir; char *c_owner;char *cla Line 1430  char *class_dir; char *c_owner;char *cla
     }      }
   }    }
   
   if ((mode==CHECK_ANSWER_MODE) || (mode== TRY_SET_MODE))    if ((mode==CHECK_ANSWER_MODE) || (mode== TRY_SET_MODE) || (mode==VIEW_PREVIOUS_MODE))
     capa_set_login_time(g_student_number,set);      capa_set_login_time(g_student_number,set);
   
   capa_get_header(&header,set);    capa_get_header(&header,set);
Line 1414  char *class_dir; char *c_owner;char *cla Line 1459  char *class_dir; char *c_owner;char *cla
   
   if ( result != 0 ) {    if ( result != 0 ) {
      if( !g_passdue ) {       if( !g_passdue ) {
        append_qtext("<FORM method=\"post\" ");         append_qtext("<FORM NAME=\"CAPA\" method=\"post\" ");
        sprintf(buf,"action=\"http://%s/%s/%s/capasbin\">",serverName,         sprintf(buf,"action=\"http://%s/%s/%s/capasbin\">",serverName,
        g_cgibin_path,c_owner);         g_cgibin_path,c_owner);
        append_qtext(buf);         append_qtext(buf);
Line 1454  char *class_dir; char *c_owner;char *cla Line 1499  char *class_dir; char *c_owner;char *cla
      append_qtext("<A href=\"#TOP\">Top</A>");       append_qtext("<A href=\"#TOP\">Top</A>");
      sprintf(buf,"&nbsp;&nbsp;<A href=\"#P%d\">Next</A>",question_idx+2);  append_qtext(buf);       sprintf(buf,"&nbsp;&nbsp;<A href=\"#P%d\">Next</A>",question_idx+2);  append_qtext(buf);
      }*/       }*/
            q_leng = strlen(prob_idx->question);     if (prob_idx->question != NULL) {
    if ( !prob_idx->show_br ) {       q_leng = strlen(prob_idx->question);
      append_qtext(prob_idx->question);       if ( !prob_idx->show_br ) {
    } else {         append_qtext(prob_idx->question);
      for(idx=0;idx<q_leng;idx++) {       } else {
        if ( g_qchar_cnt+2 >= g_qsize ) {         append_qtext_addbr(prob_idx->question);
  char *temp_text;         /*
  g_qsize=g_qchar_cnt*2;         for(idx=0;idx<q_leng;idx++) {
  temp_text=capa_malloc(g_qsize,sizeof(char));   if ( g_qchar_cnt+2 > g_qsize-2 ) {
  strncpy(temp_text,g_question_txt,g_qsize);     char *temp_text;
  capa_mfree(g_question_txt);     g_qsize=(g_qchar_cnt+2)*2;
  g_question_txt=temp_text;       temp_text=capa_malloc(g_qsize,sizeof(char));
        }     strncpy(temp_text,g_question_txt,g_qsize);
        g_question_txt[g_qchar_cnt]=prob_idx->question[idx];     capa_mfree(g_question_txt);
        g_qchar_cnt++;     g_question_txt=temp_text;  
        if(prob_idx->question[idx] == '\n' ) {   }
  append_qtext("<br>\n");   g_question_txt[g_qchar_cnt]=prob_idx->question[idx];
    g_qchar_cnt++;
    if(prob_idx->question[idx] == '\n' ) {
      append_qtext("<br>\n");
    }
        }         }
          */
      }       }
    }     }
          }           }
          if(mode == VIEW_PREVIOUS_MODE) { /* VIEW_PREVIOUS_MODE */           if(mode == VIEW_PREVIOUS_MODE) { /* VIEW_PREVIOUS_MODE */
            if( display_ans ) {     /*
              if( prob_idx->ans_type == ANSWER_IS_FLOAT ) {               if( prob_idx->ans_type == ANSWER_IS_FLOAT ) {
                  a = (double)atof(prob_idx->answer);                   a = (double)atof(prob_idx->answer);
                  sprintf(cmp_ans,prob_idx->ans_fmt, a);                   sprintf(cmp_ans,prob_idx->ans_fmt, a);
              } else {               } else {
                  strcpy(cmp_ans,prob_idx->answer);         if ( prob_idx->ans_type == ANSWER_IS_SUBJECTIVE) {
    strcpy(cmp_ans,"Subjective Answer");
          } else { 
    if (prob_idx->answer) {
      strcpy(cmp_ans,prob_idx->answer);
    } else {
      strcpy(cmp_ans,"No Answer");
    }
          }
              }               }
              if( prob_idx->ans_unit ) {               if( prob_idx->ans_unit ) {
                  sprintf(buf,"<p><tt><b>Answer:</b> %s %s</tt><br>\n",cmp_ans, prob_idx->unit_str);                    sprintf(buf,"<p><tt><b>Answer:</b> %s %s</tt><br>\n",cmp_ans, prob_idx->unit_str); 
              } else {               } else {
                  sprintf(buf,"<p><tt><b>Answer:</b> %s</tt><br>\n",cmp_ans);                    sprintf(buf,"<p><tt><b>Answer:</b> %s</tt><br>\n",cmp_ans); 
              }               }
      */
              if( display_ans ) { 
        c_ans=answers_string(ANSWER_STRING_MODE, prob_idx);
        sprintf(buf,"<p><tt><b>Answer:</b> %s</tt><br>",c_ans);
              append_qtext(buf);               append_qtext(buf);
        capa_mfree(c_ans);
      if ( prob_idx->explain) {       if ( prob_idx->explain) {
        sprintf(buf,"<p><b>Explanation: </b>\n<p>%s<br>\n",prob_idx->explain);         sprintf(buf,"<p><b>Explanation: </b>\n<p>%s<br>\n",prob_idx->explain);
        append_qtext(buf);         append_qtext(buf);
      }       }
            }     }
          } else { /* could be TRY_SET_MODE, CHECK_ANSWER_MODE */   } else { /* could be TRY_SET_MODE, CHECK_ANSWER_MODE */
              
            if( g_passdue ) {             if( g_passdue ) {
              get_response(header.partial_credit[question_idx],entry.answers[question_idx],question_idx,prob_idx);               get_response(header.partial_credit[question_idx],entry.answers[question_idx],question_idx,prob_idx);
            }else{             }else{
Line 1519  char *class_dir; char *c_owner;char *cla Line 1581  char *class_dir; char *c_owner;char *cla
      append_qtext("\n</OL>\n");       append_qtext("\n</OL>\n");
      if( EndText_p )   append_qtext(EndText_p);       if( EndText_p )   append_qtext(EndText_p);
      free_problems(first_prob);       free_problems(first_prob);
        free_units();
 #ifdef CGI_DBUG  #ifdef CGI_DBUG
   fprintf(g_cgi,"End display each problem\n"); fflush(g_cgi);    fprintf(g_cgi,"End display each problem\n"); fflush(g_cgi);
 #endif /* CGI_DBUG */  #endif /* CGI_DBUG */
Line 1567  char *class_dir; char *c_owner;char *cla Line 1629  char *class_dir; char *c_owner;char *cla
   }    }
 }  }
   
   /*if the assignment is passedue we come here to get what the answer was just in case*/
 void  void
 get_response(char pcr,char u_db,int q_idx,Problem_t *p)  get_response(char pcr,char u_db,int q_idx,Problem_t *p)
 {  {
Line 1683  void display_last_subjective(int q_idx) Line 1746  void display_last_subjective(int q_idx)
   
 void create_answer_area(Problem_t *p,int q_idx)   void create_answer_area(Problem_t *p,int q_idx) 
 {  {
   int ii;    int ii=0;
   char       buf[MAX_BUFFER_SIZE];      char       buf[MAX_BUFFER_SIZE];  
     AnswerInfo_t *ai;
 #ifdef CGI_DBUG  #ifdef CGI_DBUG
   fprintf(g_cgi,"Enter create_answer_area() [%d]\n",q_idx); fflush(g_cgi);    fprintf(g_cgi,"Enter create_answer_area() [%d]\n",q_idx); fflush(g_cgi);
 #endif /* CGI_DBUG */  #endif /* CGI_DBUG */
Line 1695  void create_answer_area(Problem_t *p,int Line 1758  void create_answer_area(Problem_t *p,int
   }    }
   if ( p->show_ans_box ) {     if ( p->show_ans_box ) { 
     if ( p->ans_op == ANS_AND ) {      if ( p->ans_op == ANS_AND ) {
       for(ii=0;ii<p->ans_cnt;ii++) {        if (p->ans_type == ANSWER_IS_FORMULA) {
  if (p->ans_type == ANSWER_IS_FORMULA) {   /* first answer is stored in p, the rest are linked off of p->ans_list */
  sprintf(buf,"<p><B>Answer %d of %d:</B><input size=80 name=\"INPUT%02d,%02d\" value=\"\">\n",ii+1,p->ans_cnt,q_idx+1,ii+1);   sprintf(buf,"<p><B>Answer %d of %d:</B><input size=80 name=\"INPUT%02d,%02d\" value=\"\">\n",ii+1,p->ans_cnt,q_idx+1,ii+1);
         } else {
    sprintf(buf,"<p><B>Answer %d of %d:</B><input name=\"INPUT%02d,%02d\" value=\"\">\n",ii+1,p->ans_cnt,q_idx+1,ii+1);
         }
         append_qtext(buf);
         for(ii=1, ai=p->ans_list;ii<p->ans_cnt;ai=ai->ans_next,ii++) {
    if (ai->ans_type == ANSWER_IS_FORMULA) {
     sprintf(buf,"<p><B>Answer %d of %d:</B><input size=80 name=\"INPUT%02d,%02d\" value=\"\">\n",ii+1,p->ans_cnt,q_idx+1,ii+1);
  } else {   } else {
   sprintf(buf,"<p><B>Answer %d of %d:</B><input name=\"INPUT%02d,%02d\" value=\"\">\n",ii+1,p->ans_cnt,q_idx+1,ii+1);    sprintf(buf,"<p><B>Answer %d of %d:</B><input name=\"INPUT%02d,%02d\" value=\"\">\n",ii+1,p->ans_cnt,q_idx+1,ii+1);
  }   }
Line 1886  char       buf[MAX_BUFFER_SIZE]; Line 1956  char       buf[MAX_BUFFER_SIZE];
 }  }
   
 /* returns a -1 if there were not enough answers, otherwise the number of responses  /* returns a -1 if there were not enough answers, otherwise the number of responses
    for the question is returned*/     for the question is returned
      !!!!!AS A SIDEEFFECT IT ALSO CROPS ANSWERS TO ANSWER_STRING_LENG!!!!!!!
   */
 int gather_answers(char ***ans,int q_idx,Problem_t *p)  int gather_answers(char ***ans,int q_idx,Problem_t *p)
 {  {
   int cnt;    int cnt;
   if(p->ans_op==ANS_AND) {    if(p->ans_op==ANS_AND) {
     int i; StudentAnswer_t *sa_p;      int i; StudentAnswer_t *sa_p;
     *ans=(char**)capa_malloc(p->ans_cnt,1);      *ans=(char**)capa_malloc(p->ans_cnt,sizeof(char*));
     sa_p= g_stu_ans_pp[q_idx+1];      sa_p= g_stu_ans_pp[q_idx+1];
     for(i=0;((i<p->ans_cnt)&&(sa_p));i++){      for(i=0;((i<p->ans_cnt)&&(sa_p));i++){
       ans[0][i]=sa_p->a_str;        ans[0][i]=sa_p->a_str;
         if ((strlen(ans[0][i])+1) > ANSWER_STRING_LENG) ans[0][i][ANSWER_STRING_LENG]='\0';
       sa_p=sa_p->a_next;        sa_p=sa_p->a_next;
     }      }
     cnt=p->ans_cnt;      cnt=p->ans_cnt;
     if (i<p->ans_cnt) return -1;      if (i<p->ans_cnt) return -1;
   } else {    } else {
     *ans=(char**)capa_malloc(p->ans_cnt,1);      *ans=(char**)capa_malloc(p->ans_cnt,sizeof(char*));
     ans[0][0]=g_stu_ans_pp[q_idx+1]->a_str;      ans[0][0]=g_stu_ans_pp[q_idx+1]->a_str;
       if ((strlen(ans[0][0])+1) > ANSWER_STRING_LENG) ans[0][0][ANSWER_STRING_LENG]='\0';
     cnt=1;      cnt=1;
   }    }
   return cnt;    return cnt;
 }  }
   
   /*logging user's answer when it is passed due.*/
 void  void
 log_user_ans(int q_idx,Problem_t *p)  log_user_ans(int q_idx,Problem_t *p)
 {  {
   char **ans;    char **ans;
     char *error;
   int cnt;    int cnt;
   if (p->ans_type==ANSWER_IS_SUBJECTIVE) {    if (p->ans_type==ANSWER_IS_SUBJECTIVE) {
     capa_set_subjective(g_login_set,q_idx+1,g_student_number,        /*capa_set_subjective(g_login_set,q_idx+1,g_student_number,
  g_stu_ans_pp[q_idx+1]->a_str);   g_stu_ans_pp[q_idx+1]->a_str);*/
   } else {    } else {
     if (-1 != (cnt=gather_answers(&ans,q_idx,p))) {      if (-1 != (cnt=gather_answers(&ans,q_idx,p))) {
       switch( capa_check_answers(p,ans,cnt) ) {        switch( capa_check_answers(p,ans,cnt,&error) ) {
         case  EXACT_ANS:  g_log_string[q_idx]='Y'; break;          case  EXACT_ANS:  g_log_string[q_idx]='Y'; break;
         case  APPROX_ANS: g_log_string[q_idx]='Y'; break;          case  APPROX_ANS: g_log_string[q_idx]='Y'; break;
         case  SIG_FAIL:   g_log_string[q_idx]='S'; break;          case  SIG_FAIL:   g_log_string[q_idx]='S'; capa_mfree(error); break;
         case  UNIT_FAIL:  g_log_string[q_idx]='U'; break;          case  UNIT_FAIL:  g_log_string[q_idx]='U'; capa_mfree(error); break;
         case  UNIT_NOTNEEDED:  g_log_string[q_idx]='U'; break;          case  UNIT_NOTNEEDED:  g_log_string[q_idx]='U'; capa_mfree(error); break;
         case  NO_UNIT:    g_log_string[q_idx]='u'; break;          case  NO_UNIT:    g_log_string[q_idx]='u'; break;
         case  BAD_FORMULA:  g_log_string[q_idx]='F'; break;          case  BAD_FORMULA:  g_log_string[q_idx]='F'; break;
         case  INCORRECT:  g_log_string[q_idx]='N'; break;          case  INCORRECT:  g_log_string[q_idx]='N'; break;
           case  WANTED_NUMERIC:  g_log_string[q_idx]='s'; break;
       }        }
     }      }
   }    }
Line 1971  int    sig_u; Line 2048  int    sig_u;
 char  *a_fmt;  char  *a_fmt;
 int    tries;  int    tries;
   char       buf[MAX_BUFFER_SIZE];    char       buf[MAX_BUFFER_SIZE];
       char *error;
   
   a_tpe = p->ans_type;    a_tpe = p->ans_type;
   t_tpe = p->tol_type;    t_tpe = p->tol_type;
   tol   = p->tolerance;    tol   = p->tolerance;
Line 1993  int    tries; Line 2071  int    tries;
     submit_subjective(q_idx,p);      submit_subjective(q_idx,p);
     return;      return;
   }    }
     
   cnt=gather_answers(&ans,q_idx,p);    cnt=gather_answers(&ans,q_idx,p);
   if (cnt == -1) {    if (cnt == -1) {
     g_tried[q_idx]--;      g_tried[q_idx]--;
Line 2008  int    tries; Line 2086  int    tries;
     return;      return;
   }    }
   
   switch( capa_check_answers(p,ans,cnt) ) {    switch( capa_check_answers(p,ans,cnt,&error) ) {
     case  EXACT_ANS:          case  EXACT_ANS:    
     case  APPROX_ANS:       case  APPROX_ANS: 
                    c_ans=answers_string(ANSWER_STRING_MODE, p);                     c_ans=answers_string(ANSWER_STRING_MODE, p);
Line 2018  int    tries; Line 2096  int    tries;
                    g_log_string[q_idx]='Y';                     g_log_string[q_idx]='Y';
    capa_mfree(c_ans);     capa_mfree(c_ans);
    break;     break;
       case  WANTED_NUMERIC:
                      create_answer_area(p,q_idx);
      g_tried[q_idx]--;  /* don't count as a try */
      sprintf(buf,"<br><tt>This question expects a numeric answer, tries %d/%d.</tt>\n",g_tried[q_idx],tries);
      append_qtext(buf);
      g_new_answerdb[q_idx] = 'N';
                      g_log_string[q_idx]='s';
                      break;
     case  SIG_FAIL:      case  SIG_FAIL:
                    create_answer_area(p,q_idx);                     create_answer_area(p,q_idx);
    g_tried[q_idx]--;  /* don't count as a try */     g_tried[q_idx]--;  /* don't count as a try */
    sprintf(buf,"<br><tt>Please adjust significant figures, tries %d/%d.</tt>\n",g_tried[q_idx],tries);     sprintf(buf,"<br><tt>Please adjust significant figures, you provided %s significant figures, tries %d/%d.</tt>\n",error,g_tried[q_idx],tries);
    append_qtext(buf);     append_qtext(buf);
      capa_mfree(error);
    g_new_answerdb[q_idx] = 'N';     g_new_answerdb[q_idx] = 'N';
                    g_log_string[q_idx]='S';                     g_log_string[q_idx]='S';
                    break;                     break;
     case  UNIT_FAIL:      case  UNIT_FAIL:
                    create_answer_area(p,q_idx);                     create_answer_area(p,q_idx);
                    g_tried[q_idx]--;  /* don't count as a try */                     g_tried[q_idx]--;  /* don't count as a try */
    sprintf(buf,"<br><tt>Units incorrect, tries %d/%d.</tt>\n",g_tried[q_idx],tries);     sprintf(buf,"<br><tt>Units incorrect, Computer reads units as %s, tries %d/%d.</tt>\n",error,g_tried[q_idx],tries);
      capa_mfree(error);
    append_qtext(buf);     append_qtext(buf);
    g_new_answerdb[q_idx] = 'N';     g_new_answerdb[q_idx] = 'N';
                    g_log_string[q_idx]='U';                     g_log_string[q_idx]='U';
Line 2038  int    tries; Line 2126  int    tries;
                    create_answer_area(p,q_idx);                     create_answer_area(p,q_idx);
                    g_tried[q_idx]--;  /* don't count as a try */                     g_tried[q_idx]--;  /* don't count as a try */
                    if(tries > 0) {                     if(tries > 0) {
                      sprintf(buf,"<br><tt>Only a number required, tries %d/%d.</tt>\n",g_tried[q_idx],tries);                       sprintf(buf,"<br><tt>Only a number required, Computer reads units of %s, tries %d/%d.</tt>\n",error,g_tried[q_idx],tries);
                      append_qtext(buf);                       append_qtext(buf);
                    }                     }
      capa_mfree(error);
                    g_new_answerdb[q_idx] = 'N';                     g_new_answerdb[q_idx] = 'N';
                    g_log_string[q_idx]='U';                     g_log_string[q_idx]='U';
                    break;                     break;
Line 2091  int    sig_u; Line 2180  int    sig_u;
 char  *a_fmt;  char  *a_fmt;
 int    tries;  int    tries;
   char       buf[MAX_BUFFER_SIZE];    char       buf[MAX_BUFFER_SIZE];
       char *error;
   
   a_tpe = p->ans_type;    a_tpe = p->ans_type;
   c_ans = p->answer;    c_ans = p->answer;
   t_tpe = p->tol_type;    t_tpe = p->tol_type;
Line 2130  int    tries; Line 2220  int    tries;
     return;      return;
   }    }
   
   switch( capa_check_answers(p,ans,cnt) ) {    switch( capa_check_answers(p,ans,cnt,&error) ) {
     case  EXACT_ANS:      case  EXACT_ANS:
     case  APPROX_ANS:       case  APPROX_ANS: 
                    g_new_answerdb[q_idx] = 'Y';                     g_new_answerdb[q_idx] = 'Y';
                    g_log_string[q_idx]='Y';                     g_log_string[q_idx]='Y';
                    break;                     break;
       case  WANTED_NUMERIC:
                      g_new_answerdb[q_idx] = 'N';
                      g_log_string[q_idx]='s';
                      break;
     case  SIG_FAIL:      case  SIG_FAIL:
                    g_new_answerdb[q_idx] = 'N';                     g_new_answerdb[q_idx] = 'N';
                    g_log_string[q_idx]='S';                     g_log_string[q_idx]='S';
      capa_mfree(error);
                    break;                     break;
     case  UNIT_FAIL:      case  UNIT_FAIL:
                    g_new_answerdb[q_idx] = 'N';                     g_new_answerdb[q_idx] = 'N';
                    g_log_string[q_idx]='U';                     g_log_string[q_idx]='U';
      capa_mfree(error);
                    break;                     break;
     case  UNIT_NOTNEEDED:      case  UNIT_NOTNEEDED:
                    g_new_answerdb[q_idx] = 'N';                     g_new_answerdb[q_idx] = 'N';
                    g_log_string[q_idx]='U';                     g_log_string[q_idx]='U';
      capa_mfree(error);
                    break;                     break;
     case  NO_UNIT:      case  NO_UNIT:
                    g_new_answerdb[q_idx] = 'N';                     g_new_answerdb[q_idx] = 'N';
Line 2185  char *class_dir;char *class;char *studen Line 2282  char *class_dir;char *class;char *studen
            set_score,                   /*    Score on a set           */             set_score,                   /*    Score on a set           */
            term_score=0,                /*    Total points received    */             term_score=0,                /*    Total points received    */
            term_valid=0,                /*    Total points possible    */             term_valid=0,                /*    Total points possible    */
            result;             result,
              tot_num_sets=0;
   T_entry  entry;                       /*    Database entry for a set */    T_entry  entry;                       /*    Database entry for a set */
   char     buf[MAX_BUFFER_SIZE]; /* Output line buffer  */    char     buf[MAX_BUFFER_SIZE]; /* Output line buffer  */
   char     buf2[MAX_BUFFER_SIZE]; /* Output line buffer  */    char     buf2[MAX_BUFFER_SIZE]; /* Output line buffer  */
Line 2200  char *class_dir;char *class;char *studen Line 2298  char *class_dir;char *class;char *studen
     fprintf(stdout,"Unable to complete actions.\n");      fprintf(stdout,"Unable to complete actions.\n");
     return;      return;
   }    }
     printf("<!--print_summary-->");
   sprintf(class_fullpath,"%s/%s",class_dir,class);    sprintf(class_fullpath,"%s/%s",class_dir,class);
   chdir(class_fullpath);    chdir(class_fullpath);
   configResult=read_capa_config("web_status_line_length",buf);    configResult=read_capa_config("web_status_line_length",buf);
Line 2221  char *class_dir;char *class;char *studen Line 2319  char *class_dir;char *class;char *studen
   for (set_idx=1; set_idx<=set; set_idx++) {    for (set_idx=1; set_idx<=set; set_idx++) {
     g_inhibit_response=capa_check_option(OPTION_INHIBIT_RESPONSE,set_idx,      g_inhibit_response=capa_check_option(OPTION_INHIBIT_RESPONSE,set_idx,
  g_student_data.s_sec);   g_student_data.s_sec);
     if (g_inhibit_response > 0) continue;      if (g_inhibit_response > 0) {
         printf("<!-- Set %d is inhibited -->\n",set_idx);
         continue;
       }
       if ( capa_check_date(CHECK_OPEN_DATE,g_student_number,
        g_student_data.s_sec,set_idx) < 0 ){
         printf("<!-- Set %d is not open -->\n",set_idx);
         continue;
       }
   
     if (capa_get_header(&header,set_idx))  return;      if (capa_get_header(&header,set_idx))  return;
       tot_num_sets++;
     capa_get_entry(&entry,student_number,set_idx);      capa_get_entry(&entry,student_number,set_idx);
     sscanf(header.num_questions,"%d", &(question_cnt) );      sscanf(header.num_questions,"%d", &(question_cnt) );
     valid_wgt = 0; set_score = 0;      valid_wgt = 0; set_score = 0;
Line 2267  char *class_dir;char *class;char *studen Line 2374  char *class_dir;char *class;char *studen
   printf("\n</TABLE>\n<hr>\n");    printf("\n</TABLE>\n<hr>\n");
   /* SHOW TOTALS */    /* SHOW TOTALS */
   /* if capalogin_show_summary_score is set to none don't show it */    /* if capalogin_show_summary_score is set to none don't show it */
   sprintf(buf,"%d sets, total = %3d/%3d (%d%%)\n", set, term_score, term_valid, 100*term_score/term_valid);    if (term_valid > 0) {
       sprintf(buf,"%d sets, total = %3d/%3d (%d%%)\n", tot_num_sets, term_score, term_valid, 100*term_score/term_valid);
     } else {
       sprintf(buf,"%d sets, total = %3d/%3d\n", tot_num_sets, term_score, term_valid);
     }
   result=read_capa_config("capalogin_show_summary_score",buf2);    result=read_capa_config("capalogin_show_summary_score",buf2);
   if (result != 0 && result != -1) {    if (result != 0 && result != -1) {
     if (strcasecmp(buf2,"none")==0) {      if (strcasecmp(buf2,"none")==0) {
Line 2393  FILE *out; Line 2504  FILE *out;
   float    hw_w, qz_w, ex_w, fe_w, pc_w;    float    hw_w, qz_w, ex_w, fe_w, pc_w;
   int      idx, entry_count, tmp_len;    int      idx, entry_count, tmp_len;
   float    *S, *F;    float    *S, *F;
   int      *X;    int      *X; /* array controlling whether to extrapolate scores */
   char     *capa_server;    char     *capa_server;
   int      max_set[4];    int      max_set[4], width=600,height=750; /* width and height of applet*/
   char     **c_path_pp;    char     **c_path_pp;
   
   /*Unused Vars      /*Unused Vars  
Line 2448  FILE *out; Line 2559  FILE *out;
           
     return;      return;
   }    }
   
     get_tscore_width_height(&width,&height);
   
   c_path_pp = (char **)capa_malloc( 4, sizeof(char *));    c_path_pp = (char **)capa_malloc( 4, sizeof(char *));
   tmp_len = strlen(class_fullpath) + 1;    tmp_len = strlen(class_fullpath) + 1;
   c_path_pp[0] = (char *)capa_malloc(tmp_len,sizeof(char));    c_path_pp[0] = (char *)capa_malloc(tmp_len,sizeof(char));
Line 2488  FILE *out; Line 2602  FILE *out;
     c_path_pp[2] = (char *)capa_malloc( (tmp_len),sizeof(char));      c_path_pp[2] = (char *)capa_malloc( (tmp_len),sizeof(char));
     sprintf(c_path_pp[2],"%s",buf);      sprintf(c_path_pp[2],"%s",buf);
     max_set[2] = check_class_get_maxset(c_path_pp[2]);      max_set[2] = check_class_get_maxset(c_path_pp[2]);
       printf("<!-- for %s max_set %d -->\n",c_path_pp[2],max_set[2]);
     if( max_set[2] <= 0 ) {      if( max_set[2] <= 0 ) {
       /* should we continue ? */   /* no sets */
       max_set[2] = 0;   max_set[2] = 0;
       for(idx=2;idx <= (fs*2); idx++) {      }
       /* start extrapolation with sets that don't yet exist */
       for(idx=2+(max_set[2]*2);idx <= (fs*2); idx++) {
         X[idx] = 1;          X[idx] = 1;
       }  
     }      }
   } else { /* if exam_path is not in capa.config, then skip exams */    } else { /* if exam_path is not in capa.config, then skip exams */
     fs = 0;      fs = 0;
Line 2540  FILE *out; Line 2656  FILE *out;
           term_score += set_score;            term_score += set_score;
           capa_mfree(header.weight);            capa_mfree(header.weight);
           capa_mfree(header.partial_credit);            capa_mfree(header.partial_credit);
     printf("<!-- %s %d %d -->\n",c_path_pp[idx],set_score,valid_wgt);
           if(idx==2) { /* exam sets */            if(idx==2) { /* exam sets */
             S[set_idx*2] = (float)set_score;              S[set_idx*2] = (float)set_score;
             F[set_idx*2] = (float)valid_wgt;              F[set_idx*2] = (float)valid_wgt;
             X[set_idx*2] = 0;              if (valid_wgt == 0) {
    X[set_idx*2] = 1;
       } else {
    X[set_idx*2] = 0;
       }
           }            }
           if(idx==3) { /* correction sets */            if(idx==3) { /* correction sets */
             S[set_idx*2+1] = (float)set_score;              S[set_idx*2+1] = (float)set_score;
             F[set_idx*2+1] = (float)valid_wgt;              F[set_idx*2+1] = (float)valid_wgt;
             X[set_idx*2+1] = 0;      if (valid_wgt == 0 ) {
    X[set_idx*2+1] = 1;
       } else {
    X[set_idx*2+1] = 0;
       }
           }            }
        }         }
        if( (idx == 0) || (idx==1) ) { /* homeworks and quizzes */         if( (idx == 0) || (idx==1) ) { /* homeworks and quizzes */
Line 2563  FILE *out; Line 2688  FILE *out;
   
       
   fprintf(out,"<CENTER>\n");    fprintf(out,"<CENTER>\n");
   fprintf(out,"<APPLET CODE=TScore.class CODEBASE=\"http://%s\" width=600 height=750>\n",capa_server);    fprintf(out,"<APPLET CODE=TScore.class CODEBASE=\"http://%s/CAPA/\" width=%d height=%d>\n",capa_server,width,height);
   fprintf(out,"<PARAM NAME=\"HW_W\"  VALUE=\"%f\">\n", hw_w);    fprintf(out,"<PARAM NAME=\"HW_W\"  VALUE=\"%f\">\n", hw_w);
   fprintf(out,"<PARAM NAME=\"QZ_W\"  VALUE=\"%f\">\n", qz_w);    fprintf(out,"<PARAM NAME=\"QZ_W\"  VALUE=\"%f\">\n", qz_w);
   fprintf(out,"<PARAM NAME=\"EX_W\"  VALUE=\"%f\">\n", ex_w);    fprintf(out,"<PARAM NAME=\"EX_W\"  VALUE=\"%f\">\n", ex_w);
Line 2607  FILE *out; Line 2732  FILE *out;
   capa_mfree((char *)capa_server);    capa_mfree((char *)capa_server);
 }  }
   
   void
   get_tscore_width_height(width,height) 
   int *width;int *height;
   {
     char     buf[MAX_BUFFER_SIZE]; 
     int      configResult;
     
     configResult=read_capa_config("tscore_width",buf);
     if (configResult != 0 && configResult != -1 ) {
       sscanf(buf,"%d", width);
       if (*width <= 0 )  { *width = DEFAULT_WIDTH; }
     } else {
         printf("<!-- tscore_width not found. %d-->\n",configResult);
     }
     configResult=read_capa_config("tscore_height",buf);
     if (configResult != 0 && configResult != -1 ) {
       sscanf(buf,"%d", height);
       if (*height <= 0 )  { *height = DEFAULT_HEIGHT; }
     } else {
         printf("<!-- tscore_height not found. %d-->\n",configResult);
     }
   }
   
 int  int
 get_termscore_params(hw,qw,ew,fw,pw,hc,qc,fs)   get_termscore_params(hw,qw,ew,fw,pw,hc,qc,fs) 
Line 2622  int   *hc;int   *qc;int   *fs; Line 2768  int   *hc;int   *qc;int   *fs;
   configResult=read_capa_config("homework_weight",buf);    configResult=read_capa_config("homework_weight",buf);
   if (configResult != 0 && configResult != -1 ) {    if (configResult != 0 && configResult != -1 ) {
     sscanf(buf,"%f", &hw_w);      sscanf(buf,"%f", &hw_w);
     if(hw_w <= 0.0 )  {      if(hw_w < 0.0 )  {
       hw_w = DEFAULT_HW_W;        hw_w = DEFAULT_HW_W;
     }      }
   } else {    } else {
Line 2631  int   *hc;int   *qc;int   *fs; Line 2777  int   *hc;int   *qc;int   *fs;
   configResult=read_capa_config("quiz_weight",buf);    configResult=read_capa_config("quiz_weight",buf);
   if (configResult != 0 && configResult != -1 ) {    if (configResult != 0 && configResult != -1 ) {
     sscanf(buf,"%f", &qz_w);      sscanf(buf,"%f", &qz_w);
     if(qz_w <= 0.0 )  {      if(qz_w < 0.0 )  {
       qz_w = DEFAULT_QZ_W;        qz_w = DEFAULT_QZ_W;
     }      }
   } else {    } else {
Line 2640  int   *hc;int   *qc;int   *fs; Line 2786  int   *hc;int   *qc;int   *fs;
   configResult=read_capa_config("exam_weight",buf);    configResult=read_capa_config("exam_weight",buf);
   if (configResult != 0 && configResult != -1 ) {    if (configResult != 0 && configResult != -1 ) {
     sscanf(buf,"%f", &ex_w);      sscanf(buf,"%f", &ex_w);
     if(ex_w <= 0.0 )  {      if(ex_w < 0.0 )  {
       ex_w = DEFAULT_EX_W;        ex_w = DEFAULT_EX_W;
     }      }
   } else {    } else {
Line 2649  int   *hc;int   *qc;int   *fs; Line 2795  int   *hc;int   *qc;int   *fs;
   configResult=read_capa_config("final_weight",buf);    configResult=read_capa_config("final_weight",buf);
   if (configResult != 0 && configResult != -1 ) {    if (configResult != 0 && configResult != -1 ) {
     sscanf(buf,"%f", &fe_w);      sscanf(buf,"%f", &fe_w);
     if(fe_w <= 0.0 )  {      if(fe_w < 0.0 )  {
       fe_w = DEFAULT_FE_W;        fe_w = DEFAULT_FE_W;
     }      }
   } else {    } else {
Line 2658  int   *hc;int   *qc;int   *fs; Line 2804  int   *hc;int   *qc;int   *fs;
   configResult=read_capa_config("correction_weight",buf);    configResult=read_capa_config("correction_weight",buf);
   if (configResult != 0 && configResult != -1 ) {    if (configResult != 0 && configResult != -1 ) {
     sscanf(buf,"%f", &pc_w);      sscanf(buf,"%f", &pc_w);
     if(pc_w <= 0.0 )  {      if(pc_w < 0.0 )  {
       pc_w = DEFAULT_PC_W;        pc_w = DEFAULT_PC_W;
     }      }
   } else {    } else {

Removed from v.1.3  
changed lines
  Added in v.1.18


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>