diff --git a/src/bindgen/config.rs b/src/bindgen/config.rs
index 28466ca58bd3396b6e1262ec1887f7c4fa02d5bb..41adcb7f3f9c58862419957372f70e50f2aa73ef 100644
--- a/src/bindgen/config.rs
+++ b/src/bindgen/config.rs
@@ -24,7 +24,7 @@ pub enum Braces {
     NextLine,
 }
 
-#[derive(Debug, Clone, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Deserialize)]
 #[serde(rename_all = "snake_case")]
 pub enum Layout {
     Horizontal,
@@ -48,9 +48,9 @@ pub struct Config {
     /// The style to use for braces
     pub braces: Braces,
     /// The preferred length of a line, used for auto breaking function arguments
-    pub line_length: u32,
+    pub line_length: usize,
     /// The amount of spaces in a tab
-    pub tab_width: u32,
+    pub tab_width: usize,
     /// The language to output bindings for
     pub language: Language,
     /// The configuration options for functions
@@ -131,7 +131,7 @@ impl Config {
             function: FunctionConfig {
                 prefix: Some(String::from("WR_INLINE")),
                 postfix: Some(String::from("WR_FUNC")),
-                args: Layout::Horizontal,
+                args: Layout::Vertical,
             },
             structure: StructConfig {
                 derive_eq: true,
diff --git a/src/bindgen/items.rs b/src/bindgen/items.rs
index 3c52aab917da132f5b2bc6fa537c97087ac56077..e4d41cc011df9763e277fb1b29e9e83ff7e29b7d 100644
--- a/src/bindgen/items.rs
+++ b/src/bindgen/items.rs
@@ -3,7 +3,7 @@ use std::fmt;
 
 use syn::*;
 
-use bindgen::config::Config;
+use bindgen::config::{Config, Layout};
 use bindgen::directive::*;
 use bindgen::library::*;
 use bindgen::syn_helpers::*;
@@ -223,83 +223,89 @@ impl Type {
         }
     }
 
-    fn write<F: Write>(&self, out: &mut Writer<F>) {
+    fn to_string(&self) -> String {
         match self {
             &Type::ConstPtr(ref t) => {
-                out.write("const ");
-                t.write(out);
-                out.write("*");
+                format!("const {}*", t.to_string())
             }
             &Type::Ptr(ref t) => {
-                t.write(out);
-                out.write("*");
+                format!("{}*", t.to_string())
             }
             &Type::Path(ref p) => {
-                out.write(p);
+                p.clone()
             }
             &Type::Primitive(ref p) => {
-                out.write(&format!("{}", p));
+                format!("{}", p)
             }
             &Type::Array(ref t, ref sz) => {
-                t.write(out);
-                out.write(&format!("[{}]", sz));
+                format!("{}[{}]", t.to_string(), sz)
             }
             &Type::FuncPtr(ref ret, ref args) => {
+                let mut out = String::new();
+
                 if let &Some(ref ret) = ret {
-                    ret.write(out);
+                    out.push_str(&ret.to_string());
                 } else {
-                    out.write("void");
+                    out.push_str("void");
                 }
-                out.write(" (*)(");
+                out.push_str(" (*)(");
                 for (i, arg) in args.iter().enumerate() {
                     if i != 0 {
-                        out.write(", ");
+                        out.push_str(", ");
                     }
-                    arg.write(out);
+                    out.push_str(&arg.to_string());
                 }
-                out.write(")");
+                out.push_str(")");
+
+                out
             }
         }
     }
 
-    fn write_with_ident<F: Write>(&self, ident: &str, out: &mut Writer<F>) {
+    fn to_string_with_ident(&self, ident: &str) -> String {
         match self {
             &Type::ConstPtr(ref t) => {
-                out.write("const ");
-                t.write(out);
-                out.write(&format!("* {}", ident));
+                format!("const {}* {}", t.to_string(), ident)
             }
             &Type::Ptr(ref t) => {
-                t.write(out);
-                out.write(&format!("* {}", ident));
+                format!("{}* {}", t.to_string(), ident)
             }
             &Type::Path(ref p) => {
-                out.write(&format!("{} {}", p, ident));
+                format!("{} {}", p, ident)
             }
             &Type::Primitive(ref p) => {
-                out.write(&format!("{} {}", p, ident));
+                format!("{} {}", p, ident)
             }
             &Type::Array(ref t, ref sz) => {
-                t.write(out);
-                out.write(&format!(" {}[{}]", ident, sz));
+                format!("{} {}[{}]", t.to_string(), ident, sz)
             }
             &Type::FuncPtr(ref ret, ref args) => {
+                let mut out = String::new();
+
                 if let &Some(ref ret) = ret {
-                    ret.write(out);
+                    out.push_str(&ret.to_string());
                 } else {
-                    out.write("void");
+                    out.push_str("void");
                 }
-                out.write(&format!(" (*{})(", ident));
+                out.push_str(" (*");
+                out.push_str(ident);
+                out.push_str(")(");
                 for (i, arg) in args.iter().enumerate() {
                     if i != 0 {
-                        out.write(", ");
+                        out.push_str(", ");
                     }
-                    arg.write(out);
+                    out.push_str(&arg.to_string());
                 }
-                out.write(")");
+                out.push_str(")");
+
+                out
             }
         }
     }
+
+    fn write_with_ident<F: Write>(&self, ident: &str, out: &mut Writer<F>) {
+        out.write(&self.to_string_with_ident(ident));
+    }
 }
 
 #[derive(Debug, Clone)]
@@ -340,30 +346,103 @@ impl Function {
     }
 
     pub fn write<F: Write>(&self, config: &Config, out: &mut Writer<F>) {
-        if let Some(ref f) = config.function.prefix(&self.directives) {
-            out.write(&format!("{} ", f));
-        }
-
-        match self.ret.as_ref() {
-            Some(ret) => ret.write(out),
-            None => out.write("void"),
-        }
-
-        out.new_line();
-        out.write(&format!("{}(", self.name));
-        for (i, arg) in self.args.iter().enumerate() {
-            if i != 0 {
-                out.write(",\n    ");
+        // Try three different ways of formatting, depending on the line length
+        //    1. PREFIX RET NAME ( ARGS ... ) POSTFIX ;
+        //    2. PREFIX
+        //       RET NAME ( ARGS ... )
+        //       POSTFIX ;
+        //    3. PREFIX
+        //       RET NAME ( ARGS
+        //                  ... )
+        //       POSTFIX ;
+
+        let prefix = config.function.prefix(&self.directives);
+        let ret = match self.ret.as_ref() {
+            Some(ret) => ret.to_string(),
+            None => format!("void"),
+        };
+        let name = &self.name;
+        let args = self.args.iter().map(|x| x.1.to_string_with_ident(&x.0)).collect::<Vec<_>>();
+        let postfix = config.function.postfix(&self.directives);
+
+        let option_1: usize = prefix.as_ref().map_or(0, |x| x.len()) +
+                              ret.len() +
+                              name.len() +
+                              args.iter().map(|x| x.len()).sum::<usize>() +
+                              postfix.as_ref().map_or(0, |x| x.len()) + 7;
+
+        let option_2: usize = ret.len() +
+                              name.len() +
+                              args.iter().map(|x| x.len()).sum::<usize>();
+
+        if (config.function.args == Layout::Auto && option_1 <= config.line_length) ||
+            config.function.args == Layout::Horizontal {
+            // 1. PREFIX RET NAME ( ARGS ... ) POSTFIX ;
+
+            if let Some(ref prefix) = prefix {
+                out.write(prefix);
+                out.write(" ");
+            }
+            out.write(&format!("{} {}({}) ",
+                      &ret,
+                      name,
+                      args.join(", ")));
+            if let Some(ref postfix) = postfix {
+                out.write(postfix);
             }
-            arg.1.write_with_ident(&arg.0, out);
-        }
-        out.write(")");
+            out.write(";");
+        } else if config.function.args == Layout::Auto && option_2 <= config.line_length {
+            // 2. PREFIX
+            //    RET NAME ( ARGS ... )
+            //    POSTFIX ;
 
-        if let Some(ref f) = config.function.postfix(&self.directives) {
-            out.new_line();
-            out.write(f)
+            if let Some(ref prefix) = prefix {
+                out.write(prefix);
+                out.new_line();
+            }
+            out.write(&format!("{} {}({}) ",
+                      &ret,
+                      name,
+                      args.join(", ")));
+            if let Some(ref postfix) = postfix {
+                out.new_line();
+                out.write(postfix);
+            }
+            out.write(";");
+        } else {
+            // 3. PREFIX
+            //    RET NAME ( ARGS 
+            //               ... )
+            //    POSTFIX ;
+
+            if let Some(ref prefix) = prefix {
+                out.write(prefix);
+                out.new_line();
+            }
+            out.write(&format!("{} {}(",
+                      &ret,
+                      name));
+            for (i, arg) in args.iter().enumerate() {
+                out.write(arg);
+                if i != args.len() - 1 {
+                    out.write(",");
+                    if i == 0 {
+                        let align_length = ret.len() + name.len() + 2;
+                        out.push_set_spaces(align_length);
+                    }
+                    out.new_line();
+                }
+            }
+            if args.len() > 1 {
+                out.pop_tab();
+            }
+            out.write(")");
+            if let Some(ref postfix) = postfix {
+                out.new_line();
+                out.write(postfix);
+            }
+            out.write(";");
         }
-        out.write(";");
     }
 }
 
diff --git a/src/bindgen/writer.rs b/src/bindgen/writer.rs
index f13dd64e7b0519156df65e14de86d6e402c2c747..0947a086ab5ab15163991b1ed510b8412f247dc9 100644
--- a/src/bindgen/writer.rs
+++ b/src/bindgen/writer.rs
@@ -4,8 +4,8 @@ use std::io::Write;
 pub struct Writer<'a, 'f, F: 'f + Write> {
     out: &'f mut F,
     config: &'a Config,
-    tabs: Vec<u32>,
-    pending_spaces: u32,
+    spaces: Vec<usize>,
+    pending_spaces: usize,
     has_written: bool,
 }
 
@@ -14,37 +14,46 @@ impl<'a, 'f, F: Write> Writer<'a, 'f, F> {
         Writer {
             out: out,
             config: config,
-            tabs: vec![0],
+            spaces: vec![0],
             pending_spaces: 0,
             has_written: false,
         }
     }
 
-    fn tabs(&mut self) -> u32 {
-        *self.tabs.last().unwrap()
+    fn spaces(&mut self) -> usize {
+        *self.spaces.last().unwrap()
     }
 
     pub fn push_tab(&mut self) {
-        let tabs = self.tabs() + 1;
-        self.tabs.push(tabs);
+        let spaces = self.spaces() -
+                     (self.spaces() % self.config.tab_width) + 
+                     self.config.tab_width;
+        self.spaces.push(spaces);
 
         if !self.has_written {
-            self.pending_spaces = self.tabs() * self.config.tab_width;
+            self.pending_spaces = self.spaces();
+        }
+    }
+    pub fn push_set_spaces(&mut self, spaces: usize) {
+        self.spaces.push(spaces);
+
+        if !self.has_written {
+            self.pending_spaces = self.spaces();
         }
     }
 
     pub fn pop_tab(&mut self) {
-        assert!(!self.tabs.is_empty());
-        self.tabs.pop();
+        assert!(!self.spaces.is_empty());
+        self.spaces.pop();
 
         if !self.has_written {
-            self.pending_spaces = self.tabs() * self.config.tab_width;
+            self.pending_spaces = self.spaces();
         }
     }
 
     pub fn new_line(&mut self) {
         write!(self.out, "\n").unwrap();
-        self.pending_spaces = self.tabs() * self.config.tab_width;
+        self.pending_spaces = self.spaces();
         self.has_written = false;
     }