~ubuntu-branches/ubuntu/edgy/fltk1.1/edgy

« back to all changes in this revision

Viewing changes to src/Fl_Menu_.cxx

  • Committer: Bazaar Package Importer
  • Author(s): Aaron M. Ucko
  • Date: 2004-04-14 21:55:19 UTC
  • Revision ID: james.westby@ubuntu.com-20040414215519-avj0ojjkjni1s4ty
Tags: upstream-1.1.4+1.1.5rc1
ImportĀ upstreamĀ versionĀ 1.1.4+1.1.5rc1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// "$Id: Fl_Menu_.cxx,v 1.7.2.8.2.9 2004/04/11 04:38:57 easysw Exp $"
 
3
//
 
4
// Common menu code for the Fast Light Tool Kit (FLTK).
 
5
//
 
6
// Copyright 1998-2004 by Bill Spitzak and others.
 
7
//
 
8
// This library is free software; you can redistribute it and/or
 
9
// modify it under the terms of the GNU Library General Public
 
10
// License as published by the Free Software Foundation; either
 
11
// version 2 of the License, or (at your option) any later version.
 
12
//
 
13
// This library is distributed in the hope that it will be useful,
 
14
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
16
// Library General Public License for more details.
 
17
//
 
18
// You should have received a copy of the GNU Library General Public
 
19
// License along with this library; if not, write to the Free Software
 
20
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 
21
// USA.
 
22
//
 
23
// Please report all bugs and problems to "fltk-bugs@fltk.org".
 
24
//
 
25
 
 
26
// This is a base class for all items that have a menu:
 
27
//      Fl_Menu_Bar, Fl_Menu_Button, Fl_Choice
 
28
// This provides storage for a menu item, functions to add/modify/delete
 
29
// items, and a call for when the user picks a menu item.
 
30
 
 
31
// More code in Fl_Menu_add.cxx
 
32
 
 
33
#include <FL/Fl.H>
 
34
#include <FL/Fl_Menu_.H>
 
35
#include "flstring.h"
 
36
#include <stdio.h>
 
37
#include <stdlib.h>
 
38
 
 
39
// Set 'pathname' of specified menuitem
 
40
//    If finditem==NULL, mvalue() is used (the most recently picked menuitem)
 
41
//    Returns:
 
42
//       0 : OK
 
43
//      -1 : item not found (name="")
 
44
//      -2 : 'name' not large enough (name="")
 
45
//
 
46
#define SAFE_STRCAT(s) \
 
47
    { len += strlen(s); if ( len >= namelen ) { *name='\0'; return(-2); } else strcat(name,(s)); }
 
48
int Fl_Menu_::item_pathname(char *name, int namelen, const Fl_Menu_Item *finditem) const {
 
49
    int len = 0;
 
50
    finditem = finditem ? finditem : mvalue();    
 
51
    name[0] = '\0';
 
52
    for ( int t=0; t<size(); t++ ) {
 
53
        const Fl_Menu_Item *m = &(menu()[t]);
 
54
        if ( m->submenu() ) {                           // submenu? descend
 
55
            if ( *name ) SAFE_STRCAT("/");
 
56
            SAFE_STRCAT(m->label());
 
57
        } else {
 
58
            if ( m->label() ) {                         // menu item?
 
59
                if ( m == finditem ) {                  // found? tack on itemname, done.
 
60
                    SAFE_STRCAT("/");
 
61
                    SAFE_STRCAT(m->label());
 
62
                    return(0);
 
63
                }
 
64
            } else {                                    // end of submenu? pop
 
65
                char *ss = strrchr(name, '/');
 
66
                if ( ss ) { *ss = 0; len = strlen(name); }      // "File/Edit" -> "File"
 
67
                else { name[0] = '\0'; len = 0; }               // "File" -> ""
 
68
                continue;
 
69
            }
 
70
        }
 
71
    }
 
72
    *name = '\0';
 
73
    return(-1);                                         // item not found
 
74
}
 
75
 
 
76
// FIND MENU ITEM INDEX, GIVEN MENU PATHNAME
 
77
//     eg. "Edit/Copy"
 
78
//     Will also return submenus, eg. "Edit"
 
79
//     Returns NULL if not found.
 
80
//
 
81
const Fl_Menu_Item *
 
82
Fl_Menu_::find_item(const char *name)
 
83
{
 
84
  char menupath[1024] = "";     // File/Export
 
85
 
 
86
  for ( int t=0; t < size(); t++ ) {
 
87
    Fl_Menu_Item *m = menu_ + t;
 
88
 
 
89
    if (m->submenu()) {
 
90
      // IT'S A SUBMENU
 
91
      if (menupath[0]) strlcat(menupath, "/", sizeof(menupath));
 
92
      strlcat(menupath, m->label(), sizeof(menupath));
 
93
      if (!strcmp(menupath, name)) return m;
 
94
    } else {
 
95
      if (!m->label()) {
 
96
        // END OF SUBMENU? Pop back one level.
 
97
        char *ss = strrchr(menupath, '/');
 
98
        if ( ss ) *ss = 0;
 
99
        continue;
 
100
      }
 
101
 
 
102
      // IT'S A MENU ITEM
 
103
      char itempath[1024];      // eg. Edit/Copy
 
104
      strcpy(itempath, menupath);
 
105
      if (itempath[0]) strlcat(itempath, "/", sizeof(itempath));
 
106
      strlcat(itempath, m->label(), sizeof(itempath));
 
107
      if (!strcmp(itempath, name)) return m;
 
108
    }
 
109
  }
 
110
 
 
111
  return (const Fl_Menu_Item *)0;
 
112
}
 
