_ _ _ ____ _ _
/ \ _ __ ___ | |_| |__ ___ _ __ | _ \ _ __ ___ (_) __| |
/ _ \ | '_ \ / _ \| __| '_ \ / _ \ '__| | | | | '__/ _ \| |/ _\` |
/ ___ \| | | | (_) | |_| | | | __/ | | |_| | | | (_) | | (_| |
/_/ \_\_| |_|\___/ \__|_| |_|\___|_| |____/|_| \___/|_|\__,_|
bbs
XQTRs lair...
Home //
Blog //
NULL emag. //
Files //
Docs //
Tutors //
GitHub repo
__ _ __ _ _ __
______\ \_\\_______________________\///__________________________//_/ /______
\___\ /___/
| .__ __ |
| | ___ __________/ |________ |
| \ \/ / ____/\ __\_ __ \ |
; > < <_| | | | | | \/ ;
: /__/\_ \__ | |__| |__| :
. \/ |__| .
. .
: H/Q Another Droid BBS - andr01d.zapto.org:9999 :
; ;
+ --- -- - . - --- --- --- - . - -- --- +
: :
| Write Pipes With Pascal In Pi |
: :
` --- -- - . - --- --- --- - . - -- --- '
Actually, not only in Pi... but it rimes better :p
So... PIPES are codes that are used in BBSes to change color in text. You
probably have seen them. Usually are something like this |07. The symbol in
front (the pipe) defines that the next two numbers are a color. To change
the foreground color we use numbers from 00 to 15 and for the background
from 16 to 23... but why?
In Pascal the color of the text is defined by a variable, which is called
TextAttr. The size of this attribute is one byte, so it can take values
from 0 to 255. To represent foreground and background color, we use this
formula:
TextAttr := Foreground + (Background * 16)
Where Foreground is 0 to 15 and Background from 0 to 7. But in pipe codes
we use the values 16 to 23 for the background color, cause the first 16
values are taken and we can't use again 0 to 7. So we continue counting
from 16.
+---------------------- FG ---------------------+---------- BG ---------+
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 | 16 17 18 19 20 21 22 23
In a Pipe code to take the actual background value we calculate it like
this:
Background = BG Pipe Code - 16
So, |23 is 23 - 16 = 7, which is actually white/grey in Pascal.
Sometimes, the pipe symbol is used for ASCII graphics, so if we translate
it every time we encounter it, as a pipe code, we may garble the text. We
must be sure that after the pipe symbol, two digits are following, else we
print the pipe as it is.
This is the theory... lets code...
Program writepipe;
{$MODE objfpc} // Use FreePascal format
{$H-} // We don't want extended strings
Uses Crt;
We will use our own String to Integer conversion, because we must know if
an error occurred while converting. If there is an error, then we know,
that we didn't process a valid color number and we have to print the text
instead of converting it in a color value.
Function S2I(N:String):Smallint;
Var
I,Code:Word;
Begin
Result := -1; // Set default value for function
Val (N,I,Code);
If Code<>0 Then Exit; // Is Everything OK? if not exit.
Result:=I; // If it's OK then our result is a color number
End;
Now... this is the sweet part.
+--+-- Really? i have to explain this?
| |
| | +-- Default color to use
| | |
| | | +-- TextAttr valid value
| | | |
| | | | + Our text with pipe codes
| | | | |
Procedure WriteXYPipe (X, Y, Attr: Byte; Text: String);
Const
Seth = '|'; // We could also use any other symbol we want ex. '
Var
Count : Byte; // Variable to know the position we are in the
// text
Code : String[2]; // Color values as text
CodeNum : Smallint; // Our color value from the pipe code
OldAttr : Byte; -\
OldX : Byte; > Values to restore color and cursor position
OldY : Byte; -/
Begin
OldAttr := TextAttr;
OldX := WhereX;
OldY := WhereY;
GotoXY (X, Y); // Go to new position
TextAttr:=Attr; // Save old attribute
Count := 1; // Start in the beginning of the text
While Count <= Length(Text) Do Begin // While we are processing the
// text, check for colors
If Text[Count] = Seth Then Begin // We found a pipe color?
Code := Copy(Text, Count + 1, 2); // Get two characters in front
CodeNum := S2I(Code); // Convert them to integer num.
if CodeNum<0 Then Begin // If the conversion fails, then
// this wasn't actually a pipe
// code, so write the char
// instead of processing it.
Write(Text[Count]);
Count+=1;
End;
If (CodeNum>0) Or (Code='00') Then Begin
// We actually got a pipe code!
Count+=3; // Increase the counter by three cause
// pipes are |23 ;)
If CodeNum in [00..15] Then // Is the color code from 0 to 15?
// then we have to change the
// foreground color.
// We only need to change the foreground color, so we need to
// know, what is the currect background color. To do that, we
// divide the current TextAttr by 16 and then multiple the
// result again with 16. This way, we get the value for the
// background only! After, we just add, the number for the
// foreground color.
+-- Foreground Color
|
| +-- Get the old value and
// | | re-apply it
TextAttr := CodeNum + (TextAttr Div 16) * 16
Else
// If our pipe color is between 16 and 23, then we change the
// background color, but we have to keep the same foreground
// color. To extract foreground color from the textattr variable
// we mod it... we want the modulus of the division TextAttr / 16
// As we said earlier, the background value is from 0 to 7, so to
// convert our background pipe color (16 to 23) we just sub 16 and
// then multiple by 16
+-- Current Foreground Color
|
| +-- Background Value
| |
TextAttr :=((TextAttr Mod 16) + (CodeNum - 16) * 16);
End;
End Else Begin // No pipe code, so we print the character and move on
Write(Text[Count]);
Count+=1;
End;
End;
TextAttr:=OldAttr; // At the end, restore old color and position
GotoXY (OldX, OldY);
End;
Begin
ClrScr;
WriteXYPipe(10,5,7,'|Hello| |15|17World |1this is '+
'|08|03write|11XY|06|23Pipe');
For f:=0 to 7 Do
For b:=0 to 7 Do
WriteXYPipe(10+f*8,8+b,7,'|'+I2S(f)+'|'+I2S(b+16)+'TEXT ');
End.
+ --- -- - . - --- --- --- - . - -- --- '
Complete Program
+ --- -- - . - --- --- --- - . - -- --- '
Program writepipe;
{$MODE objfpc} // Use FreePascal format
{$H-} // We don't want extended strings
Uses Crt;
Var
f,b:Byte;
Function I2S (N: LongInt): String;
Var
T : String;
Begin
Str(N, T);
If Length(T)=1 Then T:='0'+T;
Result := T;
End;
Function S2I(N:String):Smallint;
Var
I,Code:Word;
Begin
Result := -1;
Val (N,I,Code);
If Code<>0 Then Exit;
Result:=I;
End;
Procedure WriteXYPipe (X, Y, Attr: Byte; Text: String);
Const
Seth = '|';
Var
Count : Byte;
Code : String[2];
CodeNum : Smallint;
OldAttr : Byte;
OldX : Byte;
OldY : Byte;
Begin
OldAttr := TextAttr;
OldX := WhereX;
OldY := WhereY;
GotoXY (X, Y);
TextAttr:=Attr;
Count := 1;
While Count <= Length(Text) Do Begin
If Text[Count] = Seth Then Begin
Code := Copy(Text, Count + 1, 2);
CodeNum := S2I(Code);
if CodeNum<0 Then Begin
Write(Text[Count]);
Count+=1;
End;
If (CodeNum>0) Or (Code='00') Then Begin
Count+=3;
If CodeNum in [00..15] Then
TextAttr := CodeNum + (TextAttr Div 16) * 16
Else
TextAttr :=((TextAttr Mod 16) + (CodeNum - 16) * 16);
End;
End Else Begin
Write(Text[Count]);
Count+=1;
End;
End;
TextAttr:=OldAttr;
GotoXY (OldX, OldY);
End;
Begin
ClrScr;
WriteXYPipe(10,5,7,'|Hello| |15|17World |1this is '+
'|08|03write|11XY|06|23Pipe');
For f:=0 to 7 Do
For b:=0 to 7 Do
WriteXYPipe(10+f*8,8+b,7,'|'+I2S(f)+'|'+I2S(b+16)+'TEXT ');
End.
+ --- -- - . - --- --- --- - . - -- --- '
_____ _ _ ____ _ _
| _ |___ ___| |_| |_ ___ ___ | \ ___ ___|_|_| | 8888
| | | . | _| | -_| _| | | | _| . | | . | 8 888888 8
|__|__|_|_|___|_| |_|_|___|_| |____/|_| |___|_|___| 8888888888
8888888888
DoNt Be aNoTHeR DrOiD fOR tHe SySteM 88 8888 88
8888888888
/: HaM RaDiO /: ANSi ARt! /: MySTiC MoDS /: DooRS '88||||88'
/: NeWS /: WeATheR /: FiLEs /: SPooKNet ''8888"'
/: GaMeS /: TeXtFiLeS /: PrEPardNeSS /: FsxNet 88
/: TuTors /: bOOkS/PdFs /: SuRVaViLiSM /: ArakNet 8 8 88888888888
888 8888][][][888
TeLNeT : andr01d.zapto.org:9999 [UTC 11:00 - 20:00] 8 888888##88888
SySoP : xqtr eMAiL: xqtr@gmx.com 8 8888.####.888
DoNaTe : https://paypal.me/xqtr 8 8888##88##888