/* This is one of the cipher files for the cipher interface written ** by wart@ugcs.caltech.edu ** ** Please don't steal my code without my permission. ** */ #include #include #include #include "term.h" #include "types.h" #include "ctypes.h" swagman::swagman(){ length = 0; period = 0; num_squares = 0; cipher[0] = (char) NULL; } int swagman::execute_option(char option){ int valid = TRUE; switch(option){ case CHANGEPERIOD: change_period(); clear_to_prompt(); break; case SUBSTITUTE: substitute(); break; case UNDO: undo(); break; case MOVE: move_stuff(); break; default: valid = base_exec_option(option); break; } return valid; } int swagman::period_valid(){ if(period && length%period == 0) return TRUE; else return FALSE; } void swagman::change_period(){ period_set = FALSE; set_period(); setup_key(); } void swagman::setup_key(){ key.init(period, period); } void swagman::move_stuff(){ char tmp_str[STRINGLENGTH]; int row1, row2, i, j; prompt("Swap which rows? (x,y) "); read_line(tmp_str); if(sscanf(tmp_str, "%d,%d", &row1, &row2) != 2) msgerror("Bad coordinate format."); else if(row1 == row2) msgerror("You can't swap a row with itself."); else if(row1 < 1 || row2 < 1 || row1 > period || row2 > period) msgerror("Error: Parameters out of range."); else{ row1 += '0'; row2 += '0'; for(i = 0; i < period; i++){ for(j = 0; j < period; j++){ if(key.val(i, j) == row1) key.alter(row2, i, j); else if(key.val(i, j) == row2) key.alter(row2, i, j); } } clear_to_prompt(); } } void swagman::substitute(){ char tmp_str[STRINGLENGTH]; int row, column, number; prompt("What are the coordinates of the new number? (column,row) "); read_line(tmp_str); if(sscanf(tmp_str, "%d,%d", &column, &row) != 2) msgerror("Bad coordinate format."); else if(row < 1 || row > period || column < 1 || column > period) msgerror("Bad position."); else{ prompt("What is the new number? "); number = get_char(); if(!isdigit(number)) msgerror("Bad number."); else{ row--, column--; update_key(number, row, column); } } } void swagman::undo(){ char tmp_str[STRINGLENGTH]; int row, column; prompt("Undo which column,row? (* for all) "); read_line(tmp_str); if(*tmp_str == '*') key.clearkey(); else if(sscanf(tmp_str, "%d,%d", &column, &row) != 2) msgerror("Bad coordinate format."); else key.clearkey(row, column); } void swagman::show_menu(){ menu(2, "Options: (S)ubstitute number (U)ndo number (M)ove rows (C)hange period"); menu(1, " (W)rite (Q)uit"); } void swagman::show_cipher(){ int ssize, num_squares; int row, column; int i; ssize = period*period; num_squares = (length%ssize == 0)?(length/ssize):(1 + (length/ssize)); /* In order to make the squares all fit on one row I needed to make ** the spacing non-neat, ie, there are no horizontal spaces between ** letters. */ i = 0; while(i < length){ column = (i/period)%period; row = i%period; /* If the letter has been remove then replace it with the ** keysquare value and put the cipher letter in the ** decoded area. */ if(key.val(row, column) == BLANK){ /* Show the key */ put_char(toupper(cipher[i]), column + (i/ssize)*(period+1), row); /* Show the cipher */ put_char(BLANK, column + (i/ssize)*(period+1), key.intval(row, column) + period+3); } else{ /* Show the key */ put_char('.', column + (i/ssize)*(period+1), row); /* Show the cipher */ put_char(cipher[i], column + (i/ssize)*(period+1), key.intval(row, column) + period+3); /* put_char(key[row][column], column + (i/ssize)*(period+1), row); put_char(cipher[i], column + (i/ssize)*(period+1), key[row][column] -'0' + period+3); */ } i++; } } void swagman::update_key(char number, int row, int column){ int i, bad = FALSE; /* Are the row and column valid? */ if(row >= period && column >= period){ msgerror("Error: row/column values out of range"); bad = TRUE; } /* Does this put a number in a row or column with the same number? ** That's not allowed... */ for(i = 0; i < period; i++){ if(key.val(i, column) == number){ msgerror("Error: Identical numbers in same column."); bad = TRUE; } } for(i = 0; i < period; i++){ if(key.val(row, i) == number){ msgerror("Error: Identical numbers in same row."); bad = TRUE; } } if(!bad) key.alter(number, row, column); } void swagman::decipher(char *string){ int ssize, num_squares; int row, column, snum; int i, num_cols; num_cols = length / period; ssize = period*period; num_squares = (length%ssize == 0)?(length/ssize):(1 + (length/ssize)); for(i = 0; i < length; i++) string[i] = BLANK; i = 0; while(i < length){ column = (i/period)%period; row = i%period; snum = i / (period*period); /* If the letter has been remove then replace it with the ** keysquare value and put the cipher letter in the ** decoded area. */ if(key.val(row, column) != BLANK){ string[(key.intval(row, column)-1)*period*period + column + snum*period] = cipher[i]; } i++; } }