/* * edit.c * * Edit the database. */ /*** *** Include files ***/ #include #include #include #include #include #include "pragmas.h" #include "pinewood.h" /*** *** Local function prototypes ***/ static void delete_char(char *field, int col); static void paint_line(int cur_base, int line); static void paint_screen(int cur_base); static void place_char(char *field, int col, unsigned int ch, bool_t insert, size_t size); /*** *** Exported functions ***/ /* * edit_data * * Edit the database. * This is just a simple in memory editor. */ /*lint -esym(644,save_record) */ void edit_data(void) { unsigned int ch; int cur_base; int cur_col; int cur_line; int cur_user; bool_t delete; bool_t insert; bool_t line_dirty; struct db save_record; bool_t screen_dirty; int target; int undo_user; cur_base = 0; cur_col = 0; cur_line = 0; cur_user = 0; delete = FALSE; insert = TRUE; line_dirty = FALSE; screen_dirty = TRUE; undo_user = -1; clrscr(); for (;;) { if (Nusers == 0) { Nusers = 1; cur_user = 0; init_db(cur_user, TRUE); } if (cur_user < cur_base) { cur_base = cur_user; screen_dirty = TRUE; } else if (cur_user >= cur_base + NDATAL) { cur_base = cur_user - NDATAL + 1; screen_dirty = TRUE; } cur_line = cur_user - cur_base; if (screen_dirty) paint_screen(cur_base); else if (line_dirty) paint_line(cur_base, cur_line); screen_dirty = line_dirty = FALSE; /* Ensure that we are in a field */ if (cur_col >= C_NAME && cur_col < C_CAR && cur_col - C_NAME > (int) strlen(Database[cur_user].name)) { cur_col = strlen(Database[cur_user].name) + C_NAME; } else if (cur_col >= C_CAR && cur_col < C_TIME && cur_col - C_CAR > (int) strlen(Database[cur_user].car)) { cur_col = strlen(Database[cur_user].car) + C_CAR; } gotoxy(cur_col + 1, cur_line + 1 + 2); ch = getxch(); switch (ch) { case K_F3: /* Exit */ Database_dirty = TRUE; return; case K_F4: /* Write */ write_database(); break; case K_F5: /* Delete record */ delete = TRUE; undo_user = cur_user; save_record = Database[undo_user]; if (Nusers > 1) { memmove(&Database[cur_user], &Database[cur_user + 1], sizeof(Database[0]) * (size_t) (Nusers - cur_user)); if (cur_user >= --Nusers) cur_user = Nusers - 1; } else Nusers = 0; screen_dirty = 1; break; case '\n': case '\r': case K_DOWN: if (cur_user < Nusers - 1) { cur_user++; break; } /* Otherwise insert a new entry by falling through */ case K_F6: /* Insert record */ if (Nusers < NUSERS - 1) { cur_user++; memmove(&Database[cur_user + 1], &Database[cur_user], sizeof(Database[0]) * (size_t) (Nusers - cur_user)); init_db(cur_user, TRUE); screen_dirty = 1; cur_col = 0; Nusers++; } break; case K_F7: /* Restore record */ if (delete) { memmove(&Database[undo_user + 1], &Database[undo_user], sizeof(Database[0]) * (size_t) (Nusers - undo_user)); Database[undo_user] = save_record; delete = FALSE; cur_user = undo_user; undo_user = -1; screen_dirty = 1; cur_col = 0; Nusers++; } else if (undo_user != -1) { Database[undo_user] = save_record; line_dirty = 1; cur_user = undo_user; } break; case K_HOME: cur_col = 0; break; case K_UP: if (cur_user > 0) cur_user--; break; case K_PGUP: if (cur_line == 0) { cur_user -= NDATAL; if (cur_user < 0) cur_user = 0; screen_dirty = TRUE; } else cur_user = cur_base; break; case K_LEFT: if (cur_col > 0) cur_col--; break; case '\t': case K_RIGHT: if (cur_col < C_CAR + (int) strlen(Database[cur_user].car)) { cur_col++; if (cur_col >= C_NAME && cur_col < C_CAR && cur_col - C_NAME > (int) strlen(Database[cur_user].name)) { cur_col = C_CAR; } } break; case K_END: if (cur_col >= C_NAME && cur_col < C_CAR) { target = C_NAME + strlen(Database[cur_user].name); if (target == cur_col) target = C_CAR + strlen(Database[cur_user].car); cur_col = target; } break; case K_PGDN: if (cur_user == cur_base + NDATAL - 1) { cur_user += NDATAL; if (cur_user >= Nusers) { cur_user = Nusers - 1; cur_base = Nusers - NDATAL; screen_dirty = TRUE; } } else cur_user = cur_base + NDATAL - 1; break; case K_INSERT: insert = !insert; break; case '\b': if (cur_col == 0) break; cur_col--; /* Fall through into the delete code */ case K_DELETE: if (undo_user != cur_user) { undo_user = cur_user; save_record = Database[undo_user]; } if (cur_col >= C_NAME && cur_col < C_CAR) delete_char(Database[cur_user].name, cur_col - C_NAME); else if (cur_col >= C_CAR && cur_col < C_TIME) delete_char(Database[cur_user].car, cur_col - C_CAR); line_dirty = TRUE; break; default: if (((ch & 0xFF00) == 0) && isprint(ch)) { if (undo_user != cur_user) { undo_user = cur_user; save_record = Database[undo_user]; } if (cur_col >= C_NAME && cur_col < C_CAR) { place_char(Database[cur_user].name, cur_col - C_NAME, ch, insert, NSIZE); } else if (cur_col >= C_CAR && cur_col < C_TIME) { place_char(Database[cur_user].car, cur_col - C_CAR, ch, insert, CSIZE); } else cur_col--; /* Too far */ cur_col++; line_dirty = TRUE; } break; } } } /* * getxch * * Get an extended character. If the first byte read is 0x00, then * get an additional character. Put this second 8 bits at the high * end of the 16 bit return value. */ unsigned int getxch(void) { unsigned int retval; if ((retval = (unsigned int) getch()) == 0x00) retval = (unsigned int) getch() << 8; return (retval); } /*** *** Local helper functions ***/ /* * delete_char * * Delete a character in a string */ static void delete_char(char *field, int col) { memmove((void *) &field[col], (void *) &field[col + 1], strlen(&field[col])); } /* * paint_line * * Paint one line on the screen */ static void paint_line(int cur_base, int line) { int run; gotoxy(1, line + 3); if (cur_base + line < Nusers) { cprintf("%-30.30s%-4.4s ", Database[cur_base + line].name, Database[cur_base + line].car); cprintf("%d ", Database[cur_base + line].racenum); for (run = 0; run < NRACES; run++) { if (Database[cur_base + line].lane[run] != 0) { cprintf("%ld/%d ", Database[cur_base + line].run[run], Database[cur_base + line].lane[run]); } } } clreol(); } /* * paint_screen * * Put up a help line, the title line, and the appropriate users. */ static void paint_screen(int cur_base) { int line; highvideo(); gotoxy(1, 1); cprintf("F3 - Done F4 - Save F5-Delete F6-Insert F7-Undo"); gotoxy(1, 2); cprintf("%-30.30sCar Time ", "Name"); normvideo(); for (line = 0; line < NLINES - 2; line++) paint_line(cur_base, line); } /* * place_char * * place a character in a string */ void place_char(char *field, int col, unsigned int ch, bool_t insert, size_t size) { size_t len; if (insert) { len = strlen(&field[col]); memmove((void *) &field[col + 1], (void *) &field[col], len); field[ ((size_t) col + len + 1 < size) ? (size_t) col + len + 1 : size] = '\0'; } field[col] = (char) ch; }