⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qmenu.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{----------------------------------------------------------------------------}
{                                                                            }
{ 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
    {$IFDEF LINUX}
    libc,
    {$ENDIF}
    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
  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
  {$IFDEF WIN32}
  q_shwin,
  sys_win,
  vid_dll,
  {$ELSE}
  q_shlinux,
  sys_linux,
  vid_so,
  {$ENDIF}
  keys,
  SysUtils,
  cpas;

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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -