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

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

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