Fix for a crash which happened when a document couldn't be opened.
[AROS-Contrib.git] / bgui / commodityclass.c
blob5b031aa37958bfc33bf6630168ec0f802bb80005
1 /*
2 * @(#) $Header$
4 * BGUI library
5 * commodityclass.c
7 * (C) Copyright 1998 Manuel Lemos.
8 * (C) Copyright 1996-1997 Ian J. Einman.
9 * (C) Copyright 1993-1996 Jaba Development.
10 * (C) Copyright 1993-1996 Jan van den Baard.
11 * All Rights Reserved.
13 * $Log$
14 * Revision 42.5 2004/06/16 20:16:48 verhaegs
15 * Use METHODPROTO, METHOD_END and REGFUNCPROTOn where needed.
17 * Revision 42.4 2003/01/18 19:09:56 chodorowski
18 * Instead of using the _AROS or __AROS preprocessor symbols, use __AROS__.
20 * Revision 42.3 2000/05/29 00:40:23 bergers
21 * Update to compile with AROS now. Should also still compile with SASC etc since I only made changes that test the define __AROS__. The compilation is still very noisy but it does the trick for the main directory. Maybe members of the BGUI team should also have a look at the compiler warnings because some could also cause problems on other systems... (Comparison always TRUE due to datatype (or something like that)). And please compile it on an Amiga to see whether it still works... Thanks.
23 * Revision 42.2 2000/05/15 19:27:01 stegerg
24 * another hundreds of REG() macro replacements in func headers/protos.
26 * Revision 42.1 2000/05/14 23:32:47 stegerg
27 * changed over 200 function headers which all use register
28 * parameters (oh boy ...), because the simple REG() macro
29 * doesn't work with AROS. And there are still hundreds
30 * of headers left to be fixed :(
32 * Many of these functions would also work with stack
33 * params, but since i have fixed every single one
34 * I encountered up to now, I guess will have to do
35 * the same for the rest.
37 * Revision 42.0 2000/05/09 22:08:41 mlemos
38 * Bumped to revision 42.0 before handing BGUI to AROS team
40 * Revision 41.11 2000/05/09 19:54:06 mlemos
41 * Merged with the branch Manuel_Lemos_fixes.
43 * Revision 41.10 1998/02/25 21:11:50 mlemos
44 * Bumping to 41.10
46 * Revision 1.1 1998/02/25 17:07:55 mlemos
47 * Ian sources
52 #include "include/classdefs.h"
55 * Internal storage of the Hotkeys.
57 typedef struct Key {
58 struct Key *k_Next; /* next key */
59 struct Key *k_Prev; /* previous key */
60 CxObj *k_Object; /* The CxObj */
61 ULONG k_KeyID; /* key ID */
62 ULONG k_Flags; /* control flags */
63 } KEY;
65 typedef struct {
66 KEY *kl_First; /* first key */
67 KEY *kl_EndMark; /* end marker */
68 KEY *kl_Last; /* last key */
69 } KEYLIST;
72 * Object instance data.
74 typedef struct {
75 KEYLIST cd_Hotkeys; /* list of keys */
76 struct NewBroker cd_Broker; /* NewBroker structure */
77 CxObj *cd_BrokerPtr; /* points to broker */
78 ULONG cd_ErrorCode; /* error code */
79 ULONG cd_Flags; /* control flags */
80 } CD;
82 #define CDF_BROKERON (1<<0) /* broker is active */
85 * For PackBoolTags().
87 STATIC struct TagItem BoolTags[] = {
88 { COMM_Unique, NBU_UNIQUE, },
89 { COMM_Notify, NBU_NOTIFY, },
90 { TAG_DONE },
94 * Module prototypes.
98 * Create a shiny new object.
100 METHOD(CommClassNew, struct opSet *, ops)
102 CD *cd;
103 IPTR rc, data;
104 ULONG un = NBU_UNIQUE | NBU_NOTIFY;
105 struct TagItem *tstate = ops->ops_AttrList;
106 struct TagItem *tag;
109 * First we let the superclass
110 * setup an object.
112 if ((rc = AsmDoSuperMethodA(cl, obj, (Msg)ops)))
115 * Get the instance data.
117 cd = INST_DATA(cl, rc);
120 * Initialize Hotkey list.
122 NewList((struct List *)&cd->cd_Hotkeys);
125 * Get us a message port.
127 if ((cd->cd_Broker.nb_Port = CreateMsgPort()))
130 * Initialize the broker.
132 cd->cd_Broker.nb_Version = NB_VERSION;
134 while ((tag = NextTagItem(&tstate)))
136 data = tag->ti_Data;
137 switch (tag->ti_Tag)
139 case COMM_Name:
140 cd->cd_Broker.nb_Name = (BYTE *)data;
141 break;
143 case COMM_Title:
144 cd->cd_Broker.nb_Title = (BYTE *)data;
145 break;
147 case COMM_Description:
148 cd->cd_Broker.nb_Descr = (BYTE *)data;
149 break;
151 case COMM_Priority:
152 cd->cd_Broker.nb_Pri = (BYTE)data;
153 break;
155 case COMM_ShowHide:
156 if (data)
157 cd->cd_Broker.nb_Flags = COF_SHOW_HIDE;
158 break;
163 * Setup broker flags.
165 cd->cd_Broker.nb_Unique = PackBoolTags(un, ops->ops_AttrList, BoolTags);
168 * Setup broker.
170 if ((cd->cd_BrokerPtr = CxBroker(&cd->cd_Broker, NULL)))
171 return rc;
174 * Major screwup.
176 AsmCoerceMethod(cl, (Object *)rc, OM_DISPOSE);
178 return 0;
180 METHOD_END
183 * Get rid of an object.
185 METHOD(CommClassDispose, Msg, msg)
187 CD *cd = INST_DATA( cl, obj );
188 struct MsgPort *mp;
189 struct Message *tmp;
190 KEY *key;
193 * Scan through the list of keys.
195 while (( key = ( KEY * )RemHead(( struct List * )&cd->cd_Hotkeys ))) {
197 * Enabled?
199 if ( ! ( key->k_Flags & CAHF_DISABLED ))
201 * Yes. Remove it.
203 RemoveCxObj( key->k_Object );
205 * Delete the CxObj.
207 DeleteCxObjAll( key->k_Object );
210 * Deallocate the KEY structure.
212 BGUI_FreePoolMem( key );
216 * De-activate and delete the broker.
218 if ( cd->cd_BrokerPtr ) {
219 if ( cd->cd_Flags & CDF_BROKERON )
220 ActivateCxObj( cd->cd_BrokerPtr, FALSE );
221 DeleteCxObjAll( cd->cd_BrokerPtr );
225 * Strip the remaining messages.
227 if (( mp = cd->cd_Broker.nb_Port )) {
228 while (( tmp = GetMsg( mp ))) ReplyMsg( tmp );
229 DeleteMsgPort( mp );
233 * The superclass takes care of the rest.
235 return( AsmDoSuperMethodA( cl, obj, msg ));
237 METHOD_END
240 * They want something.
243 STATIC METHOD(CommClassGet, struct opGet *, opg)
245 CD *cd = ( CD * )INST_DATA( cl, obj );
246 ULONG rc = 1L;
247 IPTR *store = opg->opg_Storage;
249 switch ( opg->opg_AttrID ) {
251 case COMM_SigMask:
252 *store = ( ULONG )( 1L << cd->cd_Broker.nb_Port->mp_SigBit );
253 break;
255 case COMM_ErrorCode:
256 *store = cd->cd_ErrorCode;
257 break;
259 default:
260 rc = AsmDoSuperMethodA( cl, obj, ( Msg )opg );
261 break;
263 return( rc );
265 METHOD_END
268 * Search for a key by it's ID.
270 STATIC ASM KEY *FindKey( REG(a0) KEYLIST *kl, REG(d0) ULONG keyID )
272 KEY *key;
274 for ( key = kl->kl_First; key->k_Next; key = key->k_Next ) {
275 if ( keyID == key->k_KeyID )
276 return( key );
278 return( NULL );
282 * Add a hotkey to the list.
285 STATIC METHOD(CommClassAddHotkey, struct cmAddHotkey *, cah)
287 CD *cd = ( CD * )INST_DATA( cl, obj );
288 KEY *key;
291 * Deactivate the broker if active.
293 if ( cd->cd_Flags & CDF_BROKERON )
294 ActivateCxObj( cd->cd_BrokerPtr, FALSE );
297 * Key ID's must be unique.
299 if ( ! FindKey( &cd->cd_Hotkeys, cah->cah_KeyID )) {
301 * Allocate a KEY structure.
303 if (( key = ( KEY * )BGUI_AllocPoolMem( sizeof( KEY )))) {
305 * Setup the key.
307 if (( key->k_Object = HotKey( cah->cah_InputDescription, cd->cd_Broker.nb_Port, cah->cah_KeyID ))) {
309 * Initialize the KEY structure.
311 key->k_Flags = cah->cah_Flags;
312 key->k_KeyID = cah->cah_KeyID;
315 * Add the key when necessary.
317 if ( ! ( key->k_Flags & CAHF_DISABLED ))
318 AttachCxObj( cd->cd_BrokerPtr, key->k_Object );
321 * An error occured?
323 if ( ! CxObjError( key->k_Object )) {
325 * No. Add the key to the list.
327 AddTail(( struct List * )&cd->cd_Hotkeys, ( struct Node * )key );
330 * Clear the error code.
332 cd->cd_ErrorCode = CMERR_OK;
335 * Activate the broker if necessary.
337 if ( cd->cd_Flags & CDF_BROKERON )
338 ActivateCxObj( cd->cd_BrokerPtr, TRUE );
339 return 1;
340 } else
342 * Error from CxObjError();
344 cd->cd_ErrorCode = CMERR_CXOBJERROR;
346 * Remove and dispose of the Cx
347 * object.
349 if ( ! ( key->k_Flags & CAHF_DISABLED ))
350 RemoveCxObj( key->k_Object );
351 DeleteCxObjAll( key->k_Object );
352 } else
353 cd->cd_ErrorCode = CMERR_KEY_CREATION;
355 * Free memory.
357 BGUI_FreePoolMem( key );
358 } else
359 cd->cd_ErrorCode = CMERR_NO_MEMORY;
360 } else
361 cd->cd_ErrorCode = CMERR_KEYID_IN_USE;
364 * Re-activate the broker if necessary.
366 if ( cd->cd_Flags & CDF_BROKERON )
367 ActivateCxObj( cd->cd_BrokerPtr, TRUE );
369 return 0;
371 METHOD_END
374 * Remove a hotkey from the list.
376 STATIC METHOD(CommClassRemHotkey, struct cmDoKeyCommand *, com)
378 CD *cd = ( CD * )INST_DATA( cl, obj );
379 KEY *key;
380 ULONG rc = 0L;
383 * Deactivate the broker if necessary.
385 if ( cd->cd_Flags & CDF_BROKERON )
386 ActivateCxObj( cd->cd_BrokerPtr, FALSE );
389 * Locate the key.
391 if (( key = FindKey( &cd->cd_Hotkeys, com->cdkc_KeyID ))) {
393 * Remove it from the list.
395 Remove(( struct Node * )key );
398 * Remove the CxObj when necessary.
400 if ( ! ( key->k_Flags & CAHF_DISABLED ))
401 RemoveCxObj( key->k_Object );
404 * Delete the CxObj.
406 DeleteCxObjAll( key->k_Object );
409 * Deallocate the KEY structure.
411 BGUI_FreePoolMem( key );
412 rc = 1L;
416 * Activate the broker if necessary.
418 if ( cd->cd_Flags & CDF_BROKERON )
419 ActivateCxObj( cd->cd_BrokerPtr, TRUE );
421 return( rc );
423 METHOD_END
426 * Disable a hotkey.
428 STATIC METHOD(CommClassDisableHotkey, struct cmDoKeyCommand *, com)
430 CD *cd = ( CD * )INST_DATA( cl, obj );
431 KEY *key;
432 ULONG rc = 0L;
435 * Deactivate the broker if necessary.
437 if ( cd->cd_Flags & CDF_BROKERON )
438 ActivateCxObj( cd->cd_BrokerPtr, FALSE );
441 * Locate the key.
443 if (( key = FindKey( &cd->cd_Hotkeys, com->cdkc_KeyID ))) {
445 * Only disable when the key is enabled.
447 if ( ! ( key->k_Flags & CAHF_DISABLED )) {
449 * Remove the key.
451 RemoveCxObj( key->k_Object );
454 * Mark it as disabled.
456 key->k_Flags |= CAHF_DISABLED;
457 rc = 1;
462 * Activate the broker if necessary.
464 if ( cd->cd_Flags & CDF_BROKERON )
465 ActivateCxObj( cd->cd_BrokerPtr, TRUE );
467 return( rc );
469 METHOD_END
472 * Enable a hotkey.
475 STATIC METHOD(CommClassEnableHotkey, struct cmDoKeyCommand *, com)
477 CD *cd = ( CD * )INST_DATA( cl, obj );
478 KEY *key;
479 ULONG rc = 0L;
482 * Deactivate the broker if necessary.
484 if ( cd->cd_Flags & CDF_BROKERON )
485 ActivateCxObj( cd->cd_BrokerPtr, FALSE );
488 * Locate the key.
490 if (( key = FindKey( &cd->cd_Hotkeys, com->cdkc_KeyID ))) {
492 * Only enable when the key is disabled.
494 if ( key->k_Flags & CAHF_DISABLED ) {
496 * Add the key.
498 AttachCxObj( cd->cd_BrokerPtr, key->k_Object );
501 * Clear the disabled bit.
503 key->k_Flags &= ~CAHF_DISABLED;
504 rc = 1L;
509 * Activate the broker if necessary.
511 if ( cd->cd_Flags & CDF_BROKERON )
512 ActivateCxObj( cd->cd_BrokerPtr, TRUE );
514 return( rc );
516 METHOD_END
519 * Enable the broker.
521 STATIC METHOD(CommClassEnableBroker, Msg, msg)
523 CD *cd = ( CD * )INST_DATA( cl, obj );
524 ULONG rc = 0L;
527 * Only enable when the broker is disabled.
529 if ( ! ( cd->cd_Flags & CDF_BROKERON )) {
531 * Activate the broker.
533 ActivateCxObj( cd->cd_BrokerPtr, TRUE );
536 * Mark us as active.
538 cd->cd_Flags |= CDF_BROKERON;
539 rc = 1L;
541 return( rc );
543 METHOD_END
546 * Disable the broker.
548 STATIC METHOD(CommClassDisableBroker, Msg, msg)
550 CD *cd = ( CD * )INST_DATA( cl, obj );
551 ULONG rc = 0L;
554 * Only disable when the broker is enabled.
556 if ( cd->cd_Flags & CDF_BROKERON ) {
558 * Deactivate the broker.
560 ActivateCxObj( cd->cd_BrokerPtr, FALSE );
563 * Clear the enabled bit.
565 cd->cd_Flags &= ~CDF_BROKERON;
566 rc = 1L;
568 return( rc );
570 METHOD_END
573 * Poll broker port.
575 STATIC METHOD(CommClassMsgInfo, struct cmMsgInfo*, cmi)
577 CD *cd = ( CD * )INST_DATA( cl, obj );
578 CxMsg *msg;
579 ULONG rc = 0, type, id;
580 IPTR data;
583 * Get a message from the port.
585 if (( msg = ( CxMsg * )GetMsg( cd->cd_Broker.nb_Port ))) {
587 * Get message data.
589 type = CxMsgType(msg);
590 id = CxMsgID(msg);
591 data = (IPTR)CxMsgData(msg);
594 * Save data where ever possible.
596 if ( cmi->cmi_Info.Type ) *( cmi->cmi_Info.Type ) = type;
597 if ( cmi->cmi_Info.ID ) *( cmi->cmi_Info.ID ) = id;
598 if ( cmi->cmi_Info.Data ) *( cmi->cmi_Info.Data ) = data;
601 * Setup V40 return codes.
603 switch (type)
605 case CXM_IEVENT:
606 rc = id;
607 break;
609 case CXM_COMMAND:
610 switch(id)
612 case CXCMD_KILL:
613 rc = CMMI_KILL;
614 break;
616 case CXCMD_DISABLE:
617 AsmDoMethod(obj, CM_DISABLEBROKER);
618 rc = CMMI_DISABLE;
619 break;
621 case CXCMD_ENABLE:
622 AsmDoMethod(obj, CM_ENABLEBROKER);
623 rc = CMMI_ENABLE;
624 break;
626 case CXCMD_UNIQUE:
627 rc = CMMI_UNIQUE;
628 break;
630 case CXCMD_APPEAR:
631 rc = CMMI_APPEAR;
632 break;
634 case CXCMD_DISAPPEAR:
635 rc = CMMI_DISAPPEAR;
636 break;
638 break;
642 * Reply the message.
644 ReplyMsg(( struct Message *)msg );
645 } else
647 * No more messages.
649 rc = CMMI_NOMORE;
651 return( rc );
653 METHOD_END
656 * Class function table.
658 STATIC DPFUNC ClassFunc[] = {
659 { OM_NEW, CommClassNew, },
660 { OM_GET, CommClassGet, },
661 { OM_DISPOSE, CommClassDispose, },
662 { CM_ADDHOTKEY, CommClassAddHotkey, },
663 { CM_REMHOTKEY, CommClassRemHotkey, },
664 { CM_DISABLEHOTKEY, CommClassDisableHotkey, },
665 { CM_ENABLEHOTKEY, CommClassEnableHotkey, },
666 { CM_DISABLEBROKER, CommClassDisableBroker, },
667 { CM_ENABLEBROKER, CommClassEnableBroker, },
668 { CM_MSGINFO, CommClassMsgInfo, },
669 { DF_END, NULL },
673 * Simple class initialization.
675 makeproto Class *InitCxClass(void)
677 return BGUI_MakeClass(CLASS_ObjectSize, sizeof(CD),
678 CLASS_DFTable, ClassFunc,
679 TAG_DONE);