/*

/usr/src/ext2ed/blockbitmap_com.c

A part of the extended file system 2 disk editor.

-------------------------
Handles the block bitmap.
-------------------------

This file implements the commands which are specific to the blockbitmap type.

First written on: July 5 1995

Copyright (C) 1995 Gadi Oxman

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "ext2ed.h"

/*

The functions in this file use the flobal structure block_bitmap_info. This structure contains the current
position in the bitmap.

*/

void type_ext2_block_bitmap___entry (char *command_line)

/*

This function changes the current entry in the bitmap. It just changes the entry_num variable in block_bitmap_info
and dispatches a show command to show the new entry.

*/

{
	unsigned long entry_num;
	char *ptr,buffer [80];
	
	
	
	ptr=parse_word (command_line,buffer);					/* Get the requested entry */
	if (*ptr==0) {
		wprintw (command_win,"Error - No argument specified\n");
		refresh_command_win ();	return;
	}
	ptr=parse_word (ptr,buffer);

	entry_num=atol (buffer);

	
	if (entry_num >= file_system_info.super_block.s_blocks_per_group) {	/* Check if it is a valid entry number */

		wprintw (command_win,"Error - Entry number out of bounds\n");
		refresh_command_win ();return;
	}
	
	
	
	block_bitmap_info.entry_num=entry_num;					/* If it is, just change entry_num and */
	strcpy (buffer,"show");dispatch (buffer);				/* dispatch a show command */
}

void type_ext2_block_bitmap___next (char *command_line)

/*

This function passes to the next entry in the bitmap. We just call the above entry command.

*/

{
	long entry_offset=1;
	char *ptr,buffer [80];
	
	ptr=parse_word (command_line,buffer);
	if (*ptr!=0) {
		ptr=parse_word (ptr,buffer);
		entry_offset=atol (buffer);
	}

	sprintf (buffer,"entry %ld",block_bitmap_info.entry_num+entry_offset);
	dispatch (buffer);
}

void type_ext2_block_bitmap___prev (char *command_line)

{
	long entry_offset=1;
	char *ptr,buffer [80];
	
	ptr=parse_word (command_line,buffer);
	if (*ptr!=0) {
		ptr=parse_word (ptr,buffer);
		entry_offset=atol (buffer);
	}

	sprintf (buffer,"entry %ld",block_bitmap_info.entry_num-entry_offset);
	dispatch (buffer);
}

void type_ext2_block_bitmap___allocate (char *command_line)

/*

This function starts allocating block from the current position. Allocating involves setting the correct bits
in the bitmap. This function is a vector version of allocate_block below - We just run on the blocks that
we need to allocate, and call allocate_block for each one.

*/

{
	long entry_num,num=1;
	char *ptr,buffer [80];
	
	ptr=parse_word (command_line,buffer);					/* Get the number of blocks to allocate */
	if (*ptr!=0) {
		ptr=parse_word (ptr,buffer);
		num=atol (buffer);
	}
	
	entry_num=block_bitmap_info.entry_num;
										/* Check for limits */
	if (num > file_system_info.super_block.s_blocks_per_group-entry_num) {
		wprintw (command_win,"Error - There aren't that much blocks in the group\n");	
		refresh_command_win ();return;				
	}
	
	while (num) {								/* And call allocate_block */
		allocate_block (entry_num);					/* for each block */
		num--;entry_num++;
	}
	
	dispatch ("show");							/* Show the result */
}

void type_ext2_block_bitmap___deallocate (char *command_line)

/* This is the opposite of the above function - We call deallocate_block instead of allocate_block */

{
	long entry_num,num=1;
	char *ptr,buffer [80];
	
	ptr=parse_word (command_line,buffer);
	if (*ptr!=0) {
		ptr=parse_word (ptr,buffer);
		num=atol (buffer);
	}
	
	entry_num=block_bitmap_info.entry_num;
	if (num > file_system_info.super_block.s_blocks_per_group-entry_num) {
		wprintw (command_win,"Error - There aren't that much blocks in the group\n");	
		refresh_command_win ();return;				
	}
	
	while (num) {
		deallocate_block (entry_num);
		num--;entry_num++;
	}
	
	dispatch ("show");
}


void allocate_block (long entry_num)

/* In this function we convert the bit number into the right byte and inner bit positions. */

{
	unsigned char bit_mask=1;
	int byte_offset,j;
	
	byte_offset=entry_num/8;					/* Find the correct byte - entry_num/8 */
									/* The position inside the byte is entry_num %8 */
	for (j=0;j<entry_num%8;j++)
		bit_mask*=2;						/* Generate the or mask - 1 at the right place */
	type_data.u.buffer [byte_offset] |= bit_mask;			/* And apply it */
}

void deallocate_block (long entry_num)

/* This is the opposite of allocate_block above. We use an and mask instead of an or mask. */

{
	unsigned char bit_mask=1;
	int byte_offset,j;
	
	byte_offset=entry_num/8;
	for (j=0;j<entry_num%8;j++)
		bit_mask*=2;
	bit_mask^=0xff;
	
	type_data.u.buffer [byte_offset] &= bit_mask;
}

void type_ext2_block_bitmap___show (char *command_line)

/*

We show the bitmap as a series of bits, grouped at 8-bit intervals. We display 8 such groups on each line.
The current position (as known from block_bitmap_info.entry_num) is highlighted.

*/

{
	int i,j;
	unsigned char *ptr;
	unsigned long block_num,entry_num;

	ptr=type_data.u.buffer;
	show_pad_info.line=0;show_pad_info.max_line=-1;
	
	wmove (show_pad,0,0);
	for (i=0,entry_num=0;i<file_system_info.super_block.s_blocks_per_group/8;i++,ptr++) {
		for (j=1;j<=128;j*=2) {						/* j contains the and bit mask */
			if (entry_num==block_bitmap_info.entry_num) {		/* Highlight the current entry */
				wattrset (show_pad,A_REVERSE);
				show_pad_info.line=show_pad_info.max_line-show_pad_info.display_lines/2;
			}

			if ((*ptr) & j)						/* Apply the mask */
				wprintw (show_pad,"1");
			else
				wprintw (show_pad,"0");

			if (entry_num==block_bitmap_info.entry_num)
				wattrset (show_pad,A_NORMAL);

			entry_num++;						/* Pass to the next entry */
		}
		wprintw (show_pad," ");
		if (i%8==7) {							/* Display 8 groups in a row */
			wprintw (show_pad,"\n");
			show_pad_info.max_line++;
		}
	}
	
	refresh_show_pad ();	
	show_info ();								/* Show the usual information */

										/* Show the group number */
	wmove (show_win,1,0);
	wprintw (show_win,"Block bitmap of block group %ld\n",block_bitmap_info.group_num);
										/* Show the block number */
										
	block_num=block_bitmap_info.entry_num+block_bitmap_info.group_num*file_system_info.super_block.s_blocks_per_group;
	block_num+=file_system_info.super_block.s_first_data_block;	

	wprintw (show_win,"Status of block %ld - ",block_num);			/* and the allocation status */
	ptr=type_data.u.buffer+block_bitmap_info.entry_num/8;
	j=1;
	for (i=block_bitmap_info.entry_num % 8;i>0;i--)
		j*=2;
	if ((*ptr) & j)						
		wprintw (show_win,"Allocated\n");
	else
		wprintw (show_win,"Free\n");
	refresh_show_win ();
}
