/* * QMFONMV.C * * Qmodem 5.0 Phone directory record mover * * (PD) Jouni Kolehmainen, 1-Sep-1993 * * email: jouni.kolehmainen@mpoli.fi */ #include #include #include #include #include #include #define ON 1 #define OFF 0 #define TRUE 1 #define FALSE 0 #define MAXFON 200 #define PERPAGE 20 #define MAXPAGE (MAXFON / PERPAGE) #define KEY_SPACE ' ' #define KEY_ESC 27 #define KEY_UP -72 #define KEY_DOWN -80 #define KEY_HOME -71 #define KEY_END -79 #define KEY_PGUP -73 #define KEY_PGDN -81 char DetectAnsi(void); void DrawBar(char state); void ReadFON(char *fname); void WriteFON(char *fname); void DisplayFONpage(int page); void DisplayFONrec(int page); void Pascal2Zstr(char *str); void Zstr2Pascal(char *str); void MoveRecord(int from, int to); struct FON { /* QMODEM 5.0 PHONE DIRECTORY */ char name[28]; /* Pascal string */ char number[20]; /* Pascal string */ char password[15]; /* Pascal string */ long baud; /* Actual baud rate (4 bytes) */ char databits; /* 7,8 */ char stopbits; /* 1,2 */ char parity; /* N,E,O,M,S */ char comport; /* 1,2,3,4,5,6,7,8,C */ char script[9]; /* Pascal string */ char keyfile[9]; /* Pascal string */ int lastcall; /* Format unknown! (2 bytes) */ long times_on; /* # of times on-line (4 bytes) */ char protocol; /* Protocol indentifier */ char duplex; /* F,H */ char unknown1[2]; /* Unknown */ char flagged; /* 0,1 */ char emulation; /* Index to emulation table */ char unknown2; /* Unknown */ unsigned char note_ext; /* Notefile filename extension */ char unknown3; /* Unknown */ char noteflag; /* 0,1 */ char unknown4[14]; /* Unknown */ } fon[MAXFON]; /* 200 * 119 = 23800 bytes */ char *emulation[] = { " TTY", " ANSI", " VT100", " TVI925", "DEBUG_A", "DEBUG_H", " AVATAR" }; char *protocol[] = { "A:ASCII", "X:Xmodem", "C:Xmodem/CRC", "R:Xmodem/Relax", "O:1K-Xmodem", "K:1K-Xmodem/G", "Y:Ymodem", "G:Ymodem/G", "Z:Zmodem" }; int page = 0; int barline = 0; char marked = FALSE; char changes = FALSE; char fonfile[129] = "QMODEM.FON"; char bakfile[129]; /*--------------------------------------------------------------------------*/ /* Main procedure */ /*--------------------------------------------------------------------------*/ int main(argc,argv) int argc; char **argv; { int c, from, to; char *p, s[80]; char ready = FALSE; if (argc > 1) { if ((strchr(argv[1],'?') != NULL) || (strchr(argv[1],'?') != NULL) || (strchr(argv[1],'?') != NULL)) { printf("Usage: %s [fonfile]\n",argv[0]); return(1); } strcpy(fonfile,argv[1]); } if (! DetectAnsi()) { puts("ANSI terminal required\a"); return(1); } for (p=fonfile; *p; p++) *p = toupper(*p); ReadFON(fonfile); printf("\x1B[2J"); printf("\x1B[2;1H"); for (c=0; c < 80; c++) putchar('-'); printf("\x1B[23;1H"); for (c=0; c < 80; c++) putchar('-'); DisplayFONpage(page); DrawBar(ON); printf("\x1B[24;1HUp Down Home End PgUp PgDn Space Esc"); while (! ready) { if ((c = getch()) == 0) c -= getch(); switch (c) { case KEY_ESC : ready = TRUE; break; case KEY_SPACE : marked = marked ? FALSE : TRUE; DrawBar(ON); break; case KEY_HOME : if (marked) { from = page * PERPAGE + barline; to = 0; if (marked) MoveRecord(from,to); } page = barline = 0; DisplayFONpage(page); DrawBar(ON); break; case KEY_END : if (marked) { from = page * PERPAGE + barline; to = ((MAXPAGE - 1) * PERPAGE) + (PERPAGE - 1); MoveRecord(from,to); } page = MAXPAGE - 1; barline = PERPAGE - 1; DisplayFONpage(page); DrawBar(ON); break; case KEY_PGDN : from = page * PERPAGE + barline; if (++page == MAXPAGE) page = 0; to = page * PERPAGE + barline; if (marked) MoveRecord(from,to); DisplayFONpage(page); DrawBar(ON); break; case KEY_PGUP : from = page * PERPAGE + barline; if (--page < 0) page = MAXPAGE - 1; to = page * PERPAGE + barline; if (marked) MoveRecord(from,to); DisplayFONpage(page); DrawBar(ON); break; case KEY_DOWN : from = page * PERPAGE + barline; if (barline+1 == PERPAGE) { barline = 0; if (++page == MAXPAGE) page = 0; to = page * PERPAGE + barline; if (marked) MoveRecord(from,to); DisplayFONpage(page); DrawBar(ON); break; } to = page * PERPAGE + barline + 1; if (marked) MoveRecord(from,to); DrawBar(OFF); barline++; DrawBar(ON); break; case KEY_UP : from = page * PERPAGE + barline; if (barline-1 < 0) { barline = PERPAGE - 1; if (--page < 0) page = MAXPAGE - 1; to = page * PERPAGE + barline; if (marked) MoveRecord(from,to); DisplayFONpage(page); DrawBar(ON); break; } to = page * PERPAGE + barline - 1; if (marked) MoveRecord(from,to); DrawBar(OFF); barline--; DrawBar(ON); break; } } printf("\x1B[25;1H"); if (changes) { printf("\nSave changes (Y/N) ?"); while (! strchr("YN", (c = toupper(getch())))) ; if (c == 'Y') { puts("Yes"); strcpy(bakfile,fonfile); bakfile[strlen(bakfile)-1] = '&'; printf("Renaming %s -> %s\n",fonfile,bakfile); if (rename(fonfile,bakfile) == -1) { unlink(bakfile); rename(fonfile,bakfile); } printf("Writing %s\n",fonfile); WriteFON(fonfile); } else puts("No"); puts(""); } return(0); } /*--------------------------------------------------------------------------*/ /* Move record to another place */ /*--------------------------------------------------------------------------*/ void MoveRecord(int from, int to) { register int i; int nbytes = sizeof(struct FON); struct FON tmpfon; if (from == to) return; memcpy(&tmpfon, &fon[from], nbytes); if (from > to) for (i=from; i > to; i--) memcpy(&fon[i], &fon[i-1], nbytes); else memcpy(&fon[from], &fon[from+1], nbytes * (to - from)); memcpy(&fon[to], &tmpfon, nbytes); changes = TRUE; } /*--------------------------------------------------------------------------*/ /* Draw cursor bar */ /*--------------------------------------------------------------------------*/ void DrawBar(char state) { printf("\x1B[%d;1H\x1B[%dm",barline+3, state == ON ? 7 : 0); DisplayFONrec(page * PERPAGE + barline); if (state == ON) { if (marked) printf("\x1B[%d;1H\x1B[5m*",barline+3); printf("\x1B[0m"); } } /*--------------------------------------------------------------------------*/ /* Display pagefull of FON records */ /*--------------------------------------------------------------------------*/ void DisplayFONpage(int page) { register int i; int start = page * PERPAGE; int end = start + PERPAGE; printf("\x1B[1;1H%s",fonfile); printf("\x1B[1;68H Page %2d/%-2d",page+1,MAXPAGE); printf("\x1B[3;1H"); for (i=start; i < end; i++) DisplayFONrec(i); } /*--------------------------------------------------------------------------*/ /* Display one FON record */ /*--------------------------------------------------------------------------*/ void DisplayFONrec(int i) { printf(" %3d %-28s %20s %6ld-%c%1d%1d %s \n", i+1, fon[i].name, fon[i].number, fon[i].baud, fon[i].parity, fon[i].databits, fon[i].stopbits, emulation[fon[i].emulation] ); } /*--------------------------------------------------------------------------*/ /* Read FON file */ /*--------------------------------------------------------------------------*/ void ReadFON(char *fname) { register int i; FILE *fd; if ((fd = fopen(fname,"rb")) == NULL) { printf("Unable to open file %s\a\n",fname); exit(1); } if (fread(&fon, sizeof(struct FON), MAXFON, fd) != MAXFON) { printf("Unable to read file %s\a\n",fname); exit(1); } fclose(fd); for (i=0; i < MAXFON; i++) { Pascal2Zstr(fon[i].name); Pascal2Zstr(fon[i].number); Pascal2Zstr(fon[i].password); Pascal2Zstr(fon[i].script); Pascal2Zstr(fon[i].keyfile); } } /*--------------------------------------------------------------------------*/ /* Write FON file */ /*--------------------------------------------------------------------------*/ void WriteFON(char *fname) { register int i; FILE *fd; for (i=0; i < MAXFON; i++) { Zstr2Pascal(fon[i].name); Zstr2Pascal(fon[i].number); Zstr2Pascal(fon[i].password); Zstr2Pascal(fon[i].script); Zstr2Pascal(fon[i].keyfile); } if ((fd = fopen(fname,"wb")) == NULL) { printf("Unable to create file %s\a\n",fname); exit(1); } if (fwrite(&fon, sizeof(struct FON), MAXFON, fd) != MAXFON) { printf("Unable to write file %s\a\n",fname); exit(1); } fclose(fd); } /*--------------------------------------------------------------------------*/ /* Convert Pascal string to ASCIIZ string */ /*--------------------------------------------------------------------------*/ void Pascal2Zstr(char *s) { unsigned char len = *s; if (! len) return; memcpy(s, s+1, len); *(s + len) = NULL; } /*--------------------------------------------------------------------------*/ /* Convert ASCIIZ string to Pascal string */ /*--------------------------------------------------------------------------*/ void Zstr2Pascal(char *s) { unsigned char i, len; if (! *s) return; len = (unsigned char) strlen(s); for (i=len; i > 0; i--) *(s + i) = *(s + i - 1); *s = len; } /*---------------------------------------------------------------------------*/ /* Detect ANSI terminal */ /*---------------------------------------------------------------------------*/ char DetectAnsi() { char ok = FALSE; char ret = FALSE; time_t t1, t2; while (kbhit()) getch(); t1 = t2 = time(NULL); printf("\x1B[5n"); while (t2 - t1 <= 2) { if (kbhit()) { if (getch() != 27) goto EX; ok = TRUE; break; } t2 = time(NULL); } if (! ok) goto EX; t1 = t2 = time(NULL); ok = FALSE; while (t2 - t1 <= 2) { if (kbhit()) { if (getch() != '[') goto EX; ok = TRUE; break; } t2 = time(NULL); } if (ok) ret = TRUE; EX: while (kbhit()) getch(); return(ret); }