menu.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,035 行 · 第 1/2 页
C
1,035 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Menu processing routines for vi.
*
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include "vi.h"
#include "colors.h"
#include "keys.h"
#include "menu.h"
#include "win.h"
typedef struct menu_item {
struct menu_item *next,*prev;
char hi;
char hioff;
char slen;
char *cmd;
char str[1];
} menu_item;
typedef struct {
char hi;
char hioff;
} hilst;
typedef struct menu {
struct menu *next,*prev;
menu_item *itemhead,*itemtail;
int itemcnt;
int orig_itemcnt;
char **list;
hilst *hilist;
char has_file_list:1;
char need_hook:1;
char has_last_files:1;
char spare:5;
char maxwidth;
char orig_maxwidth;
char hi;
char hioff;
char slen;
char str[1];
} menu;
int CurrentMenuNumber;
static int menuCnt;
static menu *menuHead,*menuTail,*currMenu;
static menu *windowGadgetMenu;
static menu *floatMenus[MAX_FLOAT_MENUS] = { NULL, NULL, NULL, NULL };
/*
* getMenuName - get name of menu, including '&' character
*/
static void getMenuName( char *res, char *str, int slen, int hioff )
{
int i;
for( i=0;i<=slen;i++ ) {
if( i == hioff ) {
*res++ = '&';
}
*res++ = str[i];
}
} /* getMenuName */
/*
* dumpMenu - dump contents of a menu
*/
static void dumpMenu( FILE *f, menu *cmenu )
{
menu_item *citem;
char str[MAX_STR];
citem = cmenu->itemhead;
while( citem != NULL ) {
if( citem->slen == 0 ) {
MyFprintf( f, " menuitem \"\"\n" );
} else {
getMenuName( str, citem->str, citem->slen, citem->hioff );
MyFprintf( f, " menuitem \"%s\" %s\n", str, citem->cmd );
}
citem = citem->next;
}
if( cmenu->has_file_list ) {
MyFprintf( f, " menuwindowlist\n" );
}
} /* dumpMenu */
/*
* BarfMenuData - write out menu data to a specified file handle
*/
void BarfMenuData( FILE *f )
{
menu *cmenu;
char str[MAX_STR];
if( windowGadgetMenu != NULL ) {
MyFprintf( f, "menu windowgadget\n" );
dumpMenu( f, windowGadgetMenu );
MyFprintf( f, "endmenu\n" );
}
cmenu = menuHead;
while( cmenu != NULL ) {
getMenuName( str, cmenu->str, cmenu->slen, cmenu->hioff );
if( cmenu->need_hook ) {
MyFprintf( f, "menu %s 1\n", str );
} else {
MyFprintf( f, "menu %s\n", str );
}
dumpMenu( f, cmenu );
MyFprintf( f, "endmenu\n" );
cmenu = cmenu->next;
}
} /* BarfMenuData */
/*
* extractMenuStr - get the string and activation char for a menu item
*/
static int extractMenuStr( char *str, int *hioff )
{
int len,i,j;
char ch;
len = strlen( str );
*hioff = 0;
for( i=0;i<len;i++ ) {
if( str[i] == '&' ) {
ch = str[i+1];
*hioff = i;
for( j=i+1;j<=len;j++ ) {
str[j-1] = str[j];
}
return( ch );
}
}
return( -1 );
} /* extractMenuStr */
/*
* freeMenuData - release data associated with a menu
*/
static void freeMenuData( menu *cmenu )
{
menu_item *curr,*next;
menu *tmp;
if( cmenu == NULL ) {
return;
}
MemFree( cmenu->list );
MemFree( cmenu->hilist );
curr = cmenu->itemhead;
while( curr != NULL ) {
next = curr->next;
MemFree( curr );
curr = next;
}
tmp = cmenu->next;
memset( cmenu, 0, sizeof( menu ) );
cmenu->next = tmp;
} /* freeMenuData */
/*
* freeMenu - free up a given menu
*/
static void freeMenu( menu *menu )
{
freeMenuData( menu );
MemFree( menu );
} /* freeMenu */
/*
* findMenu - locate pointer to a given menu
*/
static menu *findMenu( char *str, menu ***predef_menu )
{
int len;
menu *res;
int num;
len = strlen( str );
*predef_menu = NULL;
res = NULL;
if( str[0] == 'f' || str[0] == 'w' ) {
if( !strnicmp( str, "float", 5 ) ) {
num = str[5] - '0';
if( num >=0 && num < MAX_FLOAT_MENUS ) {
res = floatMenus[num];
*predef_menu = &floatMenus[num];
}
} else if( !stricmp( str, "windowgadget" ) ) {
res = windowGadgetMenu;
*predef_menu = &windowGadgetMenu;
}
}
if( res == NULL ) {
res = menuHead;
while( res != NULL ) {
if( !stricmp( str, res->str ) ) {
break;
}
res = res->next;
}
}
return( res );
} /* findMenu */
/*
* StartMenu - start a new top level menu
*/
int StartMenu( char *data )
{
char str[MAX_STR];
menu *tmp;
char ch;
int hioff;
int len;
bool new;
bool need_hook;
menu **predef_menu;
GetStringWithPossibleQuote( data, str );
RemoveLeadingSpaces( data );
need_hook = FALSE;
if( data[0] != 0 ) {
need_hook = TRUE;
}
if( currMenu != NULL ) {
return( ERR_INVALID_MENU );
}
new = FALSE;
ch = extractMenuStr( str, &hioff );
len = strlen( str );
tmp = findMenu( str, &predef_menu );
if( predef_menu != NULL ) {
freeMenuData( tmp );
}
if( tmp == NULL ) {
tmp = MemAlloc( sizeof( menu ) + len );
new = TRUE;
}
if( predef_menu == NULL ) {
if( new ) {
AddLLItemAtEnd( (ss**)&menuHead, (ss**)&menuTail, (ss*)tmp );
} else {
freeMenuData( tmp );
}
} else {
*predef_menu = tmp;
}
strcpy( tmp->str, str );
tmp->hi = ch;
tmp->hioff = hioff;
tmp->slen = len;
tmp->need_hook = need_hook;
currMenu = tmp;
return( ERR_NO_ERR );
} /* StartMenu */
/*
* initMenuList - set up lists for current menu
*/
static void initMenuList( menu *cmenu )
{
menu_item *cmi;
int i;
MemFree( cmenu->list );
MemFree( cmenu->hilist );
cmenu->list = MemAlloc( sizeof( char * ) * cmenu->itemcnt );
cmenu->hilist = MemAlloc( sizeof( hilst) * (cmenu->itemcnt+1) );
cmi = cmenu->itemhead;
for( i=0;i<cmenu->itemcnt; i++ ) {
cmenu->list[i] = cmi->str;
cmenu->hilist[i].hi = cmi->hi;
cmenu->hilist[i].hioff = cmi->hioff;
cmi = cmi->next;
}
cmenu->hilist[i].hi = 0;
cmenu->hilist[i].hioff = 0;
} /* initMenuList */
/*
* ViEndMenu - terminate new menu
*/
int ViEndMenu( void )
{
char ch;
if( currMenu == NULL ) {
return( ERR_INVALID_MENU );
}
if( currMenu == menuTail ) {
menuCnt++;
}
ch = toupper( currMenu->hi );
if( ch >= 'A' && ch <='Z' ) {
ch = ch - 'A' + VI_KEY( ALT_A );
EventList[ ch ].rtn.old = DoMenu;
EventList[ ch ].b.keep_selection = TRUE;
EventList[ ch ].alt_rtn.old = DoMenu;
EventList[ ch ].alt_b.keep_selection = TRUE;
}
initMenuList( currMenu );
currMenu = NULL;
InitMenu();
return( ERR_NO_ERR );
} /* ViEndMenu */
/*
* MenuItem - add new item current menu
*/
int MenuItem( char *data )
{
char str[MAX_STR];
int len;
int size;
char ch;
menu_item *tmp;
int hioff;
if( currMenu == NULL ) {
return( ERR_INVALID_MENU );
}
GetStringWithPossibleQuote( data, str );
RemoveLeadingSpaces( data );
ch = extractMenuStr( str, &hioff );
len = strlen( str );
size = sizeof( menu_item ) + len + strlen( data ) + 2;
tmp = MemAlloc( size );
tmp->slen = len;
tmp->hi = ch;
tmp->hioff = hioff;
strcpy( tmp->str, str );
tmp->cmd = &(tmp->str[len+1]);
strcpy( tmp->cmd, data );
if( len > currMenu->maxwidth ) {
currMenu->maxwidth = len;
}
AddLLItemAtEnd( (ss**)&currMenu->itemhead, (ss**)&currMenu->itemtail, (ss*)tmp );
currMenu->itemcnt++;
return( ERR_NO_ERR );
} /* MenuItem */
/*
* DoItemDelete - delete an item from a menu
*/
int DoItemDelete( char *data )
{
menu *cmenu,**predef_menu;
char mname[MAX_STR];
char str[MAX_STR];
menu_item *cmi,*dmi;
int i,id,mwid;
if( currMenu != NULL ) {
return( ERR_INVALID_MENU );
}
NextWord1( data, mname );
cmenu = findMenu( mname, &predef_menu );
if( cmenu == NULL ) {
return( ERR_INVALID_MENU );
}
NextWord1( data, str );
id = atoi( str );
if( id < 0 ) {
id = cmenu->itemcnt-1;
}
if( id >= cmenu->itemcnt ) {
return( ERR_INVALID_MENU );
}
i = 0;
mwid = 0;
dmi = NULL;
for( cmi=cmenu->itemhead; cmi != NULL; cmi = cmi->next ) {
if( i == id ) {
dmi = cmi;
} else {
if( cmi->slen > mwid ) {
mwid = cmi->slen;
}
}
i++;
}
if( dmi == NULL ) {
return( ERR_INVALID_MENU );
}
cmenu->itemcnt--;
cmenu->maxwidth = mwid;
DeleteLLItem( (ss**)&cmenu->itemhead, (ss**)&cmenu->itemtail, (ss*)dmi );
MemFree( dmi );
initMenuList( cmenu );
return( ERR_NO_ERR );
} /* DoItemDelete */
/*
* AddMenuItem - add a menu item to an already created menu
*/
int AddMenuItem( char *data )
{
menu *cmenu,**predef_menu;
char mname[MAX_STR];
int rc;
if( currMenu != NULL ) {
return( ERR_INVALID_MENU );
}
NextWord1( data, mname );
cmenu = findMenu( mname, &predef_menu );
if( cmenu == NULL ) {
return( ERR_INVALID_MENU );
}
currMenu = cmenu;
rc = MenuItem( data );
initMenuList( currMenu );
currMenu = NULL;
return( rc );
} /* AddMenuItem */
/*
* DoMenuDelete - delete an existing menu
*/
int DoMenuDelete( char *data )
{
menu *cmenu,**predef_menu;
char mname[MAX_STR];
if( currMenu != NULL ) {
return( ERR_INVALID_MENU );
}
NextWord1( data, mname );
cmenu = findMenu( mname, &predef_menu );
if( cmenu == NULL ) {
return( ERR_INVALID_MENU );
}
if( predef_menu != NULL ) {
freeMenu( cmenu );
*predef_menu = NULL;
return( ERR_NO_ERR );
}
DeleteLLItem( (ss**)&menuHead, (ss**)&menuTail, (ss*)cmenu );
freeMenu( cmenu );
menuCnt--;
InitMenu();
return( ERR_NO_ERR );
} /* DeleteMenu */
/*
* addFileList - add a list of files to the current menu
*/
static void addFileList( menu *cmenu )
{
char buff[MAX_STR];
info *cinfo;
int cnt;
currMenu = cmenu;
cmenu->orig_itemcnt = cmenu->itemcnt;
cmenu->orig_maxwidth = cmenu->maxwidth;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?