diff --git a/src/main.c b/src/main.c
index 7898d31d7f06bb8500e56a1a9dd72185ec0e869a..182fc81564d237410a0f7764f4afdbe8d95f04d1 100644
--- a/src/main.c
+++ b/src/main.c
@@ -30,6 +30,15 @@ struct data {
 
 };
 
+struct colour {
+
+	float colour[3];
+	int width;
+	const double* dash;
+	int n_dashes;
+
+};
+
 struct context {
 
 	char* read_buffer;
@@ -86,7 +95,8 @@ struct context {
 	char* xaxis;
 	size_t xaxis_n;
 
-	float (* colours)[3];
+	char* colour_args;
+	struct colour* colours;
 	size_t n_colours;
 
 	double xdist;
@@ -120,7 +130,10 @@ struct fd_source {
 
 static bool add_to_column_list( const char* option_name,
 	const char* value, void* data, GError** error );
-static int parse_hex( float res[3], const char* hex );
+static bool add_colour( const char* option_name,
+	const char* value, void* data, GError** error );
+static char* parse_hex( float res[3], const char* hex );
+static void get_colours( struct context* context );
 static void app_activate( GtkApplication* app, void* data );
 static int listener_prepare( GSource* source, int* timeout );
 static int listener_check( GSource* source );
@@ -149,18 +162,6 @@ int main( int argc, char** argv ) {
 	context->font_size = 12;
 	context->show_legend = true;
 
-	static const char* colours[] = {
-		"#005C84", "#FCBC00", "#0C838C", "#E63037",
-		"#74E9C5", "#D5007F", "#83DBD2", "#4BB694",
-		"#8D3970", "#002F4C", "#EF7D00", "#C0D100",
-	};
-	context->n_colours = sizeof colours / sizeof *colours;
-	context->colours = calloc( sizeof colours / sizeof *colours,
-		sizeof *( context->colours ) );
-	for ( size_t i = 0; i < sizeof colours / sizeof *colours; i++ ) {
-		assert( 0 == parse_hex( context->colours[i], colours[i] ) );
-	}
-
 	clock_gettime( CLOCK_MONOTONIC, &( context->start_time ) );
 
 	fcntl( STDIN_FILENO, F_SETFL,
@@ -264,6 +265,14 @@ int main( int argc, char** argv ) {
 			.arg_data = &( context->yrlab ),
 			.description = "Right y-axis label",
 			.arg_description = "label",
+		}, {
+			.long_name = "colour",
+			.short_name = 'c',
+			.flags = G_OPTION_FLAG_IN_MAIN,
+			.arg = G_OPTION_ARG_CALLBACK,
+			.arg_data = &add_colour,
+			.description = "Add line colour",
+			.arg_description = "colour"
 		}, {
 			.long_name = "time",
 			.short_name = 'T',
@@ -324,7 +333,38 @@ static bool add_to_column_list( const char* option_name,
 
 }
 
-static int parse_hex( float res[3], const char* hex ) {
+static bool add_colour( const char* option_name,
+		const char* value, void* data, GError** error ) {
+
+	struct context* context = (struct context*) data;
+	(void) error;
+
+	assert( 0 == strcmp( option_name, "-c" ) ||
+		0 == strcmp( option_name, "--colour" ) );
+
+	size_t len = strlen( value );
+	if ( NULL != context->colour_args ) {
+		len += 1 + strlen( context->colour_args );
+	}
+
+	char* colours = calloc( len + 1, 1 );
+
+	if ( NULL != context->colour_args ) {
+		strcpy( colours, context->colour_args );
+		strcat( colours, ":" );
+		strcat( colours, value );
+		free( context->colour_args );
+	} else {
+		strcpy( colours, value );
+	}
+
+	context->colour_args = colours;
+
+	return true;
+
+}
+
+static char* parse_hex( float res[3], const char* hex ) {
 
 	while ( ' ' == *hex || '\t' == *hex || '#' == *hex ) {
 		hex++;
@@ -335,12 +375,12 @@ static int parse_hex( float res[3], const char* hex ) {
 		if ( !( ( hex[0] >= '0' && hex[0] <= '9' ) ||
 				( tolower( hex[0] ) >= 'a' &&
 				tolower( hex[0] ) <= 'f' ) ) ) {
-			return -1;
+			return NULL;
 		}
 		if ( !( ( hex[1] >= '0' && hex[1] <= '9' ) ||
 				( tolower( hex[1] ) >= 'a' &&
 				tolower( hex[1] ) <= 'f' ) ) ) {
-			return -1;
+			return NULL;
 		}
 
 		res[i] = ( 0x10 * ( hex[0] <= '9' ?
@@ -353,7 +393,192 @@ static int parse_hex( float res[3], const char* hex ) {
 
 	}
 
-	return 0;
+	return (char*) hex;
+
+}
+
+static void get_colours( struct context* context ) {
+
+	const char* colours;
+	static const char* default_colours =
+		"#005C84:"
+		"#FCBC00:"
+		"#8D3970:"
+		"#4BB694:"
+		"#E73037:"
+		"#74C9E5:"
+		"#005C84,dash:"
+		"#FCBC00,dash:"
+		"#8D3970,dash:"
+		"#4BB694,dash:"
+		"#E73037,dash:"
+		"#74C9E5,dash:"
+		"#005C84,dashdot:"
+		"#FCBC00,dashdot:"
+		"#8D3970,dashdot:"
+		"#4BB694,dashdot:"
+		"#E73037,dashdot:"
+		"#74C9E5,dashdot:"
+		"#005C84,dot:"
+		"#FCBC00,dot:"
+		"#8D3970,dot:"
+		"#4BB694,dot:"
+		"#E73037,dot:"
+		"#74C9E5,dot";
+	static const int n_default_colours = 24;
+
+	if ( NULL != context->colour_args ) {
+
+		colours = context->colour_args;
+
+		context->n_colours = 1;
+		for ( size_t i = 0; '\0' != colours[i]; i++ ) {
+			if ( ':' == colours[i] ) {
+				context->n_colours++;
+			}
+		}
+
+	} else if ( NULL != getenv( "EPLOT_COLOURS" ) ) {
+
+		colours = getenv( "EPLOT_COLOURS" );
+
+		context->n_colours = 1;
+		for ( size_t i = 0; '\0' != colours[i]; i++ ) {
+			if ( ':' == colours[i] ) {
+				context->n_colours++;
+			}
+		}
+
+	} else {
+
+		colours = default_colours;
+		context->n_colours = n_default_colours;
+
+	}
+
+	context->colours = calloc(
+		context->n_colours, sizeof *( context->colours ) );
+	int n = 0;
+	size_t i = 0;
+	while ( '\0' != colours[i] ) {
+
+		int error = 0;
+
+		context->colours[n].width = 1;
+		context->colours[n].n_dashes = 0;
+
+		while ( '\t' == *colours || ' ' == *colours ||
+				'\n' == *colours ) {
+			i++;
+		}
+
+		char* end = parse_hex(
+			context->colours[n].colour, &( colours[i] ) );
+		if ( NULL == end ) {
+			assert( colours != default_colours );
+			fprintf( stderr, "Invalid hex code for colour %d\n", n );
+			colours = default_colours;
+			context->n_colours = n_default_colours;
+			context->colours = realloc( context->colours,
+				context->n_colours * sizeof *( context->colours ) );
+			n = 0;
+			i = 0;
+			continue;
+		}
+		i = end - colours;
+
+		while ( '\t' == *colours || ' ' == *colours ||
+				'\n' == *colours ) {
+			i++;
+		}
+
+		while ( ',' == colours[i] ) {
+
+			i++;
+			while ( '\t' == *colours || ' ' == *colours ||
+					'\n' == *colours ) {
+				i++;
+			}
+
+			if ( '0' <= colours[i] && '9' >= colours[i] ) {
+
+				context->colours[n].width =
+					strtol( &( colours[i] ), &end, 10 );
+				i = end - colours;
+
+			} else {
+
+				if ( 0 == strncmp( &( colours[i] ), "solid", 5 ) ) {
+
+					context->colours[n].n_dashes = 0;
+					i += 5;
+
+				} else if ( 0 == strncmp(
+						&( colours[i] ), "dashdot", 7 ) ) {
+
+					static const double dashdot[] = { 10, 5, 1, 5, };
+					context->colours[n].dash = dashdot;
+					context->colours[n].n_dashes =
+						sizeof dashdot / sizeof *dashdot;
+					i += 7;
+
+				} else if ( 0 == strncmp(
+						&( colours[i] ), "dash", 4 ) ) {
+
+					static const double dash[] = { 10, 5, };
+					context->colours[n].dash = dash;
+					context->colours[n].n_dashes =
+						sizeof dash / sizeof *dash;
+					i += 4;
+
+				} else if ( 0 == strncmp(
+						&( colours[i] ), "dot", 3 ) ) {
+
+					static const double dot[] = { 0, 5, };
+					context->colours[n].dash = dot;
+					context->colours[n].n_dashes =
+						sizeof dot / sizeof *dot;
+					i += 3;
+
+				}
+
+			}
+
+			while ( '\t' == colours[i] || ' ' == colours[i] ||
+					'\n' == colours[i] ) {
+				i++;
+			}
+
+			if ( '\0' != colours[i] && ':' != colours[i] &&
+					',' != colours[i] ) {
+				assert( colours != default_colours );
+				fprintf( stderr,
+					"Invalid colour specification for colour %d\n", n );
+				colours = default_colours;
+				context->n_colours = n_default_colours;
+				context->colours = realloc( context->colours,
+					context->n_colours * sizeof *( context->colours ) );
+				n = 0;
+				i = 0;
+				error = 1;
+				break;
+			}
+
+		}
+
+		if ( 0 != error ) {
+			error = 0;
+			continue;
+		}
+
+		if ( ':' == colours[i] ) {
+			i++;
+		} else {
+			assert( '\0' == colours[i] );
+		}
+		n++;
+
+	}
 
 }
 
@@ -390,6 +615,8 @@ static void app_activate( GtkApplication* app, void* data ) {
 	g_source_set_callback(
 		(GSource*) source, &data_callback, context, NULL );
 
+	get_colours( context );
+
 	char* yrange = context->yrange.arg;
 
 	if ( NULL != yrange ) {
@@ -1402,33 +1629,45 @@ static void plot_draw( GtkDrawingArea* plot,
 	cairo_line_to( cr, m[1] - 1, height - m[0] + 1 );
 	cairo_line_to( cr, m[1] - 1, m[2] - 1 );
 	cairo_clip( cr );
-	cairo_set_line_width( cr, 1 );
 
-	for ( struct data* data = context->data;
-			NULL != data->next;
-			data = data->next ) {
+	for ( size_t i = 0; i < context->n_data_columns; i++ ) {
 
-		for ( size_t i = 0; i < context->n_data_columns; i++ ) {
+		size_t c = i % context->n_colours;
+
+		cairo_save( cr );
 
-			size_t c = i % context->n_colours;
+		cairo_set_source_rgb( cr,
+			context->colours[c].colour[0],
+			context->colours[c].colour[1],
+			context->colours[c].colour[2] );
+		cairo_set_line_width( cr, context->colours[c].width );
+		cairo_set_dash( cr, context->colours[c].dash,
+			context->colours[c].n_dashes, 0 );
+		cairo_set_line_cap( cr, CAIRO_LINE_CAP_ROUND );
+
+		double* yrange = context->data->y[i].axis == LEFT ?
+			ylrange : yrrange;
+
+		if ( context->data->y[i].present ) {
+
+			cairo_move_to( cr,
+				m[1] + ( width - m[1] - m[3] ) *
+					( context->data->x - xrange[0] ) /
+					( xrange[1] - xrange[0] ),
+				height - m[0] - ( height - m[0] - m[2] ) *
+					( context->data->y[i].v - yrange[0] ) /
+					( yrange[1] - yrange[0] ) );
 
-			cairo_set_source_rgb( cr, context->colours[c][0],
-				context->colours[c][1], context->colours[c][2] );
+		}
 
-			double* yrange = context->data->y[i].axis == LEFT ?
-				ylrange : yrrange;
+		for ( struct data* data = context->data;
+				NULL != data;
+				data = data->next ) {
 
 			if ( data->y[i].present ) {
 
-				if ( data->next->y[i].present ) {
+				if ( NULL != data->next && data->next->y[i].present ) {
 
-					cairo_move_to( cr,
-						m[1] + ( width - m[1] - m[3] ) *
-							( data->x - xrange[0] ) /
-							( xrange[1] - xrange[0] ),
-						height - m[0] - ( height - m[0] - m[2] ) *
-							( data->y[i].v - yrange[0] ) /
-							( yrange[1] - yrange[0] ) );
 					cairo_line_to( cr,
 						m[1] + ( width - m[1] - m[3] ) *
 							( data->next->x - xrange[0] ) /
@@ -1436,7 +1675,6 @@ static void plot_draw( GtkDrawingArea* plot,
 						height - m[0] - ( height - m[0] - m[2] ) *
 							( data->next->y[i].v - yrange[0] ) /
 							( yrange[1] - yrange[0] ) );
-					cairo_stroke( cr );
 
 				} else if ( NULL == data->prev ||
 						!data->prev->y[i].present ) {
@@ -1450,12 +1688,32 @@ static void plot_draw( GtkDrawingArea* plot,
 							( yrange[1] - yrange[0] ) - 1, 2, 2 );
 					cairo_fill( cr );
 
+				} else {
+
+					cairo_stroke( cr );
+
+				}
+
+			} else {
+
+				if ( NULL != data->next && data->next->y[i].present ) {
+
+					cairo_move_to( cr,
+						m[1] + ( width - m[1] - m[3] ) *
+							( data->next->x - xrange[0] ) /
+							( xrange[1] - xrange[0] ),
+						height - m[0] - ( height - m[0] - m[2] ) *
+							( data->next->y[i].v - yrange[0] ) /
+							( yrange[1] - yrange[0] ) );
+
 				}
 
 			}
 
 		}
 
+		cairo_restore( cr );
+
 	}
 
 	cairo_restore( cr );
@@ -1671,9 +1929,14 @@ static void plot_draw( GtkDrawingArea* plot,
 			}
 
 			cairo_save( cr );
-			cairo_set_source_rgb( cr, context->colours[c][0],
-				context->colours[c][1], context->colours[c][2]);
-			cairo_set_line_width( cr, 1 );
+			cairo_set_source_rgb( cr,
+				context->colours[c].colour[0],
+				context->colours[c].colour[1],
+				context->colours[c].colour[2] );
+			cairo_set_line_width( cr, context->colours[c].width );
+			cairo_set_dash( cr, context->colours[c].dash,
+				context->colours[c].n_dashes, 0 );
+			cairo_set_line_cap( cr, CAIRO_LINE_CAP_ROUND );
 			cairo_stroke( cr );
 			cairo_restore( cr );