📄 qmenu.pas
字号:
{----------------------------------------------------------------------------}
{ }
{ File(s): qmenu.c + qmenu.h }
{ }
{ Initial conversion by : YgriK (Igor Karpov) - glYgriK@hotbox.ru }
{ Initial conversion on : 13-Feb-2002 }
{ }
{ This File contains part of convertion of Quake2 source to ObjectPascal. }
{ More information about this project can be found at: }
{ http://www.sulaco.co.za/quake2/ }
{ }
{ Copyright (C) 1997-2001 Id Software, Inc. }
{ }
{ This program is free software; you can redistribute it and/or }
{ modify it under the terms of the GNU General Public License }
{ as published by the Free Software Foundation; either version 2 }
{ of the License, or (at your option) any later version. }
{ }
{ This program is distributed in the hope that it will be useful, }
{ but WITHOUT ANY WARRANTY; without even the implied warranty of }
{ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. }
{ }
{ See the GNU General Public License for more details. }
{ }
{----------------------------------------------------------------------------}
{ Updated on : 04-jun-2002 }
{ Updated by : Juha Hartikainen }
{ - Made this real unit }
{ - Added qmenu.h stuff }
{ - Finished conversion }
{ Updated on : 25-jul-2002 }
{ Updated by : burnin (leonel@linuxbr.com.br) }
{ - Pointer renaming }
{ }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on: }
{ }
{----------------------------------------------------------------------------}
{ * TODO: }
{ 1) Implement Field_key Paste from clipboard functionality }
{ 2) Error checking }
{----------------------------------------------------------------------------}
unit Qmenu;
interface
uses q_shared;
const
MAXMENUITEMS = 64;
MTYPE_SLIDER = 0;
MTYPE_LIST = 1;
MTYPE_ACTION = 2;
MTYPE_SPINCONTROL = 3;
MTYPE_SEPARATOR = 4;
MTYPE_FIELD = 5;
K_TAB = 9;
K_ENTER = 13;
K_ESCAPE = 27;
K_SPACE = 32;
// normal keys should be passed as lowercased ascii
K_BACKSPACE = 127;
K_UPARROW = 128;
K_DOWNARROW = 129;
K_LEFTARROW = 130;
K_RIGHTARROW = 131;
QMF_LEFT_JUSTIFY = $00000001;
QMF_GRAYED = $00000002;
QMF_NUMBERSONLY = $00000004;
type
// TPCharArray = array[0..22222] of PChar;
// PPCharArray = ^TPCharArray;
menuframework_p = ^menuframework_s;
menuframework_s = record
x, y: Integer;
cursor: Integer;
nitems: Integer;
nslots: Integer;
items: array[0..64-1] of pointer;
statusbar: pchar;
cursordraw: procedure (menuframework: menuframework_p);
end;
menucommon_p= ^menucommon_s;
menucommon_s = record
type_ : integer;
name : pchar;
x, y : integer;
parent: menuframework_p;
cursor_offset: integer;
localdata: array [0..3] of integer;
flags: Cardinal;
statusbar: PChar;
callback: procedure (Self : Pointer);
statusbarfunc: procedure (Self : Pointer);
ownerdraw: procedure (Self : Pointer);
cursordraw: procedure (Self : Pointer);
end;
menufield_p = ^menufield_s;
menufield_s = record
generic: menucommon_s;
buffer: array[0..80-1] of char;
cursor: integer;
length: integer;
visible_length: integer;
visible_offset: integer;
end;
menuslider_p = ^menuslider_s;
menuslider_s = record
generic: menucommon_s;
minvalue: single;
maxvalue: single;
curvalue: single;
range: single;
end;
menulist_p = ^menulist_s;
menulist_s = record
generic: menucommon_s;
curvalue: integer;
itemnames: PPCharArray;
end;
menuaction_p = ^menuaction_s;
menuaction_s = record
generic: menucommon_s;
end;
menuseparator_p = ^menuseparator_s;
menuseparator_s = record
generic: menucommon_s;
end;
function Field_Key(f: menufield_p; key: integer ): qboolean;
procedure Menu_AddItem( menu: menuframework_p; item: pointer );
procedure Menu_AdjustCursor( menu: menuframework_p; dir: integer );
procedure Menu_Center( menu: menuframework_p );
procedure Menu_Draw( menu: menuframework_p );
function Menu_ItemAtCursor( m: menuframework_p ): pointer;
function Menu_SelectItem( s: menuframework_p ): qboolean;
procedure Menu_SetStatusBar( m: menuframework_p; string_: pchar );
procedure Menu_SlideItem( s: menuframework_p; dir: integer);
function Menu_TallySlots( menu: menuframework_p ): integer;
procedure Menu_DrawString( x, y: integer; string_: pchar );
procedure Menu_DrawStringDark( x, y: integer; string_: pchar );
procedure Menu_DrawStringR2L( x, y: integer; string_: pchar );
procedure Menu_DrawStringR2LDark( x, y: integer; string_: pchar );
implementation
uses
q_shwin,
sys_win,
keys,
SysUtils,
cpas,
vid_dll;
const
RCOLUMN_OFFSET = 16;
LCOLUMN_OFFSET = -16;
{ JUHA: MACRO REPLACEMENTS }
function VID_WIDTH: integer;
begin
Result := viddef.width;
end;
function VID_HEIGHT: integer;
begin
Result := viddef.height;
end;
(*
#define re.DrawChar re.DrawChar
#define Draw_Fill re.DrawFill
*)
procedure Slider_Draw ( s: menuslider_p ); forward;
procedure MenuList_Draw ( l: menulist_p ); forward;
procedure SpinControl_Draw ( s: menulist_p ); forward;
procedure Separator_Draw ( s: menuseparator_p ); forward;
procedure Menu_DrawStatusBar (string_ : PChar); forward;
procedure Slider_DoSlide ( s: menuslider_p; dir: integer ); forward;
procedure SpinControl_DoSlide ( s: menulist_p; dir: integer ); forward;
procedure Action_DoEnter ( a: menuaction_p );
begin
if @a.generic.callback <> nil then
a.generic.callback (a);
end;
procedure Action_Draw ( a: menuaction_p );
begin
if (a^.generic.flags and QMF_LEFT_JUSTIFY) <> 0 then
begin
if (a^.generic.flags and QMF_GRAYED) <> 0 then
Menu_DrawStringDark(a^.generic.x + a^.generic.parent.x + LCOLUMN_OFFSET, a^.generic.y + a^.generic.parent.y, a^.generic.name)
else
Menu_DrawString(a^.generic.x + a^.generic.parent.x + LCOLUMN_OFFSET, a^.generic.y + a^.generic.parent.y, a^.generic.name);
end
else begin
if (a^.generic.flags and QMF_GRAYED) <> 0 then
Menu_DrawStringR2LDark(a^.generic.x + a^.generic.parent.x + LCOLUMN_OFFSET, a^.generic.y + a^.generic.parent.y, a^.generic.name)
else
Menu_DrawStringR2L(a^.generic.x + a^.generic.parent.x + LCOLUMN_OFFSET, a^.generic.y + a^.generic.parent.y, a^.generic.name);
end;
if @a^.generic.ownerdraw <> nil then
a^.generic.ownerdraw (a);
end;
function Field_DoEnter ( f: menufield_p ) : qboolean;
begin
if @f^.generic.callback <> nil then
begin
f^.generic.callback (f);
Result := true;
Exit;
end;
Result := false;
end;
procedure Field_Draw ( f: menufield_p );
var
i, offset: Integer;
tempbuffer: array[0..128-1] of Char;
begin
FillChar(tempbuffer, sizeof(tempbuffer), 0);
if f^.generic.name <> nil then
Menu_DrawStringR2LDark(f^.generic.x + f^.generic.parent.x + LCOLUMN_OFFSET, f^.generic.y + f^.generic.parent.y, f^.generic.name);
strncpy( tempbuffer, f^.buffer + f^.visible_offset, f^.visible_length );
re.DrawChar (f^.generic.x + f^.generic.parent.x + 16, f^.generic.y + f^.generic.parent.y - 4, 18);
re.DrawChar (f^.generic.x + f^.generic.parent.x + 16, f^.generic.y + f^.generic.parent.y + 4, 24);
re.DrawChar (f^.generic.x + f^.generic.parent.x + 24 + f^.visible_length * 8, f^.generic.y + f^.generic.parent.y - 4, 20);
re.DrawChar (f^.generic.x + f^.generic.parent.x + 24 + f^.visible_length * 8, f^.generic.y + f^.generic.parent.y + 4, 26);
for i := 0 to f^.visible_length-1 do
begin
re.DrawChar (f^.generic.x + f^.generic.parent.x + 24 + i * 8, f^.generic.y + f^.generic.parent.y - 4, 19);
re.DrawChar (f^.generic.x + f^.generic.parent.x + 24 + i * 8, f^.generic.y + f^.generic.parent.y + 4, 25);
end;
Menu_DrawString (f^.generic.x + f^.generic.parent.x + 24, f^.generic.y + f^.generic.parent.y, tempbuffer);
if (Menu_ItemAtCursor (f^.generic.parent) = f) then
begin
if (f^.visible_offset <> 0) then
offset := f^.visible_length
else
offset := f^.cursor;
if ((Sys_Milliseconds() div 250) and 1 <> 0) then
re.DrawChar (f^.generic.x + f^.generic.parent.x + ( offset + 2 ) * 8 + 8,
f^.generic.y + f^.generic.parent.y,
11 )
else
re.DrawChar (f^.generic.x + f^.generic.parent.x + ( offset + 2 ) * 8 + 8,
f^.generic.y + f^.generic.parent.y,
Byte(' ') );
end;
end;
function Field_Key ( f: menufield_p; key: integer ) : qboolean;
var
cbd: PChar;
begin
Case key of
K_KP_SLASH: key := byte('/');
K_KP_MINUS: key := byte('-');
K_KP_PLUS: key := byte('+');
K_KP_HOME: key := byte('7');
K_KP_UPARROW: key := byte('8');
K_KP_PGUP: key := byte('9');
K_KP_LEFTARROW: key := byte('4');
K_KP_5: key := byte('5');
K_KP_RIGHTARROW:key := byte('6');
K_KP_END: key := byte('1');
K_KP_DOWNARROW: key := byte('2');
K_KP_PGDN: key := byte('3');
K_KP_INS: key := byte('0');
K_KP_DEL: key := byte('.');
end;//case
if ( key > 127 ) then
begin
Result := false;
Exit;
end;
{*
** support pasting from the clipboard
*}
if ((UpperCase(char(key)) = 'V') and (keydown[K_CTRL]) or
( ((key = K_INS) or (key = K_KP_INS)) and keydown[K_SHIFT] ) ) then
begin
cbd := Sys_GetClipboardData();
if ( cbd <> nil ) then
begin
strtok( cbd, #10#13#08 );
strncpy( f^.buffer, cbd, f^.length - 1 );
f^.cursor := strlen( f^.buffer );
f^.visible_offset := f^.cursor - f^.visible_length;
if (f^.visible_offset < 0) then
f^.visible_offset := 0;
FreeMem( cbd );
end;
Result := true;
Exit;
end;
Case key of
K_KP_LEFTARROW,
K_LEFTARROW,
K_BACKSPACE: if (f^.cursor > 0 ) then
begin
Move( f^.buffer[f^.cursor], f^.buffer[f^.cursor-1], strlen( @f^.buffer[f^.cursor] ) + 1 );
Dec(f^.cursor);
if ( f^.visible_offset <> 0) then
Dec(f^.visible_offset);
end;
K_KP_DEL,
K_DEL: Move( f^.buffer[f^.cursor+1], f^.buffer[f^.cursor], strlen( @f^.buffer[f^.cursor+1] ) + 1 );
K_KP_ENTER,
K_ENTER,
K_ESCAPE,
K_TAB: begin
Result := false;
Exit;
end;
{K_SPACE, }
else if (isdigit(key) = 0) and
((f^.generic.flags and QMF_NUMBERSONLY) <> 0) then
begin
Result := false;
Exit;
end;
if (f^.cursor < f^.length) then
begin
// f->buffer[f->cursor++] = key;
f^.buffer[f^.cursor] := Char(key);
Inc(f^.cursor);
f^.buffer[f^.cursor] := #0;
if (f^.cursor > f^.visible_length) then
Inc(f^.visible_offset);
end;
end;//case
Result := true;
end;
procedure Menu_AddItem ( menu: menuframework_p; item: pointer);
begin
if (menu^.nitems = 0) then
menu^.nslots := 0;
if (menu^.nitems < MAXMENUITEMS) then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -