2016-06-19 21:00:24 +01:00
/****************************************
2016-08-21 16:37:38 +01:00
* Shitty Expensive Typewriter *
* A more shitty remake of the PDP - 1 ' s *
* Expensive Typewriter program *
2016-06-19 21:00:24 +01:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <stdio.h>
# include <stdlib.h>
# include <stdint.h>
# include <stdbool.h>
# include <string.h>
# define max_string 255
bool Reached_EOF ;
char temp [ max_string + 1 ] ;
2016-07-18 23:30:03 +01:00
char tty_getchar ( ) ;
2016-06-19 21:00:24 +01:00
struct Line
{
struct Line * next ;
struct Line * prev ;
2016-08-21 16:37:38 +01:00
char * Text ;
2016-06-19 21:00:24 +01:00
} ;
2016-07-18 23:30:03 +01:00
int get_linenum ( struct Line * p )
{
if ( NULL = = p - > prev )
{
return 0 ;
}
return get_linenum ( p - > prev ) + 1 ;
}
2016-06-19 21:00:24 +01:00
struct Line * newLine ( )
{
struct Line * p ;
p = calloc ( 1 , sizeof ( struct Line ) ) ;
if ( NULL = = p )
{
fprintf ( stderr , " calloc failed. \n " ) ;
exit ( EXIT_FAILURE ) ;
}
return p ;
}
struct Line * addLine ( struct Line * head , struct Line * p )
{
if ( NULL = = head )
{
return p ;
}
if ( NULL = = head - > next )
{
head - > next = p ;
p - > prev = head ;
}
else
{
addLine ( head - > next , p ) ;
}
return head ;
}
2016-08-21 16:37:38 +01:00
void Readline ( struct Line * p , FILE * source_file )
2016-06-19 21:00:24 +01:00
{
2016-08-21 16:37:38 +01:00
char * store = calloc ( max_string + 1 , sizeof ( char ) ) ;
2016-06-19 21:00:24 +01:00
int32_t c ;
uint32_t i ;
for ( i = 0 ; i < max_string ; i = i + 1 )
{
c = fgetc ( source_file ) ;
if ( - 1 = = c )
{
Reached_EOF = true ;
goto Line_complete ;
}
else if ( ( 10 = = c ) | | ( 13 = = c ) )
{
store [ i ] = ( char ) ( 10 ) ;
goto Line_complete ;
}
else
{
store [ i ] = ( char ) c ;
}
}
Line_complete :
2016-08-21 16:37:38 +01:00
p - > Text = store ;
2016-06-19 21:00:24 +01:00
}
void WriteOut ( struct Line * head , FILE * source_file )
{
if ( NULL = = head )
{
return ;
}
2016-08-21 16:37:38 +01:00
if ( NULL ! = head - > Text )
{
fputs ( head - > Text , source_file ) ;
}
else
{
fputc ( 10 , source_file ) ;
}
2016-06-19 21:00:24 +01:00
WriteOut ( head - > next , source_file ) ;
}
struct Line * GetHead ( struct Line * p )
{
if ( NULL = = p )
{
return NULL ;
}
if ( NULL = = p - > prev )
{
return p ;
}
return GetHead ( p - > prev ) ;
}
struct Line * RemoveLine ( struct Line * p )
{
if ( ( NULL = = p - > prev ) & & ( NULL = = p - > next ) )
{
return NULL ;
}
if ( NULL ! = p - > next )
{
p - > next - > prev = p - > prev ;
}
if ( NULL ! = p - > prev )
{
p - > prev - > next = p - > next ;
}
2016-07-18 23:30:03 +01:00
if ( NULL ! = p - > next )
{
return p - > next ;
}
return p - > prev ;
2016-06-19 21:00:24 +01:00
}
struct Line * InsertLine ( struct Line * head )
{
struct Line * p ;
p = newLine ( ) ;
if ( NULL = = head )
{
return p ;
}
if ( NULL ! = head - > prev )
{
head - > prev - > next = p ;
}
p - > prev = head - > prev ;
p - > next = head ;
head - > prev = p ;
return head ;
}
struct Line * AppendLine ( struct Line * head )
{
struct Line * p ;
p = newLine ( ) ;
if ( NULL = = head )
{
return p ;
}
if ( NULL ! = head - > next )
{
head - > next - > prev = p ;
}
p - > next = head - > next ;
p - > prev = head ;
head - > next = p ;
return head ;
}
2016-07-18 23:30:03 +01:00
void Editor_loop ( struct Line * head , char * file_name )
2016-06-19 21:00:24 +01:00
{
2016-07-18 23:30:03 +01:00
switch ( tty_getchar ( ) )
2016-06-19 21:00:24 +01:00
{
case ' a ' :
{
AppendLine ( head ) ;
break ;
}
case ' b ' :
{
if ( NULL ! = head - > prev )
{
2016-07-18 23:30:03 +01:00
Editor_loop ( head - > prev , file_name ) ;
2016-06-19 21:00:24 +01:00
}
break ;
}
case ' d ' :
{
head = RemoveLine ( head ) ;
break ;
}
case ' e ' :
{
2016-08-21 16:37:38 +01:00
Readline ( head , stdin ) ;
2016-06-19 21:00:24 +01:00
break ;
}
case ' f ' :
{
if ( NULL ! = head - > next )
{
2016-07-18 23:30:03 +01:00
Editor_loop ( head - > next , file_name ) ;
2016-06-19 21:00:24 +01:00
}
break ;
}
case ' i ' :
{
InsertLine ( head ) ;
break ;
}
case ' p ' :
{
2016-07-18 23:30:03 +01:00
printf ( " Showing contents of line %04x: \n " , get_linenum ( head ) ) ;
2016-06-19 21:00:24 +01:00
fputs ( head - > Text , stdout ) ;
break ;
}
case ' q ' :
{
exit ( EXIT_SUCCESS ) ;
}
case ' w ' :
{
2016-07-18 23:30:03 +01:00
FILE * source_file ;
source_file = fopen ( file_name , " w " ) ;
2016-06-19 21:00:24 +01:00
WriteOut ( GetHead ( head ) , source_file ) ;
2016-07-18 23:30:03 +01:00
fclose ( source_file ) ;
2016-06-19 21:00:24 +01:00
break ;
}
case ' ? ' :
default :
{
fputs ( " ? for help \n e to edit the line \n d to delete the line \n p print line \n f to move to next line \n b to move to previous line \n i to insert a newline before this one \n a to insert a newline after this one \n w to write out to file \n q to quit \n " , stdout ) ;
}
}
2016-07-18 23:30:03 +01:00
Editor_loop ( head , file_name ) ;
2016-06-19 21:00:24 +01:00
}
/* Standard C main program */
int main ( int argc , char * * argv )
{
/* Make sure we have a program tape to run */
if ( argc < 2 )
{
fprintf ( stderr , " Usage: %s $FileName \n Where $FileName is the name of the paper tape of the program being run \n " , argv [ 0 ] ) ;
return EXIT_FAILURE ;
}
FILE * source_file ;
2016-07-18 23:30:03 +01:00
char file_name [ 256 ] = { 0 } ;
strncpy ( file_name , argv [ 1 ] , 255 ) ;
source_file = fopen ( file_name , " rw+ " ) ;
2016-06-19 21:00:24 +01:00
Reached_EOF = false ;
struct Line * head = NULL ;
struct Line * p = NULL ;
while ( ! Reached_EOF )
{
p = newLine ( ) ;
2016-08-21 16:37:38 +01:00
Readline ( p , source_file ) ;
2016-06-19 21:00:24 +01:00
head = addLine ( head , p ) ;
}
2016-07-18 23:30:03 +01:00
fclose ( source_file ) ;
Editor_loop ( head , file_name ) ;
2016-06-19 21:00:24 +01:00
return EXIT_SUCCESS ;
}