113
 
 
114
int Fl_Menu_::value(const Fl_Menu_Item* m) {
 
115
  clear_changed();
 
116
  if (value_ != m) {value_ = m; return 1;}
 
117
  return 0;
 
118
}
 
119
 
 
120
// When user picks a menu item, call this.  It will do the callback.
 
121
// Unfortunatly this also casts away const for the checkboxes, but this
 
122
// was necessary so non-checkbox menus can really be declared const...
 
123
const Fl_Menu_Item* Fl_Menu_::picked(const Fl_Menu_Item* v) {
 
124
  if (v) {
 
125
    if (v->radio()) {
 
126
      if (!v->value()) { // they are turning on a radio item
 
127
        set_changed();
 
128
        ((Fl_Menu_Item*)v)->setonly();
 
129
      }
 
130
      redraw();
 
131
    } else if (v->flags & FL_MENU_TOGGLE) {
 
132
      set_changed();
 
133
      ((Fl_Menu_Item*)v)->flags ^= FL_MENU_VALUE;
 
134
      redraw();
 
135
    } else if (v != value_) { // normal item
 
136
      set_changed();
 
137
    }
 
138
    value_ = v;
 
139
    if (when()&(FL_WHEN_CHANGED|FL_WHEN_RELEASE)) {
 
140
      if (changed() || when()&FL_WHEN_NOT_CHANGED) {
 
141
        clear_changed();
 
142
        if (value_ && value_->callback_) value_->do_callback((Fl_Widget*)this);
 
143
        else do_callback();
 
144
      }
 
145
    }
 
146
  }
 
147
  return v;
 
148
}
 
149
 
 
150
// turn on one of a set of radio buttons
 
151
void Fl_Menu_Item::setonly() {
 
152
  flags |= FL_MENU_RADIO | FL_MENU_VALUE;
 
153
  Fl_Menu_Item* j;
 
154
  for (j = this; ; ) {  // go down
 
155
    if (j->flags & FL_MENU_DIVIDER) break; // stop on divider lines
 
156
    j++;
 
157
    if (!j->text || !j->radio()) break; // stop after group
 
158
    j->clear();
 
159
  }
 
160
  for (j = this-1; ; j--) { // go up
 
161
    if (!j->text || (j->flags&FL_MENU_DIVIDER) || !j->radio()) break;
 
162
    j->clear();
 
163
  }
 
164
}
 
165
 
 
166
Fl_Menu_::Fl_Menu_(int X,int Y,int W,int H,const char* l)
 
167
: Fl_Widget(X,Y,W,H,l) {
 
168
  set_flag(SHORTCUT_LABEL);
 
169
  box(FL_UP_BOX);
 
170
  when(FL_WHEN_RELEASE_ALWAYS);
 
171
  value_ = menu_ = 0;
 
172
  alloc = 0;
 
173
  selection_color(FL_SELECTION_COLOR);
 
174
  textfont(FL_HELVETICA);
 
175
  textsize((uchar)FL_NORMAL_SIZE);
 
176
  textcolor(FL_BLACK);
 
177
  down_box(FL_NO_BOX);
 
178
}
 
179
 
 
180
int Fl_Menu_::size() const {
 
181
  if (!menu_) return 0;
 
182
  return menu_->size();
 
183
}
 
184
 
 
185
void Fl_Menu_::menu(const Fl_Menu_Item* m) {
 
186
  clear();
 
187
  value_ = menu_ = (Fl_Menu_Item*)m;
 
188
}
 
189
 
 
190
// this version is ok with new Fl_Menu_add code with fl_menu_array_owner:
 
191
 
 
192
void Fl_Menu_::copy(const Fl_Menu_Item* m, void* ud) {
 
193
  int n = m->size();
 
194
  Fl_Menu_Item* newMenu = new Fl_Menu_Item[n];
 
195
  memcpy(newMenu, m, n*sizeof(Fl_Menu_Item));
 
196
  menu(newMenu);
 
197
  alloc = 1; // make destructor free array, but not strings
 
198
  // for convienence, provide way to change all the user data pointers:
 
199
  if (ud) for (; n--;) {
 
200
    if (newMenu->callback_) newMenu->user_data_ = ud;
 
201
    newMenu++;
 
202
  }
 
203
}
 
204
 
 
205
Fl_Menu_::~Fl_Menu_() {
 
206
  clear();
 
207
}
 
208
 
 
209
// Fl_Menu::add() uses this to indicate the owner of the dynamically-
 
210
// expanding array.  We must not free this array:
 
211
Fl_Menu_* fl_menu_array_owner = 0;
 
212
 
 
213
void Fl_Menu_::clear() {
 
214
  if (alloc) {
 
215
    if (alloc>1) for (int i = size(); i--;)
 
216
      if (menu_[i].text) free((void*)menu_[i].text);
 
217
    if (this == fl_menu_array_owner)
 
218
      fl_menu_array_owner = 0;
 
219
    else
 
220
      delete[] menu_;
 
221
    menu_ = 0;
 
222
    value_ = 0;
 
223
    alloc = 0;
 
224
  }
 
225
}
 
226
 
 
227
//
 
228
// End of "$Id: Fl_Menu_.cxx,v 1.7.2.8.2.9 2004/04/11 04:38:57 easysw Exp $".
 
229
//