📄 multilist.c
字号:
/**************************************************************************** MultiList.c This file contains the implementation of the Picasso List widget. Its functionality is intended to be similar to The Athena List widget, with some extra features added. This code is loosely based on the Athena List source which is why the MIT copyright notice appears below. The code was changed substantially in V3.4 to change the action/callback interface which was unnecessarily ugly. Code using some features of the old interface may need to be changed. Hope the changes don't make people's lives too miserable. ****************************************************************************//* * Author: * Brian Totty * Department of Computer Science * University Of Illinois at Urbana-Champaign * 1304 West Springfield Avenue * Urbana, IL 61801 * * totty@cs.uiuc.edu * */ /* * Copyright 1989 Massachusetts Institute of Technology * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of M.I.T. not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. M.I.T. makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Original Athena Author: Chris D. Peterson, MIT X Consortium */#include <stdio.h>#ifndef NOSTDHDRS#include <stdlib.h>#endif#include <ctype.h>#include <X11/IntrinsicP.h>#include <X11/StringDefs.h>#include "MultiListP.h"/*===========================================================================* D E C L A R A T I O N S A N D D E F I N I T I O N S *===========================================================================*/Pixmap XmuCreateStippledPixmap();extern void XawInitializeWidgetSet();#define SUPERCLASS &(simpleClassRec)#define FontAscent(f) ((f)->max_bounds.ascent)#define FontDescent(f) ((f)->max_bounds.descent)#define FontH(f) (FontAscent(f) + FontDescent(f) + 2)#define FontW(f,s) (XTextWidth(f,s,strlen(s)) + 1)#define FontMaxCharW(f) ((f)->max_bounds.rbearing-(f)->min_bounds.lbearing+1)#ifndef abs#define abs(a) ((a) < 0 ? -(a) : (a))#endif#define max(a,b) ((a) > (b) ? (a) : (b))#define min(a,b) ((a) < (b) ? (a) : (b))#define XtStrlen(s) ((s) ? strlen(s) : 0)#define TypeAlloc(t,n) (t *)malloc(sizeof(t) * n)#define StrCopy(s) strcpy(TypeAlloc(char,strlen(s)+1),s)#define StrCopyRetLength(s,lp) strcpy(TypeAlloc(char,(*lp=(strlen(s)+1))),s)#define CoreFieldOffset(f) XtOffset(Widget,core.f)#define SimpleFieldOffset(f) XtOffset(XfwfMultiListWidget,simple.f)#define MultiListFieldOffset(f) XtOffset(XfwfMultiListWidget,multiList.f)/*===========================================================================* I N T E R N A L P R O C E D U R E D E C L A R A T I O N S *===========================================================================*/#if (!NeedFunctionPrototypes)static void Initialize();static void Redisplay();static XtGeometryResult PreferredGeometry();static void Resize();static Boolean SetValues();static void DestroyOldData();static void InitializeNewData();static void CreateNewGCs();static void RecalcCoords();static void NegotiateSizeChange();static Boolean Layout();static void RedrawAll();static void RedrawItem();static void RedrawRowColumn();static void PixelToRowColumn();static void RowColumnToPixels();static Boolean RowColumnToItem();static Boolean ItemToRowColumn();static void Select();static void Unselect();static void Toggle();static void Extend();static void Notify();#elsestatic void Initialize(Widget request, Widget new);static void Redisplay(XfwfMultiListWidget mlw, XEvent *event, Region rectangle_union);static XtGeometryResult PreferredGeometry(XfwfMultiListWidget mlw, XtWidgetGeometry *parent_idea, XtWidgetGeometry *our_idea);static void Resize(XfwfMultiListWidget mlw);static Boolean SetValues(XfwfMultiListWidget cpl, XfwfMultiListWidget rpl, XfwfMultiListWidget npl);static void DestroyOldData(XfwfMultiListWidget mlw);static void InitializeNewData(XfwfMultiListWidget mlw);static void CreateNewGCs(XfwfMultiListWidget mlw);static void RecalcCoords(XfwfMultiListWidget mlw, Boolean width_changeable, Boolean height_changeable);static void NegotiateSizeChange(XfwfMultiListWidget mlw, Dimension width, Dimension height);static Boolean Layout(XfwfMultiListWidget mlw, Boolean w_changeable, Boolean h_changeable, Dimension *w_ptr, Dimension *h_ptr);static void RedrawAll(XfwfMultiListWidget mlw);static void RedrawItem(XfwfMultiListWidget mlw, int item_index);static void RedrawRowColumn(XfwfMultiListWidget mlw, int row, int column);static void PixelToRowColumn(XfwfMultiListWidget mlw, int x, int y, int *row_ptr, int *column_ptr);static void RowColumnToPixels(XfwfMultiListWidget mlw, int row, int col, int *x_ptr, int *y_ptr, int *w_ptr, int *h_ptr);static Boolean RowColumnToItem(XfwfMultiListWidget mlw, int row, int column, int *item_ptr);static Boolean ItemToRowColumn(XfwfMultiListWidget mlw, int item_index, int *row_ptr, int *column_ptr);static void Select(XfwfMultiListWidget mlw, XEvent *event, String *params, Cardinal *num_params);static void Unselect(XfwfMultiListWidget mlw, XEvent *event, String *params, Cardinal *num_params);static void Toggle(XfwfMultiListWidget mlw, XEvent *event, String *params, Cardinal *num_params);static void Extend(XfwfMultiListWidget mlw, XEvent *event, String *params, Cardinal *num_params);static void Notify(XfwfMultiListWidget mlw, XEvent *event, String *params, Cardinal *num_params);#endif/*===========================================================================* R E S O U R C E I N I T I A L I Z A T I O N *===========================================================================*/static XtResource resources[] ={ {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension), CoreFieldOffset(width), XtRString, "0"}, {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension), CoreFieldOffset(height), XtRString, "0"}, {XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel), CoreFieldOffset(background_pixel),XtRString,"XtDefaultBackground"}, {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor), SimpleFieldOffset(cursor), XtRString, "left_ptr"}, {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), MultiListFieldOffset(foreground), XtRString,"XtDefaultForeground"}, {XtNhighlightForeground, XtCHForeground, XtRPixel, sizeof(Pixel), MultiListFieldOffset(highlight_fg), XtRString, "XtDefaultBackground"}, {XtNhighlightBackground, XtCHBackground, XtRPixel, sizeof(Pixel), MultiListFieldOffset(highlight_bg), XtRString, "XtDefaultForeground"}, {XtNcolumnSpacing, XtCSpacing, XtRDimension, sizeof(Dimension), MultiListFieldOffset(column_space), XtRImmediate, (caddr_t)8}, {XtNrowSpacing, XtCSpacing, XtRDimension, sizeof(Dimension), MultiListFieldOffset(row_space), XtRImmediate, (caddr_t)0}, {XtNdefaultColumns, XtCColumns, XtRInt, sizeof(int), MultiListFieldOffset(default_cols), XtRImmediate, (caddr_t)1}, {XtNforceColumns, XtCColumns, XtRBoolean, sizeof(Boolean), MultiListFieldOffset(force_cols), XtRString, (caddr_t) "False"}, {XtNpasteBuffer, XtCBoolean, XtRBoolean, sizeof(Boolean), MultiListFieldOffset(paste), XtRString, (caddr_t) "False"}, {XtNverticalList, XtCBoolean, XtRBoolean, sizeof(Boolean), MultiListFieldOffset(row_major), XtRString, (caddr_t) "False"}, {XtNlongest, XtCLongest, XtRInt, sizeof(int), MultiListFieldOffset(longest), XtRImmediate, (caddr_t)0}, {XtNnumberStrings, XtCNumberStrings, XtRInt, sizeof(int), MultiListFieldOffset(nitems), XtRImmediate, (caddr_t)0}, {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *), MultiListFieldOffset(font),XtRString, "XtDefaultFont"}, {XtNlist, XtCList, XtRPointer, sizeof(char **), MultiListFieldOffset(list), XtRString, NULL}, {XtNsensitiveArray, XtCList, XtRPointer, sizeof(Boolean *), MultiListFieldOffset(sensitive_array), XtRString, NULL}, {XtNcallback, XtCCallback, XtRCallback, sizeof(caddr_t), MultiListFieldOffset(callback), XtRCallback, NULL}, {XtNmaxSelectable, XtCValue, XtRInt, sizeof(int), MultiListFieldOffset(max_selectable), XtRImmediate, (caddr_t) 1}, {XtNshadeSurplus, XtCBoolean, XtRBoolean, sizeof(Boolean), MultiListFieldOffset(shade_surplus), XtRString, "True"}, {XtNcolumnWidth, XtCValue, XtRDimension, sizeof(Dimension), MultiListFieldOffset(col_width), XtRImmediate, (caddr_t)0}, {XtNrowHeight, XtCValue, XtRDimension, sizeof(Dimension), MultiListFieldOffset(row_height), XtRImmediate, (caddr_t)0},};/*===========================================================================* A C T I O N A N D T R A N S L A T I O N T A B L E S *===========================================================================*/static char defaultTranslations[] =" Shift <Btn1Down>: Toggle()\n\ Ctrl <Btn1Down>: Unselect()\n\ <Btn1Down>: Select()\n\ Button1 <Btn1Motion>: Extend()\n\ <Btn1Up>: Notify()";static XtActionsRec actions[] ={ {"Select", (XtActionProc)Select}, {"Unselect", (XtActionProc)Unselect}, {"Toggle", (XtActionProc)Toggle}, {"Extend", (XtActionProc)Extend}, {"Notify", (XtActionProc)Notify}, {NULL, (XtActionProc)NULL}};/*===========================================================================* C L A S S A L L O C A T I O N *===========================================================================*/XfwfMultiListClassRec xfwfMultiListClassRec ={ { /* superclass */ (WidgetClass)SUPERCLASS, /* class_name */ "XfwfMultiList", /* widget_size */ sizeof(XfwfMultiListRec), /* class_initialize */ NULL, /* class_part_initialize*/ NULL, /* class_inited */ FALSE, /* initialize */ (XtInitProc)Initialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ actions, /* num_actions */ XtNumber(actions), /* resources */ resources, /* resource_count */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ FALSE, /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ NULL, /* resize */ (XtWidgetProc)Resize, /* expose */ (XtExposeProc)Redisplay, /* set_values */ (XtSetValuesFunc)SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ defaultTranslations, /* query_geometry */ (XtGeometryHandler) PreferredGeometry, /* display_accelerator */ XtInheritDisplayAccelerator, /* extension */ NULL }, /* Core Part */ { /* change_sensitive */ XtInheritChangeSensitive }};WidgetClass xfwfMultiListWidgetClass = (WidgetClass)&xfwfMultiListClassRec;/*===========================================================================* T O O L K I T M E T H O D S *===========================================================================*//*---------------------------------------------------------------------------* Initialize() This procedure is called by the X toolkit to initialize the widget instance. The hook to this routine is in the initialize part of the core part of the class. *---------------------------------------------------------------------------*//* ARGSUSED */static void Initialize(request,new)Widget request,new;{ XfwfMultiListWidget mlw; mlw = (XfwfMultiListWidget)new; CreateNewGCs(mlw); InitializeNewData(mlw); RecalcCoords(mlw,(MultiListWidth(mlw) == 0), (MultiListHeight(mlw) == 0));} /* Initialize *//*---------------------------------------------------------------------------* Redisplay(mlw,event,rectangle_union) This routine redraws the MultiList widget <mlw> based on the exposure region requested in <event>. *---------------------------------------------------------------------------*//* ARGSUSED */static void Redisplay(mlw,event,rectangle_union)XfwfMultiListWidget mlw;XEvent *event;Region rectangle_union;{ GC shade_gc; int i,x1,y1,w,h,x2,y2,row,col,ul_row,ul_col,lr_row,lr_col; if (MultiListShadeSurplus(mlw)) shade_gc = MultiListGrayGC(mlw); else shade_gc = MultiListEraseGC(mlw); if (event == NULL) { XFillRectangle(XtDisplay(mlw),XtWindow(mlw),shade_gc,0,0, MultiListWidth(mlw),MultiListHeight(mlw)); for (i = 0; i < MultiListNumItems(mlw); i++) RedrawItem(mlw,i); } else { x1 = event->xexpose.x; y1 = event->xexpose.y; w = event->xexpose.width; h = event->xexpose.height; x2 = x1 + w; y2 = y1 + h; XFillRectangle(XtDisplay(mlw),XtWindow(mlw), shade_gc,x1,y1,w,h); PixelToRowColumn(mlw,x1,y1,&ul_row,&ul_col); PixelToRowColumn(mlw,x2,y2,&lr_row,&lr_col); lr_row = min(lr_row,MultiListNumRows(mlw) - 1); lr_col = min(lr_col,MultiListNumCols(mlw) - 1); for (col = ul_col; col <= lr_col; col++) { for (row = ul_row; row <= lr_row; row++) { RedrawRowColumn(mlw,row,col); } } }} /* End Redisplay *//*---------------------------------------------------------------------------* PreferredGeometry(mlw,parent_idea,our_idea) This routine is called by the parent to tell us about the parent's idea of our width and/or height. We then suggest our preference through <our_idea> and return the information to the parent. *---------------------------------------------------------------------------*/static XtGeometryResult PreferredGeometry(mlw,parent_idea,our_idea)XfwfMultiListWidget mlw;XtWidgetGeometry *parent_idea,*our_idea;{ Dimension nw,nh; Boolean parent_wants_w,parent_wants_h,we_changed_size; parent_wants_w = (parent_idea->request_mode) & CWWidth; parent_wants_h = (parent_idea->request_mode) & CWHeight; if (parent_wants_w) nw = parent_idea->width; else nw = MultiListWidth(mlw); if (parent_wants_h) nh = parent_idea->height; else nh = MultiListHeight(mlw); our_idea->request_mode = 0; if (!parent_wants_w && !parent_wants_h) return(XtGeometryYes); we_changed_size = Layout(mlw,!parent_wants_w,!parent_wants_h,&nw,&nh); our_idea->request_mode |= (CWWidth | CWHeight); our_idea->width = nw; our_idea->height = nh; if (we_changed_size) return(XtGeometryAlmost); else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -