/* $XConsortium: tcedit.c /main/5 1995/07/15 21:01:48 drk $ */ /* * @OPENGROUP_COPYRIGHT@ * COPYRIGHT NOTICE * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc. * Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group * ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for * the full copyright text. * * This software is subject to an open license. It may only be * used on, with or for operating systems which are themselves open * source systems. You must contact The Open Group for a license * allowing distribution and sublicensing of this software on, with, * or for operating systems which are not Open Source programs. * * See http://www.opengroup.org/openmotif/license for full * details of the license agreement. Any use, reproduction, or * distribution of the program constitutes recipient's acceptance of * this agreement. * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS * PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY * OR FITNESS FOR A PARTICULAR PURPOSE * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT * NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE * EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. */ /* * HISTORY */ #include #include #include #include #include #include #include #include #include #include #include #include #include "toolchest.h" static Widget menuParent; static Pixmap decalPixmap; static Pixmap arrowPixmap; static Pixmap nullPixmap; static Pixel menuBackground, menuForeground; static XmFontList menuFontList; static Dimension menuShadowThickness; #define decal_width 18 #define decal_height 16 static char decal_bits[] = { 0xf0, 0x7f, 0x00, 0x10, 0x40, 0x00, 0x10, 0xc0, 0x00, 0xf0, 0xff, 0x00, 0xc0, 0xff, 0x00, 0xf0, 0x7f, 0x00, 0x10, 0x40, 0x00, 0x10, 0xc0, 0x00, 0x10, 0xc0, 0x00, 0x10, 0xc0, 0x00, 0x10, 0xc0, 0x00, 0x10, 0xc0, 0x00, 0x10, 0xc0, 0x00, 0x10, 0xc0, 0x00, 0xf0, 0xff, 0x00, 0xc0, 0xff, 0x00}; #define arrow_width 16 #define arrow_height 16 static char arrow_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x38, 0x00, 0xc8, 0x00, 0x08, 0x03, 0x08, 0x0c, 0x08, 0x30, 0x08, 0x70, 0x08, 0x3c, 0x08, 0x0f, 0xc8, 0x03, 0xf8, 0x00, 0x38, 0x00, 0x08, 0x00, 0x00, 0x00}; #define null_width 16 #define null_height 16 static char null_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; static Widget createMenuWidget(char *menuName, Boolean isTop); static void manageMenuWidget(Widget w, Position x, Position y); static void makeDecalPixmap(Widget w); extern void CreatePanel(Widget parent); extern void UpdatePanel(struct menu *menu); static void ParseCmdLine(int argc, char **argv) { register int i; if (argc == 1) AppendFile(NULL); else { for (i=1; itype == ME_MENU) { struct menu *menu = FindMenu(entry->menuName, FALSE); if (menu && menu->menuWidget) { if (menu->activeEntry) { deactivateEntry(menu->activeEntry); menu->activeEntry = NULL; } XtUnmanageChild(menu->menuWidget); } } } static void activateEntry(register struct menuEntry *entry) { register struct menu *menu = entry->containingMenu; Arg args[5]; int n; Position menuX, menuY; Position entryX, entryY; Dimension entryWidth; if (menu->activeEntry) { if (menu->activeEntry == entry) return; deactivateEntry(menu->activeEntry); } menu->activeEntry = entry; if (entry->type == ME_MENU) { Widget menuWidget = createMenuWidget(entry->menuName, FALSE); /* get positions of menu and entry */ n = 0; XtSetArg (args[n], XmNx, &menuX); n++; XtSetArg (args[n], XmNy, &menuY); n++; XtGetValues (menu->menuWidget, args, n); n = 0; XtSetArg (args[n], XmNx, &entryX); n++; XtSetArg (args[n], XmNy, &entryY); n++; XtSetArg (args[n], XmNwidth, &entryWidth); n++; XtGetValues (entry->entryWidget, args, n); manageMenuWidget(menuWidget, menuX+entryX+entryWidth, menuY+entryY); } } static XtCallbackProc activateEntryCB(Widget w, struct menuEntry *client_data, caddr_t call_data) { activateEntry(client_data); } static XtEventHandler activateEntryEH(Widget w, struct menuEntry *client_data, XEvent *event) { if (event->xbutton.button == Button1) activateEntry(client_data); } static Widget createMenuWidget(char *menuName, Boolean isTop) { Widget menuWidget; Widget w; Widget form,decal; register struct menu *menu; register struct menuEntry *entry; enum menuEntryType lastType = ME_NONE; Boolean thisEntryRemoved = FALSE; Boolean lastEntryRemoved; Arg args[20]; int n; Widget prev; XtCallbackProc labelChangedCB(), labelSetCB(), activateEntryCB(), decalPressedCB(); XtEventHandler activateEntryEH(); menu = FindMenu(menuName, TRUE); if (menu->menuWidget) return (menu->menuWidget); n = 0; XtSetArg (args[n], XmNshadowType, XmSHADOW_OUT);n++; XtSetArg (args[n], XmNshadowThickness, menuShadowThickness);n++; menuWidget = XmCreateForm(menuParent, "menuBar", args, n); /* don't manage at this point */ prev = NULL; for (entry = menu->firstMenuEntry; entry; entry = entry->next) { n = 0; if (prev) { XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET);n++; XtSetArg (args[n], XmNtopWidget, prev);n++; } else { XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM);n++; XtSetArg (args[n], XmNtopOffset, menuShadowThickness);n++; } XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM);n++; XtSetArg (args[n], XmNleftOffset, menuShadowThickness);n++; XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM);n++; XtSetArg (args[n], XmNrightOffset, menuShadowThickness);n++; lastEntryRemoved = thisEntryRemoved; if (entry->removed) { thisEntryRemoved = TRUE; } else { thisEntryRemoved = FALSE; switch (entry->type) { case ME_EXEC: case ME_CHECKEXEC: case ME_CHECKEXPR: case ME_MENU: case ME_LABEL: case ME_TITLE: XtSetArg (args[n], XmNbackground, menuBackground); n++; XtSetArg (args[n], XmNforeground, menuForeground); n++; XtSetArg (args[n], XmNorientation, XmHORIZONTAL); n++; form = XmCreateForm(menuWidget, entry->label, args, n); XtManageChild(form); prev = form; entry->entryWidget = form; n = 0; XtSetArg (args[n], XmNtraversalOn, FALSE);n++; XtSetArg (args[n], XmNshadowThickness, 0);n++; XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM);n++; XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM);n++; XtSetArg (args[n], XmNlabelType, XmPIXMAP);n++; if (entry->type == ME_MENU) { XtSetArg (args[n], XmNlabelPixmap, isTop?decalPixmap:arrowPixmap);n++; } else { XtSetArg (args[n], XmNlabelPixmap, nullPixmap);n++; } decal = XmCreatePushButtonGadget(form, "decal", args, n); XtManageChild(decal); n = 0; XtSetArg (args[n], XmNvalue, entry->label);n++; XtSetArg (args[n], XmNshadowThickness, 0);n++; XtSetArg (args[n], XmNbackground, menuBackground); n++; XtSetArg (args[n], XmNforeground, menuForeground); n++; XtSetArg (args[n], XmNfontList, menuFontList); n++; XtSetArg (args[n], XmNresizeWidth, TRUE); n++; XtSetArg (args[n], XmNcolumns, 1); n++; /*actually grows */ XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM);n++; XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM);n++; XtSetArg (args[n], XmNrightAttachment, XmATTACH_WIDGET);n++; XtSetArg (args[n], XmNrightWidget, decal);n++; w = XmCreateTextField(form, entry->label, args, n); XtAddCallback (w, XmNvalueChangedCallback, (XtCallbackProc) labelChangedCB, NULL); XtAddCallback (w, XmNactivateCallback, (XtCallbackProc) labelSetCB, NULL); XtAddCallback (w, XmNactivateCallback, (XtCallbackProc) activateEntryCB, entry); XtAddEventHandler (w, ButtonPressMask, FALSE, (XtEventHandler) activateEntryEH, entry); XtManageChild(w); XtAddCallback (decal, XmNactivateCallback, (XtCallbackProc) decalPressedCB, w); XtAddCallback (decal, XmNactivateCallback, (XtCallbackProc) activateEntryCB, entry); if (entry->type == ME_TITLE) { n = 0; XtSetArg (args[n], XmNseparatorType, XmDOUBLE_LINE); n++; w = XmCreateSeparatorGadget (menuWidget, "separator", args, n); n++; XtManageChild(w); prev = w; } break; case ME_SEPARATOR: /* if we removed the last entry and the last non * removed entry was a separator, a title, or the start, * remove this entry. However, don't set thisEntryRemoved * so that if another separator immediatly follows, it is * drawn. */ if (!(lastEntryRemoved && (lastType == ME_SEPARATOR || lastType == ME_TITLE || lastType == ME_NONE))) { w = XmCreateSeparatorGadget(menuWidget, entry->label, args, n); XtManageChild(w); prev = w; entry->entryWidget = w; } break; default: XtError ("Unknown menu item type"); } } } if (prev) { n = 0; XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM);n++; XtSetArg (args[n], XmNbottomOffset, menuShadowThickness);n++; XtSetValues(prev, args, n); } menu->menuWidget = menuWidget; return (menuWidget); } static void manageMenuWidget(Widget w, Position x, Position y) { XtMoveWidget(w, x, y); XtManageChild(w); } static XtCallbackProc quitCB(Widget w, caddr_t client_data, caddr_t call_data) { exit (0); } static Widget createMenuBar(Widget parent) { Widget menuBar; Widget cascade; Widget button; Widget pane; Arg args[5]; int n; XtCallbackProc quitCB(); n = 0; menuBar = XmCreateMenuBar(parent, "menuBar", args, n); XtManageChild (menuBar); n = 0; pane = XmCreatePulldownMenu (menuBar, "filePane", args, n); n = 0; button = XmCreatePushButtonGadget (pane, "menuQuit", args, n); XtManageChild (button); XtAddCallback (button, XmNactivateCallback, (XtCallbackProc) quitCB, NULL); n = 0; XtSetArg (args[n], XmNsubMenuId, pane); n++; cascade = XmCreateCascadeButtonGadget (menuBar, "menuFile", args, n); XtManageChild (cascade); /* sqirrel away menu button font, background, foreground & shadow * thickness. Get the fontlist from a button in the menu */ n = 0; XtSetArg (args[n], XmNfontList, &menuFontList); n++; XtGetValues(cascade, args, n); /* the background and foreground must come from the menubar, because * the button is a gadget. Also, only the menu itself has a shadow */ n = 0; XtSetArg (args[n], XmNbackground, &menuBackground); n++; XtSetArg (args[n], XmNforeground, &menuForeground); n++; XtSetArg (args[n], XmNshadowThickness, &menuShadowThickness); n++; XtGetValues(menuBar, args, n); makeDecalPixmap(menuBar); return (menuBar); } static void createTcEdit(Widget toplevel) { Arg args[20]; int n; Widget form; Widget mainw; Widget menuBar; Widget scrolledw; Widget topMenu; n = 0; mainw = XmCreateMainWindow(toplevel, "mainWindow", args, n); XtManageChild(mainw); menuBar = createMenuBar(mainw); n = 0; form = XmCreateForm(mainw, "topForm", args, n); XtManageChild(form); n = 0; XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM);n++; XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM);n++; XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM);n++; XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM);n++; XtSetArg (args[n], XmNscrollingPolicy, XmAUTOMATIC);n++; scrolledw = XmCreateScrolledWindow(form, "menuScroll", args, n); XtManageChild(scrolledw); /* because of the way schemes work, drawing areas are the same color * as a scrolled window, so put menus in a drawing area */ n = 0; menuParent = XmCreateDrawingArea(scrolledw, "menuParent", args, n); XtManageChild(menuParent); XmMainWindowSetAreas(mainw, menuBar, NULL, NULL, NULL, form); topMenu = createMenuWidget(TOP_MENU_NAME, TRUE); manageMenuWidget(topMenu, 10, 10); } void main (int argc, char **argv) { Arg wargs[10]; Widget toplevel; int n; progName = argv[0]; toplevel = XtInitialize(argv[0], "Tcedit", NULL, 0, &argc, argv); ParseCmdLine(argc, argv); yyparse(); createTcEdit(toplevel); XtRealizeWidget(toplevel); XtMainLoop(); } static void makeDecalPixmap(Widget w) { int n; Arg wargs[3]; GC gc; XGCValues values; static Boolean initd = FALSE; Pixmap bitmap; if (initd) return; initd = TRUE; n = 0; XtSetArg(wargs[n], XmNforeground, &values.foreground);n++; XtSetArg(wargs[n], XmNbackground, &values.background);n++; XtGetValues(w, wargs, n); gc = XtGetGC(w, GCForeground | GCBackground, &values); bitmap = XCreateBitmapFromData(XtDisplay(w), RootWindowOfScreen(XtScreen(w)), decal_bits, decal_width, decal_height); decalPixmap = XCreatePixmap(XtDisplay(w), RootWindowOfScreen(XtScreen(w)), decal_width, decal_height, DefaultDepthOfScreen(XtScreen(w))); XCopyPlane(XtDisplay(w), bitmap, decalPixmap, gc, 0, 0, decal_width, decal_height, 0, 0, 1); XFreePixmap(XtDisplay(w), bitmap); bitmap = XCreateBitmapFromData(XtDisplay(w), RootWindowOfScreen(XtScreen(w)), arrow_bits, arrow_width, arrow_height); arrowPixmap = XCreatePixmap(XtDisplay(w), RootWindowOfScreen(XtScreen(w)), arrow_width, arrow_height, DefaultDepthOfScreen(XtScreen(w))); XCopyPlane(XtDisplay(w), bitmap, arrowPixmap, gc, 0, 0, arrow_width, arrow_height, 0, 0, 1); XFreePixmap(XtDisplay(w), bitmap); bitmap = XCreateBitmapFromData(XtDisplay(w), RootWindowOfScreen(XtScreen(w)), null_bits, null_width, null_height); nullPixmap = XCreatePixmap(XtDisplay(w), RootWindowOfScreen(XtScreen(w)), null_width, null_height, DefaultDepthOfScreen(XtScreen(w))); XCopyPlane(XtDisplay(w), bitmap, nullPixmap, gc, 0, 0, null_width, null_height, 0, 0, 1); XFreePixmap(XtDisplay(w), bitmap); XtReleaseGC(w, gc); }