mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-26 20:03:49 +02:00
3290 lines
94 KiB
ObjectPascal
3290 lines
94 KiB
ObjectPascal
Unit oCrt;
|
|
{---------------------------------------------------------------------------
|
|
CncWare
|
|
(c) Copyright 1999-2000
|
|
---------------------------------------------------------------------------
|
|
Filename..: ocrt.pp
|
|
Programmer: Ken J. Wright, ken@cncware.com
|
|
Date......: 03/01/99
|
|
|
|
Purpose - crt unit replacement plus OOP windows using ncurses.
|
|
|
|
NOTE: All of the crt procedures & functions have been replaced with ncurses
|
|
driven versions. This makes the ncurses library a little easier to use in a
|
|
Pascal program and benefits from terminal independence.
|
|
|
|
-------------------------------<< REVISIONS >>--------------------------------
|
|
Ver | Date | Prog| Description
|
|
-------+----------+-----+-----------------------------------------------------
|
|
1.00 | 03/01/99 | kjw | Initial Release.
|
|
| 03/22/99 | kjw | Added nDelWindow(), delwin() does not nil pointer.
|
|
1.01 | 11/22/99 | kjw | Added the following: nEcho, ClrEol, ClrBot, InsLine,
|
|
| DelLine, Delay, nClrEol, nClrBot, nInsLine, nDelLine,
|
|
| nRefresh, nScroll, nDrawBox, nNewWindow, nWinColor,
|
|
| nWriteScr, nFrame & some functions for returning
|
|
| line drawing character values.
|
|
1.02 | 11/26/99 | kjw | Added nKeypressed().
|
|
1.03 | 12/01/99 | kjw | Added global boolean nIsActive.
|
|
1.04 | 12/03/99 | kjw | 1) Added procedures nHline, nVLine, & nWriteAC.
|
|
| 2) Changed all the line draw character functions
|
|
| (i.e., nHL, nVL) to return the longint value from
|
|
| ncurses rather than the character value (which was
|
|
| not very useful!). Now these can be passed to
|
|
| nWriteAC() to correctly write the line drawing
|
|
| characters.
|
|
| 3) Added more of the ACS characters.
|
|
1.05 | 12/08/99 | kjw | 1) StartCurses() is now done as part of the unit
|
|
| initialization block. EndCurses() is done via an
|
|
| exit procedure.
|
|
| 2) nIsActive is now a function (safer!).
|
|
| 3) Added panel unit for windowing.
|
|
| 4) Added tnWindow object.
|
|
1.10 | 12/12/99 | kjw | Added nSEdit().
|
|
1.11 | 12/12/99 | kjw | Added Special property to tEC object. Now any normal
|
|
| character can trigger sedit to exit.
|
|
------------------------------------------------------------------------------
|
|
2.00 | 12/13/99 | kjw | nCrt renamed to oCrt. A new nCrt has been created
|
|
| which is a drop-in replacement for the FPC crt unit.
|
|
| oCrt contains all of nCrt plus the OOP extensions.
|
|
| All of the common code is in ncrt.inc.
|
|
2.01 | 12/15/99 | kjw | 1) A tnWindow object now becomes the target for
|
|
| stdout following Init & Show. A Hide will put the
|
|
| target back to stdscr.
|
|
| 2) Added nSetActiveWin() to manually pick a target
|
|
| window for stdout.
|
|
2.02 | 12/15/99 | kjw | 1) PutFrame applied keypad to stdscr instead of sub.
|
|
| 2) See ncrt.inc
|
|
2.03 | 12/16/99 | kjw | 1) See ncrt.inc
|
|
| 2) Added shift/f-key constants.
|
|
2.04 | 01/04/00 | kjw | See ncrt.inc
|
|
2.05 | 01/06/00 | kjw | 1) See ncrt.inc.
|
|
| 2) Added boolean internal_fwrite. FWrite was failing
|
|
| when trying to write outside of the active window.
|
|
| 3) nSEdit was not handling tec.firsttime correctly
|
|
| when a tec.special was processed.
|
|
2.06 | 01/11/00 | kjw | See ncrt.inc.
|
|
2.07 | 01/31/00 | kjw | 1) See ncrt.inc.
|
|
| 2) Added getcolor, getframecolor, getheadercolor
|
|
| methods to tnWindow.
|
|
2.08 | 06/09/00 | kjw | 1) Added Picture property to tEC object. This is
|
|
| used for picture input masking in nSEdit.
|
|
| 2) Added nCheckPxPicture() function.
|
|
| 3) nSEdit() changed to use picture input masking.
|
|
| See pxpic.txt for a description of the picture
|
|
| string format.
|
|
|
|
2.08.01 | 06/11/2000 | kjw
|
|
| Fixed the spin cycle problem in nCheckPXPicture.
|
|
2.09.00 | 06/16/2000 | kjw
|
|
| 1) nSEdit renamed to nEdit. Now nSEdit just calls nEdit() for
|
|
| compatibility.
|
|
| 2) Added overloaded nEdit functions for Integer, LongInt, and
|
|
| Real types.
|
|
| 3) Changed nEdit() embedding of control characters to preface
|
|
| with a ^P. Also now uses a highlight attribute for the control
|
|
| characters.
|
|
| 4) Added control character cursor control to nEdit().
|
|
| 5) Added Esc/1..0 = F1..F10 to nEdit().
|
|
| 6) Added '@' to match set in pxpic.inc.
|
|
| 7) tnWindow.Align was not positioning properly. Off by one.
|
|
| 8) tnWindow.Init used wrong pointer for keypad and intrflush.
|
|
| 9) tnWindow.Edit was messing up ec.Special.
|
|
2.09.01 | 06/16/2000 | kjw
|
|
| 1) nStdScr (tnWindow) added and initialized at unit startup.
|
|
| nStdScr can be used for a default full screen window.
|
|
| 2) nEdit overloaded to work without a window pointer. It works
|
|
| with the currently active window.
|
|
2.10.00 | 06/23/2000 | kjw
|
|
| 1) Added character mapping to the tEC object. This includes the
|
|
| ChMap property and the AddChMap() and ClrChMap() methods.
|
|
| 2) Added AppendMode property to the tEC object. The character
|
|
| typed in nEdit() is always appended to the current string
|
|
| regardless of cursor position. Useful when ExitMode is true.
|
|
| 3) tnWindow.Done was not re-assigning an ActiveWn.
|
|
| 4) nEdit LeftArrow was allowing < x.
|
|
| 5) Added nEditNumber() function.
|
|
| 6) Added nEditDate() function.
|
|
| 7) I made a command decision and renamed the tEC.FirstTime
|
|
| property to tEC.ClearMode as it is more descriptive.
|
|
2.11.00 | 1) Cleaned up some loose ends with 2.10.
|
|
| 2) Some more overloading
|
|
| 3) Removed tnWindow.readln, write, and writeln methods.
|
|
| 4) See ncrt.inc.
|
|
2.12.00 | 1) Remove the "n" from the tnWindow.editxxx functions for
|
|
| consistancy. Procedurals are prefaced with an "n". Object methods
|
|
| are not.
|
|
| 2) Procedural FWrite renamed to nFWrite.
|
|
| 3) tEC object type renamed to tnEC.
|
|
| 4) Added nMakeWindow(), a one line procedural wrapper for
|
|
| tnWindow.Init and tnWindow.PutHeader.
|
|
| 5) Added GetX, GetY, IsFramed methods to tnWindow;
|
|
| 6) Fixed nFWrite for too long strings;
|
|
| 7) tnWindow.Align was wrong when justify was none.
|
|
2.13.00 | 06/30/00 | kjw | See ncrt.inc
|
|
2.14.00 | 07/05/00 | kjw | See ncrt.inc
|
|
2.15.00 | 07/12/00 | kjw |
|
|
| 1) Renamed IsBold to nIsBold. Renamed SetColorPair to nSetColorPair.
|
|
| 2) Added tnMenu object (not functional);
|
|
| 07/17/00 | kjw |
|
|
| 2) Argh!! Align method had another mistake. Changed x/y=1 to =0.
|
|
| 3) Added nShowMessage() function.
|
|
| 4) tnMenu is now minimally functional.
|
|
| 07/25/00 | kjw |
|
|
| 1) tnMenu fully functional for current level.
|
|
2.16.00 | 08/14/2000 | kjw |
|
|
| 1) Added Get/SetMark(), IsActive(), IsValid(), IsAssigned(),
|
|
| SetIndex() to tnMenu.
|
|
| 08/18/2000 | kjw |
|
|
| 1) Added nkXXX constants for all(?) extended keys.
|
|
| 2) Changed all uses of extended keys to use new nkXXX's.
|
|
| 3) Edit overloaded to return a nkXXX in ch rather that a char.
|
|
| 4) Resize method added to tnWindow.
|
|
| 5) AddChMap overloaded for preferred (easier) use with nkXXX's.
|
|
| 08/24/2000 | kjw |
|
|
| 1) Added nReadScr, nReadScrStr, nReadScrColor, nWriteScrStr,
|
|
| nGrabScreen, nPopScreen, nReleaseScreen.
|
|
| 2) Fixed some trouble with PrevWn accuracy.
|
|
------------------------------------------------------------------------------
|
|
}
|
|
Interface
|
|
|
|
Uses
|
|
{$ifdef unix}
|
|
{$ifdef ver1_0}
|
|
linux,
|
|
{$else}
|
|
unix,
|
|
{$endif}
|
|
{$endif}
|
|
ncurses,panel,menu;
|
|
|
|
Const
|
|
|
|
{ decimal number format, us or european }
|
|
nUS = 0;
|
|
nEURO = 1;
|
|
nDecFmt : byte = nUS;
|
|
|
|
{ border styles for text boxes }
|
|
btNone : integer = 0;
|
|
btSingle : integer = 1;
|
|
btDouble : integer = 2;
|
|
|
|
{ ordinal keycodes, new style, preferred }
|
|
nkEnter = 13; { Enter key }
|
|
nkEsc = 27; { Home key }
|
|
nkHome = -71; { Home key }
|
|
nkUp = -72; { Up arrow }
|
|
nkPgUp = -73; { PgUp key }
|
|
nkLeft = -75; { Left arrow }
|
|
nkRight = -77; { Right arrow }
|
|
nkEnd = -79; { End key }
|
|
nkDown = -80; { Down arrow }
|
|
nkPgDn = -81; { PgDn key }
|
|
nkIns = -82; { Insert key }
|
|
nkDel = -83; { Delete key }
|
|
nkCtrlLeft = -115; { Ctrl/left arrow }
|
|
nkCtrlRight = -116; { Ctrl/right arrow }
|
|
nkF1 = -59; { f1 key }
|
|
nkF2 = -60; { f2 key }
|
|
nkF3 = -61; { f3 key }
|
|
nkF4 = -62; { f4 key }
|
|
nkF5 = -63; { f5 key }
|
|
nkF6 = -64; { f6 key }
|
|
nkF7 = -65; { f7 key }
|
|
nkF8 = -66; { f8 key }
|
|
nkF9 = -67; { f9 key }
|
|
nkF10 = -68; { f10 key }
|
|
nkF11 = -84; { shift/f1 key }
|
|
nkF12 = -85; { shift/f2 key }
|
|
nkF13 = -86; { shift/f3 key }
|
|
nkF14 = -87; { shift/f4 key }
|
|
nkF15 = -88; { shift/f5 key }
|
|
nkF16 = -89; { shift/f6 key }
|
|
nkF17 = -90; { shift/f7 key }
|
|
nkF18 = -91; { shift/f8 key }
|
|
nkF19 = -92; { shift/f9 key }
|
|
nkF20 = -93; { shift/f10 key }
|
|
nkAltA = -30; { alt/a }
|
|
nkAltB = -48; { alt/b }
|
|
nkAltC = -46; { alt/c }
|
|
nkAltD = -32; { alt/d }
|
|
nkAltE = -18; { alt/e }
|
|
nkAltF = -33; { alt/f }
|
|
nkAltG = -34; { alt/g }
|
|
nkAltH = -35; { alt/h }
|
|
nkAltI = -23; { alt/i }
|
|
nkAltJ = -36; { alt/j }
|
|
nkAltK = -37; { alt/k }
|
|
nkAltL = -38; { alt/l }
|
|
nkAltM = -50; { alt/m }
|
|
nkAltN = -49; { alt/n }
|
|
nkAltO = -24; { alt/o }
|
|
nkAltP = -25; { alt/p }
|
|
nkAltQ = -16; { alt/q }
|
|
nkAltR = -19; { alt/r }
|
|
nkAltS = -31; { alt/s }
|
|
nkAltT = -20; { alt/t }
|
|
nkAltU = -22; { alt/u }
|
|
nkAltV = -47; { alt/v }
|
|
nkAltW = -17; { alt/w }
|
|
nkAltX = -45; { alt/x }
|
|
nkAltY = -21; { alt/y }
|
|
nkAltZ = -44; { alt/z }
|
|
nkAlt1 = -120; { alt/1 }
|
|
nkAlt2 = -121; { alt/2 }
|
|
nkAlt3 = -122; { alt/3 }
|
|
nkAlt4 = -123; { alt/4 }
|
|
nkAlt5 = -124; { alt/5 }
|
|
nkAlt6 = -125; { alt/6 }
|
|
nkAlt7 = -126; { alt/7 }
|
|
nkAlt8 = -127; { alt/8 }
|
|
nkAlt9 = -128; { alt/9 }
|
|
nkAlt0 = -129; { alt/0 }
|
|
nkAltMinus = -130; { alt/- }
|
|
nkAltEqual = -131; { alt/= }
|
|
nkAltTab = -15; { alt/tab }
|
|
|
|
{ ordinal key codes (old style, don't break any apps!) }
|
|
nKeyEnter = nkEnter;
|
|
nKeyEsc = nkEsc;
|
|
nKeyHome = abs(nkHome);
|
|
nKeyUp = abs(nkUp);
|
|
nKeyPgUp = abs(nkPgUp);
|
|
nKeyLeft = abs(nkLeft);
|
|
nKeyRight = abs(nkRight);
|
|
nKeyEnd = abs(nkEnd);
|
|
nKeyDown = abs(nkDown);
|
|
nKeyPgDn = abs(nkPgDn);
|
|
nKeyIns = abs(nkIns);
|
|
nKeyDel = abs(nkDel);
|
|
nKeyCtrlLeft = abs(nkCtrlLeft);
|
|
nKeyCtrlRight = abs(nkCtrlRight);
|
|
nKeyF1 = abs(nkF1);
|
|
nKeyF2 = abs(nkF2);
|
|
nKeyF3 = abs(nkF3);
|
|
nKeyF4 = abs(nkF4);
|
|
nKeyF5 = abs(nkF5);
|
|
nKeyF6 = abs(nkF6);
|
|
nKeyF7 = abs(nkF7);
|
|
nKeyF8 = abs(nkF8);
|
|
nKeyF9 = abs(nkF9);
|
|
nKeyF10 = abs(nkF10);
|
|
nKeyF11 = abs(nkF11);
|
|
nKeyF12 = abs(nkF12);
|
|
nKeyF13 = abs(nkF13);
|
|
nKeyF14 = abs(nkF14);
|
|
nKeyF15 = abs(nkF15);
|
|
nKeyF16 = abs(nkF16);
|
|
nKeyF17 = abs(nkF17);
|
|
nKeyF18 = abs(nkF18);
|
|
nKeyF19 = abs(nkF19);
|
|
nKeyF20 = abs(nkF20);
|
|
|
|
{ character mapping }
|
|
nMaxChMaps = 255; { maximun index for character mapping }
|
|
|
|
{ menus }
|
|
nMAXMENUITEMS = 100;
|
|
|
|
Type
|
|
{*** structures to save a screen via nGrabScreen ***}
|
|
pnOneRow = pchar;
|
|
{ a buffer for a max of 256 chtype items accessed via pchar }
|
|
tnOneRow = array [0..1023] of char;
|
|
{ a one way linked list of screen rows }
|
|
pnRowBuf = ^tnRowBuf;
|
|
tnRowBuf = Record
|
|
row : pnOneRow; { one row of a screen }
|
|
next : pnRowBuf; { next row in the list }
|
|
End;
|
|
{ the header record of a saved screen }
|
|
pnScreenBuf = ^tnScreenBuf;
|
|
tnScreenBuf = Record
|
|
x, { column origin }
|
|
y, { row origin }
|
|
n : integer; { number of columns }
|
|
first : pnRowBuf; { pointer to first row in list }
|
|
End;
|
|
|
|
tnS10 = string[10];
|
|
|
|
{ for scrolling a window }
|
|
tnUpDown = (up,down);
|
|
{ for window & header positioning }
|
|
tnJustify = (none,left,center,right,top,bottom);
|
|
{ used for nEC character mapping }
|
|
(********* Note : these are obsolete *******)
|
|
nChMapStr = string[4];
|
|
{nChMap = array [1..nMaxChMaps] of nChMapStr;}
|
|
(*******************************************)
|
|
nChMap = array [1..nMaxChMaps,1..2] of integer;
|
|
|
|
{ used for nSEdit }
|
|
{------------------------------------------------------------------------
|
|
ClearMode = true : passed string is initialized to ''.
|
|
IsHidden = true : causes a string of '*' to display in place of
|
|
the actual characters typed.
|
|
InsMode : toggle for insert/overwrite mode.
|
|
ExitMode = true : sedit exits after every keystroke.
|
|
= false: sedit only exits when #27,#13, or any extended
|
|
key *except* for Home,End,RArrow,LArrow.
|
|
Special : If a pressed key is found in this string, then
|
|
sedit exits without processing.
|
|
Picture : An input mask string. See pxpic.txt for an
|
|
explanation of picture strings.
|
|
CtrlColor : The highlight color for embedded control characters.
|
|
ChMap : An array of character triplets describing a character
|
|
that is typed and what it should map to.
|
|
------------------------------------------------------------------------}
|
|
tnEC = Object
|
|
ClearMode,
|
|
IsHidden,
|
|
InsMode,
|
|
ExitMode,
|
|
AppendMode : boolean;
|
|
Special : string;
|
|
Picture : string;
|
|
CtrlColor : integer;
|
|
ChMap : nChMap;
|
|
Constructor Init(ft,ih,im,em,ap : boolean;
|
|
s,p : string;
|
|
cc : integer;
|
|
mp : nChMap);
|
|
Destructor Done;
|
|
Function AddChMap(_in,_out : integer) : integer;
|
|
Function AddChMap(mp : nChMapStr) : integer;
|
|
Procedure ClrChMap(idx : integer);
|
|
End;
|
|
|
|
pwin = ^Window;
|
|
|
|
pnWindow = ^tnWindow;
|
|
tnWindow = Object
|
|
Private
|
|
wn : pwindow; { pointer to win or sub to read/write to }
|
|
win : pwindow; { pointer to main window record }
|
|
sub : pwindow; { sub window if a bordered window }
|
|
pan : ppanel; { pointer to panel record }
|
|
subp : ppanel; { sub panel if a bordered window }
|
|
visible : boolean; { is the window visible? }
|
|
hasframe : boolean;
|
|
wincolor, { window color }
|
|
framecolor, { frame color }
|
|
hdrcolor : integer; { header color }
|
|
hdrpos : tnJustify; { header alignment }
|
|
header : string[80]; { header string }
|
|
Procedure init_wins(x,y,x1,y1 : integer);
|
|
Procedure done_wins;
|
|
Public
|
|
data : pointer; { a pointer to user defined data }
|
|
ec : tnEC; { edit control settings }
|
|
Constructor Init(x,y,x1,y1,wcolor : integer;
|
|
border : boolean;
|
|
fcolor : integer);
|
|
Destructor Done;
|
|
Procedure Resize(cols_,rows_ : integer);
|
|
Procedure Active; { make this the current window }
|
|
Procedure Show; { display the window }
|
|
Procedure Hide; { hide the window }
|
|
Procedure ClrScr;
|
|
Procedure ClrEol;
|
|
Procedure ClrBot;
|
|
Procedure InsLine;
|
|
Procedure DelLine;
|
|
Procedure GotoXY(x,y : integer);
|
|
Function WhereX : integer;
|
|
Function WhereY : integer;
|
|
Function ReadKey : char;
|
|
Procedure WriteAC(x,y,att,c : longint);
|
|
Procedure FWrite(x,y,att,z : integer; s : string);
|
|
Procedure DrawBox(LineStyle,x1,y1,x2,y2,att : Integer);
|
|
Function GetHeader : string;
|
|
Procedure PutHeader(hdr : string; hcolor : integer; hpos : tnJustify);
|
|
Procedure SetColor(att : integer);
|
|
Function GetColor : integer;
|
|
Function GetFrameColor : integer;
|
|
Function GetHeaderColor : integer;
|
|
Procedure PutFrame(att : integer);
|
|
Procedure Move(x,y : integer);
|
|
Procedure Scroll(ln : integer; dir : tnUpDown);
|
|
Procedure Align(hpos,vpos : tnJustify);
|
|
Function Rows : integer;
|
|
Function Cols : integer;
|
|
Function GetX : integer;
|
|
Function GetY : integer;
|
|
Function IsFramed : boolean;
|
|
Function IsVisible : Boolean;
|
|
Function Edit(x,y,att,z,CursPos:Integer;es:String;Var ch : integer) : String;
|
|
Function Edit(x,y,att,z,CursPos:Integer;es:LongInt;Var ch : integer) : LongInt;
|
|
Function Edit(x,y,att,z,CursPos:Integer;es:Real;Var ch : integer) : Real;
|
|
Function Edit(x,y,att,z,CursPos:Integer;es:String;Var ch : Char) : String;
|
|
Function Edit(x,y,att,z,CursPos:Integer;es:LongInt;Var ch : Char) : LongInt;
|
|
Function Edit(x,y,att,z,CursPos:Integer;es:Real;Var ch : Char) : Real;
|
|
Function EditNumber(x,y,att,wid,decm : integer;bgd : string;initv,minv,maxv : real;var esc : boolean) : real;
|
|
Function EditNumber(x,y,att,wid,decm : integer;bgd : string;initv,minv,maxv : longint;var esc : boolean) : longint;
|
|
Function EditDate(x,y,att : integer;initv : string;var esc : boolean) : string;
|
|
End;
|
|
|
|
pnMenuStr = ^tnMenuStr;
|
|
tnMenuStr = array [0..79] of char; { storage for menu item text }
|
|
pnMenu = ^tnMenu;
|
|
tnMenu = Object
|
|
Private
|
|
tc, { text (item) color }
|
|
cc, { cursor (current item) color }
|
|
fc, { frame color }
|
|
hc, { header Color }
|
|
gc, { non-selectable color }
|
|
x,y, { top,left corner of window }
|
|
r,c, { how many rows & columns of items to display }
|
|
wid, { minimum window width }
|
|
iidx, { item index }
|
|
merr { menu error code }
|
|
: integer;
|
|
loopon,
|
|
framed,
|
|
posted : boolean; { is the menu posted? }
|
|
mark : tnS10;
|
|
items : array[1..nMAXMENUITEMS] of pnMenuStr;
|
|
pi : array[1..nMAXMENUITEMS] of pItem;
|
|
pm : pMenu;
|
|
win : pnWindow;
|
|
Procedure InitWin;
|
|
Procedure ClearItem(idx : integer);
|
|
Procedure AddItem(i : integer; s : string);
|
|
Function Selectable(idx : integer) : boolean;
|
|
Function IsValid(idx : integer) : boolean;
|
|
Public
|
|
Constructor Init(_x,_y,_w,_r,_c,_tc,_cc,_gc : integer;
|
|
_fr : boolean; _fc : integer);
|
|
Destructor Done;
|
|
Procedure Post; { create the menu of current items }
|
|
Procedure UnPost; { unbind the items and free the menu }
|
|
Procedure Start; { start user input, includes show }
|
|
Procedure Stop; { a shortcut for hide,unpost }
|
|
Procedure Show; { display the menu, includes post }
|
|
Procedure Hide; { remove the menu from the display }
|
|
Function Wind : pnWindow; { pointer to the window object }
|
|
Procedure Move(_x,_y : integer); { shortcut window move }
|
|
Procedure Align(hpos,vpos : tnJustify);{ shortcut window align }
|
|
Procedure PutHeader(hdr : string; hcolor : integer; hpos : tnJustify);
|
|
Procedure Clear; { unpost and clear the menu item list }
|
|
Function Add(s : string) : integer; { append a menu item }
|
|
Procedure Insert(idx : integer; s : string); { insert a menu item }
|
|
Procedure Remove(idx : integer); { delete a menu item }
|
|
Procedure Change(idx : integer; s : string); { change an item }
|
|
Procedure Active(idx : integer; b : boolean); { toggle gray }
|
|
Function IsActive(idx : integer) : boolean; { item active ? }
|
|
Procedure Spin(b : boolean);{ toggle item looping }
|
|
Function Status : integer;{ return the current error/status code }
|
|
Function Index : integer; { return the current item index }
|
|
Procedure SetIndex(idx : integer); { set the item index }
|
|
Function Count : integer; { number of items in the menu }
|
|
Function Rows(_r : integer) : integer; {get/set menu rows }
|
|
Function Cols(_c : integer) : integer; {get/set menu columns }
|
|
Function IsAssigned(idx : integer) : boolean; { valid & assigned }
|
|
Function GetMark : string; { return the item mark string }
|
|
Procedure SetMark(ms : string); { set the mark string }
|
|
Procedure Refresh;
|
|
Procedure SetColor(att : byte); { change text color }
|
|
Procedure SetCursorColor(att : byte); { change cursor color }
|
|
Procedure SetFrameColor(att : byte); { change frame color }
|
|
Procedure SetGrayColor(att : byte); { change inactive color }
|
|
End;
|
|
|
|
Var
|
|
nStdScr : tnWindow; { default window created at unit initialization }
|
|
nscreen : pwin; { pointer to ncurses stdscr }
|
|
nEC : tnEC; { global edit control object }
|
|
|
|
Procedure nSetActiveWin(win : pwindow);
|
|
Procedure nDoNow(donow : boolean);
|
|
Function nKeypressed(timeout : word) : boolean;
|
|
Procedure nEcho(b : boolean);
|
|
Procedure nWindow(var win : pWindow; x,y,x1,y1 : integer);
|
|
Procedure nNewWindow(var win : pWindow; x,y,x1,y1 : integer);
|
|
Procedure nDelWindow(var win : pWindow);
|
|
Procedure nWinColor(win : pWindow; att : integer);
|
|
Procedure nClrScr(win : pWindow; att : integer);
|
|
Procedure nClrEol(win : pWindow);
|
|
Procedure nClrBot(win : pWindow);
|
|
Procedure nInsLine(win : pWindow);
|
|
Procedure nDelLine(win : pWindow);
|
|
Procedure nGotoXY(win : pWindow; x,y : integer);
|
|
Function nWhereX(win : pWindow) : integer;
|
|
Function nWhereY(win : pWindow) : integer;
|
|
Function nReadkey(win : pWindow) : char;
|
|
Function nReadln(win : pWindow) : string;
|
|
Procedure nWrite(win : pWindow; s : string);
|
|
Procedure nWriteln(win : pWindow; s : string);
|
|
Procedure nWriteScr(win : pWindow; x,y,att : integer; s : string);
|
|
Procedure nRefresh(win : pWindow);
|
|
Procedure nScroll(win : pWindow; lines : integer; dir : tnUpDown);
|
|
Procedure nDrawBox(win : pWindow; LineStyle,x1,y1,x2,y2,att : Integer);
|
|
Procedure nFrame(win : pWindow);
|
|
Function nRows(win : pWindow) : integer;
|
|
Function nCols(win : pWindow) : integer;
|
|
Function nHL : longint; { horizontal line }
|
|
Function nVL : longint; { vertical line }
|
|
Function nUL : longint; { upper left corner }
|
|
Function nLL : longint; { lower loft corner }
|
|
Function nUR : longint; { upper right corner }
|
|
Function nLR : longint; { lower right corner }
|
|
Function nLT : longint; { left tee }
|
|
Function nRT : longint; { right tee }
|
|
Function nTT : longint; { top tee }
|
|
Function nBT : longint; { bottom tee }
|
|
Function nPL : longint; { plus, + }
|
|
Function nLA : longint; { left arrow }
|
|
Function nRA : longint; { right arrow }
|
|
Function nUA : longint; { up arror }
|
|
Function nDA : longint; { down arrow }
|
|
Function nDI : longint; { diamond }
|
|
Function nCB : longint; { checkerboard }
|
|
Function nDG : longint; { degree }
|
|
Function nPM : longint; { plus/minus }
|
|
Function nBL : longint; { bullet }
|
|
Procedure nHLine(win : pwindow; col,row,attr,x : integer);
|
|
Procedure nVLine(win : pwindow; col,row,attr,y : integer);
|
|
Procedure nWriteAC(win : pwindow; x,y : integer; att,acs_char : longint);
|
|
Function nIsBold(att : integer) : boolean;
|
|
Function nSetColorPair(att : integer) : integer;
|
|
Procedure nFWrite(win : pwindow; col,row,attrib : integer; clear : integer; s : string);
|
|
Procedure nFWrite(col,row,attrib : integer; clear : integer; s : string);
|
|
Function nSEdit(win : pwindow; x,y,att,z,CursPos:Integer;es:String;Var ch : Char) : String;
|
|
Function nEdit(win : pwindow; x,y,att,z,CursPos:Integer;es:String;Var ch : Char) : String;
|
|
Function nEdit(win : pwindow; x,y,att,z,CursPos:Integer;es:LongInt;Var ch : Char) : LongInt;
|
|
Function nEdit(win : pwindow; x,y,att,z,CursPos:Integer;es:Real;Var ch : Char) : Real;
|
|
Function nEdit(x,y,att,z,CursPos:Integer;es:String;Var ch : Char) : String;
|
|
Function nEdit(x,y,att,z,CursPos:Integer;es:LongInt;Var ch : Char) : LongInt;
|
|
Function nEdit(x,y,att,z,CursPos:Integer;es:Real;Var ch : Char) : Real;
|
|
Function nEdit(win : pwindow; x,y,att,z,CursPos:Integer;es:String;Var chv : integer) : String;
|
|
Function nEdit(win : pwindow; x,y,att,z,CursPos:Integer;es:LongInt;Var ch : integer) : LongInt;
|
|
Function nEdit(win : pwindow; x,y,att,z,CursPos:Integer;es:Real;Var ch : integer) : Real;
|
|
Function nEdit(x,y,att,z,CursPos:Integer;es:String;Var ch : integer) : String;
|
|
Function nEdit(x,y,att,z,CursPos:Integer;es:LongInt;Var ch : integer) : LongInt;
|
|
Function nEdit(x,y,att,z,CursPos:Integer;es:Real;Var ch : integer) : Real;
|
|
Function nEditNumber(win : pwindow; x,y,att,wid,decm : integer;bgd : string;initv,minv,maxv : real;var esc : boolean) : real;
|
|
Function nEditNumber(win : pwindow; x,y,att,wid,decm : integer;bgd : string;initv,minv,maxv : longint;var esc : boolean) : longint;
|
|
Function nEditNumber(x,y,att,wid,decm : integer;bgd : string;initv,minv,maxv : real;var esc : boolean) : real;
|
|
Function nEditNumber(x,y,att,wid,decm : integer;bgd : string;initv,minv,maxv : longint;var esc : boolean) : longint;
|
|
Function nEditDate(win : pwindow; x,y,att : integer;initv : string;var esc : boolean) : string;
|
|
Function nEditDate(x,y,att : integer;initv : string;var esc : boolean) : string;
|
|
Procedure nMakeWindow(var win : tnWindow;x1,y1,x2,y2,ta,ba,ha : integer;hasframe : boolean;hdrpos : tnJustify;hdrtxt : string);
|
|
Procedure nMakeWindow(var win : pnWindow;x1,y1,x2,y2,ta,ba,ha : integer;hasframe : boolean;hdrpos : tnJustify;hdrtxt : string);
|
|
Procedure nMakeMenu(var mnu : tnMenu;x,y,_w,_r,_c,ta,ca,ga,ba,ha : integer;hasframe : boolean;hdrpos : tnJustify;hdrtxt : string);
|
|
Procedure nMakeMenu(var mnu : pnMenu;x,y,_w,_r,_c,ta,ca,ga,ba,ha : integer;hasframe : boolean;hdrpos : tnJustify;hdrtxt : string);
|
|
Function nShowMessage(msg : string;matt : byte;hdr : string;hatt : byte;ack : boolean) : pnWindow;
|
|
Function nReadScr(win : pWindow; x,y,n : integer) : string;
|
|
Function nReadScr(x,y,n : integer) : string;
|
|
Function nReadScrStr(win : pWindow; x,y,n : integer; buf : pchtype) : pchtype;
|
|
Function nReadScrStr(x,y,n : integer; buf : pchtype) : pchtype;
|
|
Function nReadScrColor(win : pWindow; x,y : integer) : integer;
|
|
Function nReadScrColor(x,y : integer) : integer;
|
|
Procedure nWriteScrStr(win : pWindow; x,y : integer; s : pchtype);
|
|
Procedure nWriteScrStr(x,y : integer; s : pchtype);
|
|
Procedure nGrabScreen(var p : pnScreenBuf; x,y,c,r : integer; win : pWindow);
|
|
Procedure nGrabScreen(var p : pnScreenBuf; x,y,c,r : integer);
|
|
Procedure nGrabScreen(var p : pnScreenBuf);
|
|
Procedure nPopScreen(p : pnScreenBuf; x,y : integer; win : pWindow);
|
|
Procedure nPopScreen(p : pnScreenBuf; x,y : integer);
|
|
Procedure nPopScreen(p : pnScreenBuf);
|
|
Procedure nReleaseScreen(p : pnScreenBuf);
|
|
Function nCheckPxPicture(var s, Pic : string; var CPos : integer) : word;
|
|
|
|
{$i ncrt.inc}
|
|
{$i pxpic.inc}
|
|
|
|
Var
|
|
_chmap : nChMap;
|
|
|
|
{---------------------------------------------------------------------
|
|
tnWindow.Init
|
|
|
|
Create a new window.
|
|
x = upper left corner x, screen relative
|
|
y = upper left corner y, screen relative
|
|
x1 = lower right corner x, screen relative
|
|
y1 = lower right corner y, screen relative
|
|
wcolor = window/text color
|
|
border = include a frame?
|
|
fcolor = frame color
|
|
---------------------------------------------------------------------}
|
|
Constructor tnWindow.Init(x,y,x1,y1,wcolor : integer;
|
|
border : boolean;
|
|
fcolor : integer);
|
|
Var
|
|
mp : nChMap;
|
|
Begin
|
|
hasframe := border;
|
|
wincolor := wcolor;
|
|
framecolor := fcolor;
|
|
hdrcolor := wcolor;
|
|
header := '';
|
|
data := nil;
|
|
visible := false;
|
|
init_wins(x,y,x1,y1);
|
|
FillChar(mp,SizeOf(mp),#0);
|
|
ec.Init(false,false,false,false,false,'','',15,mp);
|
|
ec.ClrChMap(0);
|
|
SetActiveWn(wn);
|
|
End;
|
|
|
|
{ deallocate the window }
|
|
Destructor tnWindow.Done;
|
|
Begin
|
|
done_wins;
|
|
ec.Done;
|
|
SetActiveWn(nscreen);
|
|
End;
|
|
|
|
Procedure tnWindow.init_wins(x,y,x1,y1 : integer);
|
|
Begin
|
|
win := nil;
|
|
sub := nil;
|
|
pan := nil;
|
|
subp := nil;
|
|
win := newwin(y1-y+1,x1-x+1,y-1,x-1);
|
|
pan := new_panel(win);
|
|
hide_panel(pan);
|
|
If hasframe Then
|
|
PutFrame(framecolor)
|
|
Else Begin
|
|
wn := win;
|
|
wbkgd(win,COLOR_PAIR(nSetColorPair(wincolor)));
|
|
If nisbold(wincolor) then wattr_on(win,A_BOLD);
|
|
scrollok(win,bool(true));
|
|
intrflush(win,bool(false));
|
|
keypad(win,bool(true));
|
|
End;
|
|
End;
|
|
|
|
Procedure tnWindow.done_wins;
|
|
Begin
|
|
If subp <> nil Then del_panel(subp);
|
|
If pan <> nil Then del_panel(pan);
|
|
If sub <> nil Then delwin(sub);
|
|
If (win <> nil) and (win <> stdscr) Then delwin(win);
|
|
subp := nil;
|
|
pan := nil;
|
|
sub := nil;
|
|
If win <> stdscr Then win := nil;
|
|
End;
|
|
|
|
Procedure tnWindow.ReSize(cols_,rows_ : integer);
|
|
Var
|
|
xx,yy,
|
|
mx,my : integer;
|
|
vis : boolean;
|
|
Begin
|
|
xx := GetX;
|
|
yy := GetY;
|
|
{ can't be larger than full screen }
|
|
If cols_ > nMaxCols Then cols_ := nMaxCols;
|
|
If rows_ > nMaxRows Then rows_ := nMaxRows;
|
|
{ set the bottom, right corner }
|
|
mx := xx+cols_-1;
|
|
my := yy+rows_-1;
|
|
{ expand left? }
|
|
If mx > nMaxCols Then xx := nMaxCols-cols_+1;
|
|
{ expand up? }
|
|
If my > nMaxRows Then yy := nMaxRows-rows_+1;
|
|
If xx < 1 Then xx := 1;
|
|
If yy < 1 Then yy := 1;
|
|
{ reset the bottom, right corner }
|
|
mx := xx+cols_-1;
|
|
my := yy+rows_-1;
|
|
{ constrain to full screen }
|
|
If mx > nMaxCols Then mx := nMaxCols;
|
|
If my > nMaxRows Then my := nMaxRows;
|
|
vis := visible;
|
|
Hide;
|
|
visible := vis;
|
|
done_wins;
|
|
init_wins(xx,yy,mx,my);
|
|
If visible Then Show;
|
|
End;
|
|
|
|
{ make the window current for all normal crt requests }
|
|
Procedure tnWindow.Active;
|
|
Begin
|
|
SetActiveWn(wn);
|
|
End;
|
|
|
|
{ display the window and move to the top }
|
|
Procedure tnWindow.Show;
|
|
Begin
|
|
SetActiveWn(wn);
|
|
visible := true;
|
|
show_panel(pan);
|
|
If subp <> nil Then show_panel(subp);
|
|
update_panels;
|
|
doupdate;
|
|
End;
|
|
|
|
{ hide the window }
|
|
Procedure tnWindow.Hide;
|
|
Begin
|
|
{ don't go back to yourself }
|
|
If PrevWn <> wn Then
|
|
SetActiveWn(PrevWn)
|
|
Else
|
|
SetActiveWn(stdscr);
|
|
visible := false;
|
|
If subp <> nil Then hide_panel(subp);
|
|
hide_panel(pan);
|
|
update_panels;
|
|
doupdate;
|
|
GotoXY(WhereX,WhereY);
|
|
End;
|
|
|
|
Procedure tnWindow.ClrScr;
|
|
Begin
|
|
tmp_b := dorefresh;
|
|
dorefresh := visible;
|
|
nClrScr(wn,wincolor);
|
|
dorefresh := tmp_b;
|
|
End;
|
|
|
|
Procedure tnWindow.ClrEol;
|
|
Begin
|
|
tmp_b := dorefresh;
|
|
dorefresh := visible;
|
|
nClrEol(wn);
|
|
dorefresh := tmp_b;
|
|
End;
|
|
|
|
Procedure tnWindow.ClrBot;
|
|
Begin
|
|
tmp_b := dorefresh;
|
|
dorefresh := visible;
|
|
nClrBot(wn);
|
|
dorefresh := tmp_b;
|
|
End;
|
|
|
|
Procedure tnWindow.InsLine;
|
|
Begin
|
|
tmp_b := dorefresh;
|
|
dorefresh := visible;
|
|
nInsLine(wn);
|
|
dorefresh := tmp_b;
|
|
End;
|
|
|
|
Procedure tnWindow.DelLine;
|
|
Begin
|
|
tmp_b := dorefresh;
|
|
dorefresh := visible;
|
|
nDelLine(wn);
|
|
dorefresh := tmp_b;
|
|
End;
|
|
|
|
{ return the window border header string }
|
|
Function tnWindow.GetHeader : string;
|
|
Begin
|
|
GetHeader := header;
|
|
End;
|
|
|
|
{----------------------------------------------------------------------
|
|
put/replace a header string at the top of a bordered window
|
|
|
|
hdr = header string (top line of window, only if hasframe = true)
|
|
hcolor = header line color
|
|
hpos = justfication of header string, left, center, or right
|
|
----------------------------------------------------------------------}
|
|
Procedure tnWindow.PutHeader(hdr : string; hcolor : integer; hpos : tnJustify);
|
|
Var
|
|
cp,
|
|
hx,
|
|
len : integer;
|
|
att,
|
|
mx,my : longint;
|
|
Begin
|
|
If Hasframe Then Begin
|
|
If hdr <> '' Then Begin
|
|
header := hdr;
|
|
hdrcolor := hcolor;
|
|
hdrpos := hpos;
|
|
getmaxyx(win,my,mx);
|
|
nHline(win,2,1,framecolor,mx-1);
|
|
len := mx-2;
|
|
hdr := Copy(hdr,1,len);
|
|
len := Length(hdr);
|
|
Case hpos of
|
|
left : hx := 1;
|
|
center : hx := (mx - len) div 2;
|
|
right : hx := (mx - len) - 1;
|
|
End;
|
|
mvwaddstr(win,0,hx,StrPCopy(ps,hdr));
|
|
cp := nSetColorPair(hcolor);
|
|
If nIsBold(hcolor) Then
|
|
att := A_BOLD
|
|
Else
|
|
att := A_NORMAL;
|
|
mvwchgat(win,0,hx,len,att,cp,0);
|
|
End;
|
|
End;
|
|
End;
|
|
|
|
{ set the the color of the writable window }
|
|
Procedure tnWindow.SetColor(att : integer);
|
|
Begin
|
|
wbkgd(wn,COLOR_PAIR(nSetColorPair(att)));
|
|
If nisbold(att) then wattr_set(wn,A_BOLD);
|
|
wincolor := att;
|
|
If visible Then wrefresh(wn);
|
|
End;
|
|
|
|
{ get the writeable window color }
|
|
Function tnWindow.GetColor : integer;
|
|
Begin
|
|
GetColor := wincolor;
|
|
End;
|
|
|
|
{ get the frame color }
|
|
Function tnWindow.GetFrameColor : integer;
|
|
Begin
|
|
GetFrameColor := framecolor;
|
|
End;
|
|
|
|
{ get the header color }
|
|
Function tnWindow.GetHeaderColor : integer;
|
|
Begin
|
|
GetHeaderColor := hdrcolor;
|
|
End;
|
|
|
|
{ frame an un-framed window, or update the frame color of a framed window }
|
|
Procedure tnWindow.PutFrame(att : integer);
|
|
Var
|
|
x,y,
|
|
mx,my,
|
|
atts : longint;
|
|
Begin
|
|
wbkgd(win,COLOR_PAIR(nSetColorPair(att)));
|
|
atts := wattr_get(win);
|
|
If nisbold(att) then wattr_on(win,atts or A_BOLD);
|
|
box(win,ACS_VLINE,ACS_HLINE);
|
|
framecolor := att;
|
|
If framecolor = -1 Then framecolor := wincolor;
|
|
hasframe := true;
|
|
If header <> '' Then PutHeader(header,hdrcolor,hdrpos);
|
|
If sub = nil Then Begin
|
|
getbegyx(win,y,x);
|
|
getmaxyx(win,my,mx);
|
|
sub := newwin(my-2,mx-2,y+1,x+1);
|
|
If sub <> nil Then Begin
|
|
subp := new_panel(sub);
|
|
hide_panel(subp);
|
|
wbkgd(sub,COLOR_PAIR(nSetColorPair(wincolor)));
|
|
If nisbold(wincolor) then wattr_on(sub,A_BOLD);
|
|
scrollok(sub,bool(true));
|
|
intrflush(sub,bool(false));
|
|
keypad(sub,bool(true));
|
|
wn := sub;
|
|
End;
|
|
End;
|
|
touchwin(sub);
|
|
If visible Then Begin
|
|
wrefresh(win);
|
|
wrefresh(sub);
|
|
End;
|
|
End;
|
|
|
|
{ move the window }
|
|
Procedure tnWindow.Move(x,y : integer);
|
|
Begin
|
|
move_panel(pan,y-1,x-1);
|
|
If subp <> nil Then move_panel(subp,y,x);
|
|
If visible Then Begin
|
|
update_panels;
|
|
doupdate;
|
|
End;
|
|
End;
|
|
|
|
Procedure tnWindow.Align(hpos,vpos : tnJustify);
|
|
Var
|
|
x,y,
|
|
bx,by : longint;
|
|
Begin
|
|
getmaxyx(win,y,x);
|
|
getbegyx(win,by,bx);
|
|
Case hpos of
|
|
none : x := bx;
|
|
left : x := 0;
|
|
right : x := MaxCols - x;
|
|
center : x := (MaxCols - x) div 2;
|
|
End;
|
|
Case vpos of
|
|
none : y := by;
|
|
top : y := 0;
|
|
bottom : y := MaxRows - y;
|
|
center : y := (MaxRows - y) div 2;
|
|
End;
|
|
move(x+1,y+1);
|
|
End;
|
|
|
|
Procedure tnWindow.Scroll(ln : integer; dir : tnUpDown);
|
|
Begin
|
|
nScroll(wn,ln,dir);
|
|
End;
|
|
|
|
Procedure tnWindow.GotoXY(x,y : integer);
|
|
Begin
|
|
tmp_b := dorefresh;
|
|
dorefresh := visible;
|
|
nGotoXY(wn,x,y);
|
|
dorefresh := tmp_b;
|
|
End;
|
|
|
|
Function tnWindow.WhereX : integer;
|
|
Begin
|
|
WhereX := nWhereX(wn);
|
|
End;
|
|
|
|
Function tnWindow.WhereY : integer;
|
|
Begin
|
|
WhereY := nWhereY(wn);
|
|
End;
|
|
|
|
Function tnWindow.ReadKey : char;
|
|
Begin
|
|
ReadKey := nReadKey(wn);
|
|
End;
|
|
|
|
Procedure tnWindow.WriteAC(x,y,att,c : longint);
|
|
Begin
|
|
tmp_b := dorefresh;
|
|
dorefresh := visible;
|
|
nWriteAC(wn,x,y,att,c);
|
|
dorefresh := tmp_b;
|
|
End;
|
|
|
|
Procedure tnWindow.FWrite(x,y,att,z : integer; s : string);
|
|
Begin
|
|
tmp_b := dorefresh;
|
|
dorefresh := visible;
|
|
nFWrite(wn,x,y,att,z,s);
|
|
dorefresh := tmp_b;
|
|
End;
|
|
|
|
Procedure tnWindow.DrawBox(LineStyle,x1,y1,x2,y2,att : Integer);
|
|
Begin
|
|
tmp_b := dorefresh;
|
|
dorefresh := visible;
|
|
nDrawBox(wn,LineStyle,x1,y1,x2,y2,att);
|
|
dorefresh := tmp_b;
|
|
End;
|
|
|
|
Function tnWindow.Rows : integer;
|
|
Begin
|
|
Rows := nRows(wn);
|
|
End;
|
|
|
|
Function tnWindow.Cols : integer;
|
|
Begin
|
|
Cols := nCols(wn);
|
|
End;
|
|
|
|
Function tnWindow.GetX : integer;
|
|
Var
|
|
x,y : longint;
|
|
Begin
|
|
getbegyx(win,y,x);
|
|
GetX := x+1;
|
|
End;
|
|
|
|
Function tnWindow.GetY : integer;
|
|
Var
|
|
x,y : longint;
|
|
Begin
|
|
getbegyx(win,y,x);
|
|
GetY := y+1;
|
|
End;
|
|
|
|
Function tnWindow.IsFramed : boolean;
|
|
Begin
|
|
IsFramed := hasframe;
|
|
End;
|
|
|
|
Function tnWindow.IsVisible : boolean;
|
|
Begin
|
|
IsVisible := visible;
|
|
End;
|
|
|
|
Function tnWindow.Edit(x,y,att,z,CursPos:Integer;es:String;Var ch : integer) : String;
|
|
var
|
|
tmp_ec : tnec;
|
|
Begin
|
|
{ save global ec}
|
|
tmp_ec := nEC;
|
|
{ init global ec to window ec }
|
|
nEC := ec;
|
|
Edit := nEdit(wn,x,y,att,z,CursPos,es,ch);
|
|
{ re-init window ec to possible changed values }
|
|
ec.ClearMode := nEC.ClearMode;
|
|
ec.InsMode := nEC.InsMode;
|
|
{ init global ec to saved }
|
|
nEC := tmp_ec;
|
|
End;
|
|
|
|
Function tnWindow.Edit(x,y,att,z,CursPos:Integer;es:String;Var ch : Char) : String;
|
|
var
|
|
i : integer;
|
|
Begin
|
|
Edit := Edit(x,y,att,z,CursPos,es,i);
|
|
ch := chr(abs(i));
|
|
End;
|
|
|
|
{ overload for longint }
|
|
Function tnWindow.Edit(x,y,att,z,CursPos:Integer;es:LongInt;Var ch : integer) : LongInt;
|
|
var
|
|
tmp_ec : tnec;
|
|
Begin
|
|
tmp_ec := nEC;
|
|
nEC := ec;
|
|
Edit := nEdit(wn,x,y,att,z,CursPos,es,ch);
|
|
ec.ClearMode := nEC.ClearMode;
|
|
ec.InsMode := nEC.InsMode;
|
|
nEC := tmp_ec;
|
|
End;
|
|
|
|
Function tnWindow.Edit(x,y,att,z,CursPos:Integer;es:LongInt;Var ch : Char) : LongInt;
|
|
var
|
|
i : integer;
|
|
Begin
|
|
Edit := Edit(x,y,att,z,CursPos,es,i);
|
|
ch := chr(abs(i));
|
|
End;
|
|
|
|
{ overload for real }
|
|
Function tnWindow.Edit(x,y,att,z,CursPos:Integer;es:Real;Var ch : integer) : Real;
|
|
var
|
|
tmp_ec : tnec;
|
|
Begin
|
|
tmp_ec := nEC;
|
|
nEC := ec;
|
|
Edit := nEdit(wn,x,y,att,z,CursPos,es,ch);
|
|
ec.ClearMode := nEC.ClearMode;
|
|
ec.InsMode := nEC.InsMode;
|
|
nEC := tmp_ec;
|
|
End;
|
|
|
|
Function tnWindow.Edit(x,y,att,z,CursPos:Integer;es:Real;Var ch : Char) : Real;
|
|
var
|
|
i : integer;
|
|
Begin
|
|
Edit := Edit(x,y,att,z,CursPos,es,i);
|
|
ch := chr(abs(i));
|
|
End;
|
|
|
|
Function tnWindow.EditNumber(x,y,att,wid,decm : integer;bgd : string;initv,minv,maxv : real;var esc : boolean) : real;
|
|
var
|
|
tmp_ec : tnec;
|
|
Begin
|
|
tmp_ec := nEC;
|
|
nEC := ec;
|
|
EditNumber := nEditNumber(wn,x,y,att,wid,decm,bgd,initv,minv,maxv,esc);
|
|
ec.ClearMode := nEC.ClearMode;
|
|
ec.InsMode := nEC.InsMode;
|
|
nEC := tmp_ec;
|
|
End;
|
|
|
|
Function tnWindow.EditNumber(x,y,att,wid,decm : integer;bgd : string;initv,minv,maxv : longint;var esc : boolean) : longint;
|
|
var
|
|
tmp_ec : tnec;
|
|
Begin
|
|
tmp_ec := nEC;
|
|
nEC := ec;
|
|
EditNumber := nEditNumber(wn,x,y,att,wid,decm,bgd,initv,minv,maxv,esc);
|
|
ec.ClearMode := nEC.ClearMode;
|
|
ec.InsMode := nEC.InsMode;
|
|
nEC := tmp_ec;
|
|
End;
|
|
|
|
Function tnWindow.EditDate(x,y,att : integer;initv : string;var esc : boolean) : string;
|
|
var
|
|
tmp_ec : tnec;
|
|
Begin
|
|
tmp_ec := nEC;
|
|
nEC := ec;
|
|
EditDate := nEditDate(wn,x,y,att,initv,esc);
|
|
ec.ClearMode := nEC.ClearMode;
|
|
ec.InsMode := nEC.InsMode;
|
|
nEC := tmp_ec;
|
|
End;
|
|
|
|
{--------------------------- tnEC -------------------------------}
|
|
|
|
Constructor tnEC.Init(ft,ih,im,em,ap : boolean;
|
|
s,p : string;
|
|
cc : integer;
|
|
mp : nChMap);
|
|
Begin
|
|
ClearMode := ft;
|
|
IsHidden := ih;
|
|
InsMode := im;
|
|
ExitMode := em;
|
|
AppendMode := ap;
|
|
Special := s;
|
|
Picture := p;
|
|
CtrlColor := cc;
|
|
ChMap := mp;
|
|
End;
|
|
|
|
Destructor tnEC.Done;
|
|
Begin
|
|
End;
|
|
|
|
{ Add or replace a character map }
|
|
{ Preferred }
|
|
Function tnEC.AddChMap(_in,_out : integer) : integer;
|
|
Var
|
|
i : integer;
|
|
Begin
|
|
i := 0;
|
|
Repeat
|
|
inc(i);
|
|
Until (i > nMaxChMaps) or (ChMap[i,1] = _in) or (ChMap[i,1] = 0);
|
|
If i <= nMaxChMaps Then Begin
|
|
AddChMap := i;
|
|
ChMap[i,1] := _in;
|
|
ChMap[i,2] := _out;
|
|
End Else
|
|
AddChMap := 0;
|
|
End;
|
|
|
|
{ Add or replace a character map }
|
|
{ Obsolete, overloaded }
|
|
Function tnEC.AddChMap(mp : nChMapStr) : integer;
|
|
Var
|
|
i : integer;
|
|
_in,_out : integer;
|
|
Begin
|
|
{ convert to new type }
|
|
If mp[1] = #0 Then
|
|
_in := ord(mp[2]) * (-1)
|
|
Else
|
|
_in := ord(mp[1]);
|
|
If mp[3] = #0 Then
|
|
_out := ord(mp[4]) * (-1)
|
|
Else
|
|
_out := ord(mp[3]);
|
|
AddChMap := AddChMap(_in,_out);
|
|
End;
|
|
|
|
Procedure tnEC.ClrChMap(idx : integer);
|
|
Begin
|
|
Case idx of
|
|
0 : FillChar(ChMap,SizeOf(ChMap),0);
|
|
1..nMaxChMaps : Begin
|
|
ChMap[idx,1] := 0;
|
|
ChMap[idx,2] := 0;
|
|
End;
|
|
End;
|
|
End;
|
|
|
|
{==========================================================================}
|
|
|
|
{ set the active window for write(ln), read(ln) }
|
|
Procedure nSetActiveWin(win : pwindow);
|
|
Begin
|
|
SetActiveWn(win);
|
|
End;
|
|
|
|
{----------------------------------------------------------------
|
|
Set the refresh toggle.
|
|
If true, then all changes to a window are immediate. If false,
|
|
then changes appear following the next call to nRefresh.
|
|
----------------------------------------------------------------}
|
|
Procedure nDoNow(donow : boolean);
|
|
Begin
|
|
dorefresh := donow;
|
|
End;
|
|
|
|
{-----------------------------------------------------
|
|
Set the echo flag.
|
|
This determines whether or not, characters are
|
|
echoed to the display when entered via the keyboard.
|
|
-----------------------------------------------------}
|
|
Procedure nEcho(b : boolean);
|
|
Begin
|
|
Case b of
|
|
true : echo;
|
|
false: noecho;
|
|
End;
|
|
isEcho := b;
|
|
End;
|
|
|
|
{ create a new subwindow of stdscr }
|
|
Procedure nWindow(var win : pWindow; x,y,x1,y1 : integer);
|
|
Begin
|
|
nDelWindow(win);
|
|
win := subwin(stdscr,y1-y+1,x1-x+1,y-1,x-1);
|
|
If win = nil then Exit;
|
|
intrflush(win,bool(false));
|
|
keypad(win,bool(true));
|
|
scrollok(win,bool(true));
|
|
SetActiveWn(win);
|
|
End;
|
|
|
|
{ create a new window }
|
|
Procedure nNewWindow(var win : pWindow; x,y,x1,y1 : integer);
|
|
Begin
|
|
nDelWindow(win);
|
|
win := newwin(y1-y+1,x1-x+1,y-1,x-1);
|
|
If win = nil then Exit;
|
|
intrflush(win,bool(false));
|
|
keypad(win,bool(true));
|
|
scrollok(win,bool(true));
|
|
SetActiveWn(win);
|
|
End;
|
|
|
|
{ repaint a window }
|
|
Procedure nRefresh(win : pWindow);
|
|
Begin
|
|
touchwin(win);
|
|
wrefresh(win);
|
|
End;
|
|
|
|
{----------------------------------------------
|
|
Wait for a key to be pressed, with a timeout.
|
|
If a key is pressed, then nKeypressed returns
|
|
immediately as true, otherwise it return as
|
|
false after the timeout period.
|
|
----------------------------------------------}
|
|
function nKeypressed(timeout : word) : boolean;
|
|
var
|
|
fds : FDSet;
|
|
maxFD : longint;
|
|
Begin
|
|
FD_Zero(fds);
|
|
maxFD := 1;
|
|
{ turn on stdin bit }
|
|
If not FD_IsSet(STDIN,fds) Then FD_Set(STDIN,fds);
|
|
{ wait for some input }
|
|
If Select(maxFD,@fds,nil,nil,timeout) > 0 Then
|
|
nKeypressed := TRUE
|
|
Else
|
|
nKeypressed := FALSE;
|
|
End;
|
|
|
|
{---------------------------------
|
|
read input string from a window
|
|
---------------------------------}
|
|
Function nReadln(win : pWindow) : string;
|
|
Begin
|
|
wgetstr(win,ps);
|
|
nReadln := StrPas(ps);
|
|
End;
|
|
|
|
{ write a string to a window without refreshing screen }
|
|
{ DON'T update PrevWn! }
|
|
Procedure nWriteScr(win : pWindow; x,y,att : integer; s : string);
|
|
Var
|
|
tmp : pwindow;
|
|
Begin
|
|
tmp := ActiveWn;
|
|
tmp_b := doRefresh;
|
|
ActiveWn := win;
|
|
doRefresh := false;
|
|
nFWrite(win,x,y,att,0,s);
|
|
ActiveWn := tmp;
|
|
doRefresh := tmp_b;
|
|
End;
|
|
|
|
{----------------------------------------------------------
|
|
Scroll a window, up or down, a specified number of lines.
|
|
lines = number of lines to scroll.
|
|
dir = direction, up or down.
|
|
----------------------------------------------------------}
|
|
Procedure nScroll(win : pWindow; lines : integer; dir : tnUpDown);
|
|
Begin
|
|
ScrollOk(win,bool(True));
|
|
Case dir of
|
|
up : lines := abs(lines);
|
|
down : lines := abs(lines) * (-1);
|
|
End;
|
|
wscrl(win,lines);
|
|
If doRefresh Then wRefresh(win);
|
|
End;
|
|
|
|
{ draw a colored box, with or without a border }
|
|
Procedure nDrawBox(win : pWindow; LineStyle,x1,y1,x2,y2,att : Integer);
|
|
Var
|
|
sub : pWindow;
|
|
x,y : longint;
|
|
Begin
|
|
getbegyx(win,y,x);
|
|
sub := subwin(win,y2-y1+1,x2-x1+1,y+y1-1,x+x1-1);
|
|
If sub = nil Then exit;
|
|
wbkgd(sub,CursesAtts(att));
|
|
werase(sub);
|
|
case LineStyle of
|
|
1,2 : box(sub, ACS_VLINE, ACS_HLINE);
|
|
End;
|
|
If doRefresh Then wrefresh(sub);
|
|
nDelWindow(sub);
|
|
End;
|
|
|
|
{---------------------------
|
|
add a border to a window,
|
|
waits for a refresh
|
|
---------------------------}
|
|
Procedure nFrame(win : pWindow);
|
|
Begin
|
|
box(win, ACS_VLINE, ACS_HLINE);
|
|
End;
|
|
|
|
{-----------------------------------------------------------
|
|
write a string to a window at the current cursor position
|
|
followed by a newline
|
|
-----------------------------------------------------------}
|
|
Procedure nWriteln(win : pWindow; s : string);
|
|
Begin
|
|
waddstr(win,StrPCopy(ps,s+#10));
|
|
If doRefresh Then wrefresh(win);
|
|
End;
|
|
|
|
{ return then number of rows in a window }
|
|
Function nRows(win : pWindow) : integer;
|
|
Var
|
|
x,y : longint;
|
|
Begin
|
|
getmaxyx(win,y,x);
|
|
nRows := y;
|
|
End;
|
|
|
|
{ return then number of columns in a window }
|
|
Function nCols(win : pWindow) : integer;
|
|
Var
|
|
x,y : longint;
|
|
Begin
|
|
getmaxyx(win,y,x);
|
|
nCols := x;
|
|
End;
|
|
|
|
{-------------------------------------------------------
|
|
Line drawing characters have to be handled specially.
|
|
Use nWriteAC() to write these characters. They cannot
|
|
be simply included as characters in a string.
|
|
-------------------------------------------------------}
|
|
|
|
{ returns horizontal line character }
|
|
Function nHL : longint;
|
|
Begin
|
|
nHL := ACS_HLINE;
|
|
End;
|
|
|
|
{ returns vertical line character }
|
|
Function nVL : longint;
|
|
Begin
|
|
nVL := ACS_VLINE;
|
|
End;
|
|
|
|
{ returns upper left corner character }
|
|
Function nUL : longint;
|
|
Begin
|
|
nUL := ACS_ULCORNER;
|
|
End;
|
|
|
|
{ returns lower left corner character }
|
|
Function nLL : longint;
|
|
Begin
|
|
nLL := ACS_LLCORNER;
|
|
End;
|
|
|
|
{ returns upper right corner character }
|
|
Function nUR : longint;
|
|
Begin
|
|
nUR := ACS_URCORNER;
|
|
End;
|
|
|
|
{ returns lower right corner character }
|
|
Function nLR : longint;
|
|
Begin
|
|
nLR := ACS_LRCORNER;
|
|
End;
|
|
|
|
{ returns left tee character }
|
|
Function nLT : longint;
|
|
Begin
|
|
nLT := ACS_LTEE;
|
|
End;
|
|
|
|
{ returns right tee character }
|
|
Function nRT : longint;
|
|
Begin
|
|
nRT := ACS_RTEE;
|
|
End;
|
|
|
|
{ returns top tee character }
|
|
Function nTT : longint;
|
|
Begin
|
|
nTT := ACS_TTEE;
|
|
End;
|
|
|
|
{ returns bottom tee character }
|
|
Function nBT : longint;
|
|
Begin
|
|
nBT := ACS_BTEE;
|
|
End;
|
|
|
|
{ returns plus/cross character }
|
|
Function nPL : longint;
|
|
Begin
|
|
nPL := ACS_PLUS;
|
|
End;
|
|
|
|
{ returns left arrow character }
|
|
Function nLA : longint;
|
|
Begin
|
|
nLA := ACS_LARROW;
|
|
End;
|
|
|
|
{ returns right arrow character }
|
|
Function nRA : longint;
|
|
Begin
|
|
nRA := ACS_RARROW;
|
|
End;
|
|
|
|
{ returns up arrow character }
|
|
Function nUA : longint;
|
|
Begin
|
|
nUA := ACS_UARROW;
|
|
End;
|
|
|
|
{ returns down arrow character }
|
|
Function nDA : longint;
|
|
Begin
|
|
nDA := ACS_DARROW;
|
|
End;
|
|
|
|
{ returns diamond character }
|
|
Function nDI : longint;
|
|
Begin
|
|
nDI := ACS_DIAMOND;
|
|
End;
|
|
|
|
{ returns checkerboard character }
|
|
Function nCB : longint;
|
|
Begin
|
|
nCB := ACS_CKBOARD;
|
|
End;
|
|
|
|
{ returns degree character }
|
|
Function nDG : longint;
|
|
Begin
|
|
nDG := ACS_DEGREE;
|
|
End;
|
|
|
|
{ returns plus/minus character }
|
|
Function nPM : longint;
|
|
Begin
|
|
nPM := ACS_PLMINUS;
|
|
End;
|
|
|
|
{ returns bullet character }
|
|
Function nBL : longint;
|
|
Begin
|
|
nBL := ACS_BULLET;
|
|
End;
|
|
|
|
{ draw a horizontal line with color and a start & end position }
|
|
Procedure nHLine(win : pwindow; col,row,attr,x : integer);
|
|
var
|
|
sub : pwindow;
|
|
bx,by : longint;
|
|
Begin
|
|
getbegyx(win,by,bx);
|
|
sub := subwin(win,1,x-col+1,by+row-1,bx+col-1);
|
|
If sub = nil Then Exit;
|
|
x := getmaxx(sub);
|
|
wbkgd(sub,CursesAtts(attr));
|
|
mvwhline(sub,0,0,ACS_HLINE,x);
|
|
If doRefresh Then wrefresh(sub);
|
|
delwin(sub);
|
|
End;
|
|
|
|
{ draw a vertical line with color and a start & end position }
|
|
Procedure nVLine(win : pwindow; col,row,attr,y : integer);
|
|
var sub : pwindow;
|
|
Begin
|
|
sub := subwin(win,y-row+1,1,row-1,col-1);
|
|
If sub = nil Then Exit;
|
|
wbkgd(sub,CursesAtts(attr));
|
|
mvwvline(sub,0,0,ACS_VLINE,y);
|
|
If doRefresh Then wrefresh(sub);
|
|
delwin(sub);
|
|
End;
|
|
|
|
{----------------------------------------------------------------
|
|
Write a character from the alternate character set. A normal
|
|
value from the alternate character set is larger than $400000.
|
|
If the value passed here is 128..255, then we assume it to be
|
|
the ordinal value from the IBM extended character set, and try
|
|
to map it to curses correctly. If it does not map, then we just
|
|
make it an alternate character and hope the output is what the
|
|
programmer expected. Note: this will work on the Linux console
|
|
just fine, but for other terminals the passed value must match
|
|
the termcap definition for the alternate character.
|
|
Note: The cursor returns to it's original position.
|
|
----------------------------------------------------------------}
|
|
Procedure nWriteAC(win : pwindow; x,y : integer; att,acs_char : longint);
|
|
var
|
|
xx,yy,
|
|
cp : longint;
|
|
Begin
|
|
If acs_char in [0..255] Then Begin
|
|
Case acs_char of
|
|
176 : acs_char := ACS_CKBOARD;
|
|
179 : acs_char := ACS_VLINE;
|
|
180 : acs_char := ACS_RTEE;
|
|
191 : acs_char := ACS_URCORNER;
|
|
192 : acs_char := ACS_LLCORNER;
|
|
193 : acs_char := ACS_BTEE;
|
|
194 : acs_char := ACS_TTEE;
|
|
195 : acs_char := ACS_LTEE;
|
|
196 : acs_char := ACS_HLINE;
|
|
197 : acs_char := ACS_PLUS;
|
|
218 : acs_char := ACS_ULCORNER;
|
|
217 : acs_char := ACS_LRCORNER;
|
|
241 : acs_char := ACS_PLMINUS;
|
|
248 : acs_char := ACS_DEGREE;
|
|
249 : acs_char := ACS_BULLET;
|
|
else acs_char := acs_char or A_ALTCHARSET;
|
|
End;
|
|
End;
|
|
{ save the current cursor position }
|
|
getyx(win,yy,xx);
|
|
cp := nSetColorPair(att);
|
|
{ write character with current attributes }
|
|
mvwaddch(win,y-1,x-1,acs_char);
|
|
{ update with new attributes }
|
|
If nIsBold(att) Then
|
|
att := A_BOLD or A_ALTCHARSET
|
|
Else
|
|
att := A_NORMAL or A_ALTCHARSET;
|
|
mvwchgat(win,y-1,x-1,1,att,cp,0);
|
|
{ return cursor to saved position }
|
|
wmove(win,yy,xx);
|
|
If doRefresh Then wrefresh(win);
|
|
End;
|
|
|
|
{-------------------------------------------------------------------
|
|
write a string to stdscr with color, without moving the cursor
|
|
|
|
Col = x start position
|
|
Row = y start position
|
|
Attrib = color (0..127), note color = (background*16)+foreground
|
|
Clear = clear line up to x position
|
|
s = string to write
|
|
-------------------------------------------------------------------}
|
|
Procedure nFWrite(win : pwindow; col,row,attrib : integer; clear : integer; s : string);
|
|
var
|
|
clr : array [0..255] of char;
|
|
cs : string;
|
|
sub : pWindow;
|
|
x,y,
|
|
mx,my,
|
|
xx,yy : longint;
|
|
ctrl : boolean;
|
|
Begin
|
|
if Clear > 0 Then Begin
|
|
FillChar(clr,SizeOf(clr),' ');
|
|
clr[SizeOf(clr)-1] := #0;
|
|
If Clear > MaxCols Then Clear := MaxCols;
|
|
cs := Copy(StrPas(clr),1,(Clear-Col)-Length(s)+1);
|
|
End Else
|
|
cs := '';
|
|
s := s+cs;
|
|
If s = '' Then Exit;
|
|
getyx(win,yy,xx);
|
|
getbegyx(win,y,x);
|
|
getmaxyx(win,my,mx);
|
|
If Length(s) > mx Then s := Copy(s,1,mx);
|
|
sub := subwin(win,1,Length(s),y+row-1,x+col-1);
|
|
If sub = nil Then Exit;
|
|
cs := s;
|
|
ctrl := false;
|
|
{ look for embedded control characters }
|
|
For x := 1 to Length(s) Do Begin
|
|
If s[x] in [#0..#31] Then Begin
|
|
s[x] := ' ';
|
|
ctrl := true;
|
|
End;
|
|
End;
|
|
wbkgd(sub,COLOR_PAIR(nSetColorPair(Attrib)));
|
|
If nisbold(Attrib) then
|
|
wattr_on(sub,A_BOLD);
|
|
mvwaddstr(sub,0,0,StrPCopy(ps,s));
|
|
{ highlight the embedded control characters substitutes }
|
|
If ctrl Then Begin
|
|
{ nEC is always the current edit control object }
|
|
If Attrib <> nEC.CtrlColor Then
|
|
nWinColor(sub,nEC.CtrlColor)
|
|
Else Begin
|
|
{ reverse the highlight color if same as current attribute }
|
|
bg := nEC.CtrlColor div 16;
|
|
fg := nEC.CtrlColor - (bg * 16);
|
|
While bg > 7 Do dec(bg,8);
|
|
While fg > 7 Do dec(fg,8);
|
|
nWinColor(sub,(fg*16)+bg);
|
|
End;
|
|
For x := 1 to Length(cs) Do Begin
|
|
If cs[x] in [#0..#31] Then
|
|
mvwaddch(sub,0,x-1,ord(cs[x])+64);
|
|
End;
|
|
End;
|
|
If doRefresh Then wrefresh(sub);
|
|
delwin(sub);
|
|
wmove(win,yy,xx);
|
|
End;
|
|
|
|
{ overload - no pointer }
|
|
Procedure nFWrite(col,row,attrib : integer; clear : integer; s : string);
|
|
Begin
|
|
nFWrite(ActiveWn,col,row,attrib,clear,s);
|
|
End;
|
|
|
|
{ compatibility for the old function name }
|
|
Function nSEdit(win : pwindow; x,y,att,z,CursPos:integer;
|
|
es:string;var ch : char) : string;
|
|
Var
|
|
s : string;
|
|
Begin
|
|
s := nEdit(win,x,y,att,z,CursPos,es,ch);
|
|
nSEdit := s;
|
|
End;
|
|
|
|
{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
|
{ String Editor }
|
|
Function nEdit(win : pwindow; { window to work in }
|
|
x,y, { base x,y coordinates of edit region }
|
|
att, { color attribute }
|
|
z, { right-most column of edit region }
|
|
CursPos:integer; { place cursor on this column at start }
|
|
es:string; { initial value of string }
|
|
var chv : integer { ordinal value of character typed, }
|
|
{ negative for extended keys }
|
|
) : string;
|
|
Var
|
|
ZMode,
|
|
AppendMode,
|
|
SEditExit : boolean;
|
|
prvx,
|
|
prvy,
|
|
pidx,
|
|
pres,
|
|
Index : integer;
|
|
ts,
|
|
hes : string;
|
|
isextended : boolean;
|
|
ch : char;
|
|
|
|
{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
|
Procedure NewString;
|
|
BEGIN
|
|
nEdit := es;
|
|
hes := es;
|
|
FillChar(hes[1],Length(hes),'*');
|
|
END;
|
|
|
|
Procedure WriteString;
|
|
Var
|
|
xx,yy : integer;
|
|
Begin
|
|
xx := nWhereX(win);
|
|
yy := nWhereY(win);
|
|
If nEC.IsHidden Then
|
|
nFWrite(win,x,y,att,z,hes)
|
|
Else
|
|
nFWrite(win,x,y,att,z,es);
|
|
nGotoXY(win,xx,yy);
|
|
End;
|
|
|
|
{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
|
Procedure EInsMode;
|
|
Begin
|
|
nEC.InsMode := (not nEC.InsMode)
|
|
End;
|
|
|
|
{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
|
Procedure WriteChar;
|
|
var s : string;
|
|
Begin
|
|
ts := es;
|
|
If AppendMode Then Begin
|
|
es := es + ' ';
|
|
Index := Length(es);
|
|
End Else Begin
|
|
If nWhereX(win) >= Length(es)+x Then Repeat
|
|
es := es + ' ';
|
|
Until Length(es)+x-1 = nWhereX(win);
|
|
If es = '' Then es := ' ';
|
|
If Length(es)+x-1 = nWhereX(win) Then Index := Length(es);
|
|
End;
|
|
es[Index] := ch;
|
|
s := Copy(es,1,Index);
|
|
If nCheckPxPicture(s,nEC.Picture,pidx) <> 0 Then Begin
|
|
{ no error, picture satisfied }
|
|
If (Length(s) > Length(es)) or
|
|
((Length(s) = Length(es)) and (s <> es)) Then Begin
|
|
{ expanded/changed by picture }
|
|
es := s;
|
|
End;
|
|
If pidx > Index Then Begin
|
|
If pidx > Length(es) Then pidx := Length(es);
|
|
If pidx > Index Then Index := pidx;
|
|
End;
|
|
End Else Begin
|
|
{ error, did not fit the picture }
|
|
Sound(1000);
|
|
Delay(50);
|
|
NoSound;
|
|
es := ts;
|
|
Dec(Index);
|
|
End;
|
|
NewString;
|
|
WriteString;
|
|
If (Index < z-x+1) or not ZMode Then Begin
|
|
Index := Index+1;
|
|
nGotoXY(win,x+Index-1,y);
|
|
End;
|
|
End;
|
|
|
|
{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
|
Procedure EInsert; { Insert }
|
|
Begin
|
|
If Length(es) < Z-X+1 Then Begin
|
|
ts := es;
|
|
Insert(' ',es,Index);
|
|
If nCheckPXPicture(es,nEC.Picture,pidx) = 0 Then Begin
|
|
Sound(1000);
|
|
Delay(50);
|
|
NoSound;
|
|
es := ts;
|
|
ch := #255;
|
|
End;
|
|
NewString;
|
|
WriteString;
|
|
End;
|
|
End;
|
|
|
|
{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
|
Procedure EDelete; { Delete }
|
|
Begin
|
|
ts := es;
|
|
Delete(es,Index,1);
|
|
If nCheckPXPicture(es,nEC.Picture,pidx) = 0 Then Begin
|
|
Sound(1000);
|
|
Delay(50);
|
|
NoSound;
|
|
es := ts;
|
|
ch := #255;
|
|
End;
|
|
NewString;
|
|
WriteString;
|
|
End;
|
|
|
|
{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
|
Procedure ECtrlEnd; { <CTRL> End }
|
|
Begin
|
|
Delete(es,Index,Length(es));
|
|
NewString;
|
|
WriteString;
|
|
End;
|
|
|
|
{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
|
Procedure EHome; { Home }
|
|
Begin
|
|
Index := 1;
|
|
nGotoXY(win,x,y);
|
|
End;
|
|
|
|
{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
|
Procedure ELeftArrow; { Left Arrow }
|
|
Begin
|
|
If nWhereX(win) > x Then Begin
|
|
dec(Index);
|
|
nGotoXY(win,nWhereX(win)-1,nWhereY(win));
|
|
End;
|
|
End;
|
|
|
|
{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
|
Procedure ERightArrow; { Right Arrow }
|
|
Begin
|
|
If Index < z-x+1 Then Begin
|
|
nGotoXY(win,nWhereX(win)+1,nWhereY(win));
|
|
Index := Index + 1;
|
|
End;
|
|
End;
|
|
|
|
{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
|
Procedure EEnd; { End }
|
|
Begin
|
|
Index := Length(es)+1;
|
|
If Index > z-x+1 Then Index := Length(es);
|
|
If Index < 1 Then Index := 1;
|
|
If Index > MaxCols Then Index := MaxCols;
|
|
nGotoXY(win,x+(Index-1),y);
|
|
End;
|
|
|
|
{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
|
Procedure EBackSpace; { Backspace }
|
|
Begin
|
|
Index := Index - 1;
|
|
If Index < 1 Then Begin
|
|
Index := 1;
|
|
Exit;
|
|
End Else
|
|
If nWhereX(win) > x Then nGotoXY(win,nWhereX(win) - 1,nWhereY(win));
|
|
Delete(es,Index,1);
|
|
NewString;
|
|
WriteString;
|
|
nGotoXY(win,x+(Index-1),y);
|
|
End;
|
|
|
|
{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
|
Procedure ETurboBackSpace; { Ctrl/Backspace }
|
|
Begin
|
|
If Index = 1 Then Exit;
|
|
Delete(es,1,Index-1);
|
|
NewString;
|
|
Index := 1;
|
|
If nWhereX(win) > x Then nGotoXY(win,1,nWhereY(win));
|
|
WriteString;
|
|
nGotoXY(win,x,y);
|
|
END;
|
|
|
|
{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
|
Procedure ECtrlLeftArrow;{ Ctrl Left Arrow }
|
|
Begin
|
|
If nEC.IsHidden Then Begin
|
|
EHome;
|
|
Exit;
|
|
End;
|
|
If es[Index-1] = ' ' Then Index := Index-1;
|
|
If es[Index] <> ' ' Then Begin
|
|
While (Index > 1) And (es[Index] <> ' ') Do
|
|
Index := Index-1;
|
|
End Else
|
|
If es[Index] = ' ' Then Begin
|
|
While (Index > 1) And (es[Index] = ' ') Do
|
|
Index := Index-1;
|
|
While (Index > 1) And (es[Index] <> ' ') Do
|
|
Index := Index-1;
|
|
End;
|
|
If Index = 1 Then
|
|
nGotoXY(win,x,y)
|
|
Else Begin
|
|
nGotoXY(win,x+Index,y);
|
|
Index := Index+1;
|
|
End;
|
|
End;
|
|
|
|
{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
|
Procedure ECtrlRightArrow;{ Ctrl Right Arrow }
|
|
Begin
|
|
If nEC.IsHidden Then Begin
|
|
EEnd;
|
|
Exit;
|
|
End;
|
|
While (Index < Length(es)) And (es[Index] <> ' ') Do
|
|
Begin
|
|
Index := Index+1;
|
|
End;
|
|
While (Index < Length(es)) And (es[Index] = ' ') Do
|
|
Begin
|
|
Index := Index+1;
|
|
End;
|
|
nGotoXY(win,x+Index-1,y);
|
|
End;
|
|
|
|
{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
|
Procedure CheckForWriteChar(embed : boolean);
|
|
Begin
|
|
If embed or Not (Ch In [#27,#255]) Then Begin
|
|
If (ch in [#10,#13]) and (not embed) {and not ControlKey} Then exit;
|
|
If nEC.ClearMode Then Begin
|
|
es := '';
|
|
WriteString;
|
|
nGotoXY(win,X,Y);
|
|
Index := 1;
|
|
WriteChar;
|
|
nEC.ClearMode := False;
|
|
End Else Begin
|
|
If nEC.InsMode Then Begin
|
|
EInsert;
|
|
WriteChar;
|
|
End Else WriteChar;
|
|
End;
|
|
End;
|
|
End;
|
|
|
|
{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
|
Procedure ProcessSpecialKey;
|
|
begin
|
|
If ch = #129 Then ch := #68; { Linux, map Esc/0 to F10 }
|
|
chv := ord(ch) * (-1); { set the return value }
|
|
|
|
Case ch of
|
|
#16..#25,
|
|
#30..#38,
|
|
#44..#50,
|
|
#59..#68,
|
|
#84..#90,
|
|
#92..#113,
|
|
#118,
|
|
#132,
|
|
#72,
|
|
#73,
|
|
#80,
|
|
#81 : Begin SEditExit:=True;Exit;End;
|
|
#71 : EHome;
|
|
#75 : ELeftArrow;
|
|
#77 : ERightArrow;
|
|
#79 : EEnd;
|
|
#82 : EInsMode;
|
|
#83 : EDelete;
|
|
#15,
|
|
#115 : ECtrlLeftArrow;
|
|
#116 : ECtrlRightArrow;
|
|
#117 : ECtrlEnd;
|
|
End;
|
|
End;
|
|
|
|
{~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
|
Procedure ProcessNormalKey;
|
|
Var
|
|
i : integer;
|
|
ctrl : boolean;
|
|
begin
|
|
chv := ord(ch); { set the return value }
|
|
For i := 1 to Length(nEC.Special) Do Begin
|
|
If ch = nEC.Special[i] Then Begin
|
|
SEditExit:=True;
|
|
Exit;
|
|
End;
|
|
End;
|
|
ctrl := false;
|
|
{ standard control key assignments }
|
|
case ch of
|
|
#0..#15,
|
|
#17..#31 : Begin
|
|
nEC.ClearMode := False;
|
|
Case ch of
|
|
#1 : EHome;
|
|
#5 : EEnd;
|
|
#2 : ELeftArrow;
|
|
#6 : ERightArrow;
|
|
#19 : ECtrlLeftArrow;
|
|
#4 : ECtrlRightArrow;
|
|
#7 : EDelete;
|
|
#9 : EInsMode;
|
|
#8 : EBackSpace;
|
|
#10 : ch := #13;
|
|
#13 : Begin
|
|
pres := nCheckPxPicture(es,nEC.Picture,pidx);
|
|
If pres <> 2 Then Begin
|
|
Sound(1000);
|
|
Delay(50);
|
|
NoSound;
|
|
ch := #255;
|
|
End;
|
|
End;
|
|
#27 : If KeyPressed Then Begin
|
|
{ covers up a Linux peculiarity where the next }
|
|
{ character typed bleeds through with esc/1..9 }
|
|
nGotoXY(win,prvx,prvy);
|
|
WriteString;
|
|
ch := ReadKey;
|
|
{ make it a function key }
|
|
If ch in ['1'..'9'] Then Begin
|
|
ch := Char(Ord(ch)+10);
|
|
chv := ord(ch) * (-1);
|
|
End Else ch := #27;
|
|
SEditExit := true;
|
|
End;
|
|
End;
|
|
Exit;
|
|
End;
|
|
#16 : Begin
|
|
{ embed control characters in the string }
|
|
ch := UpCase(ReadKey);
|
|
If ch in ['@','2','A'..'Z'] Then Begin
|
|
ctrl := true;
|
|
If ch = '2' Then ch := '@';
|
|
ch := Char(Ord(ch)-64);
|
|
chv := ord(ch);
|
|
End;
|
|
End;
|
|
#127 : Begin nEC.ClearMode := False;ETurboBackSpace;Exit;End;
|
|
end;
|
|
CheckForWriteChar(ctrl);
|
|
ch := #0;
|
|
end;
|
|
|
|
{-----------------------------------------------------------------------
|
|
Map a keystroke to another character, normal or extended.
|
|
|
|
The maps are 4 character strings interpreted as 2 sets of character
|
|
pairs that represent the following:
|
|
|
|
1st char - If it is #0 then it is an extended char. Use the 2nd
|
|
character to identify.
|
|
2nd char - Only used if 1st char is #0.
|
|
|
|
The first pair of the string is the actual key pressed.
|
|
The second pair is what that key should be become.
|
|
|
|
#0#59 = F1, extended key
|
|
#59#0 = ; , normal key
|
|
|
|
So a map of #0#59#59#0 maps the F1 key to the ; key,
|
|
and #0#59#0#60 maps the F1 key to the F2 key,
|
|
and #0#59#0#0 maps the F1 key to a null.
|
|
|
|
Examples:
|
|
#0#59#0#60 = map F1 to F2
|
|
#1#0#0#59 = map ^A to F1
|
|
#0#59#1#0 = map F1 to ^A
|
|
#0#59#0#0 = map F1 to ^@ (null)
|
|
#0#0#0#59 = map ^@ to F1
|
|
#97#0#65#0 = map a to A
|
|
}
|
|
Procedure MapKey(var ch : char;var eflag : boolean);
|
|
Var
|
|
i,
|
|
cv : integer;
|
|
s2 : string[2];
|
|
s4 : string[4];
|
|
Begin
|
|
cv := Ord(ch);
|
|
If eflag Then cv := cv * (-1);
|
|
i := 0;
|
|
{ look for a character map assignment }
|
|
Repeat
|
|
inc(i);
|
|
Until (i > nMaxChMaps) or (nEC.ChMap[i,1] = cv);
|
|
{ if found, then re-assign ch to the mapped key }
|
|
If i <= nMaxChMaps Then Begin
|
|
cv := nEC.ChMap[i,2];
|
|
eflag := (cv < 0);
|
|
ch := chr(abs(cv));
|
|
End;
|
|
(*
|
|
{ look for a character map assignment }
|
|
i := 0;
|
|
s4 := #0#0#0#0;
|
|
Case eflag of
|
|
true : s2 := #0+ch;
|
|
false : s2 := ch+#0;
|
|
End;
|
|
Repeat
|
|
inc(i);
|
|
Until (i > nMaxChMaps) or (pos(s2,nEC.ChMap[i]) = 1);
|
|
{ if found, then re-assign ch to the mapped key }
|
|
If i <= nMaxChMaps Then Begin
|
|
system.Move(nEC.ChMap[i,1],s4[1],Length(nEC.ChMap[i]));
|
|
s2 := Copy(s4,3,2);
|
|
eflag := (s2[1] = #0);
|
|
Case eflag of
|
|
true : ch := s2[2];
|
|
false : ch := s2[1];
|
|
End;
|
|
If ch = #0 Then eflag := false;
|
|
End;
|
|
*)
|
|
End;
|
|
|
|
{============================================================================}
|
|
Begin
|
|
SEditExit := nEC.ExitMode;
|
|
AppendMode := nEC.AppendMode;
|
|
ZMode := z <> 0;
|
|
If CursPos > Length(es)+x Then
|
|
Index := Length(es)+1 { End Of String }
|
|
Else Index := CursPos+1-x; { Inside Of String }
|
|
If Not ZMode then z := x+length(es);
|
|
Newstring;
|
|
WriteString;
|
|
nGotoXY(win,CursPos,y);
|
|
Repeat
|
|
prvx := nWhereX(win); { save for ProcessNormalKey }
|
|
prvy := nWhereY(win);
|
|
If Not ZMode then z := x+length(es);
|
|
ch := ReadKey;
|
|
isextended := (ch = #0);
|
|
If isextended Then
|
|
ch := ReadKey;
|
|
MapKey(ch,isextended);
|
|
If isextended Then
|
|
ProcessSpecialKey
|
|
Else
|
|
ProcessNormalKey;
|
|
Until (ch In [#13,#27]) or SEditExit;
|
|
nEC.ClearMode := False;
|
|
NewString;
|
|
End;{ of nEdit }
|
|
|
|
{ compatibility for old ch type }
|
|
Function nEdit(win : pwindow; x,y,att,z,CursPos:integer;
|
|
es:string;var ch : char) : string;
|
|
Var i : integer;
|
|
Begin
|
|
nEdit := nEdit(win,x,y,att,z,CursPos,es,i);
|
|
ch := chr(abs(i));
|
|
End;
|
|
|
|
{ nEdit using currently active window }
|
|
Function nEdit(x,y,att,z,CursPos:integer;
|
|
es:string;var ch : integer) : string;
|
|
Begin
|
|
nEdit := nEdit(ActiveWn,x,y,att,z,CursPos,es,ch);
|
|
End;
|
|
|
|
Function nEdit(x,y,att,z,CursPos:integer;
|
|
es:string;var ch : char) : string;
|
|
Var i : integer;
|
|
Begin
|
|
nEdit := nEdit(ActiveWn,x,y,att,z,CursPos,es,i);
|
|
ch := chr(ord(i));
|
|
End;
|
|
|
|
{ overload for longint type }
|
|
Function nEdit(x,y,att,z,CursPos:integer;
|
|
es:longint;var ch : integer) : longint;
|
|
Begin
|
|
nEdit := nEdit(ActiveWn,x,y,att,z,CursPos,es,ch);
|
|
End;
|
|
|
|
Function nEdit(x,y,att,z,CursPos:integer;
|
|
es:longint;var ch : char) : longint;
|
|
Begin
|
|
nEdit := nEdit(ActiveWn,x,y,att,z,CursPos,es,ch);
|
|
End;
|
|
|
|
{ longint with pointer }
|
|
Function nEdit(win : pwindow; x,y,att,z,CursPos:integer;
|
|
es:LongInt;var ch : integer) : LongInt;
|
|
Var
|
|
savpic,
|
|
ess : string;
|
|
esv,
|
|
err : longint;
|
|
Begin
|
|
Str(es:0,ess);
|
|
savpic := nEC.Picture;
|
|
If savpic = '' Then nEC.Picture := '[-]#*#';
|
|
ess := nEdit(win,x,y,att,z,CursPos,ess,ch);
|
|
nEC.Picture := savpic;
|
|
val(ess,esv,err);
|
|
nEdit := esv;
|
|
End;
|
|
|
|
Function nEdit(win : pwindow; x,y,att,z,CursPos:integer;
|
|
es:longint;var ch : char) : longint;
|
|
Var i : integer;
|
|
Begin
|
|
nEdit := nEdit(win,x,y,att,z,CursPos,es,i);
|
|
ch := chr(abs(i));
|
|
End;
|
|
|
|
{ overload for real type }
|
|
Function nEdit(x,y,att,z,CursPos:integer;
|
|
es:real;var ch : integer) : real;
|
|
Begin
|
|
nEdit := nEdit(ActiveWn,x,y,att,z,CursPos,es,ch);
|
|
End;
|
|
|
|
Function nEdit(x,y,att,z,CursPos:integer;
|
|
es:real;var ch : char) : real;
|
|
Var i : integer;
|
|
Begin
|
|
nEdit := nEdit(ActiveWn,x,y,att,z,CursPos,es,i);
|
|
ch := chr(abs(i));
|
|
End;
|
|
|
|
{ with pointer }
|
|
Function nEdit(win : pwindow; x,y,att,z,CursPos:integer;
|
|
es:Real;var ch : integer) : Real;
|
|
Var
|
|
savpic,
|
|
ess : string;
|
|
esv : real;
|
|
i,
|
|
err : Integer;
|
|
Begin
|
|
Str(es:0:12,ess);
|
|
While ess[Length(ess)] = '0' Do Delete(ess,Length(ess),1);
|
|
savpic := nEC.Picture;
|
|
If savpic = '' Then Begin
|
|
Case nDecFmt of
|
|
nUS : nEC.Picture := '[+,-]#*#[[.*#][{E,e}[+,-]#[#][#][#]]]';
|
|
nEURO : Begin
|
|
nEC.Picture := '[+,-]#*#[[;,*#][{E,e}[+,-]#[#][#][#]]]';
|
|
For i := 1 to Length(ess) Do
|
|
If ess[i] = '.' Then ess[i] := ',';
|
|
End;
|
|
End;
|
|
End;
|
|
ess := nEdit(win,x,y,att,z,CursPos,ess,ch);
|
|
nEC.Picture := savpic;
|
|
For i := 1 to Length(ess) Do If ess[i] = ',' Then ess[i] := '.';
|
|
val(ess,esv,err);
|
|
nEdit := esv;
|
|
End;
|
|
|
|
Function nEdit(win : pwindow; x,y,att,z,CursPos:integer;
|
|
es:real;var ch : char) : real;
|
|
Var i : integer;
|
|
Begin
|
|
nEdit := nEdit(win,x,y,att,z,CursPos,es,i);
|
|
ch := chr(abs(i));
|
|
End;
|
|
|
|
{ And now some sugar for Rainer Hantsch! }
|
|
{------------------------------------------------------------------------
|
|
This is a right justified number editor. As a digit is typed, the
|
|
existing number string gets pushed left and the new digit is appended.
|
|
If decimal columns are specified, then pressing <space> will enter the
|
|
decimal character (. or ,). A background string can be specified that
|
|
fills the empty spaces.
|
|
------------------------------------------------------------------------}
|
|
Function nEditNumber(
|
|
win : pwindow;
|
|
x, { edit field start column }
|
|
y, { edit field start row }
|
|
att, { edit field color attribute }
|
|
wid, { edit field width }
|
|
decm : integer; { number of decimal columns }
|
|
bgd : string; { background string -
|
|
if bgd = '', then no background
|
|
if bgd = a single character, then is used as the
|
|
background fill character.
|
|
if bgd length is longer than wid, then the entire
|
|
bgd string is used as the background.}
|
|
initv, { initial value }
|
|
minv, { range minimum value }
|
|
maxv : real; { range maximum value }
|
|
var esc : boolean { if Esc key pressed = true, else = false }
|
|
) : real;
|
|
|
|
Const
|
|
{ up to 12 decimal places }
|
|
decs : string = '[#][#][#][#][#][#][#][#][#][#][#][#]';
|
|
Var
|
|
r : real;
|
|
s,s1,s2 : string;
|
|
i,
|
|
e,
|
|
bc,
|
|
bx : integer;
|
|
ch : char;
|
|
fill : array [0..255] of char;
|
|
tmp_ec : tnEC;
|
|
Begin
|
|
tmp_ec := nEC;
|
|
nEC.ExitMode := true;
|
|
nEC.AppendMode := true;
|
|
nEC.ClrChMap(0);
|
|
nEC.AddChMap(#7#0#0+Char(nKeyDel));
|
|
nEC.AddChMap(#8#0#0+Char(nKeyDel));
|
|
If decm > (Length(decs) div 3) Then
|
|
decm := (Length(decs) div 3);
|
|
If decm >= wid Then decm := (wid - 1);
|
|
If decm > 0 Then Begin
|
|
nEC.Picture := '[-]*#[{.}'+Copy(decs,1,(decm*3))+']';
|
|
If nDecFmt = nEURO Then Begin
|
|
nEC.Picture[8] := ',';
|
|
Insert(';',nEC.Picture,8);
|
|
nEC.AddChMap('.'+#0+','+#0);
|
|
End;
|
|
End Else
|
|
nEC.Picture := '[-]*#';
|
|
If bgd = '' Then Begin
|
|
bgd := ' ';
|
|
bc := att;
|
|
End Else
|
|
bc := nEC.CtrlColor;
|
|
If Length(bgd) < wid Then Begin
|
|
FillChar(fill,wid,bgd[1]);
|
|
fill[wid] := #0;
|
|
bgd := StrPas(fill);
|
|
End;
|
|
bx := x;
|
|
If Length(bgd) > wid Then inc(x);
|
|
str(initv:wid:decm,s);
|
|
While s[1] = ' ' Do Delete(s,1,1);
|
|
If Pos('.',s) <> 0 Then
|
|
While s[Length(s)] = '0' Do Delete(s,Length(s),1);
|
|
If decm = 0 Then Delete(s,Pos('.',s),1);
|
|
If nDecFmt = nEURO Then For i := 1 to Length(s) Do
|
|
If s[i] = '.' Then s[i] := ',';
|
|
Repeat
|
|
nFWrite(win,bx,y,bc,bx+Length(bgd)-(x-bx),copy(bgd,1,wid-length(s)+(x-bx)));
|
|
If x > bx Then
|
|
nFWrite(win,x+wid,y,bc,0,copy(bgd,wid+2,length(bgd)));
|
|
s1 := nEdit(win,x+wid-Length(s),y,att,x+wid-1,x+wid-1,s,ch);
|
|
s2 := s1;
|
|
If nDecFmt = nEURO Then For i := 1 to Length(s2) Do
|
|
If s2[i] = ',' Then s2[i] := '.';
|
|
val(s2,r,e);
|
|
If (s1 = '') or ((e = 0) and (r >= minv) and (r <= maxv)) Then
|
|
s := s1
|
|
Else
|
|
If ch <> #27 then Begin
|
|
ch := #0;
|
|
Sound(1000);
|
|
Delay(50);
|
|
NoSound;
|
|
End;
|
|
nEC.AppendMode := Length(s) < wid;
|
|
Until ch in [#13,#27];
|
|
esc := (ch = #27);
|
|
nEditNumber := r;
|
|
nEC := tmp_ec;
|
|
End;
|
|
|
|
{ overload - real, no pointer }
|
|
Function nEditNumber(
|
|
x,y,att,wid,decm : integer;
|
|
bgd : string;
|
|
initv,
|
|
minv,
|
|
maxv : real;
|
|
var esc : boolean) : real;
|
|
Begin
|
|
nEditNumber := nEditNumber(ActiveWn,x,y,att,wid,decm,bgd,initv,minv,maxv,esc);
|
|
End;
|
|
|
|
{ overload for longint }
|
|
Function nEditNumber(
|
|
win : pwindow;
|
|
x,y,att,wid,decm : integer;
|
|
bgd : string;
|
|
initv,
|
|
minv,
|
|
maxv : longint;
|
|
var esc : boolean) : longint;
|
|
Var
|
|
r : real;
|
|
Begin
|
|
r := nEditNumber(win,x,y,att,wid,0,bgd,Real(initv),Real(minv),Real(maxv),esc);
|
|
nEditNumber := Trunc(r);
|
|
End;
|
|
|
|
{ overload - longint, no pointer }
|
|
Function nEditNumber(
|
|
x,y,att,wid,decm : integer;
|
|
bgd : string;
|
|
initv,
|
|
minv,
|
|
maxv : longint;
|
|
var esc : boolean) : longint;
|
|
Var
|
|
r : real;
|
|
Begin
|
|
r := nEditNumber(ActiveWn,x,y,att,wid,0,bgd,Real(initv),Real(minv),Real(maxv),esc);
|
|
nEditNumber := Trunc(r);
|
|
End;
|
|
|
|
{ More sugar for Rainer }
|
|
{------------------------------------------------------------------------
|
|
A date string editor.
|
|
------------------------------------------------------------------------}
|
|
Function nEditDate(
|
|
win : pwindow;
|
|
x, { edit field start column }
|
|
y, { edit field start row }
|
|
att : integer; { edit field color attribute }
|
|
initv : string; { initial value }
|
|
var esc : boolean { if Esc key pressed = true, else = false }
|
|
) : string;
|
|
|
|
Var
|
|
s : string;
|
|
i : integer;
|
|
ch : char;
|
|
tmp_ec : tnEC;
|
|
|
|
Begin
|
|
tmp_ec := nEC;
|
|
nEC.InsMode := false;
|
|
nEC.ClearMode := false;
|
|
nEC.ExitMode := false;
|
|
nEC.AppendMode := false;
|
|
Case nDecFmt of
|
|
nUS : Begin
|
|
nEC.Picture := '{#,m,M}{#,m,M}/{#,d,D}{#,d,D}/{#,y,Y}{#,y,Y}{#,y,Y}{#,y,Y}';
|
|
s := 'mm/dd/yyyy';
|
|
End;
|
|
nEURO : Begin
|
|
nEC.Picture := '{#,d,D}{#,d,D}/{#,m,M}{#,m,M}/{#,y,Y}{#,y,Y}{#,y,Y}{#,y,Y}';
|
|
s := 'dd/mm/yyyy';
|
|
End;
|
|
End;
|
|
If nCheckPxPicture(initv,nEC.Picture,i) <> 0 Then
|
|
system.move(initv[1],s[1],Length(initv));
|
|
nEC.AddChMap(#7#0#0+Char(nKeyLeft));
|
|
nEC.AddChMap(#8#0#0+Char(nKeyLeft));
|
|
nEC.AddChMap(#0+Char(nKeyDel)+#0+Char(nKeyLeft));
|
|
Repeat
|
|
s := nEdit(win,x,y,att,x+9,x,s,ch);
|
|
If ch = #13 Then Begin
|
|
For i := 1 to Length(s) Do
|
|
If s[i] in ['m','d','y'] Then ch := #0;
|
|
End;
|
|
Until ch in [#13,#27];
|
|
esc := (ch = #27);
|
|
nEditDate := s;
|
|
nEC := tmp_ec;
|
|
End;
|
|
|
|
{ overload - no pointer }
|
|
Function nEditDate(x,y,att : integer;initv : string;var esc : boolean) : string;
|
|
Begin
|
|
nEditDate := nEditDate(ActiveWn,x,y,att,initv,esc);
|
|
End;
|
|
|
|
{ A one-line procedural wrapper }
|
|
Procedure nMakeWindow(
|
|
var win : tnWindow;
|
|
x1,y1,
|
|
x2,y2,
|
|
ta,ba,ha : integer;
|
|
hasframe : boolean;
|
|
hdrpos : tnJustify;
|
|
hdrtxt : string);
|
|
Begin
|
|
win.init(x1,y1,x2,y2,ta,hasframe,ba);
|
|
If hdrtxt <> '' Then win.PutHeader(hdrtxt,ha,hdrpos);
|
|
End;
|
|
|
|
{ And with a window pointer }
|
|
Procedure nMakeWindow(
|
|
var win : pnWindow;
|
|
x1,y1,
|
|
x2,y2,
|
|
ta,ba,ha : integer;
|
|
hasframe : boolean;
|
|
hdrpos : tnJustify;
|
|
hdrtxt : string);
|
|
Begin
|
|
New(win,init(x1,y1,x2,y2,ta,hasframe,ba));
|
|
If hdrtxt <> '' Then win^.PutHeader(hdrtxt,ha,hdrpos);
|
|
End;
|
|
|
|
{--------------------------------------------------------------------
|
|
Display a message in a centered and framed box. With ack set to
|
|
false, the window remains active for further use in the program.
|
|
|
|
Inputs:
|
|
msg = message to display
|
|
matt = message color
|
|
hdr = header text at frame top
|
|
hatt = header/frame color
|
|
ack = TRUE : display ftr text and wait for a keypress, then
|
|
remove the window.
|
|
FALSE: don't display ftr, don't wait for a keypress, and
|
|
don't remove the window.
|
|
Output:
|
|
a nil pointer if ack = true,
|
|
a pointer to the tnWindow object if ack = false
|
|
--------------------------------------------------------------------}
|
|
Function nShowMessage(msg : string;
|
|
matt : byte;
|
|
hdr : string;
|
|
hatt : byte;
|
|
ack : boolean) : pnWindow;
|
|
const
|
|
ftr = 'Press Any Key';
|
|
acklns : shortint = 0;
|
|
var
|
|
i,j,
|
|
cr,
|
|
wid,
|
|
maxwid,
|
|
lines : integer;
|
|
mwin : pnWindow;
|
|
Begin
|
|
wid := 0;
|
|
maxwid := Length(hdr);
|
|
If ack and (Length(ftr) > maxwid) Then
|
|
maxwid := Length(ftr);
|
|
lines := 1;
|
|
{ how many rows does this window need ? }
|
|
For i := 1 to Length(msg) Do Begin
|
|
inc(wid);
|
|
{ let's be consistant! }
|
|
If msg[i] = #13 Then msg[i] := #10;
|
|
{ either a forced line break or we need to word-wrap }
|
|
If (msg[i] = #10) or (wid >= (MaxCols-2)) Then Begin
|
|
inc(lines);
|
|
j := 0;
|
|
If not (msg[i] in [#10,#32]) Then Begin
|
|
{ we're in a word, so find the previous space (if any) }
|
|
Repeat
|
|
inc(j);
|
|
Until (j=wid) or ((i-j) <= 0) or (msg[i-j] = #32);
|
|
If ((i-j) > 0) and (msg[i-j] = #32) Then Begin
|
|
wid := wid-j;
|
|
msg[i-j] := #10 { force a line break }
|
|
End Else
|
|
j := 0;
|
|
End;
|
|
If wid > maxwid Then maxwid := wid;
|
|
wid := j; { either 0 or word-wrap remnent }
|
|
End;
|
|
End;
|
|
If wid > maxwid Then maxwid := wid;
|
|
If ack Then acklns := 1 else acklns := 0;
|
|
{ make the message window }
|
|
New(mwin,Init(1,1,maxwid+2,lines+acklns+2,matt,true,hatt));
|
|
With mwin^ Do Begin
|
|
PutHeader(hdr,hatt,center);
|
|
Align(center,center);
|
|
If lines = 1 Then
|
|
{ one-liners get centered }
|
|
Write(msg:Length(msg)+((maxwid-Length(msg)) div 2))
|
|
Else
|
|
Write(msg);
|
|
Show;
|
|
If ack Then Begin
|
|
cr := nCursor(cOff);
|
|
FWrite(((cols-Length(ftr)) div 2)+1,rows,matt,0,ftr);
|
|
{
|
|
The following line can be used in place of the line above to place the
|
|
footer text in the frame instead of with the message body. Make sure to
|
|
keep acklns=0.
|
|
|
|
nFWrite(win,((ncols(win)-Length(ftr)) div 2)+1,nrows(win),hatt,0,ftr);
|
|
}
|
|
Readkey;
|
|
While Keypressed Do Readkey;
|
|
Hide;
|
|
nCursor(cr);
|
|
End;
|
|
End;
|
|
If ack Then Begin
|
|
Dispose(mwin,Done);
|
|
mwin := nil;
|
|
End;
|
|
nShowMessage := mwin;
|
|
End;
|
|
|
|
{---------------------------------------
|
|
Read a character string from a window
|
|
win - window to extract info from.
|
|
x - starting column.
|
|
y - starting row.
|
|
n - number of characters to read.
|
|
---------------------------------------}
|
|
Function nReadScr(win : pWindow; x,y,n : integer) : string;
|
|
Var
|
|
i,idx : integer;
|
|
s : string;
|
|
c : longint;
|
|
{ array of char/attr values, 4 bytes each, max 256 }
|
|
buf : array[0..1023] of char;
|
|
p : pchar;
|
|
Begin
|
|
s := '';
|
|
p := nReadScrStr(win,x,y,n,buf);
|
|
If p <> nil Then Begin
|
|
idx := 0;
|
|
For i := 1 to n Do Begin
|
|
system.move(buf[idx],c,SizeOf(c));
|
|
s := s + chr(c and A_CHARTEXT);
|
|
inc(idx,SizeOf(c));
|
|
End;
|
|
End;
|
|
nReadScr := s;
|
|
End;
|
|
|
|
{ overload for current window }
|
|
Function nReadScr(x,y,n : integer) : string;
|
|
Begin
|
|
nReadScr := nReadScr(ActiveWn,x,y,n);
|
|
End;
|
|
|
|
Function nReadScrStr(win : pWindow; x,y,n : integer; buf : pchtype) : pchtype;
|
|
Var
|
|
cx,cy : integer;
|
|
mx,my : longint;
|
|
Begin
|
|
cx := nWhereX(win);
|
|
cy := nWhereY(win);
|
|
If win <> nil Then Begin
|
|
getmaxyx(win,my,mx);
|
|
If (x in [1..mx]) and (y in [1..my]) Then Begin
|
|
{ n is contrained to the right margin, so no need to range check }
|
|
mvwinchnstr(win,y-1,x-1,buf,n);
|
|
nGotoXY(win,cx,cy);
|
|
End;
|
|
End;
|
|
nReadScrStr := buf;
|
|
End;
|
|
|
|
{ overload for current window }
|
|
Function nReadScrStr(x,y,n : integer; buf : pchtype) : pchtype;
|
|
Begin
|
|
nReadScrStr := nReadScrStr(ActiveWn,x,y,n,buf);
|
|
End;
|
|
|
|
Function nReadScrColor(win : pWindow; x,y : integer) : integer;
|
|
Var
|
|
cl,
|
|
fg,bg,
|
|
cx,cy : integer;
|
|
c,cv,
|
|
mx,my : longint;
|
|
Begin
|
|
cl := -1;
|
|
cx := nWhereX(win);
|
|
cy := nWhereY(win);
|
|
If win <> nil Then Begin
|
|
getmaxyx(win,my,mx);
|
|
If (x in [1..mx]) and (y in [1..my]) Then Begin
|
|
c := mvwinch(win,y-1,x-1);
|
|
nGotoXY(win,cx,cy);
|
|
cv := PAIR_NUMBER(c and A_COLOR);
|
|
pair_content(cv,@fg,@bg);
|
|
fg := c2ibm(fg);
|
|
bg := c2ibm(bg);
|
|
cv := (c and A_ATTRIBUTES);
|
|
If A_BOLD and cv = A_BOLD Then inc(fg,8);
|
|
cl := (bg*16)+fg;
|
|
End;
|
|
End;
|
|
nReadScrColor := cl;
|
|
End;
|
|
|
|
{ overload for current window }
|
|
Function nReadScrColor(x,y : integer) : integer;
|
|
Begin
|
|
nReadScrColor := nReadScrColor(ActiveWn,x,y);
|
|
End;
|
|
|
|
{ write a string with attributes, previously saved with nReadScrStr }
|
|
Procedure nWriteScrStr(win : pWindow; x,y : integer; s : pchtype);
|
|
Begin
|
|
mvwaddchstr(win,y-1,x-1,s);
|
|
If doRefresh Then wrefresh(win);
|
|
End;
|
|
|
|
{ overload for current window }
|
|
Procedure nWriteScrStr(x,y : integer; s : pchtype);
|
|
Begin
|
|
mvwaddchstr(ActiveWn,y-1,x-1,s);
|
|
If doRefresh Then wrefresh(ActiveWn);
|
|
End;
|
|
|
|
{---------------------------------------
|
|
save a rectangular portion of a window
|
|
x = start column
|
|
y = start row
|
|
c = number of columns
|
|
r = number of rows
|
|
---------------------------------------}
|
|
Procedure nGrabScreen(var p : pnScreenBuf; x,y,c,r : integer; win : pWindow);
|
|
Var
|
|
mx,my : longint;
|
|
i,
|
|
cx,cy : integer;
|
|
prb,trb : pnRowBuf;
|
|
Begin
|
|
nReleaseScreen(p);
|
|
getmaxyx(win,my,mx);
|
|
If not (x in [1..mx]) or Not (y in [1..my]) Then Begin
|
|
p := nil;
|
|
Exit;
|
|
End;
|
|
cx := nWhereX(win);
|
|
cy := nWhereY(win);
|
|
New(p);
|
|
p^.x := x;
|
|
p^.y := y;
|
|
p^.n := c;
|
|
p^.first := nil;
|
|
trb := nil;
|
|
For i := 0 to r-1 Do Begin
|
|
If (y+i in [1..my]) Then Begin
|
|
New(prb);
|
|
GetMem(prb^.row,c*SizeOf(chtype));
|
|
mvwinchnstr(win,y-1+i,x-1,prb^.row,c);
|
|
If trb <> nil Then trb^.Next := prb;
|
|
prb^.next := nil;
|
|
trb := prb;
|
|
If i = 0 Then p^.First := prb;
|
|
End;
|
|
End;
|
|
nGotoXY(win,cx,cy);
|
|
End;
|
|
|
|
{ overload for current window }
|
|
Procedure nGrabScreen(var p : pnScreenBuf; x,y,c,r : integer);
|
|
Begin
|
|
nGrabScreen(p,x,y,c,r,ActiveWn);
|
|
End;
|
|
|
|
{ overload for current full window }
|
|
Procedure nGrabScreen(var p : pnScreenBuf);
|
|
Var
|
|
c,r : longint;
|
|
Begin
|
|
getmaxyx(ActiveWn,r,c);
|
|
nGrabScreen(p,1,1,c,r,ActiveWn);
|
|
End;
|
|
|
|
{-----------------------------------------
|
|
restore a window saved with nGrabScreen
|
|
p = pointer to the saved buffer
|
|
x = start restore to this column
|
|
y = start restore to this row
|
|
win = restore to this window
|
|
-----------------------------------------}
|
|
Procedure nPopScreen(p : pnScreenBuf; x,y : integer; win : pWindow);
|
|
Var
|
|
cx,cy : integer;
|
|
mx,my : longint;
|
|
pb : pnRowBuf;
|
|
Begin
|
|
If p = nil Then Exit;
|
|
getmaxyx(win,my,mx);
|
|
If Not (x in [1..mx]) or Not (y in [1..my]) Then Exit;
|
|
dec(x);
|
|
cx := nWhereX(win);
|
|
cy := nWhereY(win);
|
|
pb := p^.First;
|
|
While pb <> nil Do Begin
|
|
If (pb^.row <> nil) and (y in [1..my]) Then
|
|
mvwaddchnstr(win,y-1,x,pb^.row,p^.n);
|
|
inc(y);
|
|
pb := pb^.next;
|
|
End;
|
|
nGotoXY(win,cx,cy);
|
|
If doRefresh Then wrefresh(win);
|
|
End;
|
|
|
|
{ overload for current window, defined position }
|
|
Procedure nPopScreen(p : pnScreenBuf; x,y : integer);
|
|
Begin
|
|
nPopScreen(p,x,y,ActiveWn);
|
|
End;
|
|
|
|
{ overload for current window, saved position }
|
|
Procedure nPopScreen(p : pnScreenBuf);
|
|
Begin
|
|
If p = nil Then Exit;
|
|
nPopScreen(p,p^.x,p^.y,ActiveWn);
|
|
End;
|
|
|
|
{ free up the memory used to store a grabbed screen }
|
|
Procedure nReleaseScreen(p : pnScreenBuf);
|
|
Var
|
|
cur,tmp : pnRowBuf;
|
|
Begin
|
|
If p = nil Then Exit;
|
|
If p^.first <> nil Then Begin
|
|
cur := p^.first;
|
|
While cur <> nil Do Begin
|
|
tmp := cur^.next;
|
|
If cur^.row <> nil Then FreeMem(cur^.row,p^.n * SizeOf(chtype));
|
|
Dispose(cur);
|
|
cur := tmp;
|
|
End;
|
|
End;
|
|
Dispose(p);
|
|
End;
|
|
|
|
{============================== tnMenu ====================================}
|
|
|
|
{ A one-line procedural wrapper }
|
|
Procedure nMakeMenu(
|
|
var mnu : tnMenu;
|
|
x,y,
|
|
_w,_r,_c,
|
|
ta,ca,ga,ba,ha : integer;
|
|
hasframe : boolean;
|
|
hdrpos : tnJustify;
|
|
hdrtxt : string);
|
|
Begin
|
|
mnu.init(x,y,_w,_r,_c,ta,ca,ga,hasframe,ba);
|
|
If hdrtxt <> '' Then mnu.PutHeader(hdrtxt,ha,hdrpos);
|
|
End;
|
|
|
|
{ And with a menu pointer }
|
|
Procedure nMakeMenu(
|
|
var mnu : pnMenu;
|
|
x,y,
|
|
_w,_r,_c,
|
|
ta,ca,ga,ba,ha : integer;
|
|
hasframe : boolean;
|
|
hdrpos : tnJustify;
|
|
hdrtxt : string);
|
|
Begin
|
|
New(mnu,init(x,y,_w,_r,_c,ta,ca,ga,hasframe,ba));
|
|
If hdrtxt <> '' Then mnu^.PutHeader(hdrtxt,ha,hdrpos);
|
|
End;
|
|
|
|
Constructor tnMenu.Init(_x,_y,_w,_r,_c,_tc,_cc,_gc : integer;
|
|
_fr : boolean; _fc : integer);
|
|
Begin
|
|
x := _x;
|
|
y := _y;
|
|
wid := _w;
|
|
r := _r;
|
|
c := _c;
|
|
tc := _tc;
|
|
cc := _cc;
|
|
gc := _gc;
|
|
framed := _fr;
|
|
fc := _fc;
|
|
hc := fc;
|
|
iidx := 0;
|
|
mark := '';
|
|
posted := false;
|
|
If wid > MaxCols Then wid := MaxCols;
|
|
InitWin;
|
|
Spin(false);
|
|
End;
|
|
|
|
Destructor tnMenu.Done;
|
|
Begin
|
|
UnPost;
|
|
Clear;
|
|
Dispose(win,Done);
|
|
End;
|
|
|
|
Procedure tnMenu.InitWin;
|
|
Const
|
|
xhgt : shortint = 0;
|
|
Begin
|
|
If framed Then xhgt := 2 Else xhgt := 0;
|
|
New(win,Init(x,y,(x+wid-1),(y+r+xhgt-1),tc,framed,fc));
|
|
End;
|
|
|
|
Procedure tnMenu.Post;
|
|
Var
|
|
bx,by,
|
|
mx,my : longint;
|
|
p : pchar;
|
|
a : array[0..SizeOf(tnS10)-1] of char;
|
|
Begin
|
|
{ could already be posted }
|
|
UnPost;
|
|
{ see if the window size has changed (a new longer item added?) }
|
|
getmaxyx(win^.win,my,mx);
|
|
If (wid <> mx) Then Begin
|
|
getbegyx(win^.win,by,bx);
|
|
Dispose(win,Done);
|
|
x := bx+1;
|
|
y := by+1;
|
|
InitWin;
|
|
End;
|
|
{ create the new menu }
|
|
pm := new_menu(@pi);
|
|
{ only show item text }
|
|
menu_opts_off(pm,O_SHOWDESC);
|
|
{ bind the windows }
|
|
set_menu_win(pm,win^.win);
|
|
set_menu_sub(pm,win^.wn);
|
|
{ set the rows and columns }
|
|
set_menu_format(pm,r,c);
|
|
{ set the colors }
|
|
set_menu_fore(pm,CursesAtts(cc));
|
|
set_menu_back(pm,CursesAtts(tc));
|
|
set_menu_grey(pm,CursesAtts(gc));
|
|
p := StrPCopy(a,mark);
|
|
set_menu_mark(pm,p);
|
|
merr := post_menu(pm);
|
|
posted := (merr = E_OK);
|
|
Spin(loopon);
|
|
End;
|
|
|
|
Procedure tnMenu.UnPost;
|
|
Begin
|
|
merr := unpost_menu(pm);
|
|
merr := free_menu(pm);
|
|
pm := nil;
|
|
posted := false;
|
|
End;
|
|
|
|
Procedure tnMenu.Show;
|
|
Begin
|
|
If not posted Then Post;
|
|
win^.Show;
|
|
End;
|
|
|
|
{ Start user interaction loop }
|
|
Procedure tnMenu.Start;
|
|
Const
|
|
select = #13;
|
|
cancel = #27;
|
|
Var
|
|
key : char;
|
|
i,cnt,
|
|
prev,
|
|
savecurs,
|
|
xkey : integer;
|
|
direction : longint;
|
|
Begin
|
|
Show;
|
|
iidx := 0;
|
|
savecurs := nCursor(cOFF);
|
|
Repeat
|
|
prev := iidx;
|
|
win^.Show;
|
|
key := readkey;
|
|
xkey := 0;
|
|
case key of
|
|
#0 : xkey := ord(readkey);
|
|
^F : xkey := nKeyHome;
|
|
^L : xkey := nKeyEnd;
|
|
#9,
|
|
^N : xkey := nKeyDown;
|
|
^P : xkey := nKeyUp;
|
|
else menu_driver(pm,ord(key));
|
|
end;
|
|
case xkey of
|
|
nKeyHome : menu_driver(pm,REQ_FIRST_ITEM);
|
|
nKeyEnd : menu_driver(pm,REQ_LAST_ITEM);
|
|
nKeyRight,
|
|
nKeyDown : menu_driver(pm,REQ_NEXT_ITEM);
|
|
nKeyLeft,
|
|
nKeyUp : menu_driver(pm,REQ_PREV_ITEM);
|
|
end;
|
|
iidx := item_index(current_item(pm)) + 1;
|
|
If (not Selectable(iidx)) and (key <> cancel) Then Begin
|
|
cnt := Count;
|
|
If cnt > 1 Then Begin
|
|
{ temporarily enable spinning }
|
|
If not loopon Then
|
|
menu_opts_off(pm,O_NONCYCLIC);
|
|
{ which way to another item? }
|
|
If iidx > prev Then
|
|
direction := REQ_NEXT_ITEM
|
|
Else
|
|
direction := REQ_PREV_ITEM;
|
|
Repeat
|
|
menu_driver(pm,direction);
|
|
i := item_index(current_item(pm)) + 1;
|
|
Until Selectable(i) or (i = iidx);
|
|
{ reset spin }
|
|
Spin(loopon);
|
|
{ keep prev honest }
|
|
iidx := item_index(current_item(pm)) + 1;
|
|
End;
|
|
End;
|
|
Until key in [select,cancel];
|
|
menu_driver(pm,REQ_CLEAR_PATTERN);
|
|
If iidx = ERR Then merr := iidx;
|
|
If key = cancel Then iidx := 0;
|
|
nCursor(savecurs);
|
|
End;
|
|
|
|
Procedure tnMenu.Stop;
|
|
Begin
|
|
Hide;
|
|
UnPost;
|
|
End;
|
|
|
|
Procedure tnMenu.Hide;
|
|
Begin
|
|
win^.Hide;
|
|
End;
|
|
|
|
Function tnMenu.Wind : pnWindow;
|
|
Begin
|
|
Wind := win;
|
|
End;
|
|
|
|
Procedure tnMenu.Align(hpos,vpos : tnJustify);
|
|
Begin
|
|
win^.Align(hpos,vpos);
|
|
End;
|
|
|
|
Procedure tnMenu.Move(_x,_y : integer);
|
|
Begin
|
|
win^.Move(_x,_y);
|
|
End;
|
|
|
|
Procedure tnMenu.PutHeader(hdr : string; hcolor : integer; hpos : tnJustify);
|
|
Begin
|
|
win^.PutHeader(hdr,hcolor,hpos);
|
|
End;
|
|
|
|
Procedure tnMenu.Clear;
|
|
Var
|
|
i : integer;
|
|
Begin
|
|
UnPost;
|
|
For i := 1 to nMAXMENUITEMS Do ClearItem(i);
|
|
End;
|
|
|
|
{ is this menu item selectable }
|
|
Function tnMenu.Selectable(idx : integer) : boolean;
|
|
Begin
|
|
Selectable := IsAssigned(idx) and
|
|
((O_SELECTABLE and item_opts(pi[idx])) = O_SELECTABLE);
|
|
End;
|
|
|
|
Function tnMenu.IsValid(idx : integer) : boolean;
|
|
Begin
|
|
IsValid := ((idx >= 1) and (idx <= nMAXMENUITEMS));
|
|
End;
|
|
|
|
Function tnMenu.IsAssigned(idx : integer) : boolean;
|
|
Begin
|
|
IsAssigned := IsValid(idx) and (pi[idx] <> nil);
|
|
End;
|
|
|
|
Procedure tnMenu.ClearItem(idx : integer);
|
|
Begin
|
|
If IsValid(idx) Then Begin
|
|
If items[idx] <> nil Then Begin
|
|
merr := free_item(pi[idx]);
|
|
If merr = E_OK Then Begin
|
|
FreeMem(items[idx],StrLen(items[idx]^)+1);
|
|
pi[idx] := nil;
|
|
items[idx] := nil;
|
|
End;
|
|
End;
|
|
End Else merr := E_BAD_ARGUMENT;
|
|
End;
|
|
|
|
Procedure tnMenu.AddItem(i : integer; s : string);
|
|
Const
|
|
fwid : shortint = 0;
|
|
iwid : shortint = 1;
|
|
Var
|
|
rl : integer;
|
|
sp1,sp2,sp3 : plongint;
|
|
Begin
|
|
If IsValid(i) Then Begin
|
|
ClearItem(i);
|
|
GetMem(items[i],Length(s)+1);
|
|
StrPCopy(items[i]^,s);
|
|
pi[i] := new_item(pchar(items[i]),nil);
|
|
If pi[i] <> Nil Then Begin
|
|
merr := E_OK;
|
|
{ Expand the window width if necessary. Limit to screen width.
|
|
Add possibly 2 for the frame, the item indicator length, and
|
|
the item spacing value. }
|
|
If framed Then fwid := 2;
|
|
if c > 1 Then Begin
|
|
If posted Then Begin
|
|
{ need a valid pm }
|
|
menu_spacing(pm,sp1,sp2,sp3);
|
|
iwid := Length(GetMark) + sp3^;
|
|
End Else
|
|
iwid := Length(GetMark) + 1;
|
|
End Else
|
|
iwid := 0;
|
|
{ required length }
|
|
rl := ((Length(s)+iwid)*c)+fwid;
|
|
{ expand? }
|
|
If rl > wid Then wid := rl;
|
|
If wid > MaxCols Then wid := MaxCols;
|
|
End Else merr := E_REQUEST_DENIED;
|
|
End Else merr := E_BAD_ARGUMENT;
|
|
End;
|
|
|
|
Function tnMenu.Add(s : string) : integer;
|
|
Var
|
|
i : integer;
|
|
Begin
|
|
i := 0;
|
|
Add := 0;
|
|
Repeat
|
|
inc(i);
|
|
Until (i > nMAXMENUITEMS) or (items[i] = nil);
|
|
AddItem(i,s);
|
|
If merr = E_OK Then Add := i;
|
|
End;
|
|
|
|
Procedure tnMenu.Insert(idx : integer; s : string);
|
|
Begin
|
|
If IsValid(idx) Then Begin
|
|
ClearItem(nMAXMENUITEMS);
|
|
If idx < nMAXMENUITEMS Then Begin
|
|
{ shift the pointer list up and keep lists syncronized }
|
|
system.Move(pi[idx],pi[idx+1],SizeOf(pnMenuStr)*(nMAXMENUITEMS-idx));
|
|
system.Move(items[idx],items[idx+1],SizeOf(pItem)*(nMAXMENUITEMS-idx));
|
|
pi[idx] := nil;
|
|
items[idx] := nil;
|
|
End;
|
|
AddItem(idx,s);
|
|
End Else merr := E_BAD_ARGUMENT;
|
|
End;
|
|
|
|
Procedure tnMenu.Remove(idx : integer);
|
|
Begin
|
|
If IsValid(idx) Then Begin
|
|
ClearItem(idx);
|
|
{ shift the pointer list down and keep lists syncronized }
|
|
system.Move(pi[idx+1],pi[idx],SizeOf(pnMenuStr)*(nMAXMENUITEMS-idx));
|
|
system.Move(items[idx+1],items[idx],SizeOf(pItem)*(nMAXMENUITEMS-idx));
|
|
pi[nMAXMENUITEMS] := nil;
|
|
items[nMAXMENUITEMS] := nil;
|
|
End Else merr := E_BAD_ARGUMENT;
|
|
End;
|
|
|
|
Procedure tnMenu.Change(idx : integer; s : string);
|
|
Begin
|
|
AddItem(idx,s);
|
|
End;
|
|
|
|
{ toggle a menu item's selectability }
|
|
Procedure tnMenu.Active(idx : integer; b : boolean);
|
|
Begin
|
|
Case b of
|
|
true : item_opts_on(pi[idx],O_SELECTABLE);
|
|
false : item_opts_off(pi[idx],O_SELECTABLE);
|
|
End;
|
|
End;
|
|
|
|
{ is the item selectable? }
|
|
Function tnMenu.IsActive(idx : integer) : boolean;
|
|
Begin
|
|
IsActive := Selectable(idx);
|
|
End;
|
|
|
|
{ Toggle item looping. Moves to first/last when bottom/top is reached }
|
|
Procedure tnMenu.Spin(b : boolean);
|
|
Begin
|
|
loopon := b;
|
|
If posted Then
|
|
Case b of
|
|
true : menu_opts_off(pm,O_NONCYCLIC);
|
|
false : menu_opts_on(pm,O_NONCYCLIC);
|
|
End;
|
|
End;
|
|
|
|
{ return most recent error status }
|
|
Function tnMenu.Status : integer;
|
|
Begin
|
|
Status := merr;
|
|
End;
|
|
|
|
Function tnMenu.Index : integer;
|
|
Begin
|
|
Index := iidx;
|
|
End;
|
|
|
|
Procedure tnMenu.SetIndex(idx : integer);
|
|
Begin
|
|
If IsValid(idx) and IsAssigned(idx) and Selectable(idx) Then Begin
|
|
set_current_item(pm,pi[idx]);
|
|
iidx := idx;
|
|
End;
|
|
End;
|
|
|
|
Function tnMenu.Count : integer;
|
|
Begin
|
|
Count := item_count(pm);
|
|
End;
|
|
|
|
Function tnMenu.Rows(_r : integer) : integer;
|
|
Begin
|
|
Rows := r;
|
|
If _r > 0 Then r := _r;
|
|
End;
|
|
|
|
Function tnMenu.Cols(_c : integer) : integer;
|
|
Begin
|
|
Cols := c;
|
|
If _c > 0 Then c := _c;
|
|
End;
|
|
|
|
{ get the item indicator prefix string }
|
|
Function tnMenu.GetMark : string;
|
|
Begin
|
|
If posted Then
|
|
GetMark := StrPas(menu_mark(pm))
|
|
Else
|
|
GetMark := mark;
|
|
End;
|
|
|
|
{ set the item indicator prefix string }
|
|
Procedure tnMenu.SetMark(ms : string);
|
|
Begin
|
|
mark := ms;
|
|
End;
|
|
|
|
Procedure tnMenu.Refresh;
|
|
Begin
|
|
Post;
|
|
Show;
|
|
End;
|
|
|
|
Procedure tnMenu.SetColor(att : byte);
|
|
Begin
|
|
tc := att;
|
|
If posted Then set_menu_back(pm,CursesAtts(tc));
|
|
End;
|
|
|
|
Procedure tnMenu.SetCursorColor(att : byte);
|
|
Begin
|
|
cc := att;
|
|
If posted Then set_menu_fore(pm,CursesAtts(cc));
|
|
End;
|
|
|
|
Procedure tnMenu.SetFrameColor(att : byte);
|
|
Begin
|
|
fc := att;
|
|
If posted Then Wind^.PutFrame(att);
|
|
End;
|
|
|
|
Procedure tnMenu.SetGrayColor(att : byte);
|
|
Begin
|
|
gc := att;
|
|
If posted Then set_menu_grey(pm,CursesAtts(gc));
|
|
End;
|
|
|
|
{----------------------- initialize the unit!------------------------- }
|
|
Begin
|
|
FillChar(_chmap,SizeOf(_chmap),0);
|
|
nEC.Init(false,false,false,false,false,'','',15,_chmap);
|
|
{ load the color pairs array with color pair indices (0..63) }
|
|
For bg := 0 to 7 Do For fg := 0 to 7 do cp[bg,fg] := (bg*8)+fg;
|
|
{ initialize ncurses }
|
|
If StartCurses(ActiveWn) Then Begin
|
|
{ save pointer to ncurses stdscr }
|
|
nscreen := ActiveWn;
|
|
{ defaults, crtassign, etc. }
|
|
nInit;
|
|
{ create the default full screen, non-bordered window object }
|
|
nStdScr.Init(1,1,MaxCols,MaxRows,7,false,0);
|
|
{ default read/write to stdscr }
|
|
ActiveWn := nscreen;
|
|
End Else Begin
|
|
CursesFailed;
|
|
End;
|
|
End. { of Unit oCrt }
|
|
|
|
{
|
|
$Log$
|
|
Revision 1.8 2001-06-19 15:24:54 marco
|
|
* UNIX peter, UNIX, not LINUX!!!
|
|
|
|
Revision 1.7 2001/04/10 23:30:04 peter
|
|
* regenerated
|
|
|
|
Revision 1.6 2001/04/08 12:27:55 peter
|
|
* made it compilable with both 1.0.x and 1.1
|
|
|
|
Revision 1.5 2001/01/21 21:38:52 marco
|
|
* renamefest in packages
|
|
|
|
Revision 1.4 2000/08/29 05:51:09 michael
|
|
+ Merged changes and additions from fixbranch
|
|
Revision 1.3 2000/08/20 10:11:41 jonas
|
|
* added missing open comment at start of log section
|
|
|
|
Revision 1.2 2000/07/13 11:33:27 michael
|
|
+ removed logs
|
|
|
|
}
|