mirror of
https://github.com/erkin/ponysay.git
synced 2025-01-31 18:36:43 +01:00
Port of Truncater to C
This commit is contained in:
parent
fa5a06db88
commit
986d158bfe
2 changed files with 174 additions and 150 deletions
150
Truncater.java
150
Truncater.java
|
@ -1,150 +0,0 @@
|
||||||
import java.io.*;
|
|
||||||
|
|
||||||
public class Truncater
|
|
||||||
{
|
|
||||||
public static void main(final String... args) throws IOException
|
|
||||||
{
|
|
||||||
final int width;
|
|
||||||
if ((width = getWidth()) > 15) //sanity
|
|
||||||
{
|
|
||||||
final OutputStream stdout = new BufferedOutputStream(System.out);
|
|
||||||
OutputStream out = new OutputStream()
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The number of column on the current line
|
|
||||||
*/
|
|
||||||
private int x = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Escape sequence state
|
|
||||||
*/
|
|
||||||
private int esc = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Last bytes as written
|
|
||||||
*/
|
|
||||||
private boolean ok = true;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void write(final int b) throws IOException
|
|
||||||
{
|
|
||||||
if (this.esc == 0)
|
|
||||||
{
|
|
||||||
if (b == '\n')
|
|
||||||
{
|
|
||||||
if (x >= width)
|
|
||||||
{
|
|
||||||
write('\033');
|
|
||||||
write('[');
|
|
||||||
write('4');
|
|
||||||
write('9');
|
|
||||||
write('m');
|
|
||||||
}
|
|
||||||
this.x = -1;
|
|
||||||
}
|
|
||||||
else if (b == '\t')
|
|
||||||
{
|
|
||||||
int nx = 8 - (x & 7);
|
|
||||||
for (int i = 0; i < nx; i++)
|
|
||||||
write(' ');
|
|
||||||
return; //(!)
|
|
||||||
}
|
|
||||||
else if (b == '\033')
|
|
||||||
this.esc = 1;
|
|
||||||
}
|
|
||||||
else if (this.esc == 1)
|
|
||||||
{
|
|
||||||
if (b == '[') this.esc = 2;
|
|
||||||
else if (b == ']') this.esc = 3;
|
|
||||||
else this.esc = 10;
|
|
||||||
}
|
|
||||||
else if (this.esc == 2)
|
|
||||||
{
|
|
||||||
if ((('a' <= b) && (b <= 'z')) || (('A' <= b) && (b <= 'Z')))
|
|
||||||
this.esc = 10;
|
|
||||||
}
|
|
||||||
else if ((this.esc == 3) && (b == 'P'))
|
|
||||||
{
|
|
||||||
this.esc = ~0;
|
|
||||||
}
|
|
||||||
else if (this.esc < 0)
|
|
||||||
{
|
|
||||||
this.esc--;
|
|
||||||
if (this.esc == ~7)
|
|
||||||
this.esc = 10;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
this.esc = 10;
|
|
||||||
|
|
||||||
if ((x < width) || (this.esc != 0) || (ok && ((b & 0xC0) == 0x80)))
|
|
||||||
{
|
|
||||||
stdout.write(b);
|
|
||||||
if (this.esc == 0)
|
|
||||||
if ((b & 0xC0) != 0x80)
|
|
||||||
x++;
|
|
||||||
ok = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ok = false;
|
|
||||||
if (this.esc == 10)
|
|
||||||
this.esc = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void flush() throws IOException
|
|
||||||
{
|
|
||||||
stdout.flush();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
System.setOut(new PrintStream(out));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
InputStream in = System.in;
|
|
||||||
OutputStream out = System.out;
|
|
||||||
|
|
||||||
for (int d; (d = in.read()) != -1;)
|
|
||||||
out.write(d);
|
|
||||||
out.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the width of the terminal
|
|
||||||
*
|
|
||||||
* @return The width of the terminal
|
|
||||||
*/
|
|
||||||
public static int getWidth()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Process process = (new ProcessBuilder("/bin/sh", "-c", "tput cols 2> " + (new File("/dev/stderr")).getCanonicalPath())).start();
|
|
||||||
String rcs = new String();
|
|
||||||
InputStream stream = process.getInputStream();
|
|
||||||
int c;
|
|
||||||
while (((c = stream.read()) != '\n') && (c != -1))
|
|
||||||
rcs += (char)c;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
stream.close();
|
|
||||||
}
|
|
||||||
catch (final Throwable err)
|
|
||||||
{
|
|
||||||
//Ignore
|
|
||||||
}
|
|
||||||
return Integer.parseInt(rcs);
|
|
||||||
}
|
|
||||||
catch (final Throwable err)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
174
ponysaytruncater.c
Normal file
174
ponysaytruncater.c
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
/**
|
||||||
|
* ponysaytruncater — Output truncater used by ponysay to stop large ponies from being printed badly.
|
||||||
|
*
|
||||||
|
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
* See COPYING for details
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define String char*
|
||||||
|
#define boolean char
|
||||||
|
|
||||||
|
#define true 1
|
||||||
|
#define false 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stdin file descriptor ID
|
||||||
|
*/
|
||||||
|
#define STDIN 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of columns on the current line
|
||||||
|
*/
|
||||||
|
static int x = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escape sequence state
|
||||||
|
*/
|
||||||
|
static int esc = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last bytes as written
|
||||||
|
*/
|
||||||
|
static boolean ok = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void write(char b, int width);
|
||||||
|
int toInt(String string);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Mane method!</p>
|
||||||
|
* <p>
|
||||||
|
* The only argument, in addition to the executed file,
|
||||||
|
* should be the width of the terminal which you get by
|
||||||
|
* adding <code>`tput cols || echo 0`</code> as and argument.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param argc The number of startup arguments
|
||||||
|
* @param argv The startup arguments, the first is the file itself
|
||||||
|
*
|
||||||
|
* @author Mattias Andrée, maandree@kth.se
|
||||||
|
*/
|
||||||
|
void main(int argc, String* argv)
|
||||||
|
{
|
||||||
|
int width = 0;
|
||||||
|
if (argc > 1)
|
||||||
|
width = toInt(*(argv + 1));
|
||||||
|
|
||||||
|
char b = 0;
|
||||||
|
|
||||||
|
if (width > 15) //sanity
|
||||||
|
while (read(STDIN, &b, 1))
|
||||||
|
write(b, width);
|
||||||
|
else
|
||||||
|
while (read(STDIN, &b, 1))
|
||||||
|
printf("%c", b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a character to stdout, iff it fits within the terminal
|
||||||
|
*
|
||||||
|
* @param b The character (byte) to write
|
||||||
|
* @param width The width of the terminal
|
||||||
|
*/
|
||||||
|
void write(char b, int width)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char nx;
|
||||||
|
|
||||||
|
if (esc == 0)
|
||||||
|
{
|
||||||
|
if (b == '\n')
|
||||||
|
{
|
||||||
|
if (x >= width)
|
||||||
|
{
|
||||||
|
// Reset background colour
|
||||||
|
write('\e', width);
|
||||||
|
write('[', width);
|
||||||
|
write('4', width);
|
||||||
|
write('9', width);
|
||||||
|
write('m', width);
|
||||||
|
}
|
||||||
|
x = -1;
|
||||||
|
}
|
||||||
|
else if (b == '\t')
|
||||||
|
{
|
||||||
|
// Tab to next pos ≡₈ 0
|
||||||
|
nx = 8 - (x & 7);
|
||||||
|
for (i = 0; i < nx; i++)
|
||||||
|
write(' ', width);
|
||||||
|
return; //(!)
|
||||||
|
}
|
||||||
|
else if (b == '\e')
|
||||||
|
esc = 1;
|
||||||
|
}
|
||||||
|
else if (esc == 1)
|
||||||
|
{
|
||||||
|
if (b == '[') esc = 2; //CSI ends with a letter, m is for colour
|
||||||
|
else if (b == ']') esc = 3; //OSI, OSI P is for palett editing in Linux VT
|
||||||
|
else esc = 10; //Nothing to see here, move along
|
||||||
|
}
|
||||||
|
else if (esc == 2)
|
||||||
|
{
|
||||||
|
if ((('a' <= b) && (b <= 'z')) || (('A' <= b) && (b <= 'Z')))
|
||||||
|
esc = 10;
|
||||||
|
}
|
||||||
|
else if ((esc == 3) && (b == 'P'))
|
||||||
|
{
|
||||||
|
esc = ~0;
|
||||||
|
}
|
||||||
|
else if (esc < 0)
|
||||||
|
{
|
||||||
|
esc--;
|
||||||
|
if (esc == ~7)
|
||||||
|
esc = 10;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
esc = 10;
|
||||||
|
|
||||||
|
if ( // Can be printed:
|
||||||
|
(x < width) || // within bounds ∨
|
||||||
|
(esc != 0) || // ∨ escape sequence ∨
|
||||||
|
(ok && ((b & 0xC0) == 0x80))) // ∨ last with printed ∧ not first byte in character
|
||||||
|
{
|
||||||
|
printf("%c", b);
|
||||||
|
if ((esc == 0) && ((b & 0xC0) != 0x80)) // Count up columns of not in escape sequnce and
|
||||||
|
x++; // the byte is not the first byte in the character
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ok = false;
|
||||||
|
|
||||||
|
if (esc == 10)
|
||||||
|
esc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a string to an integer
|
||||||
|
*
|
||||||
|
* @param string The string to convert
|
||||||
|
* @return The integer represented by the string
|
||||||
|
*/
|
||||||
|
int toInt(String string)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
String str = string;
|
||||||
|
char c = 0;
|
||||||
|
|
||||||
|
while ((c = *str++) != 0)
|
||||||
|
rc = (rc << 1) + (rc << 3) - (c & 15);
|
||||||
|
|
||||||
|
return -rc;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue