File: macmenus.c

package info (click to toggle)
xlispstat 3.52.14-1
  • links: PTS
  • area: main
  • in suites: potato
  • size: 7,560 kB
  • ctags: 12,676
  • sloc: ansic: 91,357; lisp: 21,759; sh: 1,525; makefile: 521; csh: 1
file content (439 lines) | stat: -rw-r--r-- 13,725 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
/* macmenus - Low Level Menu Objects for Macintosh                     */
/* XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney                  */
/* Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz    */
/* You may give out copies of this software; for conditions see the    */
/* file COPYING included with this distribution.                       */
 
/***********************************************************************/
/**                                                                   **/
/**                    General Includes and Definitions               **/
/**                                                                   **/
/***********************************************************************/

#include "xlisp.h"
#include "xlstat.h"
#include "xlgraph.h"
#include "version.h"

#define IVIEW_MENU MenuHandle
#define IVIEW_WINDOW WindowPtr

/* external variables */
extern LVAL s_true, s_title, s_items, s_enabled, s_id, s_menu_list, s_key,
  s_mark, s_style, s_action, s_menu, s_menu_proto, s_apple_menu_proto,
  s_menu_item_proto, sk_select, sk_update, sk_do_action, s_bold, s_italic,
  s_underline, s_outline, s_shadow, s_condense, s_extend, sk_enabled,
  s_hardware_address, sk_allocate, sk_dispose;
extern int hasAppleEvents;

/* forward declarations */
LOCAL char *get_item_string _((LVAL item));
LOCAL Style get_item_style _((LVAL item));
LOCAL pascal void LispMenuSelect _((short i, short m));


/***********************************************************************/
/**                                                                   **/
/**                       MENU-PROTO Definitions                      **/
/**                                                                   **/
/***********************************************************************/

# define get_menu_id(m) ((int) getfixnum(slot_value(m, s_id)))

LOCAL Style get_item_style();

/***********************************************************************/
/**                                                                   **/
/**                     MENU-ITEM-PROTO Definitions                   **/
/**                                                                   **/
/***********************************************************************/

LOCAL char *get_item_string();

/***********************************************************************/
/**                                                                   **/
/**                        Support Function                           **/
/**                                                                   **/
/***********************************************************************/

LOCAL LVAL GetMenuList(void)
{
  return(slot_value(getvalue(s_menu_proto), s_menu_list));
}

/* find the position of the item in the menu */
LOCAL int get_item_position(LVAL menu, LVAL item)
{
  int i;
  LVAL items;
  
  for (items = slot_value(menu, s_items), i = 1;
       consp(items) && car(items) != item; i++, items = cdr(items))
    ;
  if (item != car(items)) xlfail("item not in the menu");
  return(i);
}

/***********************************************************************/
/**                                                                   **/
/**                            Menu Functions                         **/
/**                                                                   **/
/***********************************************************************/

int StMObInstalled(LVAL m)
{
  return(StMObAllocated(m) && GetMenuHandle(get_menu_id(m)) != nil);
}

/* find menu object with given hardware address */
LVAL get_menu_by_hardware(IVIEW_MENU m)
{
  LVAL menu = NIL, next;
  
  for (next = GetMenuList();
       menu == NIL && consp(next); next = cdr(next)) 
    if (StMObAllocated(car(next)) && m == (IVIEW_MENU) get_menu_address(car(next)))
      menu = car(next);
  
  if (menu == NIL) xlfail("can't find menu with this handle");
  return(menu);
}

/* find lisp menu with a specified macintosh menuID */
LOCAL LVAL get_menu_by_id(int m)
{
  return(get_menu_by_hardware(GetMenuHandle(m)));
}

/* menu select function for SkelMenu. Sends :SELECT message to the menu. */
LOCAL pascal void LispMenuSelect(short i, short m)
{
  /* Unhilite the menu bar */
  HiliteMenu(0);
  
  send_message1(get_menu_by_id(m), sk_select, i);
}

/* send an installed menu the :UPDATE message */
extern pascal void UpdateLispMenus(void)
{
  LVAL list;
  for (list = GetMenuList(); consp(list); list = cdr(list))
    send_message(car(list), sk_update);
}

/* allocate a macintosh internal menu */
LOCAL id_in_use(int id)
{
  LVAL next;
  
  for (next = GetMenuList(); consp(next); next = cdr(next)) {
    if (id == get_menu_id(car(next))) return(TRUE);
  }
  return(FALSE);
}
  
LOCAL unique_id(void)
{
  static int id = 2000;
  
  if (id > 32000) id = 2000;
  id++;
  
  while (id_in_use(id)) id++;
  return(id);
}

VOID StMObAllocateMach(LVAL menu)
{
  MenuHandle theMenu;
  LVAL title;
  int menuID;
  
  title = slot_value(menu, s_title);
  
  menuID = unique_id();
  
  CtoPstr(getstring(title));
  theMenu = NewMenu(menuID, (StringPtr) getstring(title));
  PtoCstr((StringPtr) getstring(title));
  if (theMenu == NULL) xlfail("menu allocation failed");
  set_menu_address((CPTR) theMenu, menu);
  set_slot_value(menu, s_id, cvfixnum((FIXTYPE) menuID));
  
  if (kind_of_p(menu, getvalue(s_apple_menu_proto))) {
    if (! hasAppleEvents) InsertMenuItem(theMenu, "\p(-", 0);
    AppendResMenu (theMenu, 'DRVR');
  }
}

/* dispose of a macintosh menu */
VOID StMObDisposeMach(LVAL menu)
{
  if (StMObAllocated(menu)) SkelRmveMenu((MenuHandle) get_menu_address(menu));
  if (StMObAllocated(menu)) DisposeMenu((MenuHandle) get_menu_address(menu));
}

/* add items to a macintosh internal menu */
VOID StMObAppendItems(LVAL menu, LVAL items)
{
  LVAL item;
  char *s;
  int i;
  MenuHandle theMenu;
  
  if (StMObAllocated(menu)) {
    theMenu = (MenuHandle) get_menu_address(menu);
    i = llength(slot_value(menu, s_items)) - llength(items);
    if (i < 0) xlfail("append list should not exceed item list");
    
    for (; consp(items); items = cdr(items), i++) {
      item = car(items);
      s = get_item_string(item);
      CtoPstr(s);
      InsertMenuItem(theMenu, (StringPtr) s, i);
      PtoCstr((StringPtr) s);
      SetItemStyle(theMenu, i, get_item_style(item));
    }
  }
}

/* remove item from a macintosh menu */
VOID StMObDeleteItem(LVAL menu, LVAL item)
{
  if (StMObAllocated(menu)) 
    DeleteMenuItem((MenuHandle) get_menu_address(menu), get_item_position(menu, item));
}

/* install a macintosh menu */
VOID StMObInstall(LVAL menu)
{
  if (! StMObInstalled(menu)) {
    if (! StMObAllocated(menu)) StMObAllocate(menu);
    if (! SkelMenu((MenuHandle) get_menu_address(menu), LispMenuSelect, nil, false, true))
      xlfail("menu installation failed");;
  }
}

/* remove a macintosh menu */
VOID StMObRemove(LVAL menu)
{
  if (StMObAllocated(menu)) SkelRmveMenu((MenuHandle) get_menu_address(menu));
  if (StMObAllocated(menu)) StMObDispose(menu);
}

/* enable or disable a macintosh menu */
VOID StMObEnable(LVAL menu, int enable)
{
  if (StMObAllocated(menu)) {
    if (enable) EnableItem((MenuHandle) get_menu_address(menu), 0);
    else DisableItem((MenuHandle) get_menu_address(menu), 0);
    if (StMObInstalled(menu)) DrawMenuBar();
  }
  set_slot_value(menu, s_enabled, (enable) ? s_true : NIL);
}

int StMObPopup(LVAL menu, int left, int top, LVAL window)
{
  IVIEW_MENU theMenu;
  IVIEW_WINDOW w;
  int item, menuID;
  GrafPtr SavePort;
  Point pt;
  
  StMObAllocate(menu);
  theMenu = (IVIEW_MENU) get_menu_address(menu);
  menuID = get_menu_id(menu);
  if (window != NIL && (w = (IVIEW_WINDOW) GETWINDOWADDRESS(window)) != nil) {
    GetPort(&SavePort);
    SetPort(w);
    pt.h = left; pt.v = top;
    LocalToGlobal(&pt);
    left = pt.h; top = pt.v;
    SetPort(SavePort);
  }
  if (! StillDown()) {
    while (! Button()) ;
    FlushEvents(mDownMask | mUpMask, 0);
  }
  InsertMenu(theMenu, -1);
  item = LoWord(PopUpMenuSelect(theMenu, top, left, 1));
  DeleteMenu(menuID);
  StMObDispose(menu);
  return(item);
}
  
/***********************************************************************/
/**                                                                   **/
/**                         Menu Item Functions                       **/
/**                                                                   **/
/***********************************************************************/

/* Get a string for use by AppendMenu. Style info is not encoded. */
LOCAL char *get_item_string(LVAL item)
{
  LVAL title, key, mark, enabled;
  static char *s;
    
  if (! menu_item_p(item)) xlerror("not a menu item", item);
  
  title = slot_value(item, s_title);
  if (! stringp(title)) xlerror("title is not a string", title);
  key = slot_value(item, s_key);
  mark = slot_value(item, s_mark);
  enabled = slot_value(item, s_enabled);
  
  s = buf;
  if (enabled == NIL)
    s += sprintf(s, "(");
  if (charp(key))
    s += sprintf(s, "/%c", getchcode(key));
  if (mark == s_true)
    s += sprintf(s, "!%c", 0x12);
  else if (charp(mark))
    s += sprintf(s, "!%c", getchcode(key));
  sprintf(s, "%s", getstring(title));
  return(buf);
}

