Annotation of capa/capa51/pProj/capalogin.c, revision 1.1

1.1     ! albertel    1: /* Copyright 1992-1997 Michigan State University, Board of Trustee  */
        !             2: /* version 4.6 */
        !             3: 
        !             4: /* Jan 28  1997  I.T. */
        !             5: /* July 23 1998  I.T. */
        !             6: 
        !             7: #ifdef NeXT
        !             8: #include <stdlib.h>
        !             9: #include <objc/zone.h>
        !            10: #include <mach/mach.h>
        !            11: #else
        !            12: #include <malloc.h>
        !            13: double atof();
        !            14: #endif
        !            15: 
        !            16: #include <ctype.h>
        !            17: 
        !            18: #ifdef TRUE
        !            19: #undef TRUE
        !            20: #endif
        !            21: #ifdef FALSE
        !            22: #undef FALSE
        !            23: #endif
        !            24: 
        !            25: #include <curses.h>
        !            26: 
        !            27: #if defined(__alpha) || defined(linux) 
        !            28: 
        !            29: #ifdef LOGIN_DBUG
        !            30: 
        !            31: #define NO_PIN
        !            32: #define NO_DATE_CHECK
        !            33: #define NO_DUP_CHECK
        !            34: 
        !            35: #endif
        !            36: 
        !            37: #include <curses.h>
        !            38: #else
        !            39: #if defined(__sun) || defined(hpux) || defined(AIX) || defined(IRIX)
        !            40: #include <curses.h>  /* #include <stdio.h> */
        !            41: #include <math.h>   /* MAXFLOAT */
        !            42: 
        !            43: #else
        !            44: 
        !            45: #include <bsd/curses.h>
        !            46: 
        !            47: #endif
        !            48: #endif
        !            49: 
        !            50: #include <signal.h>
        !            51: #include <time.h>
        !            52: #include <math.h>
        !            53: #include <string.h>
        !            54: #include <unistd.h>
        !            55: #include "capaToken.h"
        !            56: #include "capaParser.h"
        !            57: #include "capaCommon.h"
        !            58: 
        !            59: FILE      *dfp;
        !            60: 
        !            61: #define   TERM_SUMMARY    1
        !            62: #define   EXAM_SUMMARY    2
        !            63: #define   QUIZ_SUMMARY    3
        !            64: 
        !            65: #define   TRY_BOUND       99
        !            66: 
        !            67: 
        !            68: 
        !            69: 
        !            70: #define   TYR_SET_MENU_MACRO(xxx)   {					\
        !            71:  sprintf(aLine,"Total %d problems", num_questions); \
        !            72:  if(xxx) { \
        !            73:   mvaddstr(20,1,"Enter command  M,  A,  #,  T, or  X.");           mvaddstr(20,67,"COMMAND:"); \
        !            74:   mvaddstr(21,1,"M=go to Main Menu  A=Answer    T=Time   RETURN=execute command"); \
        !            75:  } else { \
        !            76:   mvaddstr(20,1,"Enter command  M,  #,  T,  or  X.    ");          mvaddstr(20,67,"COMMAND:"); \
        !            77:   mvaddstr(21,1,"M=go to Main Menu  T=Time               RETURN=execute command"); \
        !            78:  }  \
        !            79:  mvaddstr(22,1, "#=go to problem #  X=eXit CAPA"); \
        !            80:  mvaddstr(23,1,aLine); }
        !            81: 
        !            82: 
        !            83: #define   REVIEW_SET_MENU_MACRO()   {					\
        !            84:  sprintf(aLine,"Total %d problems", num_questions); \
        !            85:  mvaddstr(20,1,"Enter command  M,  #,  or  X.");              mvaddstr(20,67,"COMMAND:"); \
        !            86:  mvaddstr(21,1,"M=go to Main Menu                    RETURN=execute command"); \
        !            87:  mvaddstr(22,1,"#=go to problem #     X=eXit CAPA"); \
        !            88:  mvaddstr(23,1,aLine); } 
        !            89: 
        !            90: #define   TYRSET_MENU( )   {					\
        !            91:   mvaddstr(22,0,"Commands  :M = Main Menu   :7 = go to Problem 7            RETURN = Enter/Execute"); \
        !            92:  }
        !            93: 
        !            94: 
        !            95: #define   REVIEW_SET_MENU_MACRO()   {					\
        !            96:  sprintf(aLine,"Total %d problems", num_questions); \
        !            97:  mvaddstr(20,1,"Enter command  M,  #,  or  X.");              mvaddstr(20,67,"COMMAND:"); \
        !            98:  mvaddstr(21,1,"M=go to Main Menu                    RETURN=execute command"); \
        !            99:  mvaddstr(22,1,"#=go to problem #     X=eXit CAPA"); \
        !           100:  mvaddstr(23,1,aLine); } 
        !           101: 
        !           102: 
        !           103: #define DBUG_TSUMMARY    0
        !           104: 
        !           105: #define CLEAR()         clear(); refresh()
        !           106: #define ADDCH(c)        addch(c); refresh()
        !           107: #define CLRTOEOL()      clrtoeol(); refresh()
        !           108: #define CR 13
        !           109: #define LF 10
        !           110: #define SCREEN_BUFFER_SIZE   2048
        !           111: 
        !           112: time_t   log_in_time, log_out_time;
        !           113: char     in_t[32],    in_tty[32];
        !           114: char     Orig_path[FILE_NAME_LENGTH], Exam_path[FILE_NAME_LENGTH], 
        !           115:   Quiz_path[FILE_NAME_LENGTH];
        !           116: int      Exam_set, Quiz_set;
        !           117: int      g_inhibit_response;
        !           118: int      g_delay; /* delay when logging out */
        !           119: int      g_max_delay; /* max number of minutes to wait for input, kick_out()
        !           120:                          after this much time */
        !           121: /* Note: be careful to free entry answers */
        !           122: 
        !           123: /* ------------------------------------------------------------------------- */
        !           124: /* WRITE OUTPUT (NICELY) TO THE SCREEN                                       */
        !           125: /* ------------------------------------------------------------------------- */
        !           126: void              /* RETURNS: (nothing)         */
        !           127: wrap(str)         /* ARGUMENTS:                 */
        !           128: char *str;        /*    Block of text to output */
        !           129: {                 /* LOCAL VARIABLES:           */
        !           130:    int y,x,len;   /*    Row,Col of screen       */
        !           131:    int i,         /*    Next space              */
        !           132:        j;         /*    Next char to print      */
        !           133:   len=strlen(str);
        !           134:   for (i=j=0; i<len; i++) {
        !           135:     getyx(stdscr,y,x); 
        !           136:     while (i<len && !isspace(str[i]))    i++;
        !           137:     if (x+i-j > 78)  addch('\n');
        !           138:     while (j<=i)     addch(str[j++]);
        !           139:   }
        !           140: }
        !           141: int
        !           142: total_lines(char *str)
        !           143: {
        !           144:   int  len,  lines_cnt=1;
        !           145:   int  i, j, x=0;
        !           146:   
        !           147:   len=strlen(str);
        !           148:   for(i=j=0;i<len;i++) {
        !           149:     while (i<len && !isspace(str[i]))    i++;
        !           150:     if (x+i-j > 78)  { lines_cnt++; x = 0; }
        !           151:     while (j<=i)     { x++; if(str[j] == '\n') {lines_cnt++; x=0; }  j++; }
        !           152:   }
        !           153:   return (lines_cnt);
        !           154: }
        !           155: 
        !           156: /* --------------------------------------------- */
        !           157: /* */
        !           158: #define    LINES_PER_SCREEN     20
        !           159: 
        !           160: int  display_prob_scr(char *str,int scr_idx)
        !           161: {
        !           162:   int  len, lines_cnt=0;
        !           163:   int  i,j,y=0,x=0;
        !           164:   int  break_pt, onscreen_pr;
        !           165:   int  second_scr=0;
        !           166: 
        !           167:   if( str != NULL ) {
        !           168:     lines_cnt = total_lines(str);
        !           169:     if( lines_cnt > LINES_PER_SCREEN ) {
        !           170:       second_scr = 1;
        !           171:     } else {
        !           172:       scr_idx = 1;
        !           173:     }
        !           174:     if( scr_idx == 1 ) {
        !           175:       break_pt = LINES_PER_SCREEN + 1;
        !           176:     } else { /* which line to break the problem text into two screens */
        !           177:       if(lines_cnt>=40) { break_pt = LINES_PER_SCREEN; } else {
        !           178:         if(lines_cnt==39) { break_pt = LINES_PER_SCREEN - 1; } else {
        !           179:           if(lines_cnt==38) { break_pt = LINES_PER_SCREEN - 2; } else {
        !           180:             break_pt = LINES_PER_SCREEN - 3;
        !           181:           }
        !           182:         }
        !           183:       }
        !           184:     }
        !           185: 
        !           186: #ifdef LOGIN_DBUG
        !           187:    fprintf(dfp,"DISPLAY SCR IDX=%d total LineCnt=%d Line Break= %d:\n",scr_idx,lines_cnt,break_pt); fflush(dfp);
        !           188: #endif
        !           189: 
        !           190:   /*  start to display the text on screen */
        !           191: 
        !           192:     lines_cnt = 1; x = y =0;
        !           193:     len=strlen(str);
        !           194: #ifdef LOGIN_DBUG
        !           195:   fprintf(dfp,"SCR IDX=%d,leng=%d[[\n",scr_idx,len);
        !           196:   fflush(dfp);
        !           197: #endif  
        !           198:     for(i=j=0;i<len;i++) {
        !           199:       if( ( (scr_idx==1) && (lines_cnt < break_pt)) ||
        !           200:           ((scr_idx==2) && (lines_cnt > break_pt) && (lines_cnt <= (break_pt+LINES_PER_SCREEN))) ) {
        !           201:         getyx(stdscr,y,x);
        !           202: 	/*	if (x2>=x) x=x2; else x=x2+80;*/
        !           203:       }
        !           204:       while (i<len && !isspace(str[i]))    i++;
        !           205:       onscreen_pr = 0;
        !           206: #ifdef LOGIN_DBUG         
        !           207:       fprintf(dfp,"\n[NewWord line=%d,x=%d,i=%d,j=%d,y=%d]",lines_cnt,x,i,j,y);
        !           208: #endif         
        !           209:       if (x+i-j > 78)  { /* line break  */
        !           210:          if( (scr_idx==1) && (lines_cnt < break_pt) ) {
        !           211:            addch('\n'); onscreen_pr = 1;
        !           212: #ifdef LOGIN_DBUG         
        !           213:            fprintf(dfp,"\n[LineCnt=%d,x=%d,i=%d,j=%d]",lines_cnt,x,i,j);
        !           214: #endif         
        !           215:          }
        !           216:          if( (scr_idx==2) && (lines_cnt > break_pt) && (lines_cnt <= (break_pt+LINES_PER_SCREEN)) ) {
        !           217:          
        !           218:            addch('\n'); onscreen_pr = 1;
        !           219: #ifdef LOGIN_DBUG         
        !           220:            fprintf(dfp,"\n[LineCnt=%d,x=%d,i=%d,j=%d]",lines_cnt,x,i,j);
        !           221: #endif         
        !           222:          }
        !           223:          lines_cnt++;
        !           224:          if(onscreen_pr == 0 ) {
        !           225:            x=0;
        !           226:          }
        !           227:       }
        !           228:       while (j<=i)     { /* display on screen */
        !           229:          onscreen_pr = 0;
        !           230:          if( (scr_idx==1) && (lines_cnt < break_pt) ) {
        !           231:            addch(str[j]);   /* display that character */
        !           232:            onscreen_pr = 1;
        !           233: #ifdef LOGIN_DBUG            
        !           234:            fprintf(dfp,"%c",str[j]);
        !           235: #endif 
        !           236:          } 
        !           237:          if( (scr_idx==2) && (lines_cnt > break_pt) && (lines_cnt <= (break_pt+LINES_PER_SCREEN)) ) {
        !           238: 
        !           239:            addch(str[j]); onscreen_pr = 1;
        !           240: #ifdef LOGIN_DBUG            
        !           241:            fprintf(dfp,"%c",str[j]);
        !           242: #endif 
        !           243:          }
        !           244:          if( str[j] == '\n' )  {
        !           245:           
        !           246: #ifdef LOGIN_DBUG         
        !           247:          fprintf(dfp,"<LineCnt=%d>[j=%d]",lines_cnt,j);
        !           248: #endif
        !           249:            if(onscreen_pr == 0 ) {
        !           250:              x = 0;
        !           251:            }
        !           252:            lines_cnt++; 
        !           253:          }
        !           254:          if(onscreen_pr == 0 ) {
        !           255:            x++;
        !           256:          }
        !           257:          j++;
        !           258:        }
        !           259:     }
        !           260: #ifdef LOGIN_DBUG
        !           261:   fprintf(dfp,"\n]]"); fflush(dfp);
        !           262: #endif
        !           263: 
        !           264:   }
        !           265:   return (second_scr);
        !           266: 
        !           267: }
        !           268: 
        !           269: /* ------------------------------------------------------------------------- */
        !           270: /* DISPLAY FAREWELL MESSAGE WHEN USER GOT KICKED OUT                         */
        !           271: /* ------------------------------------------------------------------------- */
        !           272: void               /* RETURNS: (nothing)      */
        !           273: #ifdef __sun
        !           274: kick_out(int sig)
        !           275: #else
        !           276: kick_out()
        !           277: #endif
        !           278: 
        !           279: {                  /* LOCAL VARIABLES:        */
        !           280:    FILE *fp;       /*    Goodbye file pointer */
        !           281:    char  buf[255]; /*    Input buffer         */
        !           282: 
        !           283:    /* DISPLAY EXIT MESSAGE */
        !           284:    CLEAR();
        !           285:    if ((fp=fopen("goodbye.msg","r"))!=NULL) {
        !           286:       while (fgets(buf,255,fp))
        !           287:          addstr(buf);
        !           288:       fclose(fp);
        !           289:    }
        !           290:    sprintf(buf, "This message will last for only %d seconds.",g_delay);
        !           291:    mvaddstr(22,20,buf); refresh();
        !           292:    sleep(g_delay);
        !           293:    /* mypause(22,20); */
        !           294: 
        !           295:    /* CURSES RESTORATION */
        !           296:    resetty(); endwin();
        !           297:    exit(1);
        !           298: }
        !           299: 
        !           300: 
        !           301: /* ------------------------------------------------------------------------- */
        !           302: /* GET INPUT (NICELY) FROM A PLACE ON THE SCREEN                             */
        !           303: /* ------------------------------------------------------------------------- */
        !           304: void                     /* RETURNS: (nothing)             */
        !           305: get_input(y,x,str,inmax) /* ARGUMENTS:                     */
        !           306: int   y,x;               /*   Row,Col of screen to start   */
        !           307: char *str;               /*   String buffer to fill in     */
        !           308: int   inmax;             /*   Maximum number of characters */
        !           309: {                        /* LOCAL VARIABLES:               */
        !           310:    int  i=0,cx,cy;       /*   Position in buffer           */
        !           311:    char c;               /*   Input character              */
        !           312:    
        !           313:    if (y && x)  move(y,x);
        !           314:    CLRTOEOL();
        !           315:    cx = x; cy = y;
        !           316: #if defined( __alpha) || defined(__sun)
        !           317:    while (1) {
        !           318:       alarm(g_max_delay*60);
        !           319:       c=getch();
        !           320:       if (c==10 || c==13)   break;
        !           321:       else if (c==8 || c==16 || c==127) {
        !           322:          if (i>0) {
        !           323:             i--;  cx--;  echo(); move(cy,cx);
        !           324:             delch();  insch(' '); refresh(); noecho();
        !           325:          } else
        !           326:          beep();
        !           327:       } else if (i>=inmax) { beep(); } else {
        !           328:          str[i++] = c; cx++;
        !           329:          echo(); ADDCH(c); noecho();
        !           330:       }
        !           331:    }
        !           332: #else  
        !           333:    while (1) {
        !           334:       alarm(g_max_delay*60);
        !           335:       c=getch();
        !           336:       if (c==10 || c==13) break;
        !           337:       else if (c==8 || c==16 || c==127) {
        !           338:          if (i>0) {
        !           339:             i--;  printf("%c %c",8,8); refresh();
        !           340:          } else   printf("%c",7);
        !           341:       } else if (i>=inmax) { printf("%c",7);
        !           342:       } else {
        !           343:          str[i++] = c;  ADDCH(c);
        !           344:       }
        !           345:    }
        !           346: #endif
        !           347:    str[i]=0;
        !           348: }
        !           349: 
        !           350: 
        !           351: void                     /* RETURNS: (nothing)             */
        !           352: get_xinput(y,x,str,inmax)/* ARGUMENTS:                     */
        !           353: int   y,x;               /*   Row,Col of screen to start   */
        !           354: char *str;               /*   String buffer to fill in     */
        !           355: int   inmax;             /*   Maximum number of characters */
        !           356: {                        /* LOCAL VARIABLES:               */
        !           357:    int  i=0,cx,cy;       /*   Position in buffer           */
        !           358:    char c;               /*   Input character              */
        !           359: 
        !           360:    
        !           361:    for(i=0;i<inmax;i++) { move(y,x+i); ADDCH(' '); }
        !           362:    i=0;
        !           363:    if (y && x)  move(y,x);refresh();
        !           364:    cx = x; cy = y;
        !           365: #if defined( __alpha) || defined(__sun)
        !           366:    while (1) {      
        !           367:      alarm(g_max_delay*60);
        !           368:      c=getch();
        !           369:      if (c==10 || c==13)   break;
        !           370:      else if (c==8 || c==16 || c==127) {
        !           371:        if (i>0) {
        !           372: 	 i--;  cx--;  echo(); move(cy,cx);
        !           373: 	 delch();  insch(' '); refresh(); noecho();
        !           374:        } else
        !           375:          beep();
        !           376:      } else if (i>=inmax) { beep(); } else {
        !           377:        str[i++] = c; cx++;
        !           378:        echo(); ADDCH(c); noecho();
        !           379:      }
        !           380:    }
        !           381: #else  
        !           382:    while (1) {
        !           383:      alarm(g_max_delay*60);
        !           384:      c=getch();
        !           385:      if (c==10 || c==13) break;
        !           386:      else if (c==8 || c==16 || c==127) {
        !           387:        if (i>0) {
        !           388: 	 i--;  printf("%c %c",8,8); refresh();
        !           389:        } else   printf("%c",7);
        !           390:      } else if (i>=inmax) { printf("%c",7);
        !           391:      } else {
        !           392:        str[i++] = c;  ADDCH(c);
        !           393:      }
        !           394:    }
        !           395: #endif
        !           396:    str[i]=0;
        !           397: }
        !           398: 
        !           399: /*
        !           400: void                     
        !           401: input_pin(y,x,str,inmax) 
        !           402: int   y,x;               
        !           403: char *str;               
        !           404: int   inmax;             
        !           405: {                        
        !           406:    int  i=0,cx,cy;       
        !           407:    char c;               
        !           408: 
        !           409:    if (y && x)  move(y,x);
        !           410:    cx = x; cy = y;
        !           411:    CLRTOEOL();
        !           412: #ifdef __alpha
        !           413:    while (1) {
        !           414:       c=getch();
        !           415:       if (c==10 || c==13)   break;
        !           416:       else if (c==8 || c==16 || c==127) {
        !           417:          if (i>0) {
        !           418:             i--;  cx--;  echo(); move(cy,cx);
        !           419:             delch();  insch(' '); refresh(); noecho();
        !           420:          } else
        !           421:          beep();
        !           422:       } else if (i>=inmax) { beep(); } else {
        !           423:          str[i++] = c; cx++;
        !           424:          echo(); ADDCH('*'); noecho();
        !           425:       }
        !           426:    }
        !           427: #else  
        !           428:    while (1) {
        !           429:       c=getch();
        !           430:       if (c==10 || c==13) break;
        !           431:       else if (c==8 || c==16 || c==127) {
        !           432:          if (i>0) {
        !           433:             i--;  printf("%c %c",8,8); refresh();
        !           434:          } else   printf("%c",7);
        !           435:       } else if (i>=inmax) { printf("%c",7);
        !           436:       } else {
        !           437:          str[i++] = c;  ADDCH('*');
        !           438:       }
        !           439:    }
        !           440: #endif
        !           441:    str[i]=0;
        !           442: }
        !           443: */
        !           444: 
        !           445: /* ------------------------------------------------------------------------- */
        !           446: /* PAUSE UNTIL USER HITS A KEY                                               */
        !           447: /* ------------------------------------------------------------------------- */
        !           448: void         /* RETURNS: (nothing)   */
        !           449: mypause(y,x) /* ARGUMENTS:           */
        !           450: int y,x;     /*    Row,Col of screen */
        !           451: {            /* LOCAL VARIABLES:     */
        !           452:    char c;   /*    Input character   */
        !           453: 
        !           454:    mvaddstr(y,x,"Press ENTER/RETURN to continue");
        !           455:    get_input(y,x+30,&c,0);
        !           456: }
        !           457: 
        !           458: /* ------------------------------------------------------------------------- */
        !           459: /* DISPLAY FAREWELL MESSAGE WHEN USER LOGS OUT                               */
        !           460: /* ------------------------------------------------------------------------- */
        !           461: void               /* RETURNS: (nothing)      */
        !           462: properly_logout(student_number)       /* ARGUMENTS:      */
        !           463: char *student_number;
        !           464: {                  /* LOCAL VARIABLES:        */
        !           465:    FILE  *fp;       /*    Goodbye file pointer */
        !           466:    char   buf[255]; /*    Input buffer         */
        !           467:    char  *out_t;
        !           468:    char   filename[FILE_NAME_LENGTH];
        !           469:    
        !           470:    /* DISPLAY EXIT MESSAGE */
        !           471:    CLEAR();
        !           472:    time(&log_out_time);
        !           473:    out_t=ctime(&log_out_time);
        !           474:    out_t[ strlen(out_t)-1 ]=0; /* Trash newline */
        !           475: 
        !           476:    sprintf(filename,"records/duration.db");
        !           477:    if ((fp=fopen(filename,"a"))==NULL) {
        !           478:       printf("Error: can't open duration file\n");
        !           479:       return; 
        !           480:    }
        !           481:    flockstream(fp);
        !           482:    fprintf(fp,"%s\t%s\t%s\t%s\n",student_number,in_tty,in_t,out_t);
        !           483:    funlockstream(fp);
        !           484:    fclose(fp);
        !           485: 
        !           486: 
        !           487:    if ((fp=fopen("goodbye.msg","r"))!=NULL) {
        !           488:       while (fgets(buf,255,fp))
        !           489:          addstr(buf);
        !           490:       fclose(fp);
        !           491:    }
        !           492:    /* mypause(22,20); */
        !           493: #ifndef NO_DUP_CHECK
        !           494:    logout_check(student_number);
        !           495: #endif
        !           496: 
        !           497: #ifndef LOGIN_DBUG
        !           498:    sprintf(buf, "This message will last for only %d seconds.",g_delay);
        !           499:    mvaddstr(22,20,buf); refresh();
        !           500:    sleep(g_delay);
        !           501: #endif
        !           502: 
        !           503:    /* CURSES RESTORATION */
        !           504:    resetty(); endwin();
        !           505:    exit(1);
        !           506: }
        !           507: /* ------------------------------------------------------------------------- */
        !           508: /* Forbid duplicate login                                                    */
        !           509: /* ------------------------------------------------------------------------- */
        !           510: void               /* RETURNS: (nothing)      */
        !           511: dup_login_out()       /* ARGUMENTS:                */
        !           512: {                  /* LOCAL VARIABLES:        */
        !           513:    FILE *fp;       /*    Goodbye file pointer */
        !           514:    char  buf[255]; /*    Input buffer         */
        !           515: 
        !           516:    /* DISPLAY EXIT MESSAGE */
        !           517:    CLEAR();
        !           518:    if ((fp=fopen("third-login.msg","r"))!=NULL) {
        !           519:       while (fgets(buf,255,fp))   addstr(buf);
        !           520:       fclose(fp);
        !           521:    }
        !           522:    /* mypause(22,20);*/
        !           523:    /* CURSES RESTORATION */
        !           524:    sprintf(buf, "This message will last for only %d seconds.",g_delay);
        !           525:    mvaddstr(22,20,buf); refresh();
        !           526:    sleep(g_delay);
        !           527:    resetty(); endwin();
        !           528:    exit(1);
        !           529: }
        !           530: 
        !           531: void               /* RETURNS: (nothing)      */
        !           532: dup_login_warning()/* ARGUMENTS:              */
        !           533: {                  /* LOCAL VARIABLES:        */
        !           534:    FILE *fp;       /*    Welcome file pointer */
        !           535:    char  buf[255]; /*    Input buffer         */
        !           536: 
        !           537:    CLEAR();
        !           538:    if ((fp=fopen("second-login.msg","r"))!=NULL) {
        !           539:       while (fgets(buf,255,fp))
        !           540:          addstr(buf);
        !           541:       fclose(fp);
        !           542:    }
        !           543:    mypause(22,20);
        !           544: }
        !           545: 
        !           546: /* ------------------------------------------------------------------------- */
        !           547: /* ALLOW USER TO LOG IN                                                      */
        !           548: /* ------------------------------------------------------------------------- */
        !           549: char                          /* RETURNS: Student number                     */
        !           550: *login(maxset,section)        /* ARGUMENTS:                                  */
        !           551: int *maxset;                  /*    Set number                               */
        !           552: int *section;                 /*    Section number                           */
        !           553: {                             /* LOCAL VARIABLES:                            */
        !           554:    char    *student_number;   /*    Student number                           */
        !           555:    int      guess,            /*    User-entered PIN                         */
        !           556:             login_set;        /*    Set for which PIN is valid               */
        !           557:    int      login_section = 0;
        !           558:    char     buff[20];         /*    Input buffer                             */ 
        !           559:    T_entry  entry;
        !           560:    time_t   curtime;          /*    Current time                             */
        !           561:    int      leng;
        !           562:    T_student student_data;
        !           563: 
        !           564: #define    D_S_NUM_Y    11
        !           565: #define    D_S_NUM_X    13
        !           566: 
        !           567: #define    D_PIN_Y      (D_S_NUM_Y + 2)
        !           568: #define    D_PIN_X      (D_S_NUM_X + 10)
        !           569: #define    D_EXIT_Y     (D_S_NUM_Y + 5)
        !           570: #define    D_EXIT_X     (D_S_NUM_X + 6)
        !           571: #define    IN_S_NUM_Y   (D_S_NUM_Y)
        !           572: #define    IN_S_NUM_X   (D_S_NUM_X + 16)
        !           573: #define    IN_PIN_Y     (D_PIN_Y)
        !           574: #define    IN_PIN_X     (D_PIN_X + 9)
        !           575: #define    M_INVALID_Y  (IN_PIN_Y + 1)
        !           576: #define    M_INVALID_X  (IN_PIN_X)
        !           577: 
        !           578:    student_number = (char *)malloc( (MAX_STUDENT_NUMBER+4)*sizeof(char));
        !           579:    /* LOOP UNTIL WE ARE LEGALLY LOGGED IN */
        !           580:    do {
        !           581:       mvaddstr(D_S_NUM_Y,D_S_NUM_X,"STUDENT NUMBER: ");
        !           582:       mvaddstr(D_PIN_Y,D_PIN_X,"CAPA ID: ");
        !           583:       mvaddstr(D_EXIT_Y,D_EXIT_X,"To exit system, just hit ENTER/RETURN");
        !           584: 
        !           585: #ifndef  NO_PIN
        !           586:       /* LOOP UNTIL WE HAVE A STUDENT NUMBER AND PIN */
        !           587:       do {
        !           588: #endif  /* NO_PIN */
        !           589: 
        !           590:          /* LOOP UNTIL A LEGAL STUDENT NUMBER IS ENTERED */
        !           591:          do {
        !           592:             get_input(IN_S_NUM_Y,IN_S_NUM_X,buff, MAX_STUDENT_NUMBER);
        !           593: #ifdef __sun
        !           594:             if (!strlen(buff))    kick_out(0);
        !           595: #else
        !           596:             if (!strlen(buff))    kick_out();
        !           597: #endif
        !           598:             sscanf(buff,"%s",student_number); leng = strlen(student_number);
        !           599:          } while (leng < MAX_STUDENT_NUMBER);
        !           600: 
        !           601: #ifndef  NO_PIN
        !           602:          get_input(IN_PIN_Y,IN_PIN_X,buff,MAX_PIN_CHAR);
        !           603: #ifdef __sun
        !           604:          if (!strlen(buff))       kick_out(0);
        !           605: #else
        !           606:          if (!strlen(buff))       kick_out();
        !           607: #endif
        !           608:          sscanf(buff,"%d",&guess);
        !           609:       } while (guess<1);
        !           610: #endif   /* NO_PIN */
        !           611: 
        !           612:       student_number[strlen(student_number)] = 0;
        !           613:       /* VERIFY PIN */
        !           614: 
        !           615: #ifdef  NO_PIN
        !           616: login_set = 1;
        !           617: #else 
        !           618: login_set = capa_PIN(student_number,999,guess);
        !           619: #endif  /* No_PIN */
        !           620:       
        !           621: #ifdef LOGIN_DBUG
        !           622:   fprintf(dfp,"LOGIN:S=%s,Guess=%04d,Actual Pin=%04d,set=%d\n",
        !           623:    student_number,guess,capa_PIN(student_number,1, 0), login_set);
        !           624:   fprintf(dfp," PIN=%04d,%04d,%04d,%04d,%04d\n",
        !           625:    capa_PIN(student_number,1, 0), capa_PIN(student_number,2, 0),capa_PIN(student_number,3, 0),
        !           626:    capa_PIN(student_number,4, 0), capa_PIN(student_number,5, 0));
        !           627:   fflush(dfp);
        !           628: #endif
        !           629:       if (!login_set) {
        !           630:          mvaddstr(M_INVALID_Y,M_INVALID_X,   "INVALID LOGIN  ");
        !           631:       } else {
        !           632:          if ( login_set > 99 )  {
        !           633:            mvaddstr(M_INVALID_Y,M_INVALID_X, "INCORRECT PIN  ");  login_set = 0;
        !           634:          }
        !           635:          if ( capa_get_student(student_number,&student_data) == 0 ) {
        !           636:             mvaddstr(M_INVALID_Y,M_INVALID_X,"NO SUCH STUDENT");  login_set=0;
        !           637:          } else {
        !           638:             login_section = student_data.s_sec;
        !           639: #ifdef LOGIN_DBUG
        !           640:   fprintf(dfp, " Student in section %d\n",login_section);fflush(dfp);
        !           641: #endif
        !           642:             time(&curtime);
        !           643:             if( capa_check_date(CHECK_OPEN_DATE,student_number,
        !           644: 				login_section,login_set) < 0 ) {
        !           645:                mvaddstr(M_INVALID_Y,M_INVALID_X,"NOT YET OPEN!");  login_set=0;
        !           646:             }
        !           647:          }
        !           648:       }
        !           649:     } while ( !login_set );
        !           650: #ifdef LOGIN_DBUG
        !           651:   fprintf(dfp, "DEBUG:%s Access granted through set %d section %d\n",
        !           652:     student_number, login_set, login_section);  fflush(dfp);
        !           653: #endif
        !           654: #ifndef NO_DUP_CHECK
        !           655:     switch( login_check(student_number))  {
        !           656:       case 0:
        !           657:          mvaddstr(M_INVALID_Y,M_INVALID_X,"CANNOT LOGIN");  dup_login_out();
        !           658:          break;
        !           659:       case 1:
        !           660:          mvaddstr(M_INVALID_Y,M_INVALID_X,"FIRST TIME LOGIN");
        !           661:          break;
        !           662:       case 2:
        !           663:          mvaddstr(M_INVALID_Y,M_INVALID_X,"SECOND TIME LOGIN"); dup_login_warning( );
        !           664:          break;
        !           665:       case -1:
        !           666: #ifdef __sun
        !           667:         mvaddstr(M_INVALID_Y,M_INVALID_X,"FILE ERROR"); kick_out(0);
        !           668: #else
        !           669:         mvaddstr(M_INVALID_Y,M_INVALID_X,"FILE ERROR"); kick_out();
        !           670: #endif
        !           671:          break;
        !           672:     }
        !           673: #endif /* NO_DUP_CHECK */
        !           674:    capa_get_entry(&entry,student_number,login_set);
        !           675:    (*maxset) = login_set;
        !           676:    (*section) = login_section;
        !           677:    capa_mfree(entry.answers);
        !           678:    capa_mfree(entry.tries);
        !           679:    return (student_number);
        !           680: }
        !           681: 
        !           682: /* ------------------------------------------------------------------------- */
        !           683: /* LOG ANSWERS TO A FILE WITH TIMESTAMP                                      */
        !           684: /* ------------------------------------------------------------------------- */
        !           685: int                                                /* RETURNS: error code    */
        !           686: log_attempt(student_number,set,section,log_string) /* ARGUMENTS:             */
        !           687: char     student_number[MAX_STUDENT_NUMBER+1];     /*   Student number       */
        !           688: int   set;                                         /*   Set number           */
        !           689: int   section;                                     /*   Section number       */
        !           690: char *log_string;                                  /*   Answer string to log */
        !           691: {                                                  /* LOCAL VARIABLES:       */
        !           692:    char   filename[FILE_NAME_LENGTH],              /*   Log filename buffer  */
        !           693:          *ct;                                      /*   Current time string  */
        !           694:    FILE  *fp;                                      /*   Log file pointer     */
        !           695:    time_t t;                                       /*   Timestamp for log    */
        !           696: 
        !           697:    /* OPEN LOG FILE */
        !           698: 
        !           699:    sprintf(filename,"records/log%d.db",set);
        !           700:    if ((fp=fopen(filename,"a"))==NULL) {
        !           701:       printf("Error: can't open log file\n");
        !           702:       return -1; 
        !           703:    }
        !           704: 
        !           705:    /* CREATE LOG ENTRY */
        !           706:    time(&t);
        !           707:    ct=ctime(&t);
        !           708:    ct[ strlen(ct)-1 ]=0; /* Trash newline */
        !           709:    fprintf(fp,"%s %s %s\n",student_number,ct,log_string); fflush(fp);
        !           710:    fclose(fp);
        !           711:    return 0;
        !           712: }
        !           713: 
        !           714: int  log_submissions(student_number,set,log_string)
        !           715: char  student_number[MAX_STUDENT_NUMBER+1];     
        !           716: int   set;  
        !           717: char *log_string;                                
        !           718: {                                                  
        !           719:    char   filename[FILE_NAME_LENGTH], timeStr[FILE_NAME_LENGTH],buf2[MAX_BUFFER_SIZE];
        !           720:    FILE  *fp;                                     
        !           721:    time_t t;            
        !           722:    struct tm     *tmtime;
        !           723:    int do_log_submissions=1,result;
        !           724:    char buf[MAX_BUFFER_SIZE];
        !           725: 
        !           726:    result=read_capa_config("do_log_submissions",buf);
        !           727:    if (result != 0 && result != -1) {
        !           728:      if (strcasecmp(buf2,"no")==0) {
        !           729:        do_log_submissions=0;
        !           730:      } 
        !           731:    }
        !           732:    if (!do_log_submissions) return 0;
        !           733: 
        !           734:    sprintf(filename,"records/submissions%d.db",set);
        !           735:    if ((fp=fopen(filename,"a"))==NULL) {
        !           736:      return (-1);
        !           737:    }
        !           738: 
        !           739:    /* CREATE LOG ENTRY */
        !           740:    time(&t);
        !           741:    tmtime=localtime(&t);
        !           742:    strftime(timeStr,FILE_NAME_LENGTH,"%d/%m %X",tmtime);
        !           743:    /*ct[ strlen(ct)-1 ]=0;*/ /* Trash newline */
        !           744:    protect_log_string(log_string);
        !           745:    fprintf(fp,"%s\t%s\t%s\n",student_number,timeStr,log_string); fflush(fp);
        !           746:    fclose(fp);
        !           747:    return (0);
        !           748: }
        !           749: 
        !           750: #define   C_FORWARD    1
        !           751: #define   C_EXIT       2
        !           752: #define   C_MENU       3
        !           753: #define   C_HINT       4
        !           754: #define   C_EXPLAIN    5
        !           755: #define   C_ANSWER     6
        !           756: #define   C_JUMP       7
        !           757: #define   C_DONTCARE   8
        !           758: #define   C_BACKWARD   9
        !           759: #define   C_TIME       10
        !           760: #define   C_NEXTSCR    11
        !           761: #define   C_PREVSCR    12
        !           762: #define   C_SUBJANS    13
        !           763: 
        !           764: /* ------------------------------------------------------------------------- */
        !           765: /* DISPLAY SUMMARY OF SCORES FOR THE TERM                                    */
        !           766: /* ------------------------------------------------------------------------- */
        !           767: void                                     /* RETURNS: (nothing)          */
        !           768: term_summary(student_number,set,section,type) /* ARGUMENTS:             */
        !           769: char  *student_number;                   /*    Student Number           */
        !           770: int    set;                              /*    Set number               */
        !           771: int   *section;                          /*    Section Number           */
        !           772: int    type;
        !           773: {                                        /* LOCAL VARIABLES:            */
        !           774:    int      set_idx,                     /*    Set counter              */
        !           775:             i,                           /*    Question counter         */
        !           776:             tmp,                         /*    Question correct flag    */
        !           777:             set_score,                   /*    Score on a set           */
        !           778:             term_score=0,                /*    Total points received    */
        !           779:             term_total=0,                /*    Total points possible    */
        !           780:             result;
        !           781:    T_entry  entry;                       /*    Database entry for a set */
        !           782:    char     buf[MAX_BUFFER_SIZE], buf2[MAX_BUFFER_SIZE];
        !           783:    T_header header;                      /*    Problem set header       */
        !           784:    int      topset=1,                    /*    First displayed set      */
        !           785:             bottomset,                   /*    Last displayed set       */
        !           786:             done=0,                      /*    Done flag                */
        !           787:             line, col;
        !           788:    int      probs_in_set[MAX_BUFFER_SIZE],/*    # problem set questions  */
        !           789:             start_at[MAX_BUFFER_SIZE],
        !           790:             valid_wgt[SMALL_LINE_BUFFER],
        !           791:             a_valid_wgt,set_start_line,
        !           792: 	    usr_command,inhibit_response;
        !           793: 
        !           794:    /* CALCULATE TERM TOTALS */
        !           795:   start_at[0] = -2;
        !           796:   probs_in_set[0]= 0;
        !           797:   for (set_idx=1; set_idx<=set; set_idx++) {
        !           798:     if (capa_get_header(&header,set_idx))  return;
        !           799:     capa_get_entry(&entry,student_number,set_idx);
        !           800:     sscanf(header.num_questions,"%d", &(probs_in_set[set_idx]) );
        !           801:     start_at[set_idx] = start_at[set_idx-1]+2*(1+probs_in_set[set_idx-1]/50);
        !           802:     if ((start_at[set_idx]%12)+2*(1+probs_in_set[set_idx]/50) > 12)
        !           803:          start_at[set_idx] = 12*(1+start_at[set_idx]/12);
        !           804:     valid_wgt[set_idx] = 0;
        !           805:     for (i=0; i<probs_in_set[set_idx]; i++) {
        !           806:       valid_wgt[set_idx] +=  (header.weight[i] - '0');
        !           807:       if((entry.answers[i]=='Y') || (entry.answers[i]=='y'))  
        !           808: 	term_score += (header.weight[i]-'0');
        !           809:       if((entry.answers[i]=='E') || (entry.answers[i]=='e'))  
        !           810: 	valid_wgt[set_idx] -= (header.weight[i] - '0');
        !           811:       if((entry.answers[i]>='0') && (entry.answers[i]<='9'))  
        !           812: 	term_score += (entry.answers[i] - '0');
        !           813:     }
        !           814:     term_total += valid_wgt[set_idx];
        !           815:     capa_mfree(header.weight);
        !           816:     capa_mfree(header.partial_credit);
        !           817:     capa_mfree(entry.answers);
        !           818:     capa_mfree(entry.tries);
        !           819:   }
        !           820: 
        !           821:    /* FIND TOPSET */
        !           822:    line = 12*(start_at[set]/12);      /* Top line # of last screen */
        !           823:    for (topset=set; topset>1 && start_at[topset-1]>=line; topset--);
        !           824: 
        !           825:    /* SHOW HEADER */
        !           826:    CLEAR();
        !           827:    switch(type) {
        !           828:      case TERM_SUMMARY:    mvaddstr(1,30,"TERM SUMMARY"); break;
        !           829:      case EXAM_SUMMARY:    mvaddstr(1,30,"EXAM SUMMARY"); break;
        !           830:      case QUIZ_SUMMARY:    mvaddstr(1,30,"QUIZ SUMMARY"); break;
        !           831:    }
        !           832:    mvaddstr(3,22,"         1         2         3         4         5");
        !           833:    mvaddstr(4,22,"12345678901234567890123456789012345678901234567890");
        !           834: 
        !           835:    /* DISPLAY COMMAND MENU */
        !           836:    mvaddstr(21,1,"Enter a command from the list below and press ENTER/RETURN    COMMAND:");
        !           837:    mvaddstr(22,1,"M =Go to main menu  N =Next Page  P =Prev Page");
        !           838:    /* mvaddstr(22,1,"X =eXit M =Go to main menu  N =Next Page  P =Prev Page"); */
        !           839:    refresh();
        !           840: 
        !           841:    /* SHOW TOTALS */
        !           842:    /* if capalogin_show_summary_score is set to none don't show it */
        !           843:    sprintf(buf,"%d sets, total=%3d/%3d (%d%%)", set, term_score, term_total,
        !           844:       100*term_score/term_total);
        !           845:    result=read_capa_config("capalogin_show_summary_score",buf2);
        !           846:    if (result != 0 && result != -1) {
        !           847:      if (strcasecmp(buf2,"none")==0) {
        !           848:      } else {
        !           849:        mvaddstr(19,1,buf);
        !           850:      }
        !           851:    } else {
        !           852:      mvaddstr(19,1,buf);
        !           853:    }
        !           854: 
        !           855:    /* LOOP UNTIL DONE */
        !           856:   while (!done) {
        !           857:     /* PRINT 1 LINE SUMMARY PER SET */
        !           858:     line=5;
        !           859:     for (set_idx=topset; set_idx<=set; set_idx++) {
        !           860:       /* don't show summary for set if inhibit response is set*/
        !           861:       inhibit_response=capa_check_option(OPTION_INHIBIT_RESPONSE,set_idx,*section);
        !           862:       if (inhibit_response > 0) continue;
        !           863: 
        !           864:       set_score=0;
        !           865:       set_start_line=line;
        !           866:     /* Stop if not enough lines to summarize set */
        !           867:       if (line+2*(probs_in_set[set_idx]/50)>16)   break;
        !           868:       capa_get_header(&header,set_idx);
        !           869:       capa_get_entry(&entry,student_number,set_idx);
        !           870:       a_valid_wgt = 0;
        !           871:        for (i=0, col=0; i<probs_in_set[set_idx]; i++) {
        !           872:          tmp=0; a_valid_wgt += (header.weight[i] - '0');
        !           873:          move(line,  22+col); addch(entry.answers[i]);
        !           874:          move(line+1,22+col); addch(header.weight[i]);
        !           875:          switch(entry.answers[i]) {
        !           876:            case 'Y': tmp=header.weight[i] -'0'; break; /* Answer correct */
        !           877:            case 'y': tmp=header.weight[i] -'0'; break; /* Grading correct */
        !           878:            case '-': break;        /* Not answered    */
        !           879:            case 'N': break;        /* Answer incorrect */
        !           880:            case 'n': break;        /* Grading incorrect */
        !           881:            case 'e': a_valid_wgt -= (header.weight[i] - '0'); break;  /* Excuse    */
        !           882:            case 'E': a_valid_wgt -= (header.weight[i] - '0'); break;  /* Excuse    */
        !           883:            default : if( entry.answers[i] >= '0' && entry.answers[i] <= '9' ) {
        !           884:                        tmp = entry.answers[i] - '0';
        !           885:                      }
        !           886:                      break;
        !           887:          }
        !           888:          set_score  += tmp; col++;
        !           889:          if (!((i+1)%50)) { line += 2; col = 0; }
        !           890:        }
        !           891:        capa_mfree(header.weight);
        !           892:        capa_mfree(header.partial_credit);
        !           893:        capa_mfree(entry.answers);
        !           894:        capa_mfree(entry.tries);
        !           895:        move(line, 22+col);   CLRTOEOL();
        !           896:        move(line+1, 22+col); CLRTOEOL();
        !           897:        if(a_valid_wgt == 0) {
        !           898:          set_score=0;
        !           899:          sprintf(buf,"%3d:%3d/%3d(%3d%%)  ",set_idx,set_score,a_valid_wgt,set_score);
        !           900:          mvaddstr(set_start_line,1,buf);
        !           901:        } else {
        !           902:          sprintf(buf,"%3d:%3d/%3d(%3d%%)  ",set_idx,set_score,a_valid_wgt,100*set_score/a_valid_wgt);
        !           903:          mvaddstr(set_start_line,1,buf);
        !           904:        }
        !           905:        line += 2;
        !           906:     }
        !           907:     bottomset=set_idx-1;
        !           908: 
        !           909:       /* Blank out any extra lines */
        !           910:     if (line < 16) {
        !           911:      for (set_idx=line; set_idx<=16; set_idx++) {
        !           912:        move(set_idx,1);
        !           913:        CLRTOEOL();
        !           914:      }
        !           915:     }
        !           916: 
        !           917:       /* PROCESS USER COMMAND */
        !           918:       get_input(21,72,buf,1);
        !           919:       if(!strlen(buf)) { usr_command = C_FORWARD; } else {
        !           920:         
        !           921:           switch(toupper(buf[0])) {
        !           922:            /* case 'X': usr_command=C_EXIT;    break; */
        !           923:            case 'M': usr_command=C_MENU;    break;
        !           924: 	   case 'P': usr_command=C_BACKWARD; break;
        !           925:            default : usr_command=C_FORWARD;    break;
        !           926:           }
        !           927:       }
        !           928: 
        !           929:       
        !           930:       switch(usr_command) {
        !           931:       case C_DONTCARE: break;
        !           932:       case C_FORWARD: /* Forwards */
        !           933:                 if (bottomset<set) { topset=bottomset+1; } else { done=1; }
        !           934:                 break;
        !           935:       
        !           936:       case C_BACKWARD: /* Backwards */
        !           937:                 if (topset<2) break;
        !           938:                 line = 12*(start_at[topset-1]/12); /* Top line # of prev screen */
        !           939:                 for (; topset>1 && start_at[topset-1]>=line; topset--);
        !           940:                 break;
        !           941: 
        !           942:       case C_MENU: /* Menu */
        !           943:                 done=1;
        !           944:                 break;
        !           945:       case C_EXIT: /* Exit */
        !           946:                 properly_logout(student_number);
        !           947:                 break;
        !           948:       default:  /* Invalid command */
        !           949:                 break;
        !           950:       }
        !           951:    }
        !           952: }
        !           953: 
        !           954: void
        !           955: display_hint(char *h)
        !           956: {
        !           957: 
        !           958:   CLEAR();
        !           959: 
        !           960:   wrap(h);
        !           961:   mypause(22,20);
        !           962: }
        !           963: 
        !           964: #define   A_ROW    20
        !           965: #define   S_ROW    21
        !           966: #define   O_ROW    22
        !           967: #define   X_ROW    23
        !           968: 
        !           969: #define   A_COL    14
        !           970: #define   S_COL    46
        !           971: #define   H_COL    24
        !           972: #define   E_COL    39
        !           973: #define   X_COL    8
        !           974: #define   R_COL    57
        !           975: #define   U_ANS_CHAR  32
        !           976: 
        !           977: /* =============================================================================
        !           978: 0001234567890123456789012345678901234567890123456789012345678901234567890123456789
        !           979: A
        !           980: S1OPTION/ANSWER 12345678901234 -----            *Unanswered
        !           981: O2Options :M = Main Menu  :7 = go to #7  :N = Next screen  RETURN = Enter/Execute
        !           982: X3        :X = eXit       :H = Show Hint :E = Explain      RETURN = Next Problem
        !           983:   0123456789012345678901234567890123456789012345678901234567890
        !           984:           ^     ^         ^              ^      ^          ^
        !           985:           X     A         H              E      S          R
        !           986: */
        !           987: int  show_prior_response(Problem_t *p,int hgr,int prev_ans,int tried,int *allow_h)
        !           988: {
        !           989:   char     *c_answer_str, tmp_str[MAX_BUFFER_SIZE];
        !           990:   char     *response="Incorrect",*answered="Answered";
        !           991:   int       can_answer;
        !           992:   
        !           993:   if( hgr == '0' || p->ans_type==ANSWER_IS_SUBJECTIVE) {
        !           994:     switch(prev_ans) {
        !           995:       case 'Y': can_answer=NAY; *allow_h=1;
        !           996:                 c_answer_str = answers_string(ANSWER_STRING_MODE,p);
        !           997:                 move(A_ROW,A_COL); clrtoeol();  
        !           998:                 mvaddstr(A_ROW,A_COL,c_answer_str); capa_mfree(c_answer_str);
        !           999:                 move(S_ROW,S_COL); clrtoeol();
        !          1000:                 mvaddstr(S_ROW,S_COL,"**Correct              "); break;
        !          1001:       case 'y': can_answer=NAY; *allow_h=1;
        !          1002:                 c_answer_str = answers_string(ANSWER_STRING_MODE,p);
        !          1003:                 move(A_ROW,A_COL); clrtoeol();
        !          1004:                 mvaddstr(A_ROW,A_COL,c_answer_str); capa_mfree(c_answer_str);
        !          1005:                 move(S_ROW,S_COL); clrtoeol();
        !          1006:                 mvaddstr(S_ROW,S_COL,"*Hand-graded Correct      "); break;
        !          1007:       case '-': can_answer=YAK; move(S_ROW,S_COL); clrtoeol();
        !          1008:                 mvaddstr(S_ROW,S_COL,"*Unanswered               "); break;
        !          1009:       case 'E': can_answer=NAY; move(S_ROW,S_COL); clrtoeol();
        !          1010:                 mvaddstr(S_ROW,S_COL,"*Excused                  "); break;
        !          1011:       case 'e': can_answer=NAY; move(S_ROW,S_COL); clrtoeol();
        !          1012:                 mvaddstr(S_ROW,S_COL,"*Excused                  "); break;
        !          1013:       case 'n': can_answer=NAY; move(S_ROW,S_COL); clrtoeol();
        !          1014:                 mvaddstr(S_ROW,S_COL,"*Hand-graded Incorrect    "); break;
        !          1015:     case '0': case '1': case '2': case '3': case '4': case '5': 
        !          1016:     case '6': case '7': case '8': case '9':
        !          1017:       response=answered;
        !          1018:     case 'N':   if ( tried < p->tries ) {
        !          1019:                   can_answer=YAK;
        !          1020: 		  if( (p->tries - tried) == 1 ) {
        !          1021: 		    sprintf(tmp_str,"*%s, ONE try left!!",response);
        !          1022: 		  } else {
        !          1023: 		    sprintf(tmp_str,"*%s, tries %2d/%2d   ",response,tried,p->tries);
        !          1024: 		  }
        !          1025:                 } else {
        !          1026: 		  can_answer=NAY;
        !          1027: 		  sprintf(tmp_str,  "*%s, no more tries",response);
        !          1028: 		}
        !          1029:                 move(S_ROW,S_COL); clrtoeol();
        !          1030:                 mvaddstr(S_ROW,S_COL,tmp_str); 
        !          1031:                 if( (can_answer == YAK) && (p->ans_op == ANS_AND) && (p->ans_cnt > 1)) {
        !          1032:                    sprintf(tmp_str, " Entering answer   1 of %3d     ",p->ans_cnt);
        !          1033:                    mvaddstr(A_ROW,S_COL,tmp_str);
        !          1034:                 }
        !          1035:                 break;
        !          1036:     }
        !          1037:   } else {  /* hand graded question */
        !          1038:     can_answer=NAY;
        !          1039:     move(S_ROW,S_COL); clrtoeol();
        !          1040:     mvaddstr(S_ROW,S_COL,"*Hand-graded question     ");
        !          1041:   }
        !          1042:   /* ------------------------------------------------------------------ */
        !          1043:   if (*allow_h && 
        !          1044:       p->hint && 
        !          1045:       (
        !          1046:        ( p->show_hint <= tried ) || 
        !          1047:        ( prev_ans == 'y' ) ||
        !          1048:        ( prev_ans == 'Y' )
        !          1049:        )
        !          1050:       ) {
        !          1051:     mvaddstr(X_ROW,H_COL,":H = Show Hint");
        !          1052:   } else {
        !          1053:     *allow_h = 0;
        !          1054:   }
        !          1055:   if (p->next)
        !          1056:     mvaddstr(X_ROW,R_COL,"RETURN = Next Problem");
        !          1057:   else
        !          1058:     mvaddstr(X_ROW,R_COL,"RETURN = Main Menu   ");
        !          1059:   
        !          1060:   return (can_answer);
        !          1061:   
        !          1062: }
        !          1063: int  show_prior_inhibited_response(Problem_t *p,int hgr,int prev_ans,int tried,
        !          1064: 				   int *allow_h)
        !          1065: {
        !          1066:   char     tmp_str[MAX_BUFFER_SIZE];
        !          1067:   int      can_answer;
        !          1068:   
        !          1069:   if( hgr == '0' ) {
        !          1070:     switch(prev_ans) {
        !          1071:       case '-': can_answer=YAK; move(S_ROW,S_COL); clrtoeol();
        !          1072:                 mvaddstr(S_ROW,S_COL,"*Unanswered               "); break;
        !          1073:       case 'E':
        !          1074:       case 'e':
        !          1075:       case 'n':
        !          1076:       case 'y': 
        !          1077:       case 'Y': 
        !          1078:       case 'N': if ( tried < p->tries ) {
        !          1079: 	          can_answer=YAK;
        !          1080: 		  if( (p->tries - tried) == 1 ) {
        !          1081: 		    sprintf(tmp_str,"*Answered, ONE try left!! ");
        !          1082: 		  } else {
        !          1083: 		    sprintf(tmp_str,"*Answered, tries %2d/%2d    ",tried,p->tries);
        !          1084: 		  }
        !          1085:                 } else {
        !          1086: 		  can_answer=NAY;
        !          1087: 		  sprintf(tmp_str,  "*Answered, no more tries ");
        !          1088: 		}
        !          1089:                 move(S_ROW,S_COL); clrtoeol();
        !          1090:                 mvaddstr(S_ROW,S_COL,tmp_str); break;
        !          1091:            
        !          1092:     }
        !          1093:   } else {  /* hand graded question */
        !          1094:     can_answer=NAY;
        !          1095:     move(S_ROW,S_COL); clrtoeol();
        !          1096:     mvaddstr(S_ROW,S_COL,"*Hand-graded question     ");
        !          1097:   }
        !          1098:   /* ------------------------------------------------------------------ */
        !          1099:   if (*allow_h && p->hint && ( p->show_hint <= tried)){
        !          1100:     mvaddstr(X_ROW,H_COL,":H = Show Hint");
        !          1101:   } else {
        !          1102:     *allow_h = 0;
        !          1103:   }
        !          1104:   if (p->next)
        !          1105:     mvaddstr(X_ROW,R_COL,"RETURN = Next Problem");
        !          1106:   else
        !          1107:     mvaddstr(X_ROW,R_COL,"RETURN = Main Menu   ");
        !          1108:   
        !          1109:   return (can_answer);
        !          1110:   
        !          1111: }
        !          1112: /* -------------------------------------------- dbug --------------------- */
        !          1113: void
        !          1114: print_unit_components(FILE *fp,Unit_t *t) 
        !          1115: {
        !          1116:   Unit_E  *ue_p;
        !          1117: 
        !          1118:   fprintf(fp,"  Unit::[%s] = %g * ", t->u_symbol, t->u_scale);
        !          1119:   for(ue_p=t->u_list; ue_p ; ue_p = ue_p->ue_nextp) {
        !          1120:     fprintf(fp,"(%g*%s^%g) ",ue_p->ue_scale,ue_p->ue_symbol,ue_p->ue_exp);
        !          1121:   }
        !          1122:   fprintf(fp,"\n"); fflush(fp);
        !          1123: 
        !          1124: }
        !          1125: 
        !          1126: 
        !          1127: #define    ANSWER_STRING_LENG       64
        !          1128: #define    UNIT_STRING_LENG         64
        !          1129: #define    FORMAT_STRING_LENG       32
        !          1130: 
        !          1131: /* ------------------------------------------------------------------- */
        !          1132: int  give_response(Problem_t *p,char **a,int cnt,int *tried,int *log_char)
        !          1133: {
        !          1134:   int      can_answer;
        !          1135:   char     tmp_str[MAX_BUFFER_SIZE], *c_answer_str;
        !          1136: 
        !          1137: 
        !          1138:   switch( capa_check_answers(p,a,cnt) ) {
        !          1139: 
        !          1140:     case  EXACT_ANS:  move(A_ROW,S_COL); clrtoeol();
        !          1141:                       mvaddstr(A_ROW,S_COL,"*Yes Computer gets:"); 
        !          1142:                       c_answer_str = answers_string(ANSWER_STRING_MODE, p);
        !          1143:                       move(S_ROW,S_COL); clrtoeol();
        !          1144:                       mvaddstr(S_ROW,S_COL,c_answer_str);
        !          1145:                       capa_mfree((char *)c_answer_str);
        !          1146:                      *log_char='Y'; can_answer=NAY;
        !          1147:                       if( *tried < TRY_BOUND)  (*tried)++;
        !          1148:                       break;
        !          1149:     case  APPROX_ANS: 
        !          1150:                       move(A_ROW,S_COL); clrtoeol();
        !          1151:                       mvaddstr(A_ROW,S_COL,"*Yes Computer gets:");
        !          1152:                       c_answer_str = answers_string(ANSWER_STRING_MODE, p);
        !          1153:                       if(cnt == 1 ) {
        !          1154:                         move(S_ROW,S_COL); clrtoeol();
        !          1155:                         mvaddstr(S_ROW,S_COL,c_answer_str);
        !          1156:                       } else {  /* more than one answer to check ANS_AND */
        !          1157:                         move(S_ROW,S_COL); clrtoeol();
        !          1158:                         mvaddstr(S_ROW,S_COL,"*Yes Correct Answers See Above");
        !          1159:                         move(A_ROW,A_COL); clrtoeol();
        !          1160:                         mvaddstr(A_ROW,A_COL,c_answer_str);
        !          1161:                       }
        !          1162:                       capa_mfree((char *)c_answer_str);
        !          1163:                      *log_char='Y'; can_answer=NAY;
        !          1164:                       if(*tried < TRY_BOUND)  (*tried)++;
        !          1165:                       break;
        !          1166:     case  SIG_FAIL:   move(S_ROW,S_COL); clrtoeol();  
        !          1167:                       mvaddstr(S_ROW,S_COL,"*Adjust Sig. Figs. ");
        !          1168:                      *log_char='S'; can_answer=YAK;
        !          1169:                       break;
        !          1170:     case  UNIT_FAIL:  move(S_ROW,S_COL); clrtoeol();  
        !          1171:                       mvaddstr(S_ROW,S_COL,"*Units incorrect   ");
        !          1172:                      *log_char='U'; can_answer=YAK;
        !          1173:                       break;
        !          1174:     case  UNIT_NOTNEEDED:  move(S_ROW,S_COL); clrtoeol();  
        !          1175:                       mvaddstr(S_ROW,S_COL,"*Only a number required");
        !          1176:                      *log_char='U'; can_answer=YAK;
        !          1177:                       break;
        !          1178:     case  NO_UNIT:    move(S_ROW,S_COL); clrtoeol();  
        !          1179:                       mvaddstr(S_ROW,S_COL,"*Units required    ");
        !          1180:                      *log_char='u'; can_answer=YAK;
        !          1181:                       break;
        !          1182:     case  BAD_FORMULA:move(S_ROW,S_COL); clrtoeol();  
        !          1183:                       mvaddstr(S_ROW,S_COL,"*Unable to interpret formula");
        !          1184:                      *log_char='F'; can_answer=YAK;
        !          1185:                       break;
        !          1186:     case  ANS_CNT_NOT_MATCH:
        !          1187:                       move(S_ROW,S_COL); clrtoeol();  
        !          1188:                       mvaddstr(S_ROW,S_COL,"*Invalid number of answers");
        !          1189:                      *log_char='C'; can_answer=YAK;
        !          1190:                       break;
        !          1191:     case  INCORRECT: 
        !          1192:                       if(*tried < TRY_BOUND)  (*tried)++;
        !          1193: 		      if ( *tried < p->tries ) {
        !          1194: 			can_answer=YAK;
        !          1195: 			if( (p->tries - *tried) == 1 ) {
        !          1196: 			  sprintf(tmp_str,"*Incorrect, ONE try left!!");
        !          1197: 			} else {
        !          1198: 			  sprintf(tmp_str,"*Incorrect, tries %2d/%2d   ",*tried,p->tries);
        !          1199: 			}
        !          1200: 		      } else {
        !          1201: 			can_answer=NAY;
        !          1202: 			sprintf(tmp_str,  "*Incorrect, no more tries");
        !          1203: 		      }
        !          1204:                       move(S_ROW,S_COL); clrtoeol(); 
        !          1205:                       mvaddstr(S_ROW,S_COL, tmp_str);
        !          1206:                       if( (can_answer == YAK) && (p->ans_op == ANS_AND) && (p->ans_cnt > 1)  ) {
        !          1207:                          sprintf(tmp_str, " Entering answer   1 of %3d     ",p->ans_cnt);
        !          1208:                          mvaddstr(A_ROW,S_COL,tmp_str);
        !          1209:                       }
        !          1210: 	             *log_char='N';
        !          1211: 	              break;
        !          1212:   }
        !          1213:    
        !          1214:   return (can_answer);
        !          1215: }
        !          1216: 
        !          1217: int  give_inhibited_response(Problem_t *p,char **a,int cnt,int *tried,int *log_char)
        !          1218: {
        !          1219:   int      can_answer;
        !          1220:   char     tmp_str[MAX_BUFFER_SIZE];
        !          1221: 
        !          1222: 
        !          1223:   switch( capa_check_answers(p,a,cnt) ) {
        !          1224: 
        !          1225: 
        !          1226:     case  EXACT_ANS:  *log_char='Y'; break;
        !          1227:     case  APPROX_ANS: *log_char='Y'; break;
        !          1228:     case  SIG_FAIL:   *log_char='S'; break;
        !          1229:     case  UNIT_FAIL:  *log_char='U'; break;
        !          1230:     case  UNIT_NOTNEEDED: *log_char='U'; break;
        !          1231:     case  NO_UNIT:    *log_char='u'; break;
        !          1232:     case  BAD_FORMULA:*log_char='F'; break;
        !          1233:     case  INCORRECT:  *log_char='N'; break;
        !          1234:     case ANS_CNT_NOT_MATCH: *log_char='C'; break;
        !          1235:   }
        !          1236:   
        !          1237:   if(*tried < TRY_BOUND)  (*tried)++;
        !          1238:   if ( *tried < p->tries ) {
        !          1239:     can_answer=YAK;
        !          1240:     if( (p->tries - *tried) == 1 ) {
        !          1241:       sprintf(tmp_str,"*Answered, ONE try left!! ");
        !          1242:     } else {
        !          1243:       sprintf(tmp_str,"*Answered, tries %2d/%2d    ",*tried,p->tries);
        !          1244:     }
        !          1245:   } else {
        !          1246:     can_answer=NAY;
        !          1247:     sprintf(tmp_str,  "*Answered, no more tries ");
        !          1248:   }
        !          1249:   move(S_ROW,S_COL); clrtoeol(); 
        !          1250:   mvaddstr(S_ROW,S_COL, tmp_str);
        !          1251:   return (can_answer);
        !          1252: }
        !          1253: 
        !          1254: int  ask_what_prob(int q_cnt, char *ans)
        !          1255: {
        !          1256:   int  not_ok=1,num,anslength,i,j;
        !          1257:   char buf[5],buf2[MAX_BUFFER_SIZE];
        !          1258:   
        !          1259:   move(14,35); clrtoeol();
        !          1260:   move(17,5);  clrtoeol();
        !          1261:   do {
        !          1262:      move(14,35); clrtoeol();
        !          1263:      move(15,0);  clrtoeol();
        !          1264:      mvaddstr(15,13,"What problem number:");
        !          1265:      move(17,0);  clrtoeol();
        !          1266:      mvaddstr(17,16,"         1         2         3         4         5");
        !          1267:      mvaddstr(18,16,"12345678901234567890123456789012345678901234567890");
        !          1268:      anslength=strlen(ans);
        !          1269:      for(i=0;i<=(anslength/50);i++) {
        !          1270:        if ( g_inhibit_response ) {
        !          1271: 	 for(j=50*i;(j<((i+1)*50))&&(j<anslength);j++) {
        !          1272: 	   if (ans[j]=='-') 
        !          1273: 	     buf2[j-(50*i)]='-';
        !          1274: 	   else
        !          1275: 	     buf2[j-(50*i)]='A';
        !          1276: 	 }
        !          1277: 	 buf2[j-(50*i)]='\0';
        !          1278:        } else {
        !          1279: 	 strncpy(buf2,&(ans[50*i]),50);
        !          1280:        }
        !          1281:        buf2[50]='\0';
        !          1282:        mvaddstr(19+i,16,buf2);
        !          1283:        if (anslength > 50 ) {
        !          1284: 	 sprintf(buf2,"%3d-%3d",i*50+1,(i+1)*50);
        !          1285: 	 mvaddstr(19+i,5,buf2);
        !          1286:        }
        !          1287:      }
        !          1288:      do { get_input(15,34,buf,4); } while(!strlen(buf));
        !          1289:      sscanf(buf,"%d",&num);
        !          1290:      if (num<1 || num>q_cnt) {
        !          1291:         move(21,5); clrtoeol();
        !          1292:         mvaddstr(21,15,"  Error: Invalid problem number\n");
        !          1293:      } else {
        !          1294:         not_ok = 0;
        !          1295:      }
        !          1296:   } while (not_ok);
        !          1297: 
        !          1298:   return (num);
        !          1299: }
        !          1300: 
        !          1301: /* gather subjective answers from student */
        !          1302: 
        !          1303: #define    BS    8
        !          1304: #define    DEL   127
        !          1305: #define    ESC   27
        !          1306: 
        !          1307: #define    COLON 58
        !          1308: 
        !          1309: #define EDIT_HEIGHT 21
        !          1310: #define EDIT_WIDTH 80
        !          1311: #define MENULINE EDIT_HEIGHT
        !          1312: 
        !          1313: void refresh_editor (char **sbuf_pp,int cx,int cy) {
        !          1314:   int i;
        !          1315:   CLEAR();
        !          1316:   echo();
        !          1317:   mvaddstr(MENULINE,0,"Type in the answer, use up, down, left, right keys to move curser");
        !          1318:   mvaddstr(MENULINE+1,0,"Enter ctrl-e to exit and submit answer");
        !          1319:   mvaddstr(MENULINE+2,0,"Enter ctrl-f to forget answer");
        !          1320:   for(i=0;i<EDIT_HEIGHT;i++) { mvaddstr(i,0,sbuf_pp[i]); }
        !          1321:   move(cy,cx); refresh(); noecho();
        !          1322: }
        !          1323: 
        !          1324: void init_editor(char*** sbuf_pp)
        !          1325: {
        !          1326:   int   ww=EDIT_WIDTH, hh=EDIT_HEIGHT,i;
        !          1327:   *sbuf_pp = (char **)capa_malloc(sizeof(char *),hh);
        !          1328:   for(i=0;i<hh;i++) {
        !          1329:     (*sbuf_pp)[i] = (char *)capa_malloc(sizeof(char)*ww+1,1);
        !          1330:   }
        !          1331:   CLEAR();echo();
        !          1332:   mvaddstr(MENULINE,0,"Type in the answer, use up, down, left, right keys to move cursor");
        !          1333:   mvaddstr(MENULINE+1,0,"Enter ctrl-e to exit and submit answer");
        !          1334:   mvaddstr(MENULINE+2,0,"Enter ctrl-f to forget answer");
        !          1335:   move(0,0); refresh(); noecho();
        !          1336: }
        !          1337: 
        !          1338: void remove_character(char** sbuf_pp,int *cx,int *cy)
        !          1339: {
        !          1340:   int sx=(*cx)-1,sy=*cy;
        !          1341:   char temp,*temp_p;
        !          1342:   if (*cx==0) { 
        !          1343:     int abovelen,curlen,diff,i,j;
        !          1344:     if (*cy==0) { beep();return;}
        !          1345:     abovelen=strlen(sbuf_pp[(*cy-1)]);
        !          1346:     curlen=strlen(sbuf_pp[*cy]);
        !          1347:     if (abovelen > 0) sbuf_pp[(*cy)-1][abovelen-1]='\0';
        !          1348:     if ((abovelen+curlen) < EDIT_WIDTH) {
        !          1349:       strcat(sbuf_pp[(*cy)-1],sbuf_pp[*cy]);
        !          1350:       memset(sbuf_pp[(*cy)],'\0',EDIT_WIDTH+1);
        !          1351:       temp_p=sbuf_pp[*cy];
        !          1352:       i=*cy;
        !          1353:       while(i<EDIT_HEIGHT-1) {
        !          1354: 	sbuf_pp[i]=sbuf_pp[i+1];
        !          1355: 	echo();move(i,0);CLRTOEOL();mvaddstr(i,0,sbuf_pp[i]);noecho();
        !          1356: 	i++;
        !          1357:       }
        !          1358:       sbuf_pp[EDIT_HEIGHT-1]=temp_p;
        !          1359:       echo();move(EDIT_HEIGHT-1,0);CLRTOEOL();noecho();
        !          1360:     } else {
        !          1361:       diff=EDIT_WIDTH-abovelen;
        !          1362:       strncat(sbuf_pp[(*cy)-1],sbuf_pp[*cy],diff);
        !          1363:       i=diff;j=0;
        !          1364:       while(sbuf_pp[*cy][i]!='\0') {
        !          1365: 	sbuf_pp[*cy][j]=sbuf_pp[*cy][i];
        !          1366: 	i++;j++;
        !          1367:       }
        !          1368:       memset(&(sbuf_pp[(*cy)][j]),'\0',EDIT_WIDTH+1-j);
        !          1369:     }
        !          1370:     echo();move(*cy,0); CLRTOEOL(); mvaddstr(*cy,0,sbuf_pp[*cy]);noecho();
        !          1371:     (*cy)--;
        !          1372:     echo();move(*cy,0); CLRTOEOL(); mvaddstr(*cy,0,sbuf_pp[*cy]);noecho();
        !          1373:     if ( EDIT_WIDTH == ((*cx)=(abovelen-1))) (*cx)--;
        !          1374:     if (abovelen==0) *cx=0;
        !          1375:     echo();move(*cy,*cx);noecho();
        !          1376:   } else {
        !          1377:     echo();move(sy,sx);noecho();
        !          1378:     temp=sbuf_pp[sy][sx]=sbuf_pp[sy][sx+1];
        !          1379:     sx++;
        !          1380:     while(temp!='\0') {
        !          1381:       echo(); ADDCH(temp); noecho();
        !          1382:       temp=sbuf_pp[sy][sx]=sbuf_pp[sy][sx+1];
        !          1383:       sx++;
        !          1384:     }
        !          1385:     echo(); ADDCH(' '); noecho();
        !          1386:     (*cx)--;
        !          1387:   }
        !          1388:   echo();move(*cy,*cx);noecho();
        !          1389: }
        !          1390: 
        !          1391: void break_line      (char** sbuf_pp,int *cx,int *cy)
        !          1392: {
        !          1393:   int sx=*cx,sy=*cy,i;
        !          1394:   if (sy < EDIT_HEIGHT-1) {
        !          1395:     capa_mfree(sbuf_pp[EDIT_HEIGHT-1]);
        !          1396:     i=EDIT_HEIGHT-1;
        !          1397:     while (i-1 > sy) {
        !          1398:       sbuf_pp[i]=sbuf_pp[i-1];
        !          1399:       move(i,0);CLRTOEOL();mvaddstr(i,0,sbuf_pp[i]);
        !          1400:       i--;
        !          1401:     }
        !          1402:     sbuf_pp[sy+1]=capa_malloc(sizeof(char)*EDIT_WIDTH+1,1);
        !          1403:   }
        !          1404:   strcat(sbuf_pp[sy+1],&(sbuf_pp[sy][sx]));
        !          1405:   memset(&(sbuf_pp[sy][sx]),'\0',EDIT_WIDTH+1-sx);
        !          1406:   *cx=0;
        !          1407:   (*cy)++;
        !          1408:   move(sy,0);CLRTOEOL();mvaddstr(sy,0,sbuf_pp[sy]);
        !          1409:   move(sy+1,0);CLRTOEOL();mvaddstr(sy+1,0,sbuf_pp[sy+1]);
        !          1410: }
        !          1411: 
        !          1412: /* FIXME catch funtion keys and others? */
        !          1413: void handle_esc      (unsigned char ca,unsigned char cb,char** sbuf_pp,int *cx,int *cy)
        !          1414: {
        !          1415:   if( ca!='[') return;
        !          1416:   switch (cb) {
        !          1417:   case 'A':/* KEY_UP */
        !          1418:     if(*cy>0){
        !          1419:       (*cy)--;
        !          1420:       while(*cx>0 && sbuf_pp[*cy][(*cx)-1]=='\0') (*cx)--; /* goto end of line */
        !          1421:     } else {
        !          1422:       beep();
        !          1423:     }
        !          1424:     break;
        !          1425:   case 'B': /* KEY_DOWN */
        !          1426:     if (*cy<(EDIT_HEIGHT-1)) {
        !          1427:       (*cy)++;
        !          1428:       while(*cx>0 && sbuf_pp[*cy][(*cx)-1]=='\0') (*cx)--; /* goto end of line */
        !          1429:     } else {
        !          1430:       beep();
        !          1431:     }
        !          1432:     break;
        !          1433:   case 'C': /* KEY_RIGHT */
        !          1434:     if ( *cx<(EDIT_WIDTH-1) && sbuf_pp[*cy][(*cx)]!='\0' ) { 
        !          1435:       (*cx)++; 
        !          1436:     } else {
        !          1437:       if (*cy<(EDIT_HEIGHT-1)) {
        !          1438: 	(*cy)++; *cx=0; 
        !          1439:       } else {
        !          1440: 	beep();
        !          1441:       }
        !          1442:     }
        !          1443:     break;
        !          1444:   case 'D': /* KEY_LEFT */
        !          1445:     if(*cx>0) {
        !          1446:       (*cx)--;
        !          1447:     } else {
        !          1448:       if(*cy>0) { 
        !          1449: 	(*cy)--;
        !          1450: 	*cx=strlen(sbuf_pp[*cy]);
        !          1451: 	if (*cx==EDIT_WIDTH) (*cx)--;
        !          1452:       } else { 
        !          1453: 	beep(); 
        !          1454:       }
        !          1455:     }
        !          1456:     break;
        !          1457:   default: beep(); return; break;
        !          1458:   }
        !          1459:   echo(); move(*cy,*cx); refresh(); noecho();
        !          1460: }
        !          1461: 
        !          1462: void handle_error    (unsigned char c,char** sbuf_pp,int cx,int cy) 
        !          1463: {
        !          1464:   beep();
        !          1465: }
        !          1466: 
        !          1467: /*FIXME Slower than whale shit*/
        !          1468: void insert_character(unsigned char c,char** sbuf_pp,int *cx,int *cy) 
        !          1469: {
        !          1470:   int sx=*cx,sy=*cy;
        !          1471:   unsigned char temp;
        !          1472:   while(c!='\0') {
        !          1473:     if (sx == EDIT_WIDTH) {
        !          1474:       sx=0;sy++;
        !          1475:       if (sy == EDIT_HEIGHT) {
        !          1476: 	sy--;sx=EDIT_WIDTH;c='\0';break;
        !          1477:       }
        !          1478:     }	
        !          1479:     echo(); ADDCH(c); noecho();
        !          1480:     temp=sbuf_pp[sy][sx];
        !          1481:     sbuf_pp[sy][sx]=c;
        !          1482:     c=temp;
        !          1483:     sx++;
        !          1484:   }
        !          1485:   sbuf_pp[sy][sx]=c;
        !          1486:   (*cx)++;
        !          1487:   if (*cx == EDIT_WIDTH) {
        !          1488:       *cx=0;(*cy)++;
        !          1489:       if (*cy == EDIT_HEIGHT) {
        !          1490: 	(*cy)--;*cx=EDIT_WIDTH-1;
        !          1491:       }
        !          1492:   }
        !          1493:   move(*cy,*cx);refresh();
        !          1494: }
        !          1495: 
        !          1496: int handle_keystrokes_editor(char** sbuf_pp)
        !          1497: {
        !          1498:   int   done = 0, forget = 0, cx=0,cy=0;
        !          1499:   unsigned char c,ca,cb;
        !          1500: 
        !          1501:   while (!done) {
        !          1502:     move(cy,cx);refresh();
        !          1503:     c=getch();
        !          1504:     switch(c) {
        !          1505:     case BS: case DEL:
        !          1506:       remove_character(sbuf_pp,&cx,&cy);
        !          1507:       break;
        !          1508:     case CR: case LF:
        !          1509:       break_line(sbuf_pp,&cx,&cy);
        !          1510:       break;
        !          1511:     case ESC:
        !          1512:       ca=getch();cb=getch();
        !          1513:       handle_esc(ca,cb,sbuf_pp,&cx,&cy);
        !          1514:       break;
        !          1515:     case 5: /*ctrl-e*/
        !          1516:       done=1;
        !          1517:       break;
        !          1518:     case 6: /*ctrl-f*/
        !          1519:       done=1;
        !          1520:       forget=1;
        !          1521:       break;
        !          1522:     case 12:
        !          1523:       refresh_editor(sbuf_pp,cx,cy);
        !          1524:       break;
        !          1525:     default:
        !          1526:       if (c < 32 || c>126) {
        !          1527: 	handle_error(c,sbuf_pp,cx,cy);
        !          1528:       } else {
        !          1529: 	insert_character(c,sbuf_pp,&cx,&cy);
        !          1530:       }
        !          1531:       break;
        !          1532:     }
        !          1533:   }
        !          1534:   return forget;
        !          1535: }
        !          1536: 
        !          1537: int editor(char*** sbuf_pp)
        !          1538: {
        !          1539:   init_editor(sbuf_pp);
        !          1540:   return handle_keystrokes_editor(*sbuf_pp);
        !          1541: }
        !          1542: 
        !          1543: 
        !          1544: int
        !          1545: answer_subjective(student_number,set,section,prob)
        !          1546: char  *student_number; 
        !          1547: int    set; 
        !          1548: int   *section;
        !          1549: int    prob;
        !          1550: {
        !          1551:   int i,length;
        !          1552:   char date_str[DATE_LENGTH];
        !          1553:   char **sbuf_pp,answer[(EDIT_HEIGHT*(EDIT_WIDTH+1))+1];
        !          1554:   char submissions_str[(EDIT_HEIGHT*(EDIT_WIDTH+1))+MAX_BUFFER_SIZE];
        !          1555:   time_t     curtime;
        !          1556: 
        !          1557:   time(&curtime);
        !          1558:   if( capa_check_date(CHECK_DUE_DATE,student_number,*section,set) > 0 ) {
        !          1559:     capa_get_date(CHECK_DUE_DATE,student_number,*section,set,date_str);
        !          1560:     sprintf(answer,"Sorry, the due date was: %s",date_str);
        !          1561:     move(20,1); clrtobot(); addstr(answer); mypause(23,1);
        !          1562:     return 0;
        !          1563:   }
        !          1564: 
        !          1565:   if (editor(&sbuf_pp)) { return 0; }
        !          1566: 
        !          1567:   answer[0]='\0';
        !          1568:   for(i=0;i<EDIT_HEIGHT;i++) {
        !          1569:     if (strlen(sbuf_pp[i]) > 0) {
        !          1570:       strcat(answer,sbuf_pp[i]);
        !          1571:       length=strlen(answer);
        !          1572:       answer[length]='\n';
        !          1573:       answer[length+1]='\0';
        !          1574:     }
        !          1575:     capa_mfree((char *)sbuf_pp[i]);
        !          1576:   }
        !          1577:   capa_set_subjective(set,prob,student_number,answer);
        !          1578:   sprintf(submissions_str,"%d\t%s\t",prob,answer);
        !          1579:   log_submissions(student_number,set,submissions_str);
        !          1580:   capa_mfree((char *)sbuf_pp);
        !          1581:   return 1;
        !          1582: }
        !          1583: 
        !          1584: void set_entry_tries(int *tried, char *tries, int num, int num_questions) {
        !          1585:   if((tried[num] >=0) && (tried[num] <= TRY_BOUND) ) {
        !          1586:     if(tried[num] < 10 ) {
        !          1587:       tries[3*num]   = ' ';
        !          1588:       tries[3*num+1] = tried[num] + '0';
        !          1589:       if(num < num_questions-1)  tries[3*num+2] = ',';
        !          1590:     } else {
        !          1591:       tries[3*num]   = (int)(tried[num]/10) + '0';
        !          1592:       tries[3*num+1] = (tried[num] % 10) + '0';
        !          1593:       if(num < num_questions-1)  tries[3*num+2] = ',';
        !          1594:     }
        !          1595:   } else {
        !          1596:     tries[3*num]   = ' ';
        !          1597:     tries[3*num+1] = 1 + '0';
        !          1598:     if(num < num_questions-1)  tries[3*num+2] = ',';
        !          1599:   }
        !          1600: }
        !          1601: 
        !          1602: /* -------------------------------------------------------------------------- */
        !          1603: /* LET THE USER ANSWER THE CURRENT PROBLEM SET QUESTIONS                      */
        !          1604: /* -------------------------------------------------------------------------- */
        !          1605: void                                
        !          1606: try_set(student_number,set,section) 
        !          1607: char  *student_number; 
        !          1608: int    set; 
        !          1609: int   *section;
        !          1610: {
        !          1611:    char       a_student_number[MAX_STUDENT_NUMBER+1];
        !          1612:    time_t     curtime;
        !          1613:    T_header   header;
        !          1614:    Problem_t *first_problem, *p;
        !          1615:    T_entry    entry;
        !          1616:    char       answer[256], *a_str, **ans_strs;
        !          1617:    int        num, offset, num_questions, start_from, leng;
        !          1618:    char      *log_string,submissions_str[MAX_BUFFER_SIZE];
        !          1619:    int       *tried,answered;
        !          1620:    int        scr_idx=1, display=1, second_scr, canAnswer;
        !          1621:    int        usr_command, whereto, allow_hint=0, ex=0;
        !          1622:    char       u_input[64], date_str[DATE_LENGTH], one_line[81];
        !          1623:    int        log_char, i, j, allow_n, allow_p, allow_subj;
        !          1624:    
        !          1625:    strncpy(a_student_number,student_number,MAX_STUDENT_NUMBER+1);
        !          1626:    time(&curtime); /* Is due date past? */
        !          1627:    /* ---------------------------------------- check due date */
        !          1628: #ifndef NO_DATE_CHECK
        !          1629:    /* ===> if ( compare_datetime(curtime,header.due_date) > 0) { */
        !          1630:    if( capa_check_date(CHECK_DUE_DATE,student_number,*section,set) > 0 ) {
        !          1631:       capa_get_date(CHECK_DUE_DATE,student_number,*section,set,date_str);
        !          1632:       sprintf(answer,"  Sorry, the due date was: %s",date_str); 
        !          1633:       move(17,1); clrtoeol(); mvaddstr(17,15,answer);   mypause(19,17);
        !          1634:       return;
        !          1635:    }
        !          1636: #ifdef LOGIN_DBUG
        !          1637:   fprintf(dfp,"Tryset():(sec=%d,set=%d)[%s]\n",*section,set,date_str); fflush(dfp);
        !          1638: #endif /* LOGIN_DBUG */
        !          1639: #endif /* NO_DATE_CHECK */
        !          1640: 
        !          1641:    offset=capa_get_entry(&entry,student_number,set);
        !          1642:    capa_get_header(&header,set);
        !          1643:    if (offset<0) offset = -offset;  /* newly created entry */
        !          1644:    
        !          1645: #ifdef LOGIN_DBUG
        !          1646:    fprintf(dfp,"P set=%d,SN=%s,ANS=%s,TRY=%s\n",set,a_student_number,entry.answers,entry.tries); fflush(dfp);
        !          1647: #endif
        !          1648:    num = capa_parse(set,&first_problem,a_student_number,&num_questions,NULL);
        !          1649:    
        !          1650: #ifdef LOGIN_DBUG
        !          1651:   fprintf(dfp,"ParseSource:=%d\n",num); fflush(dfp);
        !          1652: #endif /* LOGIN_DBUG */
        !          1653: 
        !          1654:    /* DEBUGGING: make sure num_questions is plausible */
        !          1655:    if (num_questions>1000 || num_questions<=0)   properly_logout(student_number);
        !          1656:    
        !          1657:    start_from=ask_what_prob(num_questions,entry.answers);
        !          1658:    
        !          1659:    /* initialize log string to all '-' */
        !          1660:    tried = (int *)capa_malloc(num_questions+1,sizeof(int));
        !          1661:    log_string = (char *)capa_malloc(num_questions+1,sizeof(char));
        !          1662:    for (num=0; num<num_questions; num++)  {
        !          1663:      log_string[num]='-';
        !          1664:      sscanf(entry.tries + 3*num,"%d,",&(tried[num]) );
        !          1665:    }
        !          1666:    log_string[num_questions]=0;
        !          1667:    capa_set_login_time(student_number,set);
        !          1668:    for (num=0,p=first_problem; p; ){
        !          1669:       if( start_from > 1 ) {
        !          1670:         num=start_from-1;
        !          1671:         for (p=first_problem; start_from > 1 && p->next; start_from--)
        !          1672:              p=p->next;
        !          1673:         start_from = 0;
        !          1674:       }
        !          1675:       if (display) {
        !          1676:          /* DISPLAY QUESTION */
        !          1677:          CLEAR();
        !          1678:          second_scr = display_prob_scr(p->question,scr_idx);
        !          1679:          allow_subj = 0;
        !          1680:          if( p->ans_type == ANSWER_IS_SUBJECTIVE ) {
        !          1681:            allow_subj = 1;
        !          1682:            move(A_ROW,A_COL); clrtoeol();
        !          1683:            mvaddstr(A_ROW,A_COL,"Enter :A to answer subjective question");
        !          1684:          }
        !          1685:          mvaddstr(S_ROW,0,"OPTION/ANSWER");
        !          1686:          mvaddstr(O_ROW,0,"Options :M = Main Menu  :7 = go to # 7");
        !          1687:          allow_n = allow_p = 0;
        !          1688:          if( second_scr && (scr_idx == 1) ) {
        !          1689:            mvaddstr(O_ROW,E_COL,":N = Next screen");
        !          1690:            allow_n=1;
        !          1691:          }
        !          1692:          if( second_scr && (scr_idx == 2) ) {
        !          1693:            mvaddstr(O_ROW,E_COL,":P = Prev screen");
        !          1694:            allow_p=1;
        !          1695:          }
        !          1696:          
        !          1697:          mvaddstr(O_ROW,R_COL,"RETURN = Enter/Execute");
        !          1698: 	 
        !          1699: 	 if (g_inhibit_response ) {
        !          1700: 	   canAnswer = show_prior_inhibited_response(p,header.partial_credit[num],entry.answers[num],tried[num],&allow_hint);
        !          1701: 	 } else {
        !          1702: 	   canAnswer = show_prior_response(p,header.partial_credit[num],entry.answers[num],tried[num],&allow_hint);
        !          1703: 	 }
        !          1704: 	 
        !          1705:       }
        !          1706:       mvaddstr(X_ROW,X_COL,":X = eXit");
        !          1707:       
        !          1708:       /* <= */
        !          1709:       
        !          1710:       
        !          1711:       
        !          1712:         get_xinput(S_ROW,A_COL,u_input,U_ANS_CHAR);
        !          1713:         display=0;  usr_command=C_DONTCARE;
        !          1714:         /* DEFAULT ACTIONS on empty input */
        !          1715:         if(!strlen(u_input)) { usr_command = (p->next? C_FORWARD : C_MENU); } else {
        !          1716:           if( u_input[0] == ':' ) {
        !          1717:            switch(toupper( u_input[1] )) {
        !          1718:              case 'H': if( allow_hint ) { usr_command=C_HINT; } break;
        !          1719:              case 'M': usr_command=C_MENU;    break;
        !          1720:              case 'N': if( allow_n ) { usr_command=C_NEXTSCR; } break;
        !          1721:              case 'P': if( allow_p ) { usr_command=C_PREVSCR; } break;
        !          1722:              case 'X': usr_command=C_EXIT;    break;
        !          1723:              case 'A': if( allow_subj ) { usr_command=C_SUBJANS; } break;
        !          1724:              default : sscanf(u_input,":%d",&whereto);
        !          1725:                     if(whereto >0 && whereto <= num_questions) usr_command=C_JUMP;
        !          1726: 		    break;
        !          1727:            }
        !          1728:           } else { /* user entered some answer */
        !          1729:             if( p->ans_op == ANS_AND ) {
        !          1730:               if(canAnswer) { usr_command=C_ANSWER;
        !          1731:                 ans_strs = (char **)capa_malloc(sizeof(char *), p->ans_cnt);
        !          1732:                 ans_strs[0] = (char *)capa_malloc(strlen(u_input)+1,1);
        !          1733:                 strcpy(ans_strs[0],u_input);
        !          1734:                 for(i=1;i<p->ans_cnt;i++) {
        !          1735:                   mvaddstr(A_ROW,A_COL,"                                ");
        !          1736: 	          mvaddstr(A_ROW,A_COL,ans_strs[i-1]);
        !          1737:                   sprintf(one_line,    " Entering answer %3d of %3d     ", i+1,p->ans_cnt);
        !          1738:                   mvaddstr(A_ROW,S_COL,one_line);
        !          1739:                   mvaddstr(S_ROW,A_COL,"                                ");
        !          1740:                   get_xinput(S_ROW,A_COL,u_input,U_ANS_CHAR);
        !          1741:                   ans_strs[i] = (char *)capa_malloc(strlen(u_input)+1,1);
        !          1742:                   strcpy(ans_strs[i],u_input);
        !          1743:                   
        !          1744:                 }
        !          1745:                 
        !          1746:                 /* now in ans_strs[][] are user inputs */
        !          1747:                 
        !          1748:               }
        !          1749:             } else { /* one answer or ANS_OR */
        !          1750:               ans_strs = (char **)capa_malloc(sizeof(char *), 1);
        !          1751:               ans_strs[0] = (char *)capa_malloc(strlen(u_input)+1,1);
        !          1752:               strcpy(ans_strs[0], u_input);
        !          1753:               if(canAnswer)  { usr_command=C_ANSWER; 
        !          1754: 	         mvaddstr(S_ROW,A_COL,"                                ");
        !          1755: 	         mvaddstr(A_ROW,A_COL,"                                ");
        !          1756: 	         mvaddstr(A_ROW,A_COL,ans_strs[0]);  }
        !          1757: 	    }
        !          1758:           } /* end if  u_input[0] == ':' */
        !          1759:         } /* end if !strlen(u_input) */
        !          1760:       
        !          1761:         
        !          1762:       
        !          1763:       
        !          1764:       
        !          1765:       /* PROCESS USER COMMAND */
        !          1766:       switch(usr_command) {
        !          1767:         case C_FORWARD: /* Forwards */
        !          1768:                 if (p->next) {
        !          1769:                    p=p->next; num++;
        !          1770:                    display=1; allow_hint=0; scr_idx=1;
        !          1771:                 } else
        !          1772:                    mvaddstr(X_ROW,R_COL,"RETURN = Main Menu   ");
        !          1773:                 break;
        !          1774:         case C_NEXTSCR:  scr_idx = 2; display=1;
        !          1775:                 break;
        !          1776:         case C_PREVSCR:  scr_idx = 1; display=1;
        !          1777:                 break;
        !          1778:         case C_EXIT: /* Exit */ 
        !          1779:                 ex=1; p=0; break;
        !          1780:         case C_MENU: /* Return to main menu */
        !          1781:                 p=0;  break;
        !          1782:         case C_HINT: /* Hint */
        !          1783:                 if (! p->hint)    break;
        !          1784:                 display_hint(p->hint);
        !          1785:                 display=1;
        !          1786:                 break;
        !          1787:         case C_ANSWER: /* Answer question */
        !          1788:               { 
        !          1789: 		if(p->ans_type== ANSWER_IS_SUBJECTIVE) {
        !          1790: 		  move(A_ROW,A_COL); clrtoeol();
        !          1791: 		  mvaddstr(A_ROW,A_COL,"Enter :A to answer subjective question");
        !          1792: 		  capa_mfree(ans_strs[0]);
        !          1793: 		  break;
        !          1794: 		}
        !          1795: 		if( p->ans_op == ANS_AND ) {
        !          1796: 		    leng = 0;
        !          1797: 		    for(i=0;i<p->ans_cnt;i++) {
        !          1798: 		       leng += (strlen((char *)ans_strs[i]) + 2);
        !          1799: 		    }
        !          1800: 		    a_str = (char *)capa_malloc(leng+1,1);
        !          1801: 		    a_str[0]=0;
        !          1802: 		    strcat(a_str,ans_strs[0]);
        !          1803: 		    if ( is_all_ws(ans_strs[0]) )  break;
        !          1804: 		    trim_response_ws(ans_strs[0]);
        !          1805: 		    for(i=1;i<p->ans_cnt;i++) {
        !          1806: 		       strcat(a_str,"\t");
        !          1807: 		       strcat(a_str,ans_strs[i]);
        !          1808: 		       if ( is_all_ws(ans_strs[i]) )  break;
        !          1809: 		       trim_response_ws(ans_strs[i]);
        !          1810: 		    }
        !          1811: 		    if (i < p->ans_cnt) {
        !          1812: 		      display=1; /*handle early breaks out of the*/
        !          1813: 		      break; 	 /*loop which mean typed only ws */
        !          1814: 		    }
        !          1815: 		} else { /* only one answer */
        !          1816: 		  leng = (strlen((char *)ans_strs[0]) + 2);
        !          1817: 		  a_str = (char *)capa_malloc(leng+1,1);
        !          1818: 		  a_str[0]=0;
        !          1819: 		  strcat(a_str,ans_strs[0]);
        !          1820: 		  if ( is_all_ws(ans_strs[0]) )  break;
        !          1821: 		  trim_response_ws(ans_strs[0]);
        !          1822: 		}
        !          1823: 		
        !          1824: 		sprintf(submissions_str,"%d\t%s\t",num+1,a_str);
        !          1825: 		log_submissions(student_number,set,submissions_str);
        !          1826: 
        !          1827: 		{
        !          1828: 		  int cnt=((p->ans_op==ANS_AND)?p->ans_cnt:1);
        !          1829:      		  if (g_inhibit_response) {
        !          1830: 		    canAnswer = give_inhibited_response(p, ans_strs,cnt,
        !          1831: 							&(tried[num]),&log_char);
        !          1832: 		  } else {
        !          1833: 		    canAnswer = give_response(p, ans_strs,cnt, &(tried[num]),&log_char);
        !          1834: 		  }
        !          1835: 		}
        !          1836: 		if( p->ans_op == ANS_AND ) {
        !          1837: 		  for(i=0;i<p->ans_cnt;i++) {
        !          1838: 		    capa_mfree( (char *)ans_strs[i] );
        !          1839: 		  }
        !          1840: 		  
        !          1841: 		} else { /* there is only one user answer */
        !          1842: 		  capa_mfree( (char *)ans_strs[0] );
        !          1843: 		  
        !          1844: 		}
        !          1845: 		capa_mfree((char *)ans_strs);
        !          1846: 		capa_mfree( (char *)a_str );
        !          1847: 		
        !          1848:                 if (p->hint && 
        !          1849: 		    (
        !          1850: 		     (p->show_hint<=tried[num])||
        !          1851: 		     (log_char == 'y') ||
        !          1852: 		     (log_char == 'Y')
        !          1853: 		     )
        !          1854: 		    ){
        !          1855: 		  allow_hint=1;
        !          1856: 		  mvaddstr(X_ROW,H_COL,":H = Show Hint");
        !          1857:                 }
        !          1858:                 switch(log_char) {
        !          1859:                   case 'U': case 'u': case 'S': 
        !          1860:                             entry.answers[num]='N';      break;
        !          1861:                   case 'Y': allow_hint=1; mvaddstr(X_ROW,H_COL,":H = Show Hint");  /* fall through here */
        !          1862:                    default: entry.answers[num]=log_char; break;
        !          1863:                 }
        !          1864:                 log_string[num]=log_char;
        !          1865:                 
        !          1866:                 log_attempt(student_number,set,*section,log_string);
        !          1867:                 /* for (i=0; i<num_questions; i++) { log_string[i] = '-' ;  } */
        !          1868: 		set_entry_tries(tried,entry.tries,num,num_questions);
        !          1869: 		log_string[num]='-';
        !          1870:                 /* ------------------------------ check due date */
        !          1871:                 time(&curtime);
        !          1872:                 /* ===> if (compare_datetime(curtime,header.due_date) > 0) { */
        !          1873:                 if( capa_check_date(CHECK_DUE_DATE,student_number,*section,set) > 0 ) {
        !          1874:                   capa_get_date(CHECK_DUE_DATE,student_number,*section,set,date_str);
        !          1875:                   sprintf(answer,"Sorry, the due date was: %s",date_str);
        !          1876:                   move(20,1); clrtobot(); addstr(answer); mypause(23,1);
        !          1877:                 } else {
        !          1878:                   capa_set_entry(&entry,student_number,set,offset);
        !          1879:                 }
        !          1880:               } break;
        !          1881:         case C_JUMP: /* Jump to specific question number */
        !          1882:                 num=whereto-1;
        !          1883:                 for (p=first_problem; whereto > 1 && p->next; whereto--)
        !          1884:                    p=p->next;
        !          1885:                 display=1;  allow_hint=0; scr_idx=1;
        !          1886:                 break;
        !          1887:         case C_SUBJANS:  
        !          1888:                 answered=answer_subjective(student_number,set,section,num+1); 
        !          1889: 		if (answered) {
        !          1890: 		  tried[num]++;
        !          1891: 		  if (p->hint && ((p->show_hint<=tried[num]))) { allow_hint=1; }
        !          1892: 		  entry.answers[num]='0';
        !          1893: 		  log_string[num]='A';
        !          1894: 		  log_attempt(student_number,set,*section,log_string);
        !          1895: 		  log_string[num]='-';
        !          1896: 		  set_entry_tries(tried,entry.tries,num,num_questions);
        !          1897:                   capa_set_entry(&entry,student_number,set,offset);
        !          1898: 		}
        !          1899:                 display=1;
        !          1900:                 break;
        !          1901:         case C_DONTCARE:  break;
        !          1902:       }
        !          1903:    }
        !          1904:    for (i=0,j=0, num=0; num<num_questions; num++) {
        !          1905:      j = j + (header.weight[num] - '0');
        !          1906:      if((entry.answers[num]=='Y') || (entry.answers[num]=='y')) 
        !          1907:        i = i + (header.weight[num] - '0');
        !          1908:      if( entry.answers[num] >= '0' && entry.answers[num] <= '9' ) {
        !          1909:         i = i + (entry.answers[num] - '0');
        !          1910:      }
        !          1911:      if((entry.answers[num]=='E') || (entry.answers[num]=='e')) 
        !          1912:        j = j - (header.weight[num] - '0');
        !          1913:      if((tried[num] >=0) && (tried[num] <= TRY_BOUND) ) {
        !          1914:        if(tried[num] < 10 ) {
        !          1915:          entry.tries[3*num]   = ' ';
        !          1916:          entry.tries[3*num+1] = tried[num] + '0';
        !          1917:          if(num < num_questions-1)  entry.tries[3*num+2] = ',';
        !          1918:        } else {
        !          1919:          entry.tries[3*num]   = (int)(tried[num]/10) + '0';
        !          1920:          entry.tries[3*num+1] = (tried[num] % 10) + '0';
        !          1921:          if(num < num_questions-1)  entry.tries[3*num+2] = ',';
        !          1922:        }
        !          1923:      } else {
        !          1924:        entry.tries[3*num]   = ' ';
        !          1925:        entry.tries[3*num+1] = 1 + '0';
        !          1926:        if(num < num_questions-1)  entry.tries[3*num+2] = ',';
        !          1927:      }
        !          1928:    }
        !          1929:    capa_mfree(header.weight);
        !          1930:    capa_mfree(header.partial_credit);
        !          1931: 
        !          1932:    sprintf(answer,"Your score for this set is now: %d/%d",i,j);
        !          1933:    move(20,1); clrtobot(); addstr(answer); mypause(23,1);
        !          1934:    /* ------- original code , should check due date before save it
        !          1935:    
        !          1936:    time(&curtime);
        !          1937:    if (compare_datetime(curtime,header.due_date) > 0) {
        !          1938:    if( capa_check_date(CHECK_DUE_DATE,*section,set) > 0 ) {
        !          1939:       need to deal with due_date 
        !          1940:       sprintf(answer,"Sorry, the due date was: %s",header.due_date);
        !          1941:       move(20,1); clrtobot(); addstr(answer); mypause(23,1);
        !          1942:    } else {
        !          1943:       sprintf(answer,"Your score for this set is now: %d/%d",i,j);
        !          1944:       move(20,1); clrtobot(); addstr(answer); mypause(23,1);
        !          1945:       
        !          1946:       capa_set_entry(&entry,student_number,set,offset);
        !          1947:    }
        !          1948:    ------ */
        !          1949:    /* FREE UP MALLOC'ED SPACE (VERY IMPORTANT) */
        !          1950:    capa_mfree(entry.answers);
        !          1951:    capa_mfree(entry.tries);
        !          1952:    free_problems(first_problem);
        !          1953:    /* log_attempt(student_number,set,*section,log_string); */
        !          1954:    capa_mfree(log_string);
        !          1955:    capa_mfree((char*)tried);
        !          1956:    if (ex) properly_logout(student_number);
        !          1957:    
        !          1958: }
        !          1959: 
        !          1960: #define   COL_ONE    1
        !          1961: #define   COL_TWO    17
        !          1962: #define   COL_THREE  34
        !          1963: #define   COL_FOUR   43
        !          1964: #define   COL_FIVE   69
        !          1965: 
        !          1966: /* ------------------------------------------------------------------------- */
        !          1967: /* REVIEW PREVIOUS PROBLEM SETS                                              */
        !          1968: /* ------------------------------------------------------------------------- */
        !          1969: void                                      /* RETURNS: (nothing)              */
        !          1970: view_previous(student_number,set,section) /* ARGUMENTS:                      */
        !          1971: char  *student_number;                    /*    Student number               */
        !          1972: int  set;                                 /*    Set number                   */
        !          1973: int *section;                             /*    Section number               */
        !          1974: {                                         /* LOCAL VARIABLES:                */
        !          1975:    T_entry   entry;                       /*    Database entry               */
        !          1976:    Problem_t *first_problem,              /*    Pointer to first problem     */
        !          1977:              *problem;                    /*    Previous problem             */
        !          1978:    int        num_questions,              /*    Total # of questions         */
        !          1979:               ex=0,                       /*    Exit system flag             */
        !          1980:               display=1,                  /*    Redraw flag                  */
        !          1981: 	      usr_command,
        !          1982: 	      whereto, 
        !          1983: 	      allow_hint=0, allow_explain=0;
        !          1984:    int        num;                        /*    Temporary variable           */
        !          1985:    char       buf[4],                     /*    Command input buffer         */
        !          1986:               aLine[MAX_BUFFER_SIZE];
        !          1987:    T_header   header;                     /*    Set header                   */
        !          1988:    time_t     curtime;                    /*    Current time                 */
        !          1989:    double     upper_ans;
        !          1990:    char       fmt_ans[ANSWER_STRING_LENG], goto_str[ANSWER_STRING_LENG], 
        !          1991:               tmp_str[ANSWER_STRING_LENG];
        !          1992:    int        scr_idx=1, second_scr, allow_n, allow_p;
        !          1993:    
        !          1994:    /* QUERY USER FOR SET */
        !          1995:    move(15,5);  /* deleteln(); */
        !          1996:    addstr("            Which set would you like to view?");
        !          1997:    mvaddstr(16,15,   "Enter a set number and press ENTER/RETURN");
        !          1998:    move(17,1); clrtoeol(); /* erase Enter a command ... */
        !          1999:    do { get_input(15,51,buf,3); } while(!strlen(buf));
        !          2000:    sscanf(buf,"%d",&num);
        !          2001:    if (num<1 || num>set) {
        !          2002:       move(17,5); clrtoeol();
        !          2003:       mvaddstr(17,15,"   Error: Invalid previous set number\n");
        !          2004:       mypause(19,17);   return;
        !          2005:    }
        !          2006:    /* ------------------------------------ answer date */
        !          2007:    time(&curtime);
        !          2008:    /* ===> if (compare_datetime(curtime,header.answer_date) < 0) { */
        !          2009:    if ( capa_check_date(CHECK_ANS_DATE,student_number,*section,num) < 0 ) {
        !          2010:       move(16,1); clrtoeol();
        !          2011:       move(17,5); clrtoeol();
        !          2012:       mvaddstr(17,15,"  Answers are not yet available\n");  mypause(19,17);  return;
        !          2013:    }
        !          2014: 
        !          2015:    /* LOAD IN THE INFO NEEDED */
        !          2016:    capa_get_header(&header,num);
        !          2017:    capa_get_entry(&entry,student_number,num);
        !          2018:    capa_parse(num,&first_problem,student_number,&num_questions,NULL);
        !          2019:    sprintf(goto_str,"#=go to problem #, [%d problems]", num_questions);
        !          2020:    for (num=0,problem=first_problem; problem; ) {
        !          2021:       if (display) {
        !          2022:          allow_hint = allow_explain=0;
        !          2023:          allow_n = allow_p = 0;
        !          2024:          CLEAR();
        !          2025:          second_scr = display_prob_scr(problem->question,scr_idx);
        !          2026:          if( problem->ans_type == ANSWER_IS_FLOAT ) {
        !          2027:              upper_ans = (double)atof(problem->answer);
        !          2028:              sprintf(fmt_ans, problem->ans_fmt, upper_ans);
        !          2029:          } else {
        !          2030:              sprintf(fmt_ans, "%s", problem->answer);
        !          2031:          }
        !          2032:          if( problem->ans_unit ) {
        !          2033:              sprintf(tmp_str, "Answer: %s %s",fmt_ans,problem->unit_str);
        !          2034:          } else {
        !          2035:              sprintf(tmp_str, "Answer: %s",fmt_ans);
        !          2036:          }
        !          2037:          mvaddstr(S_ROW,COL_ONE,tmp_str);
        !          2038:          
        !          2039:          switch(entry.answers[num]) {
        !          2040:            case 'Y': mvaddstr(S_ROW,COL_FOUR,"CORRECT         "); break;
        !          2041:            case 'y': mvaddstr(S_ROW,COL_FOUR,"HANDIN CORRECT  "); break;
        !          2042:            case '-': mvaddstr(S_ROW,COL_FOUR,"UNANSWERED      "); break;
        !          2043:            case 'e': mvaddstr(S_ROW,COL_FOUR,"EXCUSED         "); break;
        !          2044:            case 'E': mvaddstr(S_ROW,COL_FOUR,"EXCUSED         "); break;
        !          2045:            case 'n': mvaddstr(S_ROW,COL_FOUR,"HANDIN INCORRECT"); break;
        !          2046:            case 'N': mvaddstr(S_ROW,COL_FOUR,"INCORRECT       "); break;
        !          2047:            default : if(entry.answers[num] >= '0' && entry.answers[num] <= '9') {
        !          2048:                       sprintf(aLine,"HAND-GRADED %c/%c ",entry.answers[num],
        !          2049: 			      header.weight[num]);
        !          2050:                       mvaddstr(S_ROW,COL_FOUR,aLine);
        !          2051:                      }
        !          2052:                      break;
        !          2053:          }
        !          2054:          mvaddstr(S_ROW,COL_FIVE,"OPTION:");
        !          2055:          
        !          2056:          mvaddstr(O_ROW,COL_ONE,"M=Main menu");
        !          2057:          if( second_scr && scr_idx == 1) {
        !          2058:            mvaddstr(O_ROW,COL_TWO,"N=Next screen");
        !          2059:            allow_n = 1;
        !          2060:          }
        !          2061:          if( second_scr && scr_idx == 2) {
        !          2062:            mvaddstr(O_ROW,COL_TWO,"P=Prev screen");
        !          2063:            allow_p = 1;
        !          2064:          }
        !          2065:          mvaddstr(O_ROW,COL_THREE,"X=eXit");
        !          2066:          mvaddstr(O_ROW,COL_FOUR, "RETURN=Enter/Execute");
        !          2067:          if ( problem->hint && 
        !          2068: 	      ( 
        !          2069: 	       (problem->show_hint <= problem->tries) || 
        !          2070: 	       (entry.answers[num] == 'Y') || 
        !          2071: 	       (entry.answers[num] == 'y')
        !          2072: 	       ) 
        !          2073: 	      )    { 
        !          2074: 	   allow_hint=1;    mvaddstr(O_ROW,COL_FIVE,"H=Hint"); 
        !          2075: 	 }
        !          2076:          mvaddstr(X_ROW,COL_ONE,goto_str);
        !          2077:          if (problem->next)
        !          2078:                mvaddstr(X_ROW,COL_FOUR,"RETURN=next problem");
        !          2079:             else
        !          2080:                mvaddstr(X_ROW,COL_FOUR,"RETURN=main menu   ");
        !          2081:          if ( problem->explain ) { allow_explain=1; mvaddstr(X_ROW,COL_FIVE,"E=Explain"); }
        !          2082:    
        !          2083:       }
        !          2084:       get_input(S_ROW,COL_FIVE+7,buf,3);
        !          2085:       display=0; usr_command=C_DONTCARE;
        !          2086:       /* DEFAULT ACTIONS on empty input */
        !          2087:       if(!strlen(buf)) { usr_command = (problem->next? C_FORWARD : C_MENU); } else {
        !          2088:         switch(toupper(buf[0])) {
        !          2089:          case 'X': usr_command=C_EXIT;    break;
        !          2090:          case 'M': usr_command=C_MENU;    break;
        !          2091: 	 case 'H': usr_command=C_HINT;    break;
        !          2092:          case 'E': usr_command=C_EXPLAIN; break;
        !          2093:          case 'N': if( allow_n ) { usr_command=C_NEXTSCR; } break;
        !          2094:          case 'P': if( allow_p ) { usr_command=C_PREVSCR; } break;
        !          2095:          default : sscanf(buf,"%d",&whereto);
        !          2096:                   if(whereto >0 && whereto <= num_questions) usr_command=C_JUMP;
        !          2097: 		  break;
        !          2098:         }
        !          2099:       }
        !          2100: 
        !          2101: 
        !          2102:       /* PROCESS USER COMMAND */
        !          2103:       switch(usr_command) {
        !          2104:       case C_FORWARD: /* FORWARDS ONE */
        !          2105:                 if (problem->next) {
        !          2106:                    problem=problem->next; display=1; scr_idx = 1; num++;
        !          2107:                 } else
        !          2108:                    mvaddstr(X_ROW,COL_FOUR,"RETURN=main menu   ");
        !          2109:                 break;
        !          2110:       case C_HINT: /* HINT */
        !          2111:                 if(allow_hint) {
        !          2112:                   display_hint(problem->hint);
        !          2113:                   display=1;
        !          2114:                   allow_hint = 0;
        !          2115:                 }
        !          2116: 		break;
        !          2117:       case C_EXPLAIN: /* Explain */
        !          2118:                 if(allow_explain) {
        !          2119:                   display_hint(problem->explain); display=1;
        !          2120: 		  allow_explain=0;
        !          2121: 		}
        !          2122: 		break;
        !          2123:       case C_NEXTSCR:  scr_idx = 2; display=1;
        !          2124:                 break;
        !          2125:       case C_PREVSCR:  scr_idx = 1; display=1;
        !          2126:                 break;
        !          2127:       case C_EXIT: /* EXIT SYSTEM */
        !          2128:                 ex=1; problem=0; break;
        !          2129: 
        !          2130:       case C_MENU: /* RETURN TO MAIN MENU */
        !          2131:                 problem=0;  break;
        !          2132: 
        !          2133:       case C_JUMP: /* JUMP TO SPECIFIC PROBLEM # */
        !          2134:                    num=whereto-1;
        !          2135:                    for (problem=first_problem; whereto > 1 && problem->next; whereto--)
        !          2136:                       problem=problem->next;
        !          2137:                    display=1;
        !          2138:                    scr_idx = 1;
        !          2139:                  break;
        !          2140:       case C_TIME:     break;
        !          2141:       case C_DONTCARE: break;
        !          2142:       }
        !          2143:    }
        !          2144: 
        !          2145:    /* FREE UP MALLOC'ED SPACE - VERY IMPORTANT */
        !          2146:    capa_mfree(header.weight);
        !          2147:    capa_mfree(header.partial_credit);
        !          2148:    capa_mfree(entry.answers);
        !          2149:    capa_mfree(entry.tries);
        !          2150:    free_problems(first_problem);
        !          2151: 
        !          2152:    if (ex) properly_logout(student_number);
        !          2153: }
        !          2154: 
        !          2155: /* -------------------------------------------------------------------------- */
        !          2156: /* DISPLAY HELP SCREEN                                                        */
        !          2157: /* -------------------------------------------------------------------------- */
        !          2158: void                  /* RETURNS: (nothing)      */
        !          2159: display_help()        /* ARGUMENTS: (none)       */
        !          2160: {                     /* LOCAL VARIABLES:        */
        !          2161:    FILE *fp;          /*    Welcome file pointer */
        !          2162:    char  buf[255];    /*    Input buffer         */
        !          2163: 
        !          2164:    CLEAR();
        !          2165:    if ((fp=fopen("help.msg","r"))!=NULL) {
        !          2166:       while (fgets(buf,255,fp))  addstr(buf);
        !          2167:       fclose(fp);
        !          2168:    }
        !          2169:    mypause(22,20);
        !          2170: }
        !          2171: 
        !          2172: 
        !          2173: /*   A class directory must have   */
        !          2174: /*     records/                    */
        !          2175: /*                                 */
        !          2176: /*  returns: 0  structure is correct, but no set.db files */
        !          2177: /*          -1  structure is not correct                  */
        !          2178: /*          >=1 the last set.db                           */
        !          2179: 
        !          2180: int
        !          2181: check_class_get_set(dir_path) char  *dir_path;
        !          2182: {
        !          2183:   char   f_name[1024];
        !          2184:   int    set;
        !          2185:   
        !          2186:   if( capa_access(dir_path, F_OK) == 0 ) { /* class dir exists */
        !          2187:     sprintf(f_name,"%s/records",dir_path);
        !          2188:     if( capa_access(f_name, F_OK) == 0 ) { /* class/records dir exists */
        !          2189:       for(set = 1; ; set++ ) {
        !          2190:         sprintf(f_name,"%s/records/set%d.db",dir_path,set);
        !          2191:         if(capa_access(f_name, F_OK) == -1 )  break;
        !          2192:       }
        !          2193:       set--;
        !          2194:     } else {
        !          2195:       set = -1;
        !          2196:     }
        !          2197:   } else {
        !          2198:     set = -1;
        !          2199:   } 
        !          2200:   return (set);
        !          2201: }
        !          2202: /* -------------------------------------------------------------------------- */
        !          2203: /* Get Exam and Quiz Path                                                     */
        !          2204: /*   return  0, 1, 2, 3         */
        !          2205: /* -------------------------------------------------------------------------- */
        !          2206: int
        !          2207: check_exam_quiz_f()
        !          2208: {
        !          2209:    char  buf[MAX_BUFFER_SIZE];
        !          2210:    int   result = 0, configResult=0;
        !          2211: 
        !          2212: #ifdef LOGIN_DBUG
        !          2213:    fprintf(dfp,"CHECK EXAM Access() success,and open(),%s\n",buf); fflush(dfp);
        !          2214: #endif
        !          2215:    configResult=read_capa_config("exam_path",buf);
        !          2216:    if (configResult != 0 && configResult != -1) {
        !          2217:      Exam_set = check_class_get_set(buf);
        !          2218:      if(Exam_set > 0 )  {
        !          2219:        result = 1;
        !          2220:        sprintf(Exam_path,buf);
        !          2221:      }
        !          2222:    }
        !          2223: #ifdef LOGIN_DBUG
        !          2224:    fprintf(dfp,"CHECK EXAM = %d,%s\n", result,Exam_path); fflush(dfp);
        !          2225: #endif
        !          2226:    configResult=read_capa_config("quiz_path",buf);
        !          2227:    if (configResult != 0 && configResult != -1) {
        !          2228:      Quiz_set = check_class_get_set(buf);
        !          2229:      if(Quiz_set > 0 )  {
        !          2230:        result = (result | 2);
        !          2231:        sprintf(Quiz_path,buf);
        !          2232:      }
        !          2233:    }
        !          2234:    
        !          2235:    return (result);
        !          2236: }
        !          2237: 
        !          2238: /* -------------------------------------------------------------------------- */
        !          2239: /* DISPLAY MAIN MENU                                                          */
        !          2240: /* -------------------------------------------------------------------------- */
        !          2241: void                  /* RETURNS: (nothing) */
        !          2242: display_menu(student, exam_f, quiz_f) 
        !          2243: T_student *student;
        !          2244: int        exam_f, quiz_f;
        !          2245: {
        !          2246:    char buff[MAX_BUFFER_SIZE];
        !          2247:    int  c_y,configResult,term_summary_button=1;
        !          2248:    
        !          2249:    configResult=read_capa_config("term_summary_button",buff);
        !          2250:    if (configResult != 0 && configResult != -1 ) {
        !          2251:      if (strcasecmp(buff,"no")==0) {
        !          2252:        term_summary_button=0;
        !          2253:      }
        !          2254:    }
        !          2255: 
        !          2256:    CLEAR();
        !          2257: 
        !          2258:    mvaddstr(1,10,student->s_nm);
        !          2259:    sprintf(buff,"Section: %d",student->s_sec);
        !          2260:    mvaddstr(1,50,buff);
        !          2261: 
        !          2262:    mvaddstr( 4,25,"  MAIN MENU"); c_y = 6;
        !          2263:    mvaddstr( c_y,25,"H=Help");    c_y++;
        !          2264:    if (term_summary_button) { mvaddstr( c_y,25,"S=Summary"); c_y++; }
        !          2265:    mvaddstr( c_y,25,"T=Try set"); c_y++;
        !          2266:    mvaddstr( c_y,25,"V=View previous set"); c_y++;
        !          2267:    if(exam_f) { mvaddstr( c_y,25,"E=view Exam summary"); c_y++; }
        !          2268:    if(quiz_f) { mvaddstr( c_y,25,"Q=view Quiz summary"); c_y++; }
        !          2269:    mvaddstr( c_y,25,"X=eXit system");
        !          2270: 
        !          2271:    mvaddstr(14,25,"COMMAND:");
        !          2272: 
        !          2273:    mvaddstr(17, 5,"Enter a command from the list above and press ENTER/RETURN");
        !          2274: }
        !          2275: 
        !          2276: /* -------------------------------------------------------------------------- */
        !          2277: /* CONTROL MAIN MENU SELECTIONS                                               */
        !          2278: /* -------------------------------------------------------------------------- */
        !          2279: void                                    /* RETURNS: (nothing)     */
        !          2280: menu_main(student_number,set,section)   /* ARGUMENTS:             */
        !          2281: char *student_number;                   /*    Student number      */
        !          2282: int set;                                /*    Set number          */
        !          2283: int section;                            /*    Section number      */
        !          2284: {                                       /* LOCAL VARIABLES:       */
        !          2285:    int       ex=0,                      /*    Exit system flag    */
        !          2286:              cmd;                       /*    User command        */
        !          2287:    char      buff[MAX_BUFFER_SIZE];     /*    User command buffer */
        !          2288:    T_student a_student;
        !          2289:    int       had_exam, had_quiz, outcome,configResult;
        !          2290: 
        !          2291: #ifdef LOGIN_DBUG
        !          2292:    fprintf(dfp,"MENU in %s sec=%d\n", student_number,section); fflush(dfp);
        !          2293: #endif
        !          2294: 
        !          2295:    outcome = check_exam_quiz_f();
        !          2296:    had_exam = outcome & 1;
        !          2297:    had_quiz = outcome & 2;
        !          2298: 
        !          2299: #ifdef LOGIN_DBUG
        !          2300:    fprintf(dfp,"After check %d\n", outcome); fflush(dfp);
        !          2301: #endif
        !          2302: 
        !          2303:    capa_get_student(student_number,&a_student);
        !          2304:    
        !          2305:    g_inhibit_response=capa_check_option(OPTION_INHIBIT_RESPONSE,set,section);
        !          2306:    if (g_inhibit_response < 0 ) g_inhibit_response=0;
        !          2307: 
        !          2308:    display_menu(&a_student,had_exam, had_quiz);
        !          2309:    while (!ex) {
        !          2310:       do {
        !          2311:          buff[0] = ' '; buff[1] = 0;
        !          2312:          get_input(14,34,buff,1);  cmd=toupper(buff[0]);
        !          2313:       } while (isspace(cmd));
        !          2314:       move(14,35); clrtoeol();
        !          2315:       /* PROCESS USER COMMAND */
        !          2316:       switch(cmd) {
        !          2317: 
        !          2318:       case 'H': /* DISPLAY HELP */
        !          2319:                 display_help();
        !          2320:                 display_menu(&a_student,had_exam, had_quiz);
        !          2321:                 break;
        !          2322:  
        !          2323:       case 'T': /* TRY CURRENT SET */
        !          2324:                 try_set(student_number,set,&section);       
        !          2325:                 display_menu(&a_student,had_exam, had_quiz);
        !          2326:                 break;
        !          2327: 
        !          2328:       case 'V': /* VIEW PREVIOUS SET */
        !          2329:                 view_previous(student_number,set,&section); 
        !          2330:                 display_menu(&a_student,had_exam, had_quiz);
        !          2331:                 break;
        !          2332: 
        !          2333:       case 'S': /* DISPLAY TERM SUMMARY */
        !          2334: 	        configResult=read_capa_config("term_summary_button",buff);
        !          2335: 		if (configResult != 0 && configResult != -1 ) {
        !          2336: 		  if ((strcasecmp(buff,"no")==0)) {
        !          2337: 		    break;
        !          2338: 		  }
        !          2339: 		}
        !          2340: 		term_summary(student_number,set,&section,TERM_SUMMARY);  
        !          2341: 		display_menu(&a_student,had_exam, had_quiz);
        !          2342: 		break;
        !          2343:       case 'E': /* VIEW EXAM SUMMARY */
        !          2344:                 if( had_exam ) {
        !          2345:                   chdir(Exam_path);
        !          2346:                   term_summary(student_number,Exam_set,&section,EXAM_SUMMARY);  
        !          2347:                   display_menu(&a_student,had_exam, had_quiz);
        !          2348:                   chdir(Orig_path);
        !          2349:                 }
        !          2350:                 break;
        !          2351:       case 'Q': /* VIEW QUIZ SUMMARY */
        !          2352:                 if( had_quiz ) {
        !          2353:                   chdir(Quiz_path);
        !          2354:                   term_summary(student_number,Quiz_set,&section,QUIZ_SUMMARY);  
        !          2355:                   display_menu(&a_student,had_exam, had_quiz);
        !          2356:                   chdir(Orig_path);
        !          2357:                 }
        !          2358:                 break;
        !          2359:       case EOF: /* EXIT SYSTEM */
        !          2360:       case 'X': ex=1; break;
        !          2361: 
        !          2362:       default:  /* INVALID COMMAND */
        !          2363:                 /* printf("Invalid choice\n"); */
        !          2364:                 break;
        !          2365:       }
        !          2366:    }
        !          2367: }
        !          2368: 
        !          2369: /* -------------------------------------------------------------------------- */
        !          2370: /* DISPLAY WELCOME MESSAGE WHEN USER LOGS IN                                  */
        !          2371: /* -------------------------------------------------------------------------- */
        !          2372: void               /* RETURNS: (nothing)      */
        !          2373: welcome()          /* ARGUMENTS:         */
        !          2374: {                  /* LOCAL VARIABLES:        */
        !          2375:    FILE *fp;       /*    Welcome file pointer */
        !          2376:    char  buf[TMP_LINE_LENGTH]; /*    Input buffer         */
        !          2377: 
        !          2378:    CLEAR();
        !          2379:    /* sprintf(buf,"This is your %d-time login to this set, good luck!",tries);
        !          2380:    addstr(buf);
        !          2381:    */
        !          2382:    if ((fp=fopen("welcome.msg","r"))!=NULL) {
        !          2383:       while (fgets(buf,TMP_LINE_LENGTH-1,fp)) addstr(buf);
        !          2384:       fclose(fp);
        !          2385:    }
        !          2386: }
        !          2387: 
        !          2388: void print_version()
        !          2389: {
        !          2390:   printf("capalogin\n");
        !          2391:   printf("       CAPA version %s, %s\n",CAPA_VER,COMPILE_DATE);
        !          2392: }
        !          2393: 
        !          2394: /* ------------------------------------------------------------------------- */
        !          2395: /* DRIVER: INITIALIZE AND GO TO LOGIN                                        */
        !          2396: /* ------------------------------------------------------------------------- */
        !          2397: int
        !          2398: main(int argc, char **argv)
        !          2399: {                            /* LOCAL VARIABLES:            */
        !          2400:    char     student_number[MAX_STUDENT_NUMBER+1]; /* Student number         */
        !          2401:    int      set,             /*    Set number               */
        !          2402:             section=0,       /*    Section number           */
        !          2403:             result;          /* stores result from read_capa_config */
        !          2404:    char     filename[FILE_NAME_LENGTH];   /*    Question filename buffer */
        !          2405: #if defined(NeXT)
        !          2406:    char     cwd[FILE_NAME_LENGTH];
        !          2407: #endif
        !          2408:    char *class_path, buf[MAX_BUFFER_SIZE],*tty;
        !          2409:    
        !          2410:    
        !          2411:    if (argc > 1) { if (strcmp(argv[1],"-v") == 0) {print_version(); exit(0); } }
        !          2412: #ifdef LOGIN_DBUG
        !          2413:    printf("Create login.DBUG file:: argc = %d\n",argc);
        !          2414:    sprintf(filename,"login.DBUG");
        !          2415:    if ((dfp=fopen(filename,"a"))==NULL) { printf("Error: can't open login debug\n"); return; }
        !          2416: #endif /* LOGIN_DBUG */
        !          2417:    /* GET CURRENT SET NUMBER */
        !          2418:   for(set = 1; ; set++ ) {
        !          2419:     sprintf(filename,"set%d.qz",set);
        !          2420:     if(capa_access(filename, F_OK) == -1 )   break;
        !          2421:   }
        !          2422:   set--;
        !          2423: #if defined(NeXT) 
        !          2424:    class_path = getwd(cwd);
        !          2425:    if( class_path ==  NULL ) class_path = cwd;
        !          2426: #else
        !          2427:    class_path = getcwd(NULL,512);
        !          2428:    
        !          2429: #endif 
        !          2430:    sprintf(Orig_path,"%s",class_path);
        !          2431:    free(class_path);
        !          2432:    /* ---------------------------------------------- CURSES INITIALIZATION */
        !          2433:    signal(SIGINT , kick_out);
        !          2434:    signal(SIGALRM, kick_out);
        !          2435:    signal(SIGFPE, SIG_IGN);
        !          2436:    initscr(); savetty(); cbreak(); noecho();
        !          2437:    time(&log_in_time);
        !          2438:    strncpy(in_t,ctime(&log_in_time),31);
        !          2439:    in_t[ strlen(in_t)-1 ]=0;    /* Trash newline */
        !          2440:    tty=ttyname(0);
        !          2441:    if ( tty == NULL ) {
        !          2442:      strcpy(in_tty,"UNKNOWN");
        !          2443:    } else {
        !          2444:      strcpy(in_tty,tty);
        !          2445:    }
        !          2446:    result=read_capa_config("capalogin_goodbye_delay",buf);
        !          2447:    if (result != 0 && result != -1) {
        !          2448:      g_delay=atoi(buf);
        !          2449:    } else {
        !          2450:      g_delay=5;
        !          2451:    }
        !          2452:    result=read_capa_config("capalogin_inactivity_delay",buf);
        !          2453:    if (result != 0 && result != -1) {
        !          2454:      g_max_delay=atoi(buf);
        !          2455:    } else {
        !          2456:      g_max_delay=60;
        !          2457:    }
        !          2458:    welcome();
        !          2459:    strcpy(student_number, login(&set,&section)); student_number[MAX_STUDENT_NUMBER] = 0;
        !          2460: #ifdef LOGIN_DBUG
        !          2461:    fprintf(dfp,"login return:SNum=%s, set=%d, sec=%d\n", student_number,set, section); fflush(dfp);
        !          2462: #endif
        !          2463:    menu_main(student_number,set,section);
        !          2464: #ifdef LOGIN_DBUG
        !          2465:    fclose(dfp);
        !          2466: #endif
        !          2467:    properly_logout(student_number);
        !          2468:    return 0;
        !          2469: }
        !          2470: 

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