aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSopár Adrián <dev.adrian.sopar@protonmail.com>2022-07-05 23:02:16 +0200
committerSopár Adrián <dev.adrian.sopar@protonmail.com>2022-07-05 23:02:16 +0200
commitc5cd2b2443dc48aaeb61feac4a96071c7bc9790e (patch)
tree38f611224caf6f3e15b7121b06c1b1e9c5e129b3
Init commit.HEADmaster
-rw-r--r--.gitignore3
-rw-r--r--Makefile78
-rw-r--r--README.md49
-rw-r--r--doc/planned.html8
-rw-r--r--doc/plock.168
-rw-r--r--doc/plock.planned.189
-rw-r--r--src/args.c89
-rw-r--r--src/args.h31
-rw-r--r--src/filter/filter.h15
-rw-r--r--src/filter/uniq.c0
-rw-r--r--src/filter/uniq.h12
-rw-r--r--src/io/io.c13
-rw-r--r--src/io/io.h24
-rw-r--r--src/io/svg.c52
-rw-r--r--src/io/svg.h10
-rw-r--r--src/io/text.c10
-rw-r--r--src/io/text.h10
-rw-r--r--src/main.c72
-rw-r--r--src/pattern/next.c79
-rw-r--r--src/pattern/next.h9
-rw-r--r--src/pattern/pattern.c83
-rw-r--r--src/pattern/pattern.h93
-rw-r--r--src/pattern/random.c1
-rw-r--r--src/pattern/random.h5
-rw-r--r--src/utils/args.c83
-rw-r--r--src/utils/args.h28
-rw-r--r--src/utils/utilities.c68
-rw-r--r--src/utils/utilities.h42
28 files changed, 1124 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..bb45970
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+/bin/
+/video/
+/writing/
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..77f176b
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,78 @@
+NAME=plock
+CC = gcc
+CFLAGS = -Isrc
+LIBS = -lX11
+
+PREFIX = /usr/local
+MANPREFIX = $(PREFIX)/man
+
+all: bin/$(NAME)
+
+debug: CFLAGS += -Wall -DEBUG -g
+debug: bin/$(NAME)
+
+app_sources = $(wildcard src/*.c src/io/*.c src/pattern/*.c src/utils/*.c)
+app_objects = $(patsubst src/%.c, bin/%.o, $(app_sources))
+
+bin/$(NAME): bin/main.o bin/args.o bin/utils/utilities.o bin/utils/args.o bin/pattern/pattern.o bin/pattern/next.o bin/io/io.o bin/io/text.o bin/io/svg.o # $(app_objects)
+ $(CC) $(CFLAGS) $^ -o $@ $(LIBS)
+
+bin/main.o: src/main.c bin
+ $(CC) $(CFLAGS) -c $< -o $@
+
+bin/args.o: src/args.c bin
+ $(CC) $(CFLAGS) -c $< -o $@
+
+bin/utils/utilities.o: src/utils/utilities.c bin bin/utils
+ $(CC) $(CFLAGS) -c $< -o $@
+
+bin/utils/args.o: src/utils/args.c bin bin/utils
+ $(CC) $(CFLAGS) -c $< -o $@
+
+bin/pattern/pattern.o: src/pattern/pattern.c bin bin/pattern
+ $(CC) $(CFLAGS) -c $< -o $@
+
+bin/pattern/next.o: src/pattern/next.c bin bin/pattern
+ $(CC) $(CFLAGS) -c $< -o $@
+
+bin/io/io.o: src/io/io.c bin bin/io
+ $(CC) $(CFLAGS) -c $< -o $@
+
+bin/io/text.o: src/io/text.c bin bin/io
+ $(CC) $(CFLAGS) -c $< -o $@
+
+bin/io/svg.o: src/io/svg.c bin bin/io
+ $(CC) $(CFLAGS) -c $< -o $@
+
+bin:
+ mkdir -p $@
+
+bin/io:
+ mkdir -p $@
+
+bin/pattern:
+ mkdir -p $@
+
+bin/utils:
+ mkdir -p $@
+
+clean:
+ rm -rf bin/*
+
+install: bin/$(NAME)
+ @echo INSTALL execuatble
+ mkdir -p $(PREFIX)/bin
+ cp $< $(PREFIX)/bin/$(NAME)
+ chmod 755 $(PREFIX)/bin/$(NAME)
+ @echo INSTALL man page
+ mkdir -p $(MANPREFIX)/man1
+ gzip -c doc/$(NAME).1 > $(MANPREFIX)/man1/$(NAME).1.gz
+ chmod 644 $(MANPREFIX)/man1/$(NAME).1.gz
+
+uninstall:
+ @echo REMOVE execuatble
+ rm -f $(PREFIX)/bin/$(NAME)
+ @echo REMOVE man page
+ rm -f $(MANPREFIX)/man1/$(NAME).1.gz
+
+.PHONY: clean install uninstall
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5aecc93
--- /dev/null
+++ b/README.md
@@ -0,0 +1,49 @@
+**Android pattern-lock generator**
+
+plock is a command line program for generating android patterns.
+
+Features
+--------
+
+- Generate all posible patterns.
+- Save patterns to multiplie formats.
+
+Dependencies
+------------
+
+Currently, there's no need for additional libraries for compiling or running the software.
+
+Installation
+------------
+
+Currently, this program is not available in any package manager, so you have to build it from source. You can run this command that will build and install the program on your system:
+
+ # make install
+
+By default, plock is installed using the prefix "/usr/local", so the full path of the executable will be "/usr/local/bin/plock". But can install it to the directory of your choice by changing the prefix. For example:
+
+ # make PREFIX="/your/dir" install
+
+In order to remove the program from your system, just run the following command:
+
+ # make uninstall
+
+Please note that the previous commands require root privileges.
+
+If you don't want to install, just run it, you can do it in this way:
+
+ $ make
+ $ ./bin/plock
+
+Usage
+-----
+
+Please consult the man page for more information.
+
+You can see the man page by runing the following command in the project directiory:
+
+ $ man doc/plock.1
+
+Or you can do this, if you installed the program:
+
+ $ man plock
diff --git a/doc/planned.html b/doc/planned.html
new file mode 100644
index 0000000..5a9cbdd
--- /dev/null
+++ b/doc/planned.html
@@ -0,0 +1,8 @@
+<h1>Tervezett funkciók</h1>
+<strong>1. Generátorok</strong>
+<p>Lehetne random generátort is használni az alapértelmezett helyett.</p>
+<strong>2. filterek</strong>
+<p>Lehetővé teszik a szűrést a generált minták között. Állapottal rendelkeznek, tehát az, hogy eddig milyen mintákat generáltunk, hatással lehet arra, hogy később miket enged át a filter. Ez lehetővé tenné az <em>egyedi</em> szűrőt, ami csak azokat a mintákat engedné át, amik még nem szerepeltek. Hasznos lenne a random generátornál.</p>
+<p>Több filtert is lehetne alkalmazni egyszerre, adott precedenciával.</p>
+<strong>3. Tömörítés</strong>
+<p>Megmondja egy mintáról, hogy ha az összes mintát kigenerálnánk, akkor ez hányadik lenne.</p>
diff --git a/doc/plock.1 b/doc/plock.1
new file mode 100644
index 0000000..a8a29b3
--- /dev/null
+++ b/doc/plock.1
@@ -0,0 +1,68 @@
+.TH PLOCK 1
+.SH NAME
+plock - a command for generating android patterns
+.SH SYNOPSIS
+.B plock
+.RB [ \-p
+.IR print_type ]
+.SH DESCRIPTION
+plock is a command line tool for generating android lock-patterns.
+
+.SH OPTIONS
+
+.TP
+.BR \-n ", " \-\-number=\fInum\fR
+.PD
+It tells the program to generate \fInum\fR amount of patterns. If \fInum\fR is negative, there will be maximum amount of patterns generated.
+
+.TP
+.BR \-p ", " \-\-print=\fItype\fR
+.PD
+Sets the type of print wich the program should use. \fItype\fR can be: text or svg.
+
+.TP
+.BR \-o ", " \-\-output=\fIpath\fR
+.PD
+Sets the path of the output file.
+
+.TP
+.BR \-os ", " \-\-outputs=\fIpath\fR
+.PD
+Sets the pattern of path of the output files. A possible pattern could be pattern_%d.svg where %d will be the number of the pattern. %d can only be at the name of the file, since plock is not capable of creating directories.
+
+.TP
+.BR \-fn ", " \-\-from-num=\fInumber\fR
+.PD
+Starts from number \fInumber\fR. If it's zero, it has no effect.
+
+.TP
+.BR \-tn ", " \-\-to-num=\fInumber\fR
+.PD
+Stops at number \fInumber\fR. If it's zero, it has no effect.
+
+.TP
+.BR \-w ", " \-\-wait
+.PD
+Makes the program wait until a char is given on stdin after each pattern generation.
+
+.SH EXIT STATUS
+Plock may return one of several error codes if it encounters problems.
+
+.ie n .IP "0" 4
+.el .IP "\f(CW0\fR" 4
+.IX Item "0"
+No problems occurred.
+
+.ie n .IP "1" 4
+.el .IP "\f(CW0\fR" 4
+.IX Item "1"
+Args error.
+
+.ie n .IP "2" 4
+.el .IP "\f(CW0\fR" 4
+.IX Item "2"
+IO error.
+
+.SH AUTHOR
+Sopár Adrián <\fIdev.adrian.sopar@protonmail.com\fR> <\fIhttps://adriansopar.hu\fR>
+
diff --git a/doc/plock.planned.1 b/doc/plock.planned.1
new file mode 100644
index 0000000..d50bd8c
--- /dev/null
+++ b/doc/plock.planned.1
@@ -0,0 +1,89 @@
+.TH PLOCK 1
+.SH NAME
+plock - a command for generating android patterns
+.SH SYNOPSIS
+.B plock
+.RB [ \-p
+.IR print_type ]
+.SH DESCRIPTION
+plock is a command line tool for generating android lock-patterns.
+
+It can also transform patterns given in text format into images.
+.SH OPTIONS
+
+.TP
+.BR \-s ", " \-\-size=\fIsize\fR
+.PD
+It sets the size of the pattern grid to \fIsize\fR. \fIsize\fR can be two integers separated by an x sign. In this case the first integer is the width and the second is the height. Or it can be only a single integer in wich case the integer is also the width and the height.
+
+.TP
+.BR \-p ", " \-\-pattern=\fIpattern\fR
+.PD
+Sets the pattern to \fIpattern\fR. The syntax of pattern is: integer sequence separated by commas. For example 0,1,2 could be a \fIpattern\fR.
+
+.TP
+.BR \-n ", " \-\-number=\fInum\fR
+.PD
+It tells the program to generate \fInum\fR amount of patterns. If \fInum\fR is negative, there will be maximum amount of patterns generated.
+
+.TP
+.BR \-g ", " \-\-gen=\fItype\fR
+.PD
+Sets the type of generation wich the program should use. \fItype\fR can be: rand or next.
+
+.TP
+.BR \-p ", " \-\-print=\fItype\fR
+.PD
+Sets the type of print wich the program should use. \fItype\fR can be: text or svg.
+
+.TP
+.BR \-o ", " \-\-output=\fIpath\fR
+.PD
+Sets the path of the output file.
+
+.TP
+.BR \-os ", " \-\-outputs=\fIpath\fR
+.PD
+Sets the pattern of path of the output files. A possible pattern could be pattern_%d.svg where %d will be the number of the pattern. %d can only be at the name of the file, since plock is not capable of creating directories.
+
+.TP
+.BR \-fn ", " \-\-from-num=\fInumber\fR
+.PD
+Starts from number \fInumber\fR. If it's zero, it has no effect.
+
+.TP
+.BR \-tn ", " \-\-to-num=\fInumber\fR
+.PD
+Stops at number \fInumber\fR. If it's zero, it has no effect.
+
+.TP
+.BR \-w ", " \-\-wait
+.PD
+Makes the program wait until a char is given on stdin after each pattern generation.
+
+.TP
+.BR \-u ", " \-\-uniq
+.PD
+The generated patterns will be unique.
+
+.SH EXIT STATUS
+Plock may return one of several error codes if it encounters problems.
+
+.ie n .IP "0" 4
+.el .IP "\f(CW0\fR" 4
+.IX Item "0"
+No problems occurred.
+
+.ie n .IP "1" 4
+.el .IP "\f(CW0\fR" 4
+.IX Item "1"
+Args error.
+
+.ie n .IP "2" 4
+.el .IP "\f(CW0\fR" 4
+.IX Item "2"
+IO error.
+
+.SH AUTHOR
+Sopár Adrián <\fIdev.adrian.sopar@protonmail.com\fR> <\fIhttps://adriansopar.hu\fR>
+
diff --git a/src/args.c b/src/args.c
new file mode 100644
index 0000000..fb73e6c
--- /dev/null
+++ b/src/args.c
@@ -0,0 +1,89 @@
+#include "args.h"
+#include <string.h>
+#include <stdlib.h>
+#include "pattern/next.h"
+#include "io/text.h"
+#include "io/svg.h"
+
+/*
+ * Options start.
+ */
+
+#define OPTIONS \
+ { \
+ {"w", "wait", false, wait}, \
+ {"n", "num", true, num}, \
+ {"p", "print", true, print}, \
+ {"os", "outputs", true, outputs}, \
+ {"fn", "from-num", true, fn}, \
+ {"tn", "to-num", true, tn}, \
+ }
+
+void wait(void *args, const char *str)
+{
+ ((struct args *)args)->wait = true;
+}
+
+void num(void *args, const char *str)
+{
+ ((struct args *)args)->gen_count = atoi(str);
+}
+
+void fn(void *args, const char *str)
+{
+ ((struct args *)args)->from_count = atoi(str);
+}
+
+void tn(void *args, const char *str)
+{
+ ((struct args *)args)->to_count = atoi(str);
+}
+
+void print(void *args, const char *str)
+{
+ ((struct args *)args)->print = str[0] == 's' ? print_pattern_svg : print_pattern_text;
+}
+
+void outputs(void *args, const char *str)
+{
+ struct args *args_ = (struct args *)args;
+ args_->standard_output = false;
+ args_->single_output = false;
+ strcpy(args_->output, str);
+}
+
+/*
+ * Options end.
+ */
+
+void load_defaults(struct args *args)
+{
+ // Pattern
+ args->pattern.length = 0;
+ args->pattern.type = gen_pattern_type(3, 4, -1);
+ // Params
+ args->params.aggregated = false;
+ args->params.count = 0;
+ args->params.print_author = true;
+ args->params.print_code = true;
+ args->params.print_count = true;
+ // Egyéb
+ args->gen_count = -1;
+ args->from_count = -1;
+ args->to_count = -1;
+ args->gen = next_point;
+ args->print = print_pattern_text;
+ args->single_output = true;
+ args->standard_output = true;
+ args->wait = false;
+}
+
+enum alr load_args(int argc, char **argv, struct args *args)
+{
+ // Init
+ load_defaults(args);
+ struct option options[] = OPTIONS;
+ int opt_length = sizeof(options) / sizeof(struct option);
+ // Process
+ return process_args(argc, argv, options, opt_length, args);
+} \ No newline at end of file
diff --git a/src/args.h b/src/args.h
new file mode 100644
index 0000000..780a621
--- /dev/null
+++ b/src/args.h
@@ -0,0 +1,31 @@
+#ifndef PLOC_GEN_ARGS_H
+#define PLOC_GEN_ARGS_H
+
+#include <stdbool.h>
+#include "pattern/pattern.h"
+#include "io/io.h"
+#include "utils/args.h"
+#include <stdio.h>
+
+struct args
+{
+ struct pattern pattern;
+ /*
+ * Negative value means unlimited.
+ */
+ int gen_count;
+ int from_count;
+ int to_count;
+ bool (*gen)(struct pattern *);
+ void (*print)(FILE *, struct print_params, struct pattern *);
+ struct print_params params;
+ bool wait;
+
+ bool single_output;
+ bool standard_output;
+ char output[512];
+};
+
+enum alr load_args(int argc, char **argv, struct args *args);
+
+#endif \ No newline at end of file
diff --git a/src/filter/filter.h b/src/filter/filter.h
new file mode 100644
index 0000000..7cdb640
--- /dev/null
+++ b/src/filter/filter.h
@@ -0,0 +1,15 @@
+#ifndef PLOC_GEN_FILTER_H
+#define PLOC_GEN_FILTER_H
+
+#include "stdbool.h"
+#include "pattern/pattern.h"
+
+struct filter
+{
+ void *state;
+ void *(*create)();
+ void (*free)(void *);
+ bool (*filter)(void *, struct pattern *);
+};
+
+#endif \ No newline at end of file
diff --git a/src/filter/uniq.c b/src/filter/uniq.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/filter/uniq.c
diff --git a/src/filter/uniq.h b/src/filter/uniq.h
new file mode 100644
index 0000000..fa235a5
--- /dev/null
+++ b/src/filter/uniq.h
@@ -0,0 +1,12 @@
+#ifndef PLOC_GEN_FILTER_UNIQ_H
+#define PLOC_GEN_FILTER_UNIQ_H
+
+#include "stdbool.h"
+#include "pattern/pattern.h"
+
+void *create_uniq();
+void free_uniq(void *state);
+
+bool uniq(void *state, struct pattern *pattern);
+
+#endif \ No newline at end of file
diff --git a/src/io/io.c b/src/io/io.c
new file mode 100644
index 0000000..e9f4fb8
--- /dev/null
+++ b/src/io/io.c
@@ -0,0 +1,13 @@
+#include "io.h"
+#include "stdio.h"
+
+void pattern_nums_to_str(char *str, struct pattern *pattern)
+{
+ str[0] = 0;
+ if (pattern->length >= 1)
+ str += sprintf(str, "%d", pattern_point_to_index(pattern, 0));
+ for (int i = 1; i < pattern->length; i++)
+ {
+ str += sprintf(str, ",%d", pattern_point_to_index(pattern, i));
+ }
+} \ No newline at end of file
diff --git a/src/io/io.h b/src/io/io.h
new file mode 100644
index 0000000..97af398
--- /dev/null
+++ b/src/io/io.h
@@ -0,0 +1,24 @@
+#ifndef PLOC_GEN_IO_H
+#define PLOC_GEN_IO_H
+
+#include "pattern/pattern.h"
+
+/*
+ * Print parameters.
+ */
+struct print_params
+{
+ unsigned int count;
+ /*
+ * aggregated is true, if the print function gets called on the
+ * same file over and over again.
+ */
+ bool aggregated;
+ bool print_count;
+ bool print_code;
+ bool print_author;
+};
+
+void pattern_nums_to_str(char *str, struct pattern *pattern);
+
+#endif \ No newline at end of file
diff --git a/src/io/svg.c b/src/io/svg.c
new file mode 100644
index 0000000..a8e2129
--- /dev/null
+++ b/src/io/svg.c
@@ -0,0 +1,52 @@
+#include "svg.h"
+
+void print_pattern_svg(FILE *out, struct print_params params, struct pattern *pattern)
+{
+ // Init variables.
+ double horizontal = 100 / (pattern->type.height + 1);
+ double vertical = 100 / (pattern->type.width + 1);
+ int hd = horizontal; // Horizontal distance
+ int vd = vertical; // Vertical distance
+ // Print
+ fprintf(out, "<svg width=\"500\" height=\"500\" style=\"background-color:black\">");
+ fprintf(out, "<rect width=\"100%%\" height=\"100%%\" fill=\"black\" />");
+
+ if (params.print_code)
+ {
+ char code[128];
+ pattern_nums_to_str(code, pattern);
+ fprintf(out, "<text x=\"0\" y=\"1em\" font-size=\"2em\" fill=\"white\">Code:%s</text>", code);
+ }
+ if (params.print_count)
+ fprintf(out, "<text x=\"0\" y=\"2em\" font-size=\"2em\" fill=\"white\">Count:%d</text>", params.count);
+ if (params.print_author)
+ fprintf(out, "<text x=\"500\" y=\"500\" font-size=\"1em\" fill=\"white\" text-anchor=\"end\">adriansopar.hu</text>");
+
+ // TODO: Print text!
+ // Print points.
+ for (int y = 0; y < pattern->type.height; y++)
+ {
+ for (int x = 0; x < pattern->type.width; x++)
+ {
+ fprintf(out,
+ "<circle cx=\"%f%%\" cy=\"%f%%\" r=\"%d%%\" fill=\"white\" />",
+ (double)(x + 1) * hd, (double)(y + 1) * vd, 3);
+ }
+ }
+ // Print pattern.
+ struct coord prev;
+ for (int i = 0; i < pattern->length; i++)
+ {
+ struct coord current = pattern->path[i];
+ fprintf(out,
+ "<circle cx=\"%f%%\" cy=\"%f%%\" r=\"6%%\" stroke=\"#00ff00\" stroke-width=\"2\" fill=\"none\" />",
+ (double)(current.x + 1) * hd, (double)(current.y + 1) * vd);
+ if (i > 0)
+ fprintf(out,
+ "<line x1=\"%f%%\" y1=\"%f%%\" x2=\"%f%%\" y2=\"%f%%\" stroke=\"white\" stroke-width=\"6%%\" stroke-opacity=\"0.5\" />",
+ (double)(prev.x + 1) * hd, (double)(prev.y + 1) * vd,
+ (double)(current.x + 1) * hd, (double)(current.y + 1) * vd);
+ prev = current;
+ }
+ fprintf(out, "</svg>");
+} \ No newline at end of file
diff --git a/src/io/svg.h b/src/io/svg.h
new file mode 100644
index 0000000..75559a2
--- /dev/null
+++ b/src/io/svg.h
@@ -0,0 +1,10 @@
+#ifndef PLOC_GEN_IO_SVG_H
+#define PLOC_GEN_IO_SVG_H
+
+#include <stdio.h>
+#include "pattern/pattern.h"
+#include "io.h"
+
+void print_pattern_svg(FILE *out, struct print_params params, struct pattern *pattern);
+
+#endif \ No newline at end of file
diff --git a/src/io/text.c b/src/io/text.c
new file mode 100644
index 0000000..a035cc5
--- /dev/null
+++ b/src/io/text.c
@@ -0,0 +1,10 @@
+#include "text.h"
+
+void print_pattern_text(FILE *out, struct print_params params, struct pattern *pattern)
+{
+ for (int i = 0; i < pattern->length; i++)
+ {
+ fprintf(out, "%d,", pattern_point_to_index(pattern, i));
+ }
+ fprintf(out, "\n");
+} \ No newline at end of file
diff --git a/src/io/text.h b/src/io/text.h
new file mode 100644
index 0000000..435294d
--- /dev/null
+++ b/src/io/text.h
@@ -0,0 +1,10 @@
+#ifndef PLOC_GEN_IO_TEXT_H
+#define PLOC_GEN_IO_TEXT_H
+
+#include <stdio.h>
+#include "pattern/pattern.h"
+#include "io.h"
+
+void print_pattern_text(FILE *out, struct print_params params, struct pattern *pattern);
+
+#endif \ No newline at end of file
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..7f961e7
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,72 @@
+#include <stdio.h>
+#include "args.h"
+#include "pattern/pattern.h"
+#include "io/text.h"
+#include "io/svg.h"
+
+/*
+ * EX stands for EXIT STATUS and
+ * EXE stands for EXIT STATUS ERROR
+ */
+#define EX_OK 0
+#define EXE_ARGS 1
+#define EXE_IO 2
+
+int main(int argc, char **argv)
+{
+ struct args args;
+ enum alr alr = load_args(argc, argv, &args);
+ if (alr != ALR_OK)
+ {
+ if (alr == ALR_INVALID_OPTION)
+ fprintf(stderr, "Invalid option!");
+ else
+ fprintf(stderr, "Args processing error!\n");
+ return EXE_ARGS;
+ }
+ struct pattern *pattern = &args.pattern;
+ struct coord path[16];
+ pattern->path = path;
+
+ args.params.count = 0;
+ FILE *out = stdout;
+ if (!args.standard_output && args.single_output)
+ {
+ if ((out = fopen(args.output, "w")) == NULL)
+ {
+ fprintf(stderr, "%s file cannot be opened.", args.output);
+ return EXE_IO;
+ }
+ }
+ while (args.gen(pattern) && (args.gen_count < 0 || args.params.count < args.gen_count))
+ {
+ args.params.count++;
+ if ((args.from_count <= (int)args.params.count) && (((int)args.params.count <= args.to_count) || (args.to_count < 0)))
+ {
+ if (!args.standard_output && !args.single_output)
+ {
+ char file_path[512];
+ sprintf(file_path, args.output, args.params.count);
+ if ((out = fopen(file_path, "w")) == NULL)
+ {
+ fprintf(stderr, "%s file cannot be opened.", file_path);
+ return EXE_IO;
+ }
+ }
+
+ args.print(out, args.params, pattern);
+ if (args.wait)
+ {
+ char c;
+ getchar();
+ }
+
+ if (!args.standard_output && !args.single_output)
+ fclose(out);
+ }
+ }
+ if (!args.standard_output && args.single_output)
+ fclose(out);
+
+ return EX_OK;
+} \ No newline at end of file
diff --git a/src/pattern/next.c b/src/pattern/next.c
new file mode 100644
index 0000000..10261bc
--- /dev/null
+++ b/src/pattern/next.c
@@ -0,0 +1,79 @@
+#include "next.h"
+#include <stdlib.h>
+
+/*
+ * It gives the first point that:
+ * - Isn't part of pattern->path
+ * - Its index the lowest possible, but minimum min_index
+ * - There isn't any point in-line between it and the last of the path
+ * Returns true if such a point exsist, otherwise returns false.
+ */
+bool free_point(struct pattern *pattern, int min_index, struct coord *new_point)
+{
+ //printf("min_index=%d\n", min_index);
+ struct coord result = index_to_coord(pattern->type.width, min_index);
+ struct coord *last = pattern->length > 0 ? &pattern->path[pattern->length - 1] : NULL;
+ while (result.y < pattern->type.height)
+ {
+ while (result.x < pattern->type.width)
+ {
+ if (last == NULL)
+ {
+ *new_point = result;
+ return true;
+ }
+ else if (find_in_pattern(pattern, &result) < 0 &&
+ nothing_inbetween(pattern, &result))
+ {
+ //printf("fp(%d;%d)\n", result.x, result.y);
+ *new_point = result;
+ return true;
+ }
+ result.x++;
+ }
+ result.y++;
+ result.x = 0;
+ }
+ return false;
+}
+
+/*
+ * Changes pattern->path to the next possible pattern.
+ * It returns false if there's no possible pattern left,
+ * otherwise it returns true.
+ */
+bool next_point(struct pattern *pattern)
+{
+ struct coord next_point;
+ if (len_is_max(pattern))
+ {
+ do
+ {
+ if (pattern->length == 0)
+ return false; //Nincs több minta
+ next_point = pattern->path[--pattern->length];
+ } while (!free_point(
+ pattern,
+ coord_to_index(pattern->type.width, next_point) + 1,
+ &next_point));
+ //printf("(%d;%d)\n", next_point.x, next_point.y);
+ pattern->path[pattern->length++] = next_point;
+ if (pattern->length >= pattern->type.min_length)
+ return true;
+ }
+
+ do
+ {
+ if (free_point(pattern, 0, &next_point))
+ {
+ pattern->path[pattern->length++] = next_point;
+ //return true;
+ }
+ } while (pattern->length < pattern->type.min_length);
+
+ return true;
+
+ // Ha visszalépés volt, akkor az első újra előrelépésnél, csak nagyobb indexű
+ // elemre szabad lépni.
+ // Ha előrelépés volt, akkor a legkissebb indexű szabad elemre kell lépni.
+}
diff --git a/src/pattern/next.h b/src/pattern/next.h
new file mode 100644
index 0000000..c6aa380
--- /dev/null
+++ b/src/pattern/next.h
@@ -0,0 +1,9 @@
+#ifndef PLOC_GEN_PATTERN_NEXT_H
+#define PLOC_GEN_PATTERN_NEXT_H
+
+#include <stdbool.h>
+#include "pattern.h"
+
+bool next_point(struct pattern *pattern);
+
+#endif \ No newline at end of file
diff --git a/src/pattern/pattern.c b/src/pattern/pattern.c
new file mode 100644
index 0000000..85e21c7
--- /dev/null
+++ b/src/pattern/pattern.c
@@ -0,0 +1,83 @@
+#include "pattern.h"
+#include <stdlib.h>
+#include "utils/utilities.h"
+
+/*
+ * Inline functions
+ */
+bool len_is_max(struct pattern *pattern);
+bool len_is_min(struct pattern *pattern);
+int coord_to_index(int width, struct coord point);
+struct coord index_to_coord(int width, int index);
+int pattern_point_to_index(struct pattern *pattern, int index);
+
+struct pattern_type gen_pattern_type(int side_len, int min, int max)
+{
+ struct pattern_type result;
+ result.width = side_len;
+ result.height = side_len;
+
+ int max_possible = side_len * side_len;
+ result.min_length = min >= 0 ? min : max_possible;
+ if (max >= 0 && max <= max_possible)
+ result.max_length = max;
+ else
+ result.max_length = max_possible;
+ return result;
+}
+
+int coord_cmp(const void *a, const void *b)
+{
+ const struct coord *ac = a;
+ const struct coord *bc = b;
+ if (ac->x == bc->x && ac->y == bc->y)
+ return 0;
+ //TODO: Handle when the inputs are not equal!
+ return -1;
+}
+
+bool is_in_line(struct coord a, struct coord c, struct coord b)
+{
+ if (!(monotonic(a.x, b.x, c.x) && monotonic(a.y, b.y, c.y)))
+ return false;
+ return ((b.x - a.x) * (c.y - a.y)) + ((b.y - a.y) * (a.x - c.x)) == 0;
+}
+
+int find_in_pattern(struct pattern *pattern, struct coord *coord)
+{
+ for (int i = 0; i < pattern->length; i++)
+ {
+ struct coord *current = &pattern->path[i];
+ if (current->x == coord->x && current->y == coord->y)
+ return i;
+ }
+ return -1;
+}
+
+int inbetween(int width, int height, struct coord *from, struct coord *to, struct coord *arr)
+{
+ int length = 0;
+ struct coord current;
+ for (current.y = 0; current.y < height; current.y++)
+ for (current.x = 0; current.x < width; current.x++)
+ if ((current.x != from->x || current.y != from->y) &&
+ (current.x != to->x || current.y != to->y))
+ if (is_in_line(*from, *to, current))
+ arr[length++] = current;
+ return length;
+}
+
+bool nothing_inbetween(struct pattern *pattern, struct coord *next)
+{
+ if (pattern->length == 0)
+ return true;
+ struct coord *last = &pattern->path[pattern->length - 1];
+ struct coord arr[pattern->type.width * pattern->type.height];
+ size_t length = inbetween(pattern->type.width, pattern->type.height, last, next, arr);
+ if (length > pattern->length)
+ return false;
+ for (int i = 0; i < length; i++)
+ if (find_in_pattern(pattern, &arr[i]) < 0)
+ return false;
+ return true;
+}
diff --git a/src/pattern/pattern.h b/src/pattern/pattern.h
new file mode 100644
index 0000000..d53576e
--- /dev/null
+++ b/src/pattern/pattern.h
@@ -0,0 +1,93 @@
+#ifndef PLOC_GEN_PATTERN_PATTERN_H
+#define PLOC_GEN_PATTERN_PATTERN_H
+
+#include <stdbool.h>
+
+struct coord
+{
+ int x;
+ int y;
+};
+
+struct pattern_type
+{
+ int width;
+ int height;
+ int min_length;
+ int max_length;
+};
+
+struct pattern
+{
+ struct pattern_type type;
+ struct coord *path;
+ int length;
+};
+
+/*
+ * Creates a pattern_type.
+ * If max has an invalid value the max_length is set to the
+ * maximum possible length.
+ */
+struct pattern_type gen_pattern_type(int side_len, int min, int max);
+
+/*
+ * Returns 0 if a equals b.
+ */
+int coord_cmp(const void *a, const void *b);
+
+/*
+ * If the point happend to be on the line that connects start and end,
+ * the result is true, otherwise is false.
+ */
+bool is_in_line(struct coord a, struct coord c, struct coord b);
+
+/*
+ * Returns the index of coord in pattern->path.
+ * The return value is negative if coord not found in pattern->path.
+ */
+int find_in_pattern(struct pattern *pattern, struct coord *coord);
+
+/*
+ * Gives back the points in arr, that are between from and to.
+ */
+int inbetween(int width, int height, struct coord *from, struct coord *to, struct coord *arr);
+
+/*
+ * Returns true if there's no unvisited point between
+ * the last point of path and next.
+ */
+bool nothing_inbetween(struct pattern *pattern, struct coord *next);
+
+/*
+ * Inline functions.
+ */
+inline bool len_is_max(struct pattern *pattern)
+{
+ return pattern->length >= pattern->type.max_length;
+}
+
+inline bool len_is_min(struct pattern *pattern)
+{
+ return pattern->length <= pattern->type.min_length;
+}
+
+inline int coord_to_index(int width, struct coord point)
+{
+ return (point.y * width) + point.x;
+}
+
+inline struct coord index_to_coord(int width, int index)
+{
+ struct coord result;
+ result.y = index / width;
+ result.x = index % width;
+ return result;
+}
+
+inline int pattern_point_to_index(struct pattern *pattern, int index)
+{
+ return coord_to_index(pattern->type.width, pattern->path[index]);
+}
+
+#endif \ No newline at end of file
diff --git a/src/pattern/random.c b/src/pattern/random.c
new file mode 100644
index 0000000..b7dba62
--- /dev/null
+++ b/src/pattern/random.c
@@ -0,0 +1 @@
+#include "random.h"
diff --git a/src/pattern/random.h b/src/pattern/random.h
new file mode 100644
index 0000000..68aeddc
--- /dev/null
+++ b/src/pattern/random.h
@@ -0,0 +1,5 @@
+#ifndef PLOC_GEN_PATTERN_RANDOM_H
+#define PLOC_GEN_PATTERN_RANDOM_H
+
+
+#endif \ No newline at end of file
diff --git a/src/utils/args.c b/src/utils/args.c
new file mode 100644
index 0000000..e569b15
--- /dev/null
+++ b/src/utils/args.c
@@ -0,0 +1,83 @@
+#include "args.h"
+#include <stdlib.h>
+#include <string.h>
+#include "utilities.h"
+
+#include <stdio.h>
+enum alr process_args(int argc, char **argv, struct option *options, int opt_length, void *args)
+{
+ // Processing
+ for (int i = 1; i < argc; i++)
+ {
+ //printf("%d: Init variables.\n", i);
+ // Init variables.
+ char *arg_name = argv[i];
+ char *arg_param = NULL;
+ bool long_name = false;
+ //printf("%d: Extract name.\n", i);
+ // Extract name.
+ if (arg_name[0] == '-')
+ arg_name++;
+ if (arg_name[0] == '-')
+ {
+ arg_name++;
+ long_name = true;
+ }
+ if (arg_name[0] == 0)
+ {
+ // Syntax error
+ }
+
+ //printf("%d: Find option (%s)(%s).\n", i, arg_name, long_name ? "long" : "short");
+ // Find option.
+ struct option *option = NULL;
+ for (int i = 0; i < opt_length; i++)
+ {
+ //printf("option[i]: %s\n", options[i].short_name);
+ if (long_name)
+ {
+ if (cmpstr_tillchar(arg_name, options[i].name, '\0', '=') == 0)
+ option = &options[i];
+ }
+ else
+ {
+ if (cmpstr_tillchar(arg_name, options[i].short_name, '\0', '\0') == 0)
+ option = &options[i];
+ }
+ }
+ if (option == NULL)
+ return ALR_INVALID_OPTION;
+
+ //printf("%d: Find param.\n", i);
+ // Find param.
+ if (option->has_param)
+ {
+ if (long_name)
+ {
+ arg_param = strchr(arg_name, '=');
+ if (arg_param != NULL)
+ {
+ arg_param++;
+ if (arg_param[0] == '\0')
+ arg_param = NULL;
+ }
+ }
+ else
+ {
+ i++;
+ if (i < argc)
+ arg_param = argv[i];
+ }
+
+ if (arg_param == NULL)
+ {
+ // Error: Missing param.
+ }
+ }
+
+ //printf("%d: Process.\n", i);
+ // Process.
+ option->handle(args, arg_param);
+ }
+ return ALR_OK;
+} \ No newline at end of file
diff --git a/src/utils/args.h b/src/utils/args.h
new file mode 100644
index 0000000..ddf086d
--- /dev/null
+++ b/src/utils/args.h
@@ -0,0 +1,28 @@
+#ifndef UTILS_ARGS_H
+#define UTILS_ARGS_H
+
+#include <stdbool.h>
+
+struct option
+{
+ char short_name[16];
+ char name[32];
+ bool has_param;
+ // first: args struct; second: param;
+ void (*handle)(void *, const char *);
+};
+
+// ALR stands for Args Load Result
+enum alr
+{
+ ALR_OK,
+ ALR_INVALID_OPTION
+};
+
+/*
+ * opt_length: options length
+ * args: args struct
+ */
+enum alr process_args(int argc, char **argv, struct option *options, int opt_length, void *args);
+
+#endif \ No newline at end of file
diff --git a/src/utils/utilities.c b/src/utils/utilities.c
new file mode 100644
index 0000000..717dce0
--- /dev/null
+++ b/src/utils/utilities.c
@@ -0,0 +1,68 @@
+#include "utils/utilities.h"
+#include <string.h>
+#include <time.h>
+
+bool monotonic(int a, int b, int c);
+
+// TODO: Handle the case when they are not equal (greater or smaller)
+int cmpstr_tillchar(const char *a, const char *b, char a_until, char b_until)
+{
+ while (*a != 0 && *b != 0 && *a != a_until && *b != b_until)
+ {
+ if (*a != *b)
+ return -1;
+ a++;
+ b++;
+ }
+ return 0;
+}
+
+static unsigned int random_number(unsigned int max)
+{
+ return rand() / (RAND_MAX / max);
+}
+
+void shuffle(void *base, size_t nitems, size_t size)
+{
+ char *c_base = base;
+ char swap[size];
+ for (int i = 0; i < nitems; i++)
+ {
+ char *a = c_base + (i * size);
+ char *b = c_base + (random_number(nitems - 1) * size);
+ memcpy(swap, a, size);
+ memcpy(a, b, size);
+ memcpy(b, swap, size);
+ }
+}
+
+void init2d(void **array, size_t width, size_t height, size_t size)
+{
+ char **c_array = (char **)array;
+ char *start = (char *)array;
+ for (size_t x = 0; x < width; x++)
+ c_array[x] = start + (width * sizeof(int *)) + (x * height * size);
+}
+
+size_t sizeof_2d(size_t width, size_t height, size_t size)
+{
+ return (width * sizeof(char *)) + (width * height * size);
+}
+
+int find_lr_ints(char *text, char **left, char **right)
+{
+ *left = text;
+ while (**left != 0 && (**left < '0' || **left > '9'))
+ (*left)++;
+ if (**left == 0)
+ return 0;
+
+ *right = text + strlen(text);
+ while (**right < '0' || **right > '9')
+ (*right)--;
+
+ while (**right >= '0' && **right <= '9')
+ (*right)--;
+ (*right)++;
+ return 1;
+} \ No newline at end of file
diff --git a/src/utils/utilities.h b/src/utils/utilities.h
new file mode 100644
index 0000000..9447c1f
--- /dev/null
+++ b/src/utils/utilities.h
@@ -0,0 +1,42 @@
+#ifndef UTILS_UTILITIES_H
+#define UTILS_UTILITIES_H
+
+#include <stdlib.h>
+#include <stdbool.h>
+
+/*
+ * Compare the part a before a_until and
+ * the part b before b_until
+ */
+int cmpstr_tillchar(const char *a, const char *b, char a_until, char b_until);
+
+//int cmpstr_tillindex(const char *a, const char *b, int a_until, int b_until);
+
+void shuffle(void *base, size_t nitems, size_t size);
+
+void init2d(void **array, size_t width, size_t height, size_t size);
+
+size_t sizeof_2d(size_t width, size_t height, size_t size);
+
+/*
+ * Find the first integer numbers from the left and the right
+ * and sets the pointers *left, *right to the first digit of
+ * left and right numbers respectively.
+ */
+int find_lr_ints(char *text, char **left, char **right);
+
+/*
+ * Returns ture, if
+ * a <= b <= c OR
+ * a >= b >= c
+ */
+inline bool monotonic(int a, int b, int c)
+{
+ if (a <= b && b <= c)
+ return true;
+ if (a >= b && b >= c)
+ return true;
+ return false;
+}
+
+#endif \ No newline at end of file