gint hex_document_read(HexDocument *doc) { FILE *file; static HexChangeData change_data; if(doc->file_name == NULL) return FALSE; if(!get_document_attributes(doc)) return FALSE; if((file = fopen(doc->file_name, "r")) == NULL) return FALSE; doc->gap_size = doc->buffer_size - doc->file_size; if(fread(doc->buffer + doc->gap_size, 1, doc->file_size, file) != doc->file_size) { g_return_val_if_reached(FALSE); } doc->gap_pos = doc->buffer; fclose(file); undo_stack_free(doc); change_data.start = 0; change_data.end = doc->file_size - 1; doc->changed = FALSE; hex_document_changed(doc, &change_data, FALSE); return TRUE; }
void hex_document_set_byte(HexDocument *doc, guchar val, guint offset, gboolean insert, gboolean undoable) { static HexChangeData change_data; if(offset <= doc->file_size) { if(!insert && offset == doc->file_size) return; doc->changed = TRUE; change_data.start = offset; change_data.end = offset; change_data.rep_len = (insert?0:1); change_data.v_string = NULL; change_data.type = HEX_CHANGE_BYTE; change_data.lower_nibble = FALSE; change_data.insert = insert; if(insert) { move_gap_to(doc, offset, 1); doc->gap_size--; doc->gap_pos++; doc->file_size++; } else if(doc->buffer + offset >= doc->gap_pos) offset += doc->gap_size; change_data.v_byte = doc->buffer[offset]; doc->buffer[offset] = val; hex_document_changed(doc, &change_data, undoable); } }
void hex_document_set_data(HexDocument *doc, guint offset, guint len, guint rep_len, guchar *data, gboolean undoable) { guint i; guchar *ptr; static HexChangeData change_data; if(offset <= doc->file_size) { if(doc->file_size - offset < rep_len) rep_len -= doc->file_size - offset; doc->changed = TRUE; change_data.v_string = g_realloc(change_data.v_string, rep_len); change_data.start = offset; change_data.end = change_data.start + len - 1; change_data.rep_len = rep_len; change_data.type = HEX_CHANGE_STRING; change_data.lower_nibble = FALSE; i = 0; ptr = &doc->buffer[offset]; if(ptr >= doc->gap_pos) ptr += doc->gap_size; while(offset + i < doc->file_size && i < rep_len) { if(ptr >= doc->gap_pos && ptr < doc->gap_pos + doc->gap_size) ptr += doc->gap_size; change_data.v_string[i] = *ptr++; i++; } if(rep_len == len) { if(doc->buffer + offset >= doc->gap_pos) offset += doc->gap_size; } else { if(rep_len > len) { move_gap_to(doc, offset + rep_len, 1); } else if(rep_len < len) { move_gap_to(doc, offset + rep_len, len - rep_len); } doc->gap_pos -= (gint)rep_len - (gint)len; doc->gap_size += (gint)rep_len - (gint)len; doc->file_size += (gint)len - (gint)rep_len; } ptr = &doc->buffer[offset]; i = 0; while(offset + i < doc->buffer_size && i < len) { *ptr++ = *data++; i++; } hex_document_changed(doc, &change_data, undoable); } }
void hex_document_set_nibble(HexDocument *doc, guchar val, guint offset, gboolean lower_nibble, gboolean insert, gboolean undoable) { static HexChangeData change_data; if(offset <= doc->file_size) { if(!insert && offset == doc->file_size) return; doc->changed = TRUE; change_data.start = offset; change_data.end = offset; change_data.v_string = NULL; change_data.type = HEX_CHANGE_BYTE; change_data.lower_nibble = lower_nibble; change_data.insert = insert; if(!lower_nibble && insert) { move_gap_to(doc, offset, 1); doc->gap_size--; doc->gap_pos++; doc->file_size++; change_data.rep_len = 0; if(offset == doc->file_size) doc->buffer[offset] = 0; } else { if(doc->buffer + offset >= doc->gap_pos) offset += doc->gap_size; change_data.rep_len = 1; } change_data.v_byte = doc->buffer[offset]; doc->buffer[offset] = (doc->buffer[offset] & (lower_nibble?0xF0:0x0F)) | (lower_nibble?val:(val << 4)); hex_document_changed(doc, &change_data, undoable); } }
static void hex_document_real_undo (HexDocument *doc) { HexChangeData *cd; gint len; guchar *rep_data; gchar c_val; cd = (HexChangeData *)doc->undo_top->data; switch(cd->type) { case HEX_CHANGE_BYTE: if(cd->start >= 0 && cd->end < doc->file_size) { c_val = hex_document_get_byte(doc, cd->start); if(cd->rep_len > 0) hex_document_set_byte(doc, cd->v_byte, cd->start, FALSE, FALSE); else if(cd->rep_len == 0) hex_document_delete_data(doc, cd->start, 1, FALSE); else hex_document_set_byte(doc, cd->v_byte, cd->start, TRUE, FALSE); cd->v_byte = c_val; } break; case HEX_CHANGE_STRING: len = cd->end - cd->start + 1; rep_data = hex_document_get_data(doc, cd->start, len); hex_document_set_data(doc, cd->start, cd->rep_len, len, cd->v_string, FALSE); g_free(cd->v_string); cd->end = cd->start + cd->rep_len - 1; cd->rep_len = len; cd->v_string = rep_data; break; } hex_document_changed(doc, cd, FALSE); undo_stack_descend(doc); }