/* Convert style symbol to Style value */
static Style style_value(LVAL sym)
{
  if (sym == NIL) return(0);
  else if (! symbolp(sym)) xlerror("not a symbol", sym);
  else if (sym == s_bold) return(bold);
  else if (sym == s_italic) return(italic);
  else if (sym == s_underline) return(underline);
  else if (sym == s_outline) return(outline);
  else if (sym == s_shadow) return(shadow);
  else if (sym == s_condense) return(condense);
  else if (sym == s_extend) return(extend);
  else xlerror("unknown style symbol", sym);
  return 0; /* not reached */
}

/* compute the style value for a style symbol or list using bit-or */
LOCAL Style get_item_style(LVAL item)
{
  LVAL style;
  Style s;
  
  style = slot_value(item, s_style);
  if (consp(style)) {
    for (s = 0; consp(style); style = cdr(style))
      s = s | style_value(car(style));
    return(s);
  }
  else return (style_value(style));
}
	
/* adjust internal implementation of allocated menu to new instance value */ 
VOID StMObSetItemProp(LVAL item, int which)
{
  char *s, ch;
  MenuHandle theMenu;
  LVAL menu;
  int i;
  
  menu = slot_value(item, s_menu);
  if (menu != NIL && StMObAllocated(menu)) {
    theMenu = (MenuHandle) get_menu_address(menu);
    i = get_item_position(menu, item);
    switch (which) {
    case 'T': {
                LVAL title = slot_value(item, s_title);
                if (! stringp(title))
                  xlerror("title is not a string", title);
                s = (char *) getstring(title); 
                CtoPstr(s);
                SetMenuItemText(theMenu, i, (StringPtr) s);
                PtoCstr((StringPtr) s);
                break;
              }
    case 'K': DeleteMenuItem(theMenu, i);
              s = get_item_string(item);
              CtoPstr(s);
              InsertMenuItem(theMenu, (StringPtr) s, i - 1);
              PtoCstr((StringPtr) s);
              SetItemStyle(theMenu, i, get_item_style(item));
              break;
    case 'M': {
                LVAL mark = slot_value(item, s_mark);
                CheckItem(theMenu, i, FALSE);
                if (mark == s_true) ch = 0x12;
                else if (charp(mark)) ch = getchcode(mark);
                else break; 
                SetItemMark(theMenu, i, ch);
                break;
              }
    case 'S': SetItemStyle(theMenu, i, get_item_style(item)); break;
    case 'A': break;
    case 'E': if (slot_value(item, s_enabled) != NIL) 
                EnableItem(theMenu, i);
              else DisableItem(theMenu, i);
              break;
    default:  xlfail("unknown item instance variable");
    }
  }
}

/***********************************************************************/
/***********************************************************************/
/**                                                                   **/
/**                    APPLE-MENU-PROTO Methods                       **/
/**                                                                   **/
/***********************************************************************/
/***********************************************************************/

LVAL xsapple_menu_isnew(void) { return(xsmenu_isnew()); }

LVAL xsapple_menu_select(void)
{
  LVAL menu = peekarg(0), item = peekarg(1);
  int i, n;
  GrafPtr SavePort;
  
  if (! menu_p(menu)) xlerror("not a menu", menu);
  if (! fixp(item)) xlerror("not an integer", item);

  i = getfixnum(item);
  n = llength(slot_value(menu, s_items));
  
  if (i <= n) return(xsmenu_select());
  else {
    menu = xlgetarg();
    i = getfixnum(xlgetarg());
    xllastarg();
    
    if (StMObAllocated(menu)) {
      GetPort (&SavePort);
      GetMenuItemText ((MenuHandle) get_menu_address(menu), i, (StringPtr) buf);  /* get DA name */
      OpenDeskAcc((StringPtr) buf);                          /* open it     */
      SetPort (SavePort);
    }
    return(NIL);
  }
}

/* about alert for the */
# define	aboutAlrt		1000
#ifdef applec
#define COMPILER "\pMPW C, V3.2"
#endif /* applec */
#ifdef THINK_C
#define COMPILER "\pThink C, V7.0"
#endif /* THINK_C */
#ifdef __MWERKS__
#define COMPILER "\pMetroWerks CodeWarrior"
#endif /* __MWERKS__ */
LVAL xsabout_xlisp_stat(void) 
{
  xllastarg();
  sprintf(buf, "Release %d.%d.%d%s.",
	  XLS_MAJOR_RELEASE, XLS_MINOR_RELEASE, XLS_SUBMINOR_RELEASE,
	  XLS_RELEASE_STATUS);
  CtoPstr(buf);
  ParamText((StringPtr) buf, COMPILER, "\p", "\p");
  Alert (aboutAlrt, nil);
  return(NIL);